diff --git a/src/libcalamaresui/viewpages/ViewStep.cpp b/src/libcalamaresui/viewpages/ViewStep.cpp
index b5525d365d77b34bda2affebeaf7d4c4f888828e..2629560d4b2c27714b6ff7584d3475b47756c67a 100644
--- a/src/libcalamaresui/viewpages/ViewStep.cpp
+++ b/src/libcalamaresui/viewpages/ViewStep.cpp
@@ -36,6 +36,11 @@ ViewStep::prettyStatus() const
     return QString();
 }
 
+QWidget*
+ViewStep::createSummaryWidget() const
+{
+    return nullptr;
+}
 
 void
 ViewStep::onActivate()
diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h
index 1bdf78e0b1c8fef9d09fbc0716d27105d61316cb..8da845ee058b934cbb80fc01f272ee363e35d535 100644
--- a/src/libcalamaresui/viewpages/ViewStep.h
+++ b/src/libcalamaresui/viewpages/ViewStep.h
@@ -37,6 +37,12 @@ public:
     virtual QString prettyName() const = 0;
     virtual QString prettyStatus() const;
 
+    /**
+     * Optional. Should return a widget which will be inserted in the summary
+     * page. The caller takes ownership of the widget.
+     */
+    virtual QWidget* createSummaryWidget() const;
+
     //TODO: we might want to make this a QSharedPointer
     virtual QWidget* widget() = 0;
 
diff --git a/src/modules/partition/PartitionCoreModule.cpp b/src/modules/partition/PartitionCoreModule.cpp
index aa34a2e01355f5257c15df130606f19139449cdb..a32961d6e2a35b92a02260a2e56a9c2bad1e708c 100644
--- a/src/modules/partition/PartitionCoreModule.cpp
+++ b/src/modules/partition/PartitionCoreModule.cpp
@@ -349,3 +349,30 @@ PartitionCoreModule::revert()
     init();
     updateIsDirty();
 }
+
+QList< PartitionCoreModule::SummaryInfo >
+PartitionCoreModule::createSummaryInfo() const
+{
+    QList< SummaryInfo > lst;
+    CoreBackend* backend = CoreBackendManager::self()->backend();
+    for ( auto deviceInfo : m_deviceInfos )
+    {
+        if ( !deviceInfo->isDirty() )
+            continue;
+        SummaryInfo summaryInfo;
+        summaryInfo.deviceName = deviceInfo->device->name();
+
+        Device* deviceBefore = backend->scanDevice( deviceInfo->device->deviceNode() );
+        summaryInfo.partitionModelBefore = new PartitionModel;
+        summaryInfo.partitionModelBefore->init( deviceBefore );
+        // Make deviceBefore a child of partitionModelBefore so that it is not
+        // leaked (as long as partitionModelBefore is deleted)
+        deviceBefore->setParent( summaryInfo.partitionModelBefore );
+
+        summaryInfo.partitionModelAfter = new PartitionModel;
+        summaryInfo.partitionModelAfter->init( deviceInfo->device.data() );
+
+        lst << summaryInfo;
+    }
+    return lst;
+}
diff --git a/src/modules/partition/PartitionCoreModule.h b/src/modules/partition/PartitionCoreModule.h
index 79d54e5cc77d9234ae1be1d290fdfd7b7197707f..4a29f0994e22d401dbd9f0b554168f1077894888 100644
--- a/src/modules/partition/PartitionCoreModule.h
+++ b/src/modules/partition/PartitionCoreModule.h
@@ -45,6 +45,13 @@ class PartitionCoreModule : public QObject
 {
     Q_OBJECT
 public:
+    struct SummaryInfo
+    {
+        QString deviceName;
+        PartitionModel* partitionModelBefore;
+        PartitionModel* partitionModelAfter;
+    };
+
     PartitionCoreModule( QObject* parent = nullptr );
     ~PartitionCoreModule();
 
@@ -80,6 +87,12 @@ public:
      */
     void refreshPartition( Device* device, Partition* partition );
 
+    /**
+     * Returns a list of SummaryInfo for devices which have pending changes.
+     * Caller is responsible for deleting the partition models
+     */
+    QList< SummaryInfo > createSummaryInfo() const;
+
 Q_SIGNALS:
     void hasRootMountPointChanged( bool value );
     void isDirtyChanged( bool value );
diff --git a/src/modules/partition/PartitionViewStep.cpp b/src/modules/partition/PartitionViewStep.cpp
index 9e16a5e502107c86001e661229358d677f035278..f9ebabbe54f6d22da93aefa89bfab2cbc7602622 100644
--- a/src/modules/partition/PartitionViewStep.cpp
+++ b/src/modules/partition/PartitionViewStep.cpp
@@ -18,8 +18,15 @@
 
 #include <PartitionViewStep.h>
 
-#include <PartitionPage.h>
+#include <DeviceModel.h>
 #include <PartitionCoreModule.h>
+#include <PartitionModel.h>
+#include <PartitionPage.h>
+#include <PartitionPreview.h>
+
+// Qt
+#include <QFormLayout>
+#include <QLabel>
 
 PartitionViewStep::PartitionViewStep( QObject* parent )
     : Calamares::ViewStep( parent )
@@ -45,6 +52,33 @@ PartitionViewStep::widget()
 }
 
 
+QWidget*
+PartitionViewStep::createSummaryWidget() const
+{
+    QWidget* widget = new QWidget;
+    QFormLayout* layout = new QFormLayout( widget );
+    layout->setMargin( 0 );
+
+    QList< PartitionCoreModule::SummaryInfo > list = m_core->createSummaryInfo();
+    for ( const auto& info : list )
+    {
+        PartitionPreview* preview;
+
+        layout->addRow( new QLabel( info.deviceName ) );
+
+        preview = new PartitionPreview;
+        preview->setModel( info.partitionModelBefore );
+        info.partitionModelBefore->setParent( widget );
+        layout->addRow( tr( "Before:" ), preview );
+
+        preview = new PartitionPreview;
+        preview->setModel( info.partitionModelAfter );
+        info.partitionModelAfter->setParent( widget );
+        layout->addRow( tr( "After:" ), preview );
+    }
+    return widget;
+}
+
 void
 PartitionViewStep::next()
 {
diff --git a/src/modules/partition/PartitionViewStep.h b/src/modules/partition/PartitionViewStep.h
index 6a305556424889c12bcd2728dbb04d9604e73117..eb2a8e5a442e44ecd3412427b904c5195a95d1c3 100644
--- a/src/modules/partition/PartitionViewStep.h
+++ b/src/modules/partition/PartitionViewStep.h
@@ -37,6 +37,7 @@ public:
     explicit PartitionViewStep( QObject* parent = 0 );
 
     QString prettyName() const override;
+    QWidget* createSummaryWidget() const override;
 
     QWidget* widget() override;
 
diff --git a/src/modules/summary/SummaryPage.cpp b/src/modules/summary/SummaryPage.cpp
index 8ef08e40bb1af5dc7039bd32e6517d29c9aeade7..d803a3d61fe66e6c16d38e8c888847107db81137 100644
--- a/src/modules/summary/SummaryPage.cpp
+++ b/src/modules/summary/SummaryPage.cpp
@@ -24,40 +24,67 @@
 #include <QBoxLayout>
 #include <QLabel>
 
+static const int SECTION_SPACING = 12;
 
 SummaryPage::SummaryPage( QWidget* parent )
     : QWidget()
 {
-    QBoxLayout *mainLayout = new QVBoxLayout;
-    setLayout( mainLayout );
-
-    mainLayout->addStretch();
-
-    m_label = new QLabel( this );
-    mainLayout->addWidget( m_label );
-    m_label->setWordWrap( true );
-
-    mainLayout->addStretch();
+    QVBoxLayout* layout = new QVBoxLayout( this );
+    layout->setContentsMargins( 0, 0, 0, 0 );
 }
 
 
 void
 SummaryPage::onActivate()
 {
+    createContentWidget();
+
     QString text;
+    bool first = true;
     foreach ( Calamares::ViewStep* step,
               Calamares::ViewManager::instance()->prepareSteps() )
     {
-        //TODO: make it nice!
-        if ( !step->prettyStatus().isEmpty() )
-        {
-            if ( !text.isEmpty() )
-                text += "<br/><br/>";
-
-            text += "<h3>" + step->prettyName() +
-                    "</h3><br/>" + step->prettyStatus();
-        }
+        QString text = step->prettyStatus();
+        QWidget* widget = step->createSummaryWidget();
+
+        if ( text.isEmpty() && !widget )
+            continue;
+
+        if ( first )
+            first = false;
+        else
+            m_layout->addSpacing( SECTION_SPACING );
+
+        m_layout->addWidget( createTitleLabel( step->prettyName() ) );
+        if ( !text.isEmpty() )
+            m_layout->addWidget( createBodyLabel( text ) );
+        if ( widget )
+            m_layout->addWidget( widget );
     }
+    m_layout->addStretch();
+}
 
-    m_label->setText( text );
+void
+SummaryPage::createContentWidget()
+{
+    delete m_contentWidget;
+    m_contentWidget = new QWidget;
+    m_layout = new QVBoxLayout( m_contentWidget );
+    layout()->addWidget( m_contentWidget );
+}
+
+QLabel*
+SummaryPage::createTitleLabel( const QString& text ) const
+{
+    QLabel* label = new QLabel( text );
+    QFont fnt = font();
+    fnt.setBold( true );
+    label->setFont( fnt );
+    return label;
+}
+
+QLabel*
+SummaryPage::createBodyLabel( const QString& text ) const
+{
+    return new QLabel( text );
 }
diff --git a/src/modules/summary/SummaryPage.h b/src/modules/summary/SummaryPage.h
index 86afe6958a5784d3056094ca777a6b28a9b50132..6e4fa395fc3404f904cdd9a0cceaf81114458380 100644
--- a/src/modules/summary/SummaryPage.h
+++ b/src/modules/summary/SummaryPage.h
@@ -22,6 +22,7 @@
 #include <QWidget>
 
 class QLabel;
+class QVBoxLayout;
 
 class SummaryPage : public QWidget
 {
@@ -32,7 +33,12 @@ public:
     void onActivate();
 
 private:
-    QLabel* m_label;
+    QVBoxLayout* m_layout = nullptr;
+    QWidget* m_contentWidget = nullptr;
+
+    void createContentWidget();
+    QLabel* createTitleLabel( const QString& text ) const;
+    QLabel* createBodyLabel( const QString& text ) const;
 };
 
 #endif // SUMMARYPAGE_H