From 03c5a38b9069db53cd3fa04604f094c38e209698 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= <agateau@kde.org>
Date: Wed, 30 Jul 2014 14:15:29 +0200
Subject: [PATCH] Show a summary of the partition changes on the summary page

---
 src/libcalamaresui/viewpages/ViewStep.cpp     |  5 ++
 src/libcalamaresui/viewpages/ViewStep.h       |  6 ++
 src/modules/partition/PartitionCoreModule.cpp | 27 ++++++++
 src/modules/partition/PartitionCoreModule.h   | 13 ++++
 src/modules/partition/PartitionViewStep.cpp   | 36 +++++++++-
 src/modules/partition/PartitionViewStep.h     |  1 +
 src/modules/summary/SummaryPage.cpp           | 67 +++++++++++++------
 src/modules/summary/SummaryPage.h             |  8 ++-
 8 files changed, 141 insertions(+), 22 deletions(-)

diff --git a/src/libcalamaresui/viewpages/ViewStep.cpp b/src/libcalamaresui/viewpages/ViewStep.cpp
index b5525d365d..2629560d4b 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 1bdf78e0b1..8da845ee05 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 aa34a2e013..a32961d6e2 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 79d54e5cc7..4a29f0994e 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 9e16a5e502..f9ebabbe54 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 6a30555642..eb2a8e5a44 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 8ef08e40bb..d803a3d61f 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 86afe6958a..6e4fa395fc 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
-- 
GitLab