diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index d4195e1302..15872eef30 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -2430,6 +2430,7 @@
"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"
+
$(QTDIR)\bin\moc.exe;%(FullPath)
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index e45b4743a9..8e4a7ce449 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -1218,6 +1218,9 @@
Gui\custom items
+
+ Gui\custom items
+
Gui\custom items
diff --git a/rpcs3/rpcs3qt/pkg_install_dialog.cpp b/rpcs3/rpcs3qt/pkg_install_dialog.cpp
index 65ff65a122..a4694af316 100644
--- a/rpcs3/rpcs3qt/pkg_install_dialog.cpp
+++ b/rpcs3/rpcs3qt/pkg_install_dialog.cpp
@@ -1,6 +1,7 @@
#include "pkg_install_dialog.h"
#include "game_compatibility.h"
#include "numbered_widget_item.h"
+#include "richtext_item_delegate.h"
#include
#include
@@ -22,6 +23,7 @@ pkg_install_dialog::pkg_install_dialog(const QStringList& paths, game_compatibil
: QDialog(parent)
{
m_dir_list = new QListWidget(this);
+ m_dir_list->setItemDelegate(new richtext_item_delegate(m_dir_list->itemDelegate()));
for (const QString& path : paths)
{
diff --git a/rpcs3/rpcs3qt/richtext_item_delegate.h b/rpcs3/rpcs3qt/richtext_item_delegate.h
new file mode 100644
index 0000000000..e7dffc8167
--- /dev/null
+++ b/rpcs3/rpcs3qt/richtext_item_delegate.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+class richtext_item_delegate : public QStyledItemDelegate
+{
+private:
+ QTextDocument* m_document;
+
+public:
+ explicit richtext_item_delegate(QObject* parent = 0)
+ : QStyledItemDelegate(parent)
+ , m_document(new QTextDocument(this))
+ {
+ }
+
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
+ {
+ painter->save();
+
+ // Initialize style option
+ QStyleOptionViewItem opt = option;
+ initStyleOption(&opt, index);
+
+ // Setup the QTextDocument with our HTML
+ m_document->setHtml(opt.text);
+ opt.text.clear();
+
+ // Get the available style
+ QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
+
+ // Draw our widget if available
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
+
+ // Adjust our painter parameters with some magic that looks good.
+ // This is necessary so that we don't draw on top of the optional widget.
+ const int margin = (option.rect.height() - opt.fontMetrics.height() - 4);
+ QRect text_rect = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, nullptr);
+
+ if (index.column() != 0)
+ {
+ text_rect.adjust(5, 0, 0, 0);
+ }
+
+ text_rect.setTop(text_rect.top() + margin);
+
+ painter->translate(text_rect.topLeft());
+ painter->setClipRect(text_rect.translated(-text_rect.topLeft()));
+
+ // Create a context for our painter
+ QAbstractTextDocumentLayout::PaintContext context;
+
+ // We can change the text color based on state (Unused because it didn't look good)
+ //context.palette.setColor(QPalette::Text, option.palette.color(QPalette::Active, (option.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::Text));
+
+ // Draw the text
+ m_document->documentLayout()->draw(painter, context);
+
+ painter->restore();
+
+ //QStyledItemDelegate::paint(painter, opt, index); // Unused
+ }
+};