From d97bb47f0941b3b32d5b2d5acee55959ecb868c1 Mon Sep 17 00:00:00 2001
From: Teo Mrnjavac <teo@kde.org>
Date: Tue, 26 Aug 2014 15:18:30 +0200
Subject: [PATCH] Add proper QResrouce system to libcalamaresui, finish up
 prepare checks This also adds ImageRegistry, a SVG cache, a bunch of utility
 functions for shared pixmaps in CalamaresUtilsGui and renames several qrc
 files in viewmodules.

---
 CMakeLists.txt                                |   2 +-
 CalamaresAddLibrary.cmake                     |   6 +-
 CalamaresAddPlugin.cmake                      |   9 +-
 data/images/no.svgz                           | Bin 0 -> 1082 bytes
 {images => data/images}/squid.png             | Bin
 {images => data/images}/squid.svg             |   0
 data/images/yes.svgz                          | Bin 0 -> 1138 bytes
 src/libcalamares/utils/CalamaresUtils.h       |   2 +
 src/libcalamaresui/CMakeLists.txt             |   3 +
 src/libcalamaresui/libcalamaresui.qrc         |   6 +
 .../utils/CalamaresUtilsGui.cpp               |  83 +++++++++
 src/libcalamaresui/utils/CalamaresUtilsGui.h  |  26 ++-
 src/libcalamaresui/utils/ImageRegistry.cpp    | 163 ++++++++++++++++++
 src/libcalamaresui/utils/ImageRegistry.h      |  47 +++++
 src/modules/keyboard/CMakeLists.txt           |   2 +
 .../keyboard/{resources.qrc => keyboard.qrc}  |   0
 src/modules/locale/CMakeLists.txt             |   2 +
 .../locale/{resources.qrc => locale.qrc}      |   0
 src/modules/prepare/CMakeLists.txt            |   3 +-
 src/modules/prepare/PrepareCheckWidget.cpp    |  50 ++++++
 src/modules/prepare/PrepareCheckWidget.h      |  36 ++++
 src/modules/prepare/PreparePage.cpp           |  21 ++-
 src/modules/prepare/PreparePage.h             |   5 +-
 src/modules/prepare/PrepareViewStep.cpp       |  18 +-
 src/modules/users/CMakeLists.txt              |   2 +
 .../users/{resources.qrc => users.qrc}        |   0
 26 files changed, 470 insertions(+), 16 deletions(-)
 create mode 100644 data/images/no.svgz
 rename {images => data/images}/squid.png (100%)
 rename {images => data/images}/squid.svg (100%)
 create mode 100644 data/images/yes.svgz
 create mode 100644 src/libcalamaresui/libcalamaresui.qrc
 create mode 100644 src/libcalamaresui/utils/ImageRegistry.cpp
 create mode 100644 src/libcalamaresui/utils/ImageRegistry.h
 rename src/modules/keyboard/{resources.qrc => keyboard.qrc} (100%)
 rename src/modules/locale/{resources.qrc => locale.qrc} (100%)
 create mode 100644 src/modules/prepare/PrepareCheckWidget.cpp
 create mode 100644 src/modules/prepare/PrepareCheckWidget.h
 rename src/modules/users/{resources.qrc => users.qrc} (100%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 74f62c7702..750cf57e19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,7 @@ include( MacroLogFeature )
 
 set( QT_VERSION 5.3.0 )
 
-find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core Gui Widgets LinguistTools )
+find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core Gui Widgets LinguistTools Svg )
 find_package( YamlCpp 0.5.1 REQUIRED )
 
 option( WITH_PYTHON "Enable Python modules support." ON )
diff --git a/CalamaresAddLibrary.cmake b/CalamaresAddLibrary.cmake
index 050c08a5d2..a774b1f317 100644
--- a/CalamaresAddLibrary.cmake
+++ b/CalamaresAddLibrary.cmake
@@ -4,7 +4,7 @@ function(calamares_add_library)
     # parse arguments (name needs to be saved before passing ARGN into the macro)
     set(NAME ${ARGV0})
     set(options NO_INSTALL NO_VERSION)
-    set(oneValueArgs NAME TYPE EXPORT_MACRO TARGET TARGET_TYPE EXPORT VERSION SOVERSION INSTALL_BINDIR)
+    set(oneValueArgs NAME TYPE EXPORT_MACRO TARGET TARGET_TYPE EXPORT VERSION SOVERSION INSTALL_BINDIR RESOURCES)
     set(multiValueArgs SOURCES UI LINK_LIBRARIES LINK_PRIVATE_LIBRARIES COMPILE_DEFINITIONS QT5_MODULES)
     cmake_parse_arguments(LIBRARY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
     set(LIBRARY_NAME ${NAME})
@@ -30,8 +30,8 @@ function(calamares_add_library)
     endif()
 
     # add resources from current dir
-    if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/resources.qrc")
-        qt5_add_resources(LIBRARY_RC_SOURCES "resources.qrc")
+    if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${LIBRARY_RESOURCES}")
+        qt5_add_resources(LIBRARY_RC_SOURCES "${LIBRARY_RESOURCES}")
         list(APPEND LIBRARY_SOURCES ${LIBRARY_RC_SOURCES})
         unset(LIBRARY_RC_SOURCES)
     endif()
diff --git a/CalamaresAddPlugin.cmake b/CalamaresAddPlugin.cmake
index 63e63d009e..e9d5607c9f 100644
--- a/CalamaresAddPlugin.cmake
+++ b/CalamaresAddPlugin.cmake
@@ -5,7 +5,7 @@ function( calamares_add_plugin )
     # parse arguments ( name needs to be saved before passing ARGN into the macro )
     set( NAME ${ARGV0} )
     set( options NO_INSTALL SHARED_LIB )
-    set( oneValueArgs NAME TYPE EXPORT_MACRO )
+    set( oneValueArgs NAME TYPE EXPORT_MACRO RESOURCES )
     set( multiValueArgs SOURCES UI LINK_LIBRARIES COMPILE_DEFINITIONS )
     cmake_parse_arguments( PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
     set( PLUGIN_NAME ${NAME} )
@@ -30,6 +30,9 @@ function( calamares_add_plugin )
         if( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_CONFIG_FILE}" )
             message( "   ${Green}CONFIGURATION_FILE:${ColorReset} ${PLUGIN_CONFIG_FILE} => ${PLUGIN_DATA_DESTINATION}" )
         endif()
+        if( PLUGIN_RESOURCES )
+            message( "   ${Green}RESOURCES:${ColorReset} ${PLUGIN_RESOURCES}" )
+        endif()
         message( "" )
     endif()
     # create target name once for convenience
@@ -65,6 +68,10 @@ function( calamares_add_plugin )
 
     list( APPEND calamares_add_library_args "INSTALL_BINDIR" "${PLUGIN_DESTINATION}" )
 
+    if( PLUGIN_RESOURCES )
+        list( APPEND calamares_add_library_args "RESOURCES" "${PLUGIN_RESOURCES}" )
+    endif()
+
     calamares_add_library( ${calamares_add_library_args} )
 
     configure_file( ${PLUGIN_DESC_FILE} ${PLUGIN_DESC_FILE} COPYONLY )
diff --git a/data/images/no.svgz b/data/images/no.svgz
new file mode 100644
index 0000000000000000000000000000000000000000..423fdaca7fddc8afc7e2b69a18fefbc2963bc1d5
GIT binary patch
literal 1082
zcmb2|=HRH8_!-Q=T%MVil3%WyoReRis#jc=&M-GTF#nN-K;853AD5<wxeHl)a;7v+
z&09V7+t)n*?{AK=tx+@V@@@S4)!grmiU`+Rw^dTr`(}Rpp8Ce{^ZNEp4(s=XIfZfe
zv)pjrb4peCYSqKPzd!G`|2pB)mZU8cMB^)_e%Ytz{@K1pzIL_c)j13IUXcE>xGK={
zZc)kpi&e8*AJ*;XZ<))JvX@VO!h3!9#XGBF`vsgPY!8w=Ek3XG#=BRG7&qBGVb!l(
z8tTC$RAp=P{^8D(dU2I{r-Q;)eOz<pE<?=b&~~%cH;?mnoJrd(;GQV*v*E+ljhDVW
zn7`|gl>SaPiN^vtwx5z$_%tqv{_*-jo>D+j`12apI-3<c_~zHymAc8Z`)qcUSpMAe
zn(##JsG_Y)EyEYi&j0hh>E+o&-HXz;JWSeq@ovC|R`%Dq?9EXMYp)(VX~oSqNph9v
z6t!!vAO6OFVqj|t6k)w#!*cUQpYO4hylLA%d|Q-M^!|Bkh>d}hE~9yR%~GCyvHg;&
za$M5E;)i}1PhQ7v7ko9yCByrA0AK4G@q2eyRjzp$d9COAIg`wJ!joA}w%BcxK5(pT
zi|>_lefqbrwlOISd|CT(`V>_c-)0lV&Bu+4`4*`%b|%TFPBvZ~=`Zx)c*!)M`%;c)
z=H68Lw@ygvR6(^x@%^h?8AZOFXe|5OA2H$9iNCwdKE14Z{-oM`k|TfQx{QmN_g<wJ
z^E8#7`<8s0N#)~{p5?AP7Wtf%jO=FE_{W%YE$^1DN98%HwjDu#9yv@m*=nY<@~fZ0
zy<d*3o~k9mkGFLd8ub-?_6j<`Fh$oP;uh1x+vjGb_gFUwZtI+#u;8}X$LB@2rd&R4
z`EkeTD#Pbr9$TI~qx;{@??2l`k^f<rUO#%Yv3_c%RIN>B&eh)I6aKvtuifKk@^kK-
zjlMtiF6zBLI%ob0C8N^Q`zK!B@A}0!^@{3V#dSXyU7z8{o_ghNa&d^|8oOEl$}MK?
zyv$%QQNSnWGROJdZpQINzLHnB<SXW>m9{hA;oh`={yzQOAC>dc|DXJIG}ZY8!;8&#
z4i-Mu-Tl(?wDF54s#m=O4^?LBG1fahpVz+kAxqAVFOIi2nC7o%5r6Nhqu*M{_5b1`
zjk*~sb7Nuy7IN>)DcZKa&ov`6V$#Egr#2;0CX2t$F5a@>{GN!4`!A*`efl;b_IlBF
zUDe0ij#up6pl<7aeM^uV>t*!^TN_S4-mA$j^H^b?%SC5(`}12DFZr^u;e_^r*>??R
zsq}voH~x_8eeQ(#((IpyHgmmOuFjfx$ieZ*-6gwOCMF1dT|Vcv^^TRNGOs*dcz;Qu
z%#oB?UkWlzGEI0ByoE0L^6fb2zV7HlId)Ay&Us5Ne|&ItzfJG)9}D$=EB;;G_?Lf=
z`9k*W@0V3L)e5KB@MZqWwBddvc}#xd(@j0hM}J?K|EDVN`MQVVZ8vRBU;HosOZVjh
H9tH*ga}_6S

literal 0
HcmV?d00001

diff --git a/images/squid.png b/data/images/squid.png
similarity index 100%
rename from images/squid.png
rename to data/images/squid.png
diff --git a/images/squid.svg b/data/images/squid.svg
similarity index 100%
rename from images/squid.svg
rename to data/images/squid.svg
diff --git a/data/images/yes.svgz b/data/images/yes.svgz
new file mode 100644
index 0000000000000000000000000000000000000000..a4a8f6c8460700aa47e0c980d2534d8439c024a1
GIT binary patch
literal 1138
zcmb2|=HRH8_!-Q=oRXQClb^1epRJo%P>@rpS6r6PFgN^U(QONXy}z{$zNoI`P&qhP
z%F|M1>Z%yynX`<297Im39AsK}Hr}3hU6kzYqMJ&)<$o=dmvX57_%%Q*<9MiY%GNC%
zZ=*WGXQnJVHT~ND{q+xyIQ1?QUEI3n$E8(EzLtL7@Pj+~i*Mm7OXuo^<}cE}-bvZ=
z?8Rlb*H!N<e*e8Ew)f&Rt#Ui%o^XEt?zHLl3M~!Wv!3ZhNBwQ6THPgf!l+$*&y%Tn
zGD*V6XFa&da-L`RjgLOlmadsqmU7i*UV~_Ke}?hwz4x0uW-aS`Z8@)<v2k|t(wB_$
z`CBdTNxj;+?sY@H(>`9)e1{8Cb?!eBHc0Obm5e`Zkry6geZRh5e(sH}Gt<-)*=)~8
zoOfB5adP&ov^|Av)z)?TGw$i=p3lB-7V|{fb|2TaEeZSf&7bh??-CiS!va}$RWa5c
z`waFyW)0F!nelnf$umAlnTCw2lar&aAH8T+w1#1OLd{)?n&Vmb8m?`haJlNZh8oLl
z&VBPY_-}bx<hWv)<(g{6tCy-`w$H!!QAPA|R)Oo==Vw$Mr5E<cF8#i-{fW<&i|_A!
zGnYQ~L~hFNl6@YLQjTv=bTbRZ@7l~9&{ifgS%YWYoCD&wJ%!o|XT@1Lo?m;DyCRyC
z_iLE^y0-kOMh#7JmP_u|O_aNm^TaOP&2H_s=9=t<g`S~$T5D2ycgEf3-gnJhcGc=R
z((}|;ZoT-xYx~|64#sz;D||ezy3>UxRnqmOEX#_H^-JE@DlB?_|Krpz3SJ)%IkFdV
z8Vb$Tdpk=kdEwSixvY<U^&hO-s(<XD+ikwC33jvQR$55SHkIi8a!f!#=u2o_)brdA
zjM1mvUX)e;G@GNSr}$B4!^0h3k5y!py;KvnX0n&0t5`iZVq_Njm9MUxdHk8<nm*mV
z?rrZk9L-PveC$fYcT=-TXYNF&T(l0dR{XuV@1*ah53(umRy=;4@*^+n{l&th>R9*9
zS=)=f?Sm$$RMuWybbIB|C(0@Jj<2%+7x49eBhP)`x3Z>1o36)Q|M)JhyIm^M;`;W~
zZ2g_fda|ry=QgvhyOm*aXu<cH|9|~Uz8b8vDd*q(kn_ySPHYbIpNR3LWSh<s*O~3S
zJt%0ekm{US%P#(8x_k1_OqukAVl6+%-5a{fbI+f>*Ppu7pm|RH7LBg?Z7EmEd9+Fn
zsy{yTGX4JZXLD4x7qq>(z5UOlFZwTp^`~7kj|wg+HGSfh_d3Yv-u+eAR9@cHT`js+
zYVw|)st-0c?E4}7ZSeuVWT79%GF1y@m*>gU$vs)W@*a<->8}U|*Zb9HPTtS<sQD*h
z@cHt-2Pdy*sLubnrzx*Shkx^t6aF^VoejEQ?oQKjo8d73nR=l~bGt!T6T`y;YK~Ku
z8GoK|Y-9U^(>-@3w1oCORPn#i@Pgsk`(4Ml>jT@rR_F9s$;-`|?vNBCD>UEncjr;#
zJLh%gJiEx>dEs>AU+sCBJ6!*sv@mnnwCaGSXj@o@``56-%WXWjRoefD`^;P?_mBPO
LTZx_Tco-M}l~XuV

literal 0
HcmV?d00001

diff --git a/src/libcalamares/utils/CalamaresUtils.h b/src/libcalamares/utils/CalamaresUtils.h
index c0839f96fe..915b4c2a66 100644
--- a/src/libcalamares/utils/CalamaresUtils.h
+++ b/src/libcalamares/utils/CalamaresUtils.h
@@ -26,6 +26,8 @@
 
 #include "DllMacro.h"
 
+#define RESPATH ":/data/"
+
 class QDir;
 class QObject;
 
diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt
index 6ded069b0f..357ee97127 100644
--- a/src/libcalamaresui/CMakeLists.txt
+++ b/src/libcalamaresui/CMakeLists.txt
@@ -7,6 +7,7 @@ list( APPEND ${CALAMARESUI_LIBRARY_TARGET}_SOURCES
     modulesystem/ViewModule.cpp
 
     utils/CalamaresUtilsGui.cpp
+    utils/ImageRegistry.cpp
     utils/YamlUtils.cpp
 
     viewpages/AbstractPage.cpp
@@ -35,6 +36,8 @@ calamares_add_library( ${CALAMARESUI_LIBRARY_TARGET}
     EXPORT_MACRO UIDLLEXPORT_PRO
     LINK_LIBRARIES
         yaml-cpp
+        Qt5::Svg
+    RESOURCES libcalamaresui.qrc
     EXPORT CalamaresLibraryDepends
     VERSION ${CALAMARES_VERSION_SHORT}
 )
diff --git a/src/libcalamaresui/libcalamaresui.qrc b/src/libcalamaresui/libcalamaresui.qrc
new file mode 100644
index 0000000000..4bea23aeb4
--- /dev/null
+++ b/src/libcalamaresui/libcalamaresui.qrc
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/data">
+        <file alias="images/yes.svgz">../../data/images/yes.svgz</file>
+        <file alias="images/no.svgz">../../data/images/no.svgz</file>
+    </qresource>
+</RCC>
diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp
index e43dc966c0..747460261e 100644
--- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp
+++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp
@@ -18,9 +18,14 @@
 
 #include "CalamaresUtilsGui.h"
 
+#include "ImageRegistry.h"
+
+#include <QBrush>
 #include <QFont>
 #include <QFontMetrics>
 #include <QLayout>
+#include <QPainter>
+#include <QPen>
 
 namespace CalamaresUtils
 {
@@ -29,6 +34,84 @@ static int s_defaultFontSize   = 0;
 static int s_defaultFontHeight = 0;
 
 
+
+QPixmap
+defaultPixmap( ImageType type, ImageMode mode, const QSize& size )
+{
+    QPixmap pixmap;
+
+    switch ( type )
+    {
+        case Yes:
+            pixmap = ImageRegistry::instance()->pixmap( RESPATH "images/yes.svgz", size );
+            break;
+
+        case No:
+            pixmap = ImageRegistry::instance()->pixmap( RESPATH "images/no.svgz", size );
+            break;
+
+        default:
+            break;
+    }
+
+    if ( pixmap.isNull() )
+    {
+        Q_ASSERT( false );
+        return QPixmap();
+    }
+
+    return pixmap;
+}
+
+
+QPixmap
+createRoundedImage( const QPixmap& pixmap, const QSize& size, float frameWidthPct )
+{
+    int height;
+    int width;
+
+    if ( !size.isEmpty() )
+    {
+        height = size.height();
+        width = size.width();
+    }
+    else
+    {
+        height = pixmap.height();
+        width = pixmap.width();
+    }
+
+    if ( !height || !width )
+        return QPixmap();
+
+    QPixmap scaledAvatar = pixmap.scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
+    if ( frameWidthPct == 0.00 )
+        return scaledAvatar;
+
+    QPixmap frame( width, height );
+    frame.fill( Qt::transparent );
+
+    QPainter painter( &frame );
+    painter.setRenderHint( QPainter::Antialiasing );
+
+    QRect outerRect( 0, 0, width, height );
+    QBrush brush( scaledAvatar );
+    QPen pen;
+    pen.setColor( Qt::transparent );
+    pen.setJoinStyle( Qt::RoundJoin );
+
+    painter.setBrush( brush );
+    painter.setPen( pen );
+    painter.drawRoundedRect( outerRect, frameWidthPct * 100.0, frameWidthPct * 100.0, Qt::RelativeSize );
+
+/*    painter.setBrush( Qt::transparent );
+    painter.setPen( Qt::white );
+    painter.drawRoundedRect( outerRect, frameWidthPct, frameWidthPct, Qt::RelativeSize ); */
+
+    return frame;
+}
+
+
 void
 unmarginLayout( QLayout* layout )
 {
diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h
index c835ddbf7a..1a52bf3058 100644
--- a/src/libcalamaresui/utils/CalamaresUtilsGui.h
+++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h
@@ -22,19 +22,37 @@
 #include "utils/CalamaresUtils.h"
 #include "UiDllMacro.h"
 
+#include <QPixmap>
 #include <QSize>
 
 class QLayout;
 
 namespace CalamaresUtils
 {
+enum ImageType
+{
+    Yes,
+    No
+};
+
+enum ImageMode
+{
+    Original,
+    CoverInCase,
+    Grid,
+    DropShadow,
+    RoundedCorners
+};
+
+UIDLLEXPORT QPixmap defaultPixmap( ImageType type, ImageMode mode = CalamaresUtils::Original, const QSize& size = QSize( 0, 0 ) );
+UIDLLEXPORT QPixmap createRoundedImage( const QPixmap& avatar, const QSize& size, float frameWidthPct = 0.20 );
 
 UIDLLEXPORT void unmarginLayout( QLayout* layout );
 
-DLLEXPORT void setDefaultFontSize( int points );
-DLLEXPORT int defaultFontSize();
-DLLEXPORT int defaultFontHeight();
-DLLEXPORT QSize defaultIconSize();
+UIDLLEXPORT void setDefaultFontSize( int points );
+UIDLLEXPORT int defaultFontSize();
+UIDLLEXPORT int defaultFontHeight();
+UIDLLEXPORT QSize defaultIconSize();
 
 }
 
diff --git a/src/libcalamaresui/utils/ImageRegistry.cpp b/src/libcalamaresui/utils/ImageRegistry.cpp
new file mode 100644
index 0000000000..48f5ea8676
--- /dev/null
+++ b/src/libcalamaresui/utils/ImageRegistry.cpp
@@ -0,0 +1,163 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.org>
+ *
+ *   Originally from Tomahawk,
+ *   Copyright 2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ImageRegistry.h"
+
+#include <QSvgRenderer>
+#include <QPainter>
+#include <QIcon>
+
+#include "utils/Logger.h"
+
+static QHash< QString, QHash< int, QHash< qint64, QPixmap > > > s_cache;
+ImageRegistry* ImageRegistry::s_instance = 0;
+
+
+ImageRegistry*
+ImageRegistry::instance()
+{
+    return s_instance;
+}
+
+
+ImageRegistry::ImageRegistry()
+{
+    s_instance = this;
+}
+
+
+QIcon
+ImageRegistry::icon( const QString& image, CalamaresUtils::ImageMode mode )
+{
+    return pixmap( image, CalamaresUtils::defaultIconSize(), mode );
+}
+
+
+qint64
+ImageRegistry::cacheKey( const QSize& size, float opacity, QColor tint )
+{
+    return size.width() * 100 + size.height() * 10 + ( opacity * 100.0 ) + tint.value();
+}
+
+
+QPixmap
+ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, QColor tint )
+{
+    QHash< qint64, QPixmap > subsubcache;
+    QHash< int, QHash< qint64, QPixmap > > subcache;
+
+    if ( s_cache.contains( image ) )
+    {
+        subcache = s_cache.value( image );
+
+        if ( subcache.contains( mode ) )
+        {
+            subsubcache = subcache.value( mode );
+
+            const qint64 ck = cacheKey( size, opacity, tint );
+            if ( subsubcache.contains( ck ) )
+            {
+                return subsubcache.value( ck );
+            }
+        }
+    }
+
+    // Image not found in cache. Let's load it.
+    QPixmap pixmap;
+    if ( image.toLower().endsWith( ".svg" ) ||
+         image.toLower().endsWith( ".svgz" ) )
+    {
+        QSvgRenderer svgRenderer( image );
+        QPixmap p( size.isNull() ? svgRenderer.defaultSize() : size );
+        p.fill( Qt::transparent );
+
+        QPainter pixPainter( &p );
+        pixPainter.setOpacity( opacity );
+        svgRenderer.render( &pixPainter );
+        pixPainter.end();
+
+        if ( tint.alpha() > 0 )
+        {
+            QImage resultImage( p.size(), QImage::Format_ARGB32_Premultiplied );
+            QPainter painter( &resultImage );
+            painter.drawPixmap( 0, 0, p );
+            painter.setCompositionMode( QPainter::CompositionMode_Screen );
+            painter.fillRect( resultImage.rect(), tint );
+            painter.end();
+
+            resultImage.setAlphaChannel( p.toImage().alphaChannel() );
+            p = QPixmap::fromImage( resultImage );
+        }
+
+        pixmap = p;
+    }
+    else
+        pixmap = QPixmap( image );
+
+    if ( !pixmap.isNull() )
+    {
+        switch ( mode )
+        {
+            case CalamaresUtils::RoundedCorners:
+                pixmap = CalamaresUtils::createRoundedImage( pixmap, size );
+                break;
+
+            default:
+                break;
+        }
+
+        if ( !size.isNull() && pixmap.size() != size )
+            pixmap = pixmap.scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
+
+        putInCache( image, size, mode, opacity, pixmap, tint );
+    }
+
+    return pixmap;
+}
+
+
+void
+ImageRegistry::putInCache( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, const QPixmap& pixmap, QColor tint )
+{
+    cDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Adding to image cache:" << image << size << mode;
+
+    QHash< qint64, QPixmap > subsubcache;
+    QHash< int, QHash< qint64, QPixmap > > subcache;
+
+    if ( s_cache.contains( image ) )
+    {
+        subcache = s_cache.value( image );
+
+        if ( subcache.contains( mode ) )
+        {
+            subsubcache = subcache.value( mode );
+
+/*            if ( subsubcache.contains( size.width() * size.height() ) )
+            {
+                Q_ASSERT( false );
+            }*/
+        }
+    }
+
+    subsubcache.insert( cacheKey( size, opacity, tint ), pixmap );
+    subcache.insert( mode, subsubcache );
+    s_cache.insert( image, subcache );
+}
diff --git a/src/libcalamaresui/utils/ImageRegistry.h b/src/libcalamaresui/utils/ImageRegistry.h
new file mode 100644
index 0000000000..41ed2d6ac8
--- /dev/null
+++ b/src/libcalamaresui/utils/ImageRegistry.h
@@ -0,0 +1,47 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.org>
+ *
+ *   Originally from Tomahawk,
+ *   Copyright 2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IMAGE_REGISTRY_H
+#define IMAGE_REGISTRY_H
+
+#include <QPixmap>
+
+#include "utils/CalamaresUtilsGui.h"
+#include "UiDllMacro.h"
+
+class UIDLLEXPORT ImageRegistry
+{
+public:
+    static ImageRegistry* instance();
+
+    explicit ImageRegistry();
+
+    QIcon icon( const QString& image, CalamaresUtils::ImageMode mode = CalamaresUtils::Original );
+    QPixmap pixmap( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode = CalamaresUtils::Original, float opacity = 1.0, QColor tint = QColor( 0, 0, 0, 0 ) );
+
+private:
+    qint64 cacheKey( const QSize& size, float opacity, QColor tint );
+    void putInCache( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, const QPixmap& pixmap, QColor tint );
+
+    static ImageRegistry* s_instance;
+};
+
+#endif // IMAGE_REGISTRY_H
diff --git a/src/modules/keyboard/CMakeLists.txt b/src/modules/keyboard/CMakeLists.txt
index fdfc6695e4..99405c99f6 100644
--- a/src/modules/keyboard/CMakeLists.txt
+++ b/src/modules/keyboard/CMakeLists.txt
@@ -10,6 +10,8 @@ calamares_add_plugin( keyboard
         keyboardwidget/keyboardpreview.cpp
     UI
         KeyboardPage.ui
+    RESOURCES
+        keyboard.qrc
     LINK_LIBRARIES
         calamaresui
     SHARED_LIB
diff --git a/src/modules/keyboard/resources.qrc b/src/modules/keyboard/keyboard.qrc
similarity index 100%
rename from src/modules/keyboard/resources.qrc
rename to src/modules/keyboard/keyboard.qrc
diff --git a/src/modules/locale/CMakeLists.txt b/src/modules/locale/CMakeLists.txt
index 3fa6c00ce0..1a00821595 100644
--- a/src/modules/locale/CMakeLists.txt
+++ b/src/modules/locale/CMakeLists.txt
@@ -10,6 +10,8 @@ calamares_add_plugin( locale
         timezonewidget/timezonewidget.cpp
         timezonewidget/localeglobal.cpp
     UI
+    RESOURCES
+        locale.qrc
     LINK_LIBRARIES
         calamaresui
     SHARED_LIB
diff --git a/src/modules/locale/resources.qrc b/src/modules/locale/locale.qrc
similarity index 100%
rename from src/modules/locale/resources.qrc
rename to src/modules/locale/locale.qrc
diff --git a/src/modules/prepare/CMakeLists.txt b/src/modules/prepare/CMakeLists.txt
index b89b26eda1..c9bad01818 100644
--- a/src/modules/prepare/CMakeLists.txt
+++ b/src/modules/prepare/CMakeLists.txt
@@ -9,8 +9,9 @@ calamares_add_plugin( prepare
     TYPE viewmodule
     EXPORT_MACRO PLUGINDLLEXPORT_PRO
     SOURCES
-        PrepareViewStep.cpp
+        PrepareCheckWidget.cpp
         PreparePage.cpp
+        PrepareViewStep.cpp
         partman_devices.c
     UI
     LINK_LIBRARIES
diff --git a/src/modules/prepare/PrepareCheckWidget.cpp b/src/modules/prepare/PrepareCheckWidget.cpp
new file mode 100644
index 0000000000..59686241f4
--- /dev/null
+++ b/src/modules/prepare/PrepareCheckWidget.cpp
@@ -0,0 +1,50 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PrepareCheckWidget.h"
+
+#include "utils/CalamaresUtilsGui.h"
+#include "utils/Logger.h"
+
+#include <QBoxLayout>
+
+PrepareCheckWidget::PrepareCheckWidget( const QString &text,
+                                        bool checked,
+                                        QWidget* parent )
+    : QWidget( parent )
+{
+    QBoxLayout* mainLayout = new QHBoxLayout;
+    setLayout( mainLayout );
+
+    m_iconLabel = new QLabel( this );
+    mainLayout->addWidget( m_iconLabel );
+    m_textLabel = new QLabel( text, this );
+    mainLayout->addWidget( m_textLabel );
+    m_textLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
+
+    if ( checked )
+        m_iconLabel->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
+                                                               CalamaresUtils::Original,
+                                                               QSize( m_iconLabel->height(),
+                                                                      m_iconLabel->height() ) ) );
+    else
+        m_iconLabel->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
+                                                               CalamaresUtils::Original,
+                                                               QSize( m_iconLabel->height(),
+                                                                      m_iconLabel->height() ) ) );
+}
diff --git a/src/modules/prepare/PrepareCheckWidget.h b/src/modules/prepare/PrepareCheckWidget.h
new file mode 100644
index 0000000000..43efad018a
--- /dev/null
+++ b/src/modules/prepare/PrepareCheckWidget.h
@@ -0,0 +1,36 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PREPARECHECKWIDGET_H
+#define PREPARECHECKWIDGET_H
+
+#include <QLabel>
+
+class PrepareCheckWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit PrepareCheckWidget( const QString &text,
+                                 bool checked,
+                                 QWidget* parent = nullptr );
+private:
+    QLabel* m_textLabel;
+    QLabel* m_iconLabel;
+};
+
+#endif // PREPARECHECKWIDGET_H
diff --git a/src/modules/prepare/PreparePage.cpp b/src/modules/prepare/PreparePage.cpp
index 46f7445fa7..5219113773 100644
--- a/src/modules/prepare/PreparePage.cpp
+++ b/src/modules/prepare/PreparePage.cpp
@@ -18,6 +18,10 @@
 
 #include "PreparePage.h"
 
+#include "PrepareCheckWidget.h"
+
+#include "utils/CalamaresUtilsGui.h"
+
 #include <QBoxLayout>
 #include <QLabel>
 
@@ -30,16 +34,25 @@ PreparePage::PreparePage( QWidget* parent )
 
     QLabel* text = new QLabel( tr( "For best results, please ensure that this "
                                    "computer:" ), this );
-    text->setAlignment( Qt::AlignCenter );
 
-    mainLayout->addStretch();
     mainLayout->addWidget( text );
+    QHBoxLayout* spacerLayout = new QHBoxLayout;
+    mainLayout->addLayout( spacerLayout );
+    spacerLayout->addSpacing( CalamaresUtils::defaultFontHeight() * 2 );
+    m_entriesLayout = new QVBoxLayout;
+    spacerLayout->addLayout( m_entriesLayout );
+    CalamaresUtils::unmarginLayout( spacerLayout );
     mainLayout->addStretch();
 }
 
 
 void
-PreparePage::init()
+PreparePage::init( const QList< QPair< QString, bool > > &checkEntries )
 {
-
+    for ( const QPair< QString, bool >& entry : checkEntries )
+    {
+        PrepareCheckWidget* pcw = new PrepareCheckWidget( entry.first, entry.second );
+        m_entriesLayout->addWidget( pcw );
+        pcw->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
+    }
 }
diff --git a/src/modules/prepare/PreparePage.h b/src/modules/prepare/PreparePage.h
index 6ee64c49a5..3230656d9f 100644
--- a/src/modules/prepare/PreparePage.h
+++ b/src/modules/prepare/PreparePage.h
@@ -19,6 +19,7 @@
 #ifndef PREPAREPAGE_H
 #define PREPAREPAGE_H
 
+#include <QBoxLayout>
 #include <QWidget>
 
 class PreparePage : public QWidget
@@ -27,8 +28,10 @@ class PreparePage : public QWidget
 public:
     explicit PreparePage( QWidget* parent = nullptr );
 
-    void init();
+    void init( const QList< QPair< QString, bool > >& checkEntries );
 
+private:
+    QBoxLayout* m_entriesLayout;
 };
 
 #endif // PREPAREPAGE_H
diff --git a/src/modules/prepare/PrepareViewStep.cpp b/src/modules/prepare/PrepareViewStep.cpp
index 174c4b9e17..f49d3c0bb6 100644
--- a/src/modules/prepare/PrepareViewStep.cpp
+++ b/src/modules/prepare/PrepareViewStep.cpp
@@ -97,7 +97,23 @@ PrepareViewStep::PrepareViewStep( QObject* parent )
         cDebug() << "enoughStorage, enoughRam, hasPower, hasInternet: "
                  << enoughStorage << enoughRam << hasPower << hasInternet;
 
-        m_actualWidget->init();
+        QList< QPair< QString, bool > > checkEntries;
+        checkEntries.append( qMakePair(
+            tr( "has at least %1 GB available drive space" )
+                .arg( m_requiredStorageGB ),
+            enoughStorage ) );
+        checkEntries.append( qMakePair(
+            tr( "has at least %1 GB working memory" )
+                .arg( m_requiredRamGB ),
+            enoughRam ) );
+        checkEntries.append( qMakePair(
+            tr( "is plugged in to a power source" ),
+            hasPower ) );
+        checkEntries.append( qMakePair(
+            tr( "is connected to the Internet" ),
+            hasInternet ) );
+
+        m_actualWidget->init( checkEntries );
         m_widget->layout()->removeWidget( waitingWidget );
         waitingWidget->deleteLater();
         m_widget->layout()->addWidget( m_actualWidget );
diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt
index 4905ccf948..4d4ef208fe 100644
--- a/src/modules/users/CMakeLists.txt
+++ b/src/modules/users/CMakeLists.txt
@@ -13,6 +13,8 @@ calamares_add_plugin( users
         UsersPage.cpp
     UI
         page_usersetup.ui
+    RESOURCES
+        users.qrc
     LINK_LIBRARIES
         calamaresui
         ${CRYPT_LIBRARIES}
diff --git a/src/modules/users/resources.qrc b/src/modules/users/users.qrc
similarity index 100%
rename from src/modules/users/resources.qrc
rename to src/modules/users/users.qrc
-- 
GitLab