QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskSimpleListBox.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskSimpleListBox.h"
7#include "QskAspect.h"
8#include "QskFunctions.h"
9
10#include <qfontmetrics.h>
11
12static inline qreal qskMaxWidth(
13 const QFont& font, const QStringList& list )
14{
15 const QFontMetricsF fm( font );
16
17 qreal max = 0.0;
18 for ( int i = 0; i < list.size(); i++ )
19 {
20 const qreal w = qskHorizontalAdvance( fm, list[ i ] );
21 if ( w > max )
22 max = w;
23 }
24
25 return max;
26}
27
28class QskSimpleListBox::PrivateData
29{
30 public:
31 PrivateData()
32 : maxTextWidth( 0.0 )
33 , columnWidthHint( 0.0 )
34 {
35 }
36
37 // one column at the moment only
38 qreal maxTextWidth;
39 qreal columnWidthHint;
40
41 QStringList entries;
42};
43
44QskSimpleListBox::QskSimpleListBox( QQuickItem* parent )
45 : Inherited( parent )
46 , m_data( new PrivateData() )
47{
48 connect( this, &Inherited::selectedRowChanged,
49 this, [ this ]( int row ) { Q_EMIT selectedEntryChanged( entryAt( row ) ); } );
50}
51
52QskSimpleListBox::~QskSimpleListBox()
53{
54}
55
56QString QskSimpleListBox::entryAt( int row ) const
57{
58 if ( row >= 0 && row < m_data->entries.size() )
59 return m_data->entries[ row ];
60
61 return QString();
62}
63
64QVariant QskSimpleListBox::valueAt( int row, int col ) const
65{
66 if ( col == 0 && row >= 0 && row < m_data->entries.size() )
67 return m_data->entries[ row ];
68
69 return QVariant();
70}
71
72void QskSimpleListBox::setColumnWidthHint( int column, qreal width )
73{
74 if ( column != 0 )
75 return;
76
77 if ( width != m_data->columnWidthHint )
78 {
79 m_data->columnWidthHint = qMax( width, qreal( 0.0 ) );
80
81 if ( m_data->columnWidthHint > 0.0 )
82 m_data->maxTextWidth = m_data->columnWidthHint;
83 else
84 m_data->maxTextWidth = qskMaxWidth( effectiveFont( Text ), m_data->entries );
85
86 updateScrollableSize();
87 }
88}
89
90qreal QskSimpleListBox::columnWidthHint( int column ) const
91{
92 if ( column == 0 )
93 return m_data->columnWidthHint;
94
95 return 0.0;
96}
97
98void QskSimpleListBox::insert( const QStringList& list, int index )
99{
100 if ( list.isEmpty() )
101 return;
102
103 if ( m_data->columnWidthHint <= 0.0 )
104 {
105 const auto w = qskMaxWidth( effectiveFont( Text ), list );
106 if ( w > m_data->maxTextWidth )
107 m_data->maxTextWidth = w;
108 }
109
110 if ( m_data->entries.isEmpty() )
111 {
112 m_data->entries = list;
113 }
114 else if ( index < 0 || index >= m_data->entries.size() )
115 {
116 m_data->entries += list;
117 }
118 else
119 {
120 // is there no better way ???
121 for ( int i = 0; i < list.size(); i++ )
122 m_data->entries.insert( index + i, list[ i ] );
123 }
124
125 propagateEntries();
126}
127
128void QskSimpleListBox::setEntries( const QStringList& entries )
129{
130 if ( m_data->entries.isEmpty() && entries.isEmpty() )
131 return;
132
133 m_data->entries.clear();
134
135 if ( m_data->columnWidthHint <= 0.0 )
136 m_data->maxTextWidth = 0.0;
137
138 insert( entries, -1 );
139}
140
141QStringList QskSimpleListBox::entries() const
142{
143 return m_data->entries;
144}
145
146void QskSimpleListBox::insert( const QString& text, int index )
147{
148 if ( m_data->columnWidthHint <= 0.0 )
149 {
150 const auto w = qskHorizontalAdvance( effectiveFont( Cell ), text );
151 if ( w > m_data->maxTextWidth )
152 m_data->maxTextWidth = w;
153 }
154
155 if ( index < 0 )
156 m_data->entries.append( text );
157 else
158 m_data->entries.insert( index, text );
159
160 propagateEntries();
161}
162
163void QskSimpleListBox::removeAt( int index )
164{
165 auto& entries = m_data->entries;
166
167 if ( index < 0 || index >= entries.size() )
168 return;
169
170 if ( m_data->columnWidthHint <= 0.0 )
171 {
172 const auto w = qskHorizontalAdvance( effectiveFont( Cell ), entries[ index ] );
173 if ( w >= m_data->maxTextWidth )
174 m_data->maxTextWidth = qskMaxWidth( effectiveFont( Text ), entries );
175 }
176
177 entries.removeAt( index );
178
179 propagateEntries();
180
181 int row = selectedRow();
182 if ( row == index )
183 {
184 row = qMin( row, m_data->entries.size() - 1 );
185
186 if ( row != selectedRow() )
187 setSelectedRow( row );
188 else
189 Q_EMIT selectedRowChanged( row );
190 }
191}
192
193void QskSimpleListBox::removeBulk( int from, int to )
194{
195 if ( from < 0 )
196 from = 0;
197
198 if ( to < 0 || to >= m_data->entries.size() - 1 )
199 to = m_data->entries.size() - 1;
200
201 if ( to < from )
202 return;
203
204 for ( int i = to; i >= from; i-- )
205 m_data->entries.removeAt( i );
206
207 if ( m_data->columnWidthHint <= 0.0 )
208 m_data->maxTextWidth = qskMaxWidth( effectiveFont( Text ), m_data->entries );
209
210 propagateEntries();
211
212 int row = selectedRow();
213 if ( row >= 0 )
214 {
215 if ( m_data->entries.isEmpty() )
216 {
217 row = -1;
218 }
219 else if ( row < from )
220 {
221 // nothing to do
222 }
223 else if ( row <= to )
224 {
225 // we might end up here with the same row TODO ...
226 row = qMin( from, m_data->entries.size() - 1 );
227 }
228 else
229 {
230 row -= ( to - from + 1 );
231 }
232
233 if ( row != selectedRow() )
234 {
235 setSelectedRow( row );
236 }
237 }
238}
239
240void QskSimpleListBox::clear()
241{
242 if ( m_data->entries.isEmpty() )
243 return;
244
245 m_data->entries.clear();
246
247 if ( m_data->columnWidthHint <= 0.0 )
248 m_data->maxTextWidth = 0.0;
249
250 propagateEntries();
251 setSelectedRow( -1 );
252}
253
254void QskSimpleListBox::propagateEntries()
255{
256#if 1
257 // when removing we might have lost the selected row -> what to do then ?
258#endif
259 updateScrollableSize();
260 update();
261
262 Q_EMIT entriesChanged();
263}
264
265int QskSimpleListBox::rowCount() const
266{
267 return m_data->entries.size();
268}
269
270int QskSimpleListBox::columnCount() const
271{
272 return 1;
273}
274
275qreal QskSimpleListBox::columnWidth( int col ) const
276{
277 if ( col >= columnCount() )
278 return 0.0;
279
280 const auto padding = paddingHint( Cell );
281 return m_data->maxTextWidth + padding.left() + padding.right();
282}
283
284qreal QskSimpleListBox::rowHeight() const
285{
286 const auto hint = strutSizeHint( Cell );
287 const auto padding = paddingHint( Cell );
288
289 qreal h = effectiveFontHeight( Text );
290 h += padding.top() + padding.bottom();
291
292 return qMax( h, hint.height() );
293}
294
295#include "moc_QskSimpleListBox.cpp"
QMarginsF paddingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a padding hint.
QFont effectiveFont(QskAspect) const
QSizeF strutSizeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a strut size hint.