6#include "QskListView.h"
8#include "QskColorFilter.h"
10#include "QskSkinlet.h"
12#include <qguiapplication.h>
13#include <qstylehints.h>
23#define FOCUS_ON_CURRENT 1
25static inline int qskRowAt(
const QskListView* listView,
const QPointF& pos )
27 const auto rect = listView->viewContentsRect();
28 if ( rect.contains( pos ) )
30 const auto y = pos.y() - rect.top() + listView->scrollPos().y();
32 const int row = y / listView->rowHeight();
33 if ( row >= 0 && row < listView->rowCount() )
40class QskListView::PrivateData
44 : preferredWidthFromColumns( false )
54 ? hoveredRow : ( ( state ==
Q::Pressed ) ? pressedRow : selectedRow );
56 if ( row == storedRow )
61 const auto states = listView->rowStates( storedRow );
62 startTransitions( listView, storedRow, states, states & ~state );
67 const auto states = listView->rowStates( row );
68 startTransitions( listView, row, states, states | state );
76 inline void startTransitions(
QskListView* listView,
int row,
77 QskAspect::States oldStates, QskAspect::States newStates )
81 listView->startHintTransitions(
82 { Q::Cell, Q::Text }, oldStates, newStates, row );
92 bool preferredWidthFromColumns : 1;
93 SelectionMode selectionMode : 4;
100QskListView::QskListView( QQuickItem* parent )
102 , m_data( new PrivateData() )
109QskListView::~QskListView()
113void QskListView::setPreferredWidthFromColumns(
bool on )
115 if ( on != m_data->preferredWidthFromColumns )
117 m_data->preferredWidthFromColumns = on;
120 Q_EMIT preferredWidthFromColumnsChanged();
124bool QskListView::preferredWidthFromColumns()
const
126 return m_data->preferredWidthFromColumns;
129void QskListView::setTextOptions(
const QskTextOptions& textOptions )
131 if ( setTextOptionsHint( Text, textOptions ) )
133 updateScrollableSize();
134 Q_EMIT textOptionsChanged();
140 return textOptionsHint( Text );
143void QskListView::resetTextOptions()
145 if ( resetTextOptionsHint( Text ) )
147 updateScrollableSize();
148 Q_EMIT textOptionsChanged();
152void QskListView::setSelectedRow(
int row )
157 if ( row >= rowCount() )
159 if ( !isComponentComplete() )
166 if ( row >= rowCount() )
171 if ( row != m_data->selectedRow )
173 m_data->setRowState(
this, row, Selected );
175 Q_EMIT selectedRowChanged( row );
182int QskListView::selectedRow()
const
184 return m_data->selectedRow;
187void QskListView::setSelectionMode( SelectionMode mode )
189 if ( mode != m_data->selectionMode )
191 m_data->selectionMode = mode;
193 if ( m_data->selectionMode == NoSelection )
194 setSelectedRow( -1 );
196 Q_EMIT selectionModeChanged();
200QskListView::SelectionMode QskListView::selectionMode()
const
202 return m_data->selectionMode;
208 if( m_data->selectedRow >= 0 )
213 rect =
rect.translated( -scrollPos() );
214 if (
rect.intersects( viewContentsRect() ) )
222void QskListView::keyPressEvent( QKeyEvent* event )
224 if ( m_data->selectionMode == NoSelection )
226 Inherited::keyPressEvent( event );
230 int row = selectedRow();
232 switch ( event->key() )
236 if ( row < rowCount() - 1 )
243 row = rowCount() - 1;
257 row = rowCount() - 1;
261 case Qt::Key_PageDown:
264 Inherited::keyPressEvent( event );
269 Inherited::keyPressEvent( event );
274 const int r = selectedRow();
276 setSelectedRow( row );
282 auto pos = scrollPos();
284 const qreal rowPos = row * rowHeight();
285 if ( rowPos < scrollPos().y() )
291 const QRectF vr = viewContentsRect();
293 const double scrolledBottom = scrollPos().y() + vr.height();
294 if ( rowPos + rowHeight() > scrolledBottom )
296 const double y = rowPos + rowHeight() - vr.height();
301 if ( pos != scrollPos() )
303 if ( event->isAutoRepeat() )
311void QskListView::keyReleaseEvent( QKeyEvent* event )
313 Inherited::keyReleaseEvent( event );
316void QskListView::mousePressEvent( QMouseEvent* event )
318 if ( m_data->selectionMode != NoSelection )
320 const int row = qskRowAt(
this, qskMousePosition( event ) );
323 m_data->setRowState(
this, row, Pressed );
324 setSelectedRow( row );
329 Inherited::mousePressEvent( event );
332void QskListView::mouseReleaseEvent( QMouseEvent* event )
334 m_data->setRowState(
this, -1, Pressed );
335 Inherited::mouseReleaseEvent( event );
338void QskListView::mouseUngrabEvent()
340 m_data->setRowState(
this, -1, Pressed );
341 Inherited::mouseUngrabEvent();
344void QskListView::hoverEnterEvent( QHoverEvent* event )
346 if ( m_data->selectionMode != NoSelection )
348 const int row = qskRowAt(
this, qskHoverPosition( event ) );
349 m_data->setRowState(
this, row,
Hovered );
352 Inherited::hoverEnterEvent( event );
355void QskListView::hoverMoveEvent( QHoverEvent* event )
357 if ( m_data->selectionMode != NoSelection )
359 const int row = qskRowAt(
this, qskHoverPosition( event ) );
360 m_data->setRowState(
this, row,
Hovered );
363 Inherited::hoverMoveEvent( event );
366void QskListView::hoverLeaveEvent( QHoverEvent* event )
368 m_data->setRowState(
this, -1,
Hovered );
369 Inherited::hoverLeaveEvent( event );
374 if ( event->type() == QEvent::StyleChange )
375 updateScrollableSize();
380QskAspect::States QskListView::rowStates(
int row )
const
382 auto states = skinStates();
386 if ( row == m_data->selectedRow )
389 if ( row == m_data->hoveredRow )
392 if ( row == m_data->pressedRow )
399#ifndef QT_NO_WHEELEVENT
401static qreal qskAlignedToRows(
const qreal y0, qreal dy,
402 qreal rowHeight, qreal viewHeight )
408 y = qFloor( y / rowHeight ) * rowHeight;
413 y = qCeil( y / rowHeight ) * rowHeight;
420QPointF QskListView::scrollOffset(
const QWheelEvent* event )
const
424 const auto pos = qskWheelPosition( event );
428 const auto steps = qskWheelSteps( event );
429 offset.setY( steps );
433 const auto steps = qskWheelSteps( event );
434 offset.setX( steps );
436 else if ( viewContentsRect().contains( pos ) )
438 offset =
event->angleDelta() / QWheelEvent::DefaultDeltasPerStep;
441 if ( offset.x() != 0.0 )
443 offset.rx() *= viewContentsRect().width();
445 else if ( offset.y() != 0.0 )
447 const qreal y0 = scrollPos().y();
448 const auto viewHeight = viewContentsRect().height();
449 const qreal rowHeight = this->rowHeight();
451 const int numLines = QGuiApplication::styleHints()->wheelScrollLines();
453 qreal dy = numLines * rowHeight;
454 if ( event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) )
455 dy = qMax( dy, viewHeight );
460 dy = qskAlignedToRows( y0, dy, rowHeight, viewHeight );
462 offset.setY( y0 - dy );
472void QskListView::updateScrollableSize()
474 const double h = rowCount() * rowHeight();
477 for (
int col = 0; col < columnCount(); col++ )
478 w += columnWidth( col );
480 const QSizeF sz = scrollableSize();
482 setScrollableSize( QSizeF( w, h ) );
484 if ( m_data->preferredWidthFromColumns &&
485 sz.width() != scrollableSize().width() )
491void QskListView::componentComplete()
495 if ( m_data->selectedRow >= 0 )
500 if ( m_data->selectedRow >= rowCount() )
501 setSelectedRow( -1 );
505#include "moc_QskListView.cpp"
QRectF subControlRect(QskAspect::Subcontrol) const
void focusIndicatorRectChanged()
static const QskAspect::State Hovered
virtual QRectF focusIndicatorRect() const
QRectF contentsRect() const
virtual void changeEvent(QEvent *)
void componentComplete() override
QRectF focusIndicatorRect() const override
void changeEvent(QEvent *) override
const QskSkinlet * effectiveSkinlet() const