Index: /trunk/src/VBox/Frontends/VirtualBox/include/VBoxSnapshotDetailsDlg.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/include/VBoxSnapshotDetailsDlg.h	(revision 24731)
+++ /trunk/src/VBox/Frontends/VirtualBox/include/VBoxSnapshotDetailsDlg.h	(revision 24732)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2006-2008 Sun Microsystems, Inc.
+ * Copyright (C) 2008-2009 Sun Microsystems, Inc.
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -24,10 +24,13 @@
 #define __VBoxSnapshotDetailsDlg_h__
 
+/* Local includes */
 #include "VBoxSnapshotDetailsDlg.gen.h"
 #include "QIWithRetranslateUI.h"
 #include "COMDefs.h"
 
-class VBoxSnapshotDetailsDlg : public QIWithRetranslateUI<QDialog>,
-                               public Ui::VBoxSnapshotDetailsDlg
+/* Global forwards */
+class QScrollArea;
+
+class VBoxSnapshotDetailsDlg : public QIWithRetranslateUI <QDialog>, public Ui::VBoxSnapshotDetailsDlg
 {
     Q_OBJECT;
@@ -44,4 +47,7 @@
     void retranslateUi();
 
+    bool eventFilter (QObject *aObject, QEvent *aEvent);
+    void showEvent (QShowEvent *aEvent);
+
 private slots:
 
@@ -51,4 +57,36 @@
 
     CSnapshot mSnapshot;
+
+    QPixmap mThumbnail;
+};
+
+class VBoxScreenshotViewer : public QIWithRetranslateUI2 <QWidget>
+{
+    Q_OBJECT;
+
+public:
+
+    VBoxScreenshotViewer (QWidget *aParent, const QPixmap &aScreenshot,
+                          const QString &aSnapshotName, const QString &aMachineName);
+
+private:
+
+    void retranslateUi();
+
+    void showEvent (QShowEvent *aEvent);
+    void resizeEvent (QResizeEvent *aEvent);
+    void mousePressEvent (QMouseEvent *aEvent);
+    void keyPressEvent (QKeyEvent *aEvent);
+
+    void adjustPicture();
+
+    QScrollArea *mArea;
+    QLabel *mPicture;
+
+    QPixmap mScreenshot;
+    QString mSnapshotName;
+    QString mMachineName;
+
+    bool mZoomMode;
 };
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxSnapshotDetailsDlg.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxSnapshotDetailsDlg.cpp	(revision 24731)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxSnapshotDetailsDlg.cpp	(revision 24732)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2006-2008 Sun Microsystems, Inc.
+ * Copyright (C) 2008-2009 Sun Microsystems, Inc.
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -21,29 +21,32 @@
  */
 
-#include <VBoxSnapshotDetailsDlg.h>
+/* Global includes */
+#include <QDateTime>
+#include <QPushButton>
+#include <QScrollArea>
+
+/* Local includes */
 #include <VBoxGlobal.h>
 #include <VBoxProblemReporter.h>
+#include <VBoxSnapshotDetailsDlg.h>
 #include <VBoxUtils.h>
 
-/* Qt includes */
-#include <QPushButton>
-
 VBoxSnapshotDetailsDlg::VBoxSnapshotDetailsDlg (QWidget *aParent)
-    : QIWithRetranslateUI<QDialog> (aParent)
+    : QIWithRetranslateUI <QDialog> (aParent)
 {
     /* Apply UI decorations */
     Ui::VBoxSnapshotDetailsDlg::setupUi (this);
 
-    /* Setup mTeSummary browser. */
-    mTeSummary->viewport()->setAutoFillBackground (false);
-    mTeSummary->setFocus();
+    /* Setup mLbThumbnail label */
+    mLbThumbnail->setCursor (Qt::PointingHandCursor);
+    mLbThumbnail->installEventFilter (this);
+
+    /* Setup mTeDetails browser */
+    mTeDetails->viewport()->setAutoFillBackground (false);
+    mTeDetails->setFocus();
 
     /* Setup connections */
-    connect (mLeName, SIGNAL (textChanged (const QString&)),
-             this, SLOT (onNameChanged (const QString&)));
-    connect (mButtonBox, SIGNAL (helpRequested()),
-             &vboxProblem(), SLOT (showHelpHelpDialog()));
-
-    resize (450, 450);
+    connect (mLeName, SIGNAL (textChanged (const QString&)), this, SLOT (onNameChanged (const QString&)));
+    connect (mButtonBox, SIGNAL (helpRequested()), &vboxProblem(), SLOT (showHelpHelpDialog()));
 }
 
@@ -51,10 +54,45 @@
 {
     mSnapshot = aSnapshot;
-    CMachine machine = aSnapshot.GetMachine();
-
-    /* Get properties */
+    CMachine machine = mSnapshot.GetMachine();
+
+    /* Get general properties */
     mLeName->setText (aSnapshot.GetName());
     mTeDescription->setText (aSnapshot.GetDescription());
 
+    /* Get timestamp info */
+    QDateTime timestamp;
+    timestamp.setTime_t (mSnapshot.GetTimeStamp() / 1000);
+    bool dateTimeToday = timestamp.date() == QDate::currentDate();
+    QString dateTime = dateTimeToday ? timestamp.time().toString (Qt::LocalDate) : timestamp.toString (Qt::LocalDate);
+    mTxTaken->setText (dateTime);
+
+    /* Get thumbnail if present */
+    ULONG width = 0, height = 0;
+    QVector <BYTE> data = machine.ReadSavedThumbnailToArray (true, width, height);
+    mThumbnail = data.size() != 0 ? QPixmap::fromImage (QImage (data.data(), width, height, QImage::Format_RGB32)) : QPixmap();
+    QGridLayout *lt = qobject_cast <QGridLayout*> (layout());
+    Assert (lt);
+    if (mThumbnail.isNull())
+    {
+        lt->removeWidget (mLbThumbnail);
+        mLbThumbnail->setHidden (true);
+
+        lt->removeWidget (mLeName);
+        lt->removeWidget (mTxTaken);
+        lt->addWidget (mLeName, 0, 1, 1, 2);
+        lt->addWidget (mTxTaken, 1, 1, 1, 2);
+    }
+    else
+    {
+        lt->removeWidget (mLeName);
+        lt->removeWidget (mTxTaken);
+        lt->addWidget (mLeName, 0, 1);
+        lt->addWidget (mTxTaken, 1, 1);
+
+        lt->removeWidget (mLbThumbnail);
+        lt->addWidget (mLbThumbnail, 0, 2, 2, 1);
+        mLbThumbnail->setHidden (false);
+    }
+
     retranslateUi();
 }
@@ -78,10 +116,37 @@
     CMachine machine = mSnapshot.GetMachine();
 
-    setWindowTitle (tr ("Details of %1 (%2)")
-                    .arg (mSnapshot.GetName()).arg (machine.GetName()));
-
-    /* Compose summary */
-    mTeSummary->setText (
-        vboxGlobal().detailsReport (machine, false /* withLinks */));
+    setWindowTitle (tr ("Details of %1 (%2)").arg (mSnapshot.GetName()).arg (machine.GetName()));
+
+    mTeDetails->setText (vboxGlobal().detailsReport (machine, false /* with links? */));
+}
+
+bool VBoxSnapshotDetailsDlg::eventFilter (QObject *aObject, QEvent *aEvent)
+{
+    Assert (aObject == mLbThumbnail);
+    if (aEvent->type() == QEvent::MouseButtonPress)
+    {
+        CMachine machine = mSnapshot.GetMachine();
+
+        ULONG width = 0, height = 0;
+        QVector <BYTE> data = machine.ReadSavedScreenshotPNGToArray (width, height);
+        Assert (data.size());
+        QPixmap pixmap = QPixmap::fromImage (QImage::fromData (data.data(), data.size(), "PNG"));
+
+        VBoxScreenshotViewer *viewer = new VBoxScreenshotViewer (this, pixmap, machine.GetName(), mSnapshot.GetName());
+        viewer->show();
+    }
+    return QDialog::eventFilter (aObject, aEvent);
+}
+
+void VBoxSnapshotDetailsDlg::showEvent (QShowEvent *aEvent)
+{
+    if (!mLbThumbnail->pixmap() && !mThumbnail.isNull())
+    {
+        mLbThumbnail->setPixmap (mThumbnail.scaled (QSize (1, mLbThumbnail->height()),
+                                                    Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
+        retranslateUi();
+    }
+
+    QDialog::showEvent (aEvent);
 }
 
@@ -91,2 +156,82 @@
 }
 
+VBoxScreenshotViewer::VBoxScreenshotViewer (QWidget *aParent, const QPixmap &aScreenshot,
+                                            const QString &aSnapshotName, const QString &aMachineName)
+    : QIWithRetranslateUI2 <QWidget> (aParent, Qt::Tool)
+    , mArea (new QScrollArea (this))
+    , mPicture (new QLabel)
+    , mScreenshot (aScreenshot)
+    , mSnapshotName (aSnapshotName)
+    , mMachineName (aMachineName)
+    , mZoomMode (true)
+{
+    setWindowModality (Qt::ApplicationModal);
+    setCursor (Qt::PointingHandCursor);
+    QVBoxLayout *layout = new QVBoxLayout (this);
+    layout->setMargin (0);
+
+    mArea->setWidget (mPicture);
+    mArea->setWidgetResizable (true);
+    layout->addWidget (mArea);
+
+    QSize maxSize = aScreenshot.size() + QSize (mArea->frameWidth() * 2, mArea->frameWidth() * 2);
+    QSize initSize = QSize (640, 480).boundedTo (maxSize);
+
+    setMaximumSize (maxSize);
+
+    QRect geo (QPoint (0, 0), initSize);
+    geo.moveCenter (parentWidget()->geometry().center());
+    setGeometry (geo);
+
+    retranslateUi();
+}
+
+void VBoxScreenshotViewer::retranslateUi()
+{
+    setWindowTitle (tr ("Screenshot of %1 (%2)").arg (mSnapshotName).arg (mMachineName));
+}
+
+void VBoxScreenshotViewer::showEvent (QShowEvent *aEvent)
+{
+    adjustPicture();
+    QIWithRetranslateUI2 <QWidget>::showEvent (aEvent);
+}
+
+void VBoxScreenshotViewer::resizeEvent (QResizeEvent *aEvent)
+{
+    adjustPicture();
+    QIWithRetranslateUI2 <QWidget>::resizeEvent (aEvent);
+}
+
+void VBoxScreenshotViewer::mousePressEvent (QMouseEvent *aEvent)
+{
+    mZoomMode = !mZoomMode;
+    adjustPicture();
+    QIWithRetranslateUI2 <QWidget>::mousePressEvent (aEvent);
+}
+
+void VBoxScreenshotViewer::keyPressEvent (QKeyEvent *aEvent)
+{
+    if (aEvent->key() == Qt::Key_Escape)
+        deleteLater();
+    QIWithRetranslateUI2 <QWidget>::keyPressEvent (aEvent);
+}
+
+void VBoxScreenshotViewer::adjustPicture()
+{
+    if (mZoomMode)
+    {
+        mArea->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
+        mArea->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
+        mPicture->setPixmap (mScreenshot.scaled (mArea->viewport()->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+        mPicture->setToolTip (tr ("Click to view non-scaled screenshot."));
+    }
+    else
+    {
+        mArea->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded);
+        mArea->setHorizontalScrollBarPolicy (Qt::ScrollBarAsNeeded);
+        mPicture->setPixmap (mScreenshot);
+        mPicture->setToolTip (tr ("Click to view scaled screenshot."));
+    }
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/ui/VBoxSnapshotDetailsDlg.ui
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/ui/VBoxSnapshotDetailsDlg.ui	(revision 24731)
+++ /trunk/src/VBox/Frontends/VirtualBox/ui/VBoxSnapshotDetailsDlg.ui	(revision 24732)
@@ -1,7 +1,7 @@
-<ui version="4.0" >
+<ui version="4.0">
  <comment>
  VBox frontends: Qt4 GUI ("VirtualBox"):
 
- Copyright (C) 2008 Sun Microsystems, Inc.
+ Copyright (C) 2008-2009 Sun Microsystems, Inc.
 
  This file is part of VirtualBox Open Source Edition (OSE), as
@@ -18,113 +18,143 @@
  </comment>
  <class>VBoxSnapshotDetailsDlg</class>
- <widget class="QDialog" name="VBoxSnapshotDetailsDlg" >
-  <property name="geometry" >
+ <widget class="QDialog" name="VBoxSnapshotDetailsDlg">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>408</width>
-    <height>388</height>
+    <width>450</width>
+    <height>450</height>
    </rect>
   </property>
-  <property name="windowTitle" >
-   <string>VBoxSnapshotDetailsDlg</string>
+  <property name="windowIcon">
+   <iconset resource="../VirtualBox1.qrc">:/settings_16px.png</iconset>
   </property>
-  <property name="windowIcon" >
-   <iconset resource="../VirtualBox1.qrc" >:/settings_16px.png</iconset>
-  </property>
-  <layout class="QVBoxLayout" >
-   <item>
-    <widget class="QGroupBox" name="mGbSnapshotDetails" >
-     <property name="title" >
-      <string>Snapshot Details</string>
-     </property>
-     <layout class="QVBoxLayout" >
-      <property name="topMargin" >
-       <number>4</number>
-      </property>
-      <item>
-       <layout class="QVBoxLayout" >
-        <item>
-         <widget class="QLabel" name="mTxName" >
-          <property name="text" >
-           <string>&amp;Name</string>
-          </property>
-          <property name="buddy" >
-           <cstring>mLeName</cstring>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QLineEdit" name="mLeName" />
-        </item>
-       </layout>
-      </item>
-      <item>
-       <layout class="QVBoxLayout" >
-        <item>
-         <widget class="QLabel" name="mTxDescription" >
-          <property name="text" >
-           <string>&amp;Description</string>
-          </property>
-          <property name="buddy" >
-           <cstring>mTeDescription</cstring>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QTextEdit" name="mTeDescription" >
-          <property name="sizePolicy" >
-           <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="tabChangesFocus" >
-           <bool>true</bool>
-          </property>
-          <property name="acceptRichText" >
-           <bool>false</bool>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="mGbMachineDetails" >
-     <property name="title" >
-      <string>&amp;Machine Details</string>
-     </property>
-     <layout class="QVBoxLayout" >
-      <property name="topMargin" >
-       <number>4</number>
-      </property>
-      <item>
-       <widget class="QTextEdit" name="mTeSummary" >
-        <property name="sizePolicy" >
-         <sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="frameShape" >
-         <enum>QFrame::NoFrame</enum>
-        </property>
-        <property name="frameShadow" >
-         <enum>QFrame::Plain</enum>
-        </property>
-        <property name="readOnly" >
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QIDialogButtonBox" name="mButtonBox" >
-     <property name="standardButtons" >
+  <layout class="QGridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="mLbName">
+     <property name="text">
+      <string>&amp;Name:</string>
+     </property>
+     <property name="buddy">
+      <cstring>mLeName</cstring>
+     </property>
+     <property name="alignment" >
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="mLeName">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>1</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+    </widget>
+   </item>
+   <item row="0" rowspan="2" column="2">
+    <widget class="QLabel" name="mLbThumbnail">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="toolTip">
+      <string>Click to enlarge the screenshot.</string>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::Box</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="mLbTaken">
+     <property name="text">
+      <string>Taken:</string>
+     </property>
+     <property name="alignment" >
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLabel" name="mTxTaken">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>1</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="mLbDescription">
+     <property name="text">
+      <string>&amp;Description:</string>
+     </property>
+     <property name="buddy">
+      <cstring>mTeDescription</cstring>
+     </property>
+     <property name="alignment" >
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignTop</set>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1" colspan="2">
+    <widget class="QTextEdit" name="mTeDescription">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>1</horstretch>
+       <verstretch>1</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="tabChangesFocus">
+      <bool>true</bool>
+     </property>
+     <property name="acceptRichText">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QLabel" name="mLbDetails">
+     <property name="text">
+      <string>D&amp;etails:</string>
+     </property>
+     <property name="buddy">
+      <cstring>mTeDetails</cstring>
+     </property>
+     <property name="alignment" >
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignTop</set>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1" colspan="2">
+    <widget class="QTextEdit" name="mTeDetails">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>1</horstretch>
+       <verstretch>1</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Plain</enum>
+     </property>
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0" colspan="3">
+    <widget class="QIDialogButtonBox" name="mButtonBox">
+     <property name="standardButtons">
       <set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
      </property>
@@ -141,5 +171,5 @@
  </customwidgets>
  <resources>
-  <include location="../VirtualBox1.qrc" />
+  <include location="../VirtualBox1.qrc"/>
  </resources>
  <connections>
@@ -150,9 +180,9 @@
    <slot>accept()</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>203</x>
      <y>365</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>203</x>
      <y>193</y>
@@ -166,9 +196,9 @@
    <slot>reject()</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>203</x>
      <y>365</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>203</x>
      <y>193</y>
