aboutsummaryrefslogtreecommitdiff
path: root/launcher/ui/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/ui/widgets')
-rw-r--r--launcher/ui/widgets/Common.cpp22
-rw-r--r--launcher/ui/widgets/Common.h9
-rw-r--r--launcher/ui/widgets/ProjectItem.cpp78
-rw-r--r--launcher/ui/widgets/ProjectItem.h25
4 files changed, 123 insertions, 11 deletions
diff --git a/launcher/ui/widgets/Common.cpp b/launcher/ui/widgets/Common.cpp
index f72f3596..097bb6d4 100644
--- a/launcher/ui/widgets/Common.cpp
+++ b/launcher/ui/widgets/Common.cpp
@@ -1,27 +1,33 @@
#include "Common.h"
// Origin: Qt
-QStringList viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
- qreal &widthUsed)
+// More specifically, this is a trimmed down version on the algorithm in:
+// https://code.woboq.org/qt5/qtbase/src/widgets/styles/qcommonstyle.cpp.html#846
+QList<std::pair<qreal, QString>> viewItemTextLayout(QTextLayout& textLayout, int lineWidth, qreal& height)
{
- QStringList lines;
+ QList<std::pair<qreal, QString>> lines;
height = 0;
- widthUsed = 0;
+
textLayout.beginLayout();
+
QString str = textLayout.text();
- while (true)
- {
+ while (true) {
QTextLine line = textLayout.createLine();
+
if (!line.isValid())
break;
if (line.textLength() == 0)
break;
+
line.setLineWidth(lineWidth);
line.setPosition(QPointF(0, height));
+
height += line.height();
- lines.append(str.mid(line.textStart(), line.textLength()));
- widthUsed = qMax(widthUsed, line.naturalTextWidth());
+
+ lines.append(std::make_pair(line.naturalTextWidth(), str.mid(line.textStart(), line.textLength())));
}
+
textLayout.endLayout();
+
return lines;
}
diff --git a/launcher/ui/widgets/Common.h b/launcher/ui/widgets/Common.h
index b3fbe1a0..b3dd5ca8 100644
--- a/launcher/ui/widgets/Common.h
+++ b/launcher/ui/widgets/Common.h
@@ -1,6 +1,9 @@
#pragma once
-#include <QStringList>
+
#include <QTextLayout>
-QStringList viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
- qreal &widthUsed); \ No newline at end of file
+/** Cuts out the text in textLayout into smaller pieces, according to the lineWidth.
+ * Returns a list of pairs, each containing the width of that line and that line's string, respectively.
+ * The total height of those lines is set in the last argument, 'height'.
+ */
+QList<std::pair<qreal, QString>> viewItemTextLayout(QTextLayout& textLayout, int lineWidth, qreal& height);
diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp
new file mode 100644
index 00000000..56ae35fb
--- /dev/null
+++ b/launcher/ui/widgets/ProjectItem.cpp
@@ -0,0 +1,78 @@
+#include "ProjectItem.h"
+
+#include "Common.h"
+
+#include <QIcon>
+#include <QPainter>
+
+ProjectItemDelegate::ProjectItemDelegate(QWidget* parent) : QStyledItemDelegate(parent) {}
+
+void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ painter->save();
+
+ QStyleOptionViewItem opt(option);
+ initStyleOption(&opt, index);
+
+ auto& rect = opt.rect;
+ auto icon_width = rect.height(), icon_height = rect.height();
+ auto remaining_width = rect.width() - icon_width;
+
+ if (opt.state & QStyle::State_Selected) {
+ painter->fillRect(rect, opt.palette.highlight());
+ painter->setPen(opt.palette.highlightedText().color());
+ } else if (opt.state & QStyle::State_MouseOver) {
+ painter->fillRect(rect, opt.palette.window());
+ }
+
+ { // Icon painting
+ // Square-sized, occupying the left portion
+ opt.icon.paint(painter, rect.x(), rect.y(), icon_width, icon_height);
+ }
+
+ { // Title painting
+ auto title = index.data(UserDataTypes::TITLE).toString();
+
+ painter->save();
+
+ auto font = opt.font;
+ if (index.data(UserDataTypes::SELECTED).toBool()) {
+ // Set nice font
+ font.setBold(true);
+ font.setUnderline(true);
+ }
+
+ font.setPointSize(font.pointSize() + 2);
+ painter->setFont(font);
+
+ // On the top, aligned to the left after the icon
+ painter->drawText(rect.x() + icon_width, rect.y() + QFontMetrics(font).height(), title);
+
+ painter->restore();
+ }
+
+ { // Description painting
+ auto description = index.data(UserDataTypes::DESCRIPTION).toString();
+
+ QTextLayout text_layout(description, opt.font);
+
+ qreal height = 0;
+ auto cut_text = viewItemTextLayout(text_layout, remaining_width, height);
+
+ // Get first line unconditionally
+ description = cut_text.first().second;
+ // Get second line, elided if needed
+ if (cut_text.size() > 1) {
+ if (cut_text.size() > 2)
+ description += opt.fontMetrics.elidedText(cut_text.at(1).second, opt.textElideMode, cut_text.at(1).first);
+ else
+ description += cut_text.at(1).second;
+ }
+
+ // On the bottom, aligned to the left after the icon, and featuring at most two lines of text (with some margin space to spare)
+ painter->drawText(rect.x() + icon_width, rect.y() + rect.height() - 2.2 * opt.fontMetrics.height(), remaining_width,
+ 2 * opt.fontMetrics.height(), Qt::TextWordWrap, description);
+ }
+
+ painter->restore();
+}
diff --git a/launcher/ui/widgets/ProjectItem.h b/launcher/ui/widgets/ProjectItem.h
new file mode 100644
index 00000000..f668edf6
--- /dev/null
+++ b/launcher/ui/widgets/ProjectItem.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <QStyledItemDelegate>
+
+/* Custom data types for our custom list models :) */
+enum UserDataTypes {
+ TITLE = 257, // QString
+ DESCRIPTION = 258, // QString
+ SELECTED = 259 // bool
+};
+
+/** This is an item delegate composed of:
+ * - An Icon on the left
+ * - A title
+ * - A description
+ * */
+class ProjectItemDelegate final : public QStyledItemDelegate {
+ Q_OBJECT
+
+ public:
+ ProjectItemDelegate(QWidget* parent);
+
+ void paint(QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const override;
+
+};