comparison src/gui/widgets/text.cc @ 370:ea3a74ed2ef9

*: hm, last commit wasn't quite finished?
author Paper <paper@tflc.us>
date Fri, 25 Jul 2025 10:22:04 -0400
parents f81bed4e04ac
children
comparison
equal deleted inserted replaced
369:47c9f8502269 370:ea3a74ed2ef9
3 #include "core/strings.h" 3 #include "core/strings.h"
4 4
5 #include <QDebug> 5 #include <QDebug>
6 #include <QFrame> 6 #include <QFrame>
7 #include <QLabel> 7 #include <QLabel>
8 #include <QPainter>
9 #include <QScrollArea>
8 #include <QTextBlock> 10 #include <QTextBlock>
9 #include <QVBoxLayout> 11 #include <QVBoxLayout>
10 #include <QScrollArea>
11 #include <QDebug>
12 #include <QPainter>
13 12
14 namespace TextWidgets { 13 namespace TextWidgets {
15 14
16 /* Generic header meant to be used in conjunction with Section<T> */ 15 /* Generic header meant to be used in conjunction with Section<T> */
17 16
18 Header::Header(QWidget* parent) 17 Header::Header(QWidget *parent) : QWidget(parent), title_(new QLabel), separator_(new QFrame)
19 : QWidget(parent) 18 {
20 , title_(new QLabel) 19 QVBoxLayout *layout = new QVBoxLayout(this);
21 , separator_(new QFrame) {
22 QVBoxLayout* layout = new QVBoxLayout(this);
23 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); 20 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
24 21
25 title_->setTextFormat(Qt::PlainText); 22 title_->setTextFormat(Qt::PlainText);
26 23
27 { 24 {
38 layout->addWidget(separator_.data()); 35 layout->addWidget(separator_.data());
39 layout->setSpacing(0); 36 layout->setSpacing(0);
40 layout->setContentsMargins(0, 0, 0, 0); 37 layout->setContentsMargins(0, 0, 0, 0);
41 } 38 }
42 39
43 void Header::SetText(const std::string& text) { 40 void Header::SetText(const std::string &text)
41 {
44 title_->setText(Strings::ToQString(text)); 42 title_->setText(Strings::ToQString(text));
45 updateGeometry(); 43 updateGeometry();
46 } 44 }
47 45
48 Label::Label(QWidget *parent) : QLabel(parent) {} 46 Label::Label(QWidget *parent) : QLabel(parent)
49 Label::Label(const QString &string, QWidget *parent) : QLabel(string, parent) {} 47 {
50 48 }
51 void Label::SetElidingMode(bool elide) { 49 Label::Label(const QString &string, QWidget *parent) : QLabel(string, parent)
50 {
51 }
52
53 void Label::SetElidingMode(bool elide)
54 {
52 elide_ = elide; 55 elide_ = elide;
53 update(); 56 update();
54 } 57 }
55 58
56 void Label::paintEvent(QPaintEvent *event) { 59 void Label::paintEvent(QPaintEvent *event)
60 {
57 if (elide_) { 61 if (elide_) {
58 /* bruh */ 62 /* bruh */
59 if (wordWrap()) { 63 if (wordWrap()) {
60 QFrame::paintEvent(event); 64 QFrame::paintEvent(event);
61 65
62 const QString content = text(); 66 const QString content = text();
63 67
64 QPainter painter(this); 68 QPainter painter(this);
65 QFontMetrics fontMetrics = painter.fontMetrics(); 69 QFontMetrics fontMetrics = painter.fontMetrics();
66 70
67 bool didElide = false; 71 bool didElide = false;
68 int lineSpacing = fontMetrics.lineSpacing(); 72 int lineSpacing = fontMetrics.lineSpacing();
69 int y = 0; 73 int y = 0;
70 74
71 QTextLayout textLayout(content, painter.font()); 75 QTextLayout textLayout(content, painter.font());
72 textLayout.beginLayout(); 76 textLayout.beginLayout();
73 for (;;) { 77 for (;;) {
74 QTextLine line = textLayout.createLine(); 78 QTextLine line = textLayout.createLine();
75 79
76 if (!line.isValid()) 80 if (!line.isValid())
77 break; 81 break;
78 82
79 line.setLineWidth(width()); 83 line.setLineWidth(width());
80 int nextLineY = y + lineSpacing; 84 int nextLineY = y + lineSpacing;
81 85
82 if (height() >= nextLineY + lineSpacing) { 86 if (height() >= nextLineY + lineSpacing) {
83 line.draw(&painter, QPoint(0, y)); 87 line.draw(&painter, QPoint(0, y));
84 y = nextLineY; 88 y = nextLineY;
85 } else { 89 } else {
86 QString lastLine = content.mid(line.textStart()); 90 QString lastLine = content.mid(line.textStart());
87 QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width()); 91 QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width());
88 painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine); 92 painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine);
89 line = textLayout.createLine(); 93 line = textLayout.createLine();
109 } 113 }
110 114
111 /* ---------------------------------------------------------------------------------- */ 115 /* ---------------------------------------------------------------------------------- */
112 /* "Paragraph" widgets, as in widgets meant to hold a bunch of text. */ 116 /* "Paragraph" widgets, as in widgets meant to hold a bunch of text. */
113 117
114 Paragraph::Paragraph(QWidget *parent) : QWidget(parent), label_(new QLabel) { 118 Paragraph::Paragraph(QWidget *parent) : QWidget(parent), label_(new QLabel)
119 {
115 QVBoxLayout *layout = new QVBoxLayout(this); 120 QVBoxLayout *layout = new QVBoxLayout(this);
116 layout->setSpacing(0); 121 layout->setSpacing(0);
117 layout->setContentsMargins(0, 0, 0, 0); 122 layout->setContentsMargins(0, 0, 0, 0);
118 123
119 label_->setTextInteractionFlags(Qt::TextBrowserInteraction); 124 label_->setTextInteractionFlags(Qt::TextBrowserInteraction);
123 SetSelectable(true); 128 SetSelectable(true);
124 129
125 layout->addWidget(label_.data()); 130 layout->addWidget(label_.data());
126 } 131 }
127 132
128 void Paragraph::SetText(const std::string& text) { 133 void Paragraph::SetText(const std::string &text)
134 {
129 label_->setText(Strings::ToQString(text)); 135 label_->setText(Strings::ToQString(text));
130 } 136 }
131 137
132 void Paragraph::SetSelectable(bool enable) { 138 void Paragraph::SetSelectable(bool enable)
139 {
133 label_->setAttribute(Qt::WidgetAttribute::WA_TransparentForMouseEvents, !enable); 140 label_->setAttribute(Qt::WidgetAttribute::WA_TransparentForMouseEvents, !enable);
134 label_->setCursor(enable ? Qt::IBeamCursor : Qt::ArrowCursor); 141 label_->setCursor(enable ? Qt::IBeamCursor : Qt::ArrowCursor);
135 } 142 }
136 143
137 void Paragraph::SetWordWrap(bool enable) { 144 void Paragraph::SetWordWrap(bool enable)
145 {
138 label_->setWordWrap(enable); 146 label_->setWordWrap(enable);
139 } 147 }
140 148
141 /* LabelledParagraph implementation */ 149 /* LabelledParagraph implementation */
142 150
143 LabelledParagraph::LabelledParagraph(QWidget* parent) 151 LabelledParagraph::LabelledParagraph(QWidget *parent)
144 : QWidget(parent) 152 : QWidget(parent), contents_(new QWidget), contents_layout_(new QGridLayout)
145 , contents_(new QWidget) 153 {
146 , contents_layout_(new QGridLayout) { 154 QHBoxLayout *ly = new QHBoxLayout(this);
147 QHBoxLayout* ly = new QHBoxLayout(this);
148 155
149 contents_layout_->setVerticalSpacing(1); 156 contents_layout_->setVerticalSpacing(1);
150 contents_layout_->setHorizontalSpacing(20); 157 contents_layout_->setHorizontalSpacing(20);
151 contents_layout_->setContentsMargins(0, 0, 0, 0); 158 contents_layout_->setContentsMargins(0, 0, 0, 0);
152 contents_layout_->setColumnStretch(1, 0); 159 contents_layout_->setColumnStretch(1, 0);
155 162
156 ly->addWidget(contents_.data()); 163 ly->addWidget(contents_.data());
157 ly->setContentsMargins(0, 0, 0, 0); 164 ly->setContentsMargins(0, 0, 0, 0);
158 } 165 }
159 166
160 LabelledParagraph::~LabelledParagraph() { 167 LabelledParagraph::~LabelledParagraph()
168 {
161 data_.clear(); 169 data_.clear();
162 } 170 }
163 171
164 void LabelledParagraph::Clear(void) { 172 void LabelledParagraph::Clear(void)
165 for (auto& [label, data] : data_) { 173 {
174 for (auto &[label, data] : data_) {
166 contents_layout_->removeWidget(label.data()); 175 contents_layout_->removeWidget(label.data());
167 contents_layout_->removeWidget(data.data()); 176 contents_layout_->removeWidget(data.data());
168 } 177 }
169 178
170 data_.clear(); 179 data_.clear();
171 } 180 }
172 181
173 void LabelledParagraph::SetData(const std::vector<std::pair<std::string, std::string>>& data) { 182 void LabelledParagraph::SetData(const std::vector<std::pair<std::string, std::string>> &data)
183 {
174 Clear(); 184 Clear();
175 185
176 data_.reserve(data.size()); 186 data_.reserve(data.size());
177 for (std::size_t i = 0; i < data.size(); i++) { 187 for (std::size_t i = 0; i < data.size(); i++) {
178 QSharedPointer<Label> first(new Label); 188 QSharedPointer<Label> first(new Label);
183 first->setText(Strings::ToQString(data[i].first)); 193 first->setText(Strings::ToQString(data[i].first));
184 second->setText(Strings::ToQString(data[i].second)); 194 second->setText(Strings::ToQString(data[i].second));
185 195
186 data_.push_back({first, second}); 196 data_.push_back({first, second});
187 197
188 contents_layout_->addWidget(first.data(), i, 0); 198 contents_layout_->addWidget(first.data(), i, 0);
189 contents_layout_->addWidget(second.data(), i, 1); 199 contents_layout_->addWidget(second.data(), i, 1);
190 } 200 }
191 } 201 }
192 202
193 void LabelledParagraph::SetStyle(int style) { 203 void LabelledParagraph::SetStyle(int style)
204 {
194 const QString style_sheet = (style & LabelledParagraph::BoldedLabels) ? "font-weight: bold;" : ""; 205 const QString style_sheet = (style & LabelledParagraph::BoldedLabels) ? "font-weight: bold;" : "";
195 for (auto& [label, data] : data_) 206 for (auto &[label, data] : data_)
196 label->setStyleSheet(style_sheet); 207 label->setStyleSheet(style_sheet);
197 208
198 if (style & LabelledParagraph::ElidedData) { 209 if (style & LabelledParagraph::ElidedData) {
199 for (auto& [label, data] : data_) { 210 for (auto &[label, data] : data_) {
200 data->setWordWrap(false); 211 data->setWordWrap(false);
201 data->SetElidingMode(true); 212 data->SetElidingMode(true);
202 } 213 }
203 } 214 }
204 } 215 }