Commit a5d85eb7 authored by Thomas BOUTROUE's avatar Thomas BOUTROUE

Initial version imported from various on-going projects

parents
*.user*
*.qmlc
*.jsc
*.autosave
*.bak
*.tmp
*.old
#include "QtQmlTricks.h"
#include "QQmlContainerEnums.h"
#include "QQmlObjectListModel.h"
#include "QQuickColumnContainer.h"
#include "QQuickContainerAttachedObject.h"
#include "QQuickExtraAnchors.h"
#include "QQuickGridContainer.h"
#include "QQuickRowContainer.h"
#include <qqml.h>
void QtQmlTricks::registerComponents (void) {
qmlRegisterType<QQuickColumnContainer> ("QtQmlTricks", 3, 0, "ColumnContainer");
qmlRegisterType<QQuickGridContainer> ("QtQmlTricks", 3, 0, "GridContainer");
qmlRegisterType<QQuickRowContainer> ("QtQmlTricks", 3, 0, "RowContainer");
qmlRegisterUncreatableType<VerticalDirections> ("QtQmlTricks", 3, 0, "VerticalDirections", "Enum-class !");
qmlRegisterUncreatableType<HorizontalDirections> ("QtQmlTricks", 3, 0, "HorizontalDirections", "Enum-class !");
qmlRegisterUncreatableType<FlowDirections> ("QtQmlTricks", 3, 0, "FlowDirections", "Enum-class !");
qmlRegisterUncreatableType<QQuickExtraAnchors> ("QtQmlTricks", 3, 0, "ExtraAnchors", "Attached-object class !");
qmlRegisterUncreatableType<QQuickContainerAttachedObject> ("QtQmlTricks", 3, 0, "Container", "Attached-object class !");
qmlRegisterUncreatableType<QQmlObjectListModelBase> ("QtQmlTricks", 3, 0, "ObjectListModel", "Abstract base class !");
}
#ifndef QTQMLTRICKS_H
#define QTQMLTRICKS_H
class QtQmlTricks {
public:
static void registerComponents (void);
};
#endif // QTQMLTRICKS_H
#ifndef QMLENUMHELPERS_H
#define QMLENUMHELPERS_H
#include <QObject>
#include <QString>
#include <QQmlEngine>
#include <QMetaEnum>
#include <QMetaObject>
#include <qqml.h>
#ifndef Q_ENUM
# define Q_ENUM Q_ENUMS
#endif
#define QML_ENUM_CLASS(NAME, ...) \
struct NAME { \
Q_GADGET \
public: \
enum Type { __VA_ARGS__ }; Q_ENUM (Type) \
static QByteArray asByteArray (const int value) { \
return QByteArray (staticMetaObject.enumerator (0).valueToKey (value)); \
} \
static QString asString (const int value) { \
return QString::fromLatin1 (asByteArray (value)); \
} \
private: \
NAME (void) = delete; \
NAME (const NAME &) = delete; \
NAME & operator= (const NAME &) = delete; \
}; \
Q_DECLARE_METATYPE (NAME::Type)
QML_ENUM_CLASS (_Test_QmlEnumClass_) // NOTE : to avoid "no suitable class found" MOC note
#endif // QMLENUMHELPERS_H
#ifndef QMLVARPROPERTYHELPERS_H
#define QMLVARPROPERTYHELPERS_H
#include <QObject>
#define QML_PROPERTY_MEMBER_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
VAR_TYPE m_##PROP_NAME;
#define QML_PROPERTY_GETTER_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
RET_TYPE get_##PROP_NAME (void) const { \
return m_##PROP_NAME; \
}
#define QML_PROPERTY_SETTER_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
bool set_##PROP_NAME (ARG_TYPE PROP_NAME) { \
bool ret = false; \
if ((ret = (m_##PROP_NAME != PROP_NAME))) { \
m_##PROP_NAME = PROP_NAME; \
emit PROP_NAME##Changed (m_##PROP_NAME); \
} \
return ret; \
}
#define QML_PROPERTY_NOTIFIER_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
void PROP_NAME##Changed (ARG_TYPE PROP_NAME);
#define QML_WRITABLE_PROPERTY_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
private: \
Q_PROPERTY (VAR_TYPE PROP_NAME READ get_##PROP_NAME WRITE set_##PROP_NAME NOTIFY PROP_NAME##Changed) \
private: QML_PROPERTY_MEMBER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
public: QML_PROPERTY_GETTER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
public Q_SLOTS: QML_PROPERTY_SETTER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
Q_SIGNALS: QML_PROPERTY_NOTIFIER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
private:
#define QML_READONLY_PROPERTY_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
private: \
Q_PROPERTY (VAR_TYPE PROP_NAME READ get_##PROP_NAME NOTIFY PROP_NAME##Changed) \
private: QML_PROPERTY_MEMBER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
public: QML_PROPERTY_GETTER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
public: QML_PROPERTY_SETTER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
Q_SIGNALS: QML_PROPERTY_NOTIFIER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
private:
#define QML_CONSTANT_PROPERTY_IMPL(PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
private: \
Q_PROPERTY (VAR_TYPE PROP_NAME READ get_##PROP_NAME CONSTANT) \
private: QML_PROPERTY_MEMBER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
public: QML_PROPERTY_GETTER_IMPL (PROP_NAME, VAR_TYPE, ARG_TYPE, RET_TYPE) \
private:
#define QML_WRITABLE_VAR_PROPERTY(NAME, TYPE) \
QML_WRITABLE_PROPERTY_IMPL(NAME, TYPE, const TYPE, TYPE)
#define QML_READONLY_VAR_PROPERTY(NAME, TYPE) \
QML_READONLY_PROPERTY_IMPL(NAME, TYPE, const TYPE, TYPE)
#define QML_CONSTANT_VAR_PROPERTY(NAME, TYPE) \
QML_CONSTANT_PROPERTY_IMPL(NAME, TYPE, const TYPE, TYPE)
#define QML_WRITABLE_CSTREF_PROPERTY(NAME, TYPE) \
QML_WRITABLE_PROPERTY_IMPL(NAME, TYPE, const TYPE &, const TYPE &)
#define QML_READONLY_CSTREF_PROPERTY(NAME, TYPE) \
QML_READONLY_PROPERTY_IMPL(NAME, TYPE, const TYPE &, const TYPE &)
#define QML_CONSTANT_CSTREF_PROPERTY(NAME, TYPE) \
QML_CONSTANT_PROPERTY_IMPL(NAME, TYPE, const TYPE &, const TYPE &)
#define QML_WRITABLE_PTR_PROPERTY(NAME, TYPE) \
QML_WRITABLE_PROPERTY_IMPL(NAME, TYPE *, TYPE *, TYPE *)
#define QML_READONLY_PTR_PROPERTY(NAME, TYPE) \
QML_READONLY_PROPERTY_IMPL(NAME, TYPE *, TYPE *, TYPE *)
#define QML_CONSTANT_PTR_PROPERTY(NAME, TYPE) \
QML_CONSTANT_PROPERTY_IMPL(NAME, TYPE *, TYPE *, TYPE *)
struct _QMLVARPROPERTYHELPERS_ { Q_GADGET }; // mock object
#endif // QMLVARPROPERTYHELPERS_H
This diff is collapsed.
#ifndef QQMLCONTAINERENUMS_H
#define QQMLCONTAINERENUMS_H
#include <QObject>
#include "QmlEnumHelpers.h"
QML_ENUM_CLASS (VerticalDirections,
TOP_TO_BOTTOM,
BOTTOM_TO_TOP,
)
QML_ENUM_CLASS (HorizontalDirections,
LEFT_TO_RIGHT,
RIGHT_TO_LEFT,
)
QML_ENUM_CLASS (FlowDirections,
VERTICAL,
HORIZONTAL,
)
struct _QQMLCONTAINERENUMS_ { Q_GADGET }; // mock object
#endif // QQMLCONTAINERENUMS_H
#include "QQuickAbstractContainerBase.h"
#include "QQuickContainerAttachedObject.h"
const char * QQuickAbstractContainerBase::REPEATER_CLASSNAME { "QQuickRepeater" };
QQuickAbstractContainerBase::QQuickAbstractContainerBase (QQuickItem * parent)
: QQuickItem { parent }
, m_layoutItemsCount { 0 }
{ }
QQuickAbstractContainerBase::~QQuickAbstractContainerBase (void) { }
void QQuickAbstractContainerBase::doLayout (void) {
polish ();
}
QQuickContainerAttachedObject * QQuickAbstractContainerBase::getContainerAttachedObject (QQuickItem * item) const {
return qobject_cast<QQuickContainerAttachedObject *> (qmlAttachedPropertiesObject<QQuickContainerAttachedObject> (item, false));
}
void QQuickAbstractContainerBase::classBegin (void) {
QQuickItem::classBegin ();
}
void QQuickAbstractContainerBase::componentComplete (void) {
QQuickItem::componentComplete ();
connect (this, &QQuickAbstractContainerBase::widthChanged, this, &QQuickAbstractContainerBase::polish);
connect (this, &QQuickAbstractContainerBase::heightChanged, this, &QQuickAbstractContainerBase::polish);
connect (this, &QQuickAbstractContainerBase::visibleChanged, this, &QQuickAbstractContainerBase::polish);
setupHandlers ();
polish ();
}
void QQuickAbstractContainerBase::itemChange (ItemChange change, const ItemChangeData & value) {
QQuickItem::itemChange (change, value);
switch (int (change)) {
case ItemChildAddedChange: {
if (QQuickItem * child { value.item }) {
connect (child, &QQuickItem::visibleChanged, this, &QQuickAbstractContainerBase::polish);
connect (child, &QQuickItem::implicitWidthChanged, this, &QQuickAbstractContainerBase::polish);
connect (child, &QQuickItem::implicitHeightChanged, this, &QQuickAbstractContainerBase::polish);
if (const QQuickContainerAttachedObject * attached { getContainerAttachedObject (child) }) {
connect (attached, &QQuickContainerAttachedObject::ignoredChanged, this, &QQuickAbstractContainerBase::polish);
connect (attached, &QQuickContainerAttachedObject::forcedWidthChanged, this, &QQuickAbstractContainerBase::polish);
connect (attached, &QQuickContainerAttachedObject::forcedHeightChanged, this, &QQuickAbstractContainerBase::polish);
connect (attached, &QQuickContainerAttachedObject::verticalStretchChanged, this, &QQuickAbstractContainerBase::polish);
connect (attached, &QQuickContainerAttachedObject::horizontalStretchChanged, this, &QQuickAbstractContainerBase::polish);
}
polish ();
}
break;
}
case ItemChildRemovedChange: {
if (QQuickItem * child { value.item }) {
disconnect (child, Q_NULLPTR, this, Q_NULLPTR);
if (const QQuickContainerAttachedObject * attached { getContainerAttachedObject (child) }) {
disconnect (attached, Q_NULLPTR, this, Q_NULLPTR);
}
polish ();
}
break;
}
}
}
void QQuickAbstractContainerBase::updatePolish (void) {
QQuickItem::updatePolish ();
relayout ();
emit layoutDone ();
}
#ifndef QQUICKABSTRACTCONTAINERBASE_H
#define QQUICKABSTRACTCONTAINERBASE_H
#include <QQuickItem>
#include "QmlPropertyHelpers.h"
#include "QQmlContainerEnums.h"
class QQuickContainerAttachedObject;
class QQuickAbstractContainerBase : public QQuickItem {
Q_OBJECT
QML_READONLY_VAR_PROPERTY (layoutItemsCount, int)
public:
explicit QQuickAbstractContainerBase (QQuickItem * parent = Q_NULLPTR);
virtual ~QQuickAbstractContainerBase (void);
Q_INVOKABLE void doLayout (void);
signals:
void layoutDone (void);
protected:
virtual void setupHandlers (void) = 0;
virtual void relayout (void) = 0;
static const char * REPEATER_CLASSNAME;
QQuickContainerAttachedObject * getContainerAttachedObject (QQuickItem * item) const;
private:
void classBegin (void) Q_DECL_FINAL;
void componentComplete (void) Q_DECL_FINAL;
void updatePolish (void) Q_DECL_FINAL;
void itemChange (ItemChange change, const ItemChangeData & value) Q_DECL_FINAL;
};
#endif // QQUICKABSTRACTCONTAINERBASE_H
#include "QQuickColumnContainer.h"
#include "QQuickContainerAttachedObject.h"
#include <QtMath>
QQuickColumnContainer::QQuickColumnContainer (QQuickItem * parent)
: QQuickAbstractContainerBase { parent }
, m_verticalSpacing { 0 }
, m_verticalDirection { HorizontalDirections::LEFT_TO_RIGHT }
{ }
QQuickColumnContainer::~QQuickColumnContainer (void) { }
void QQuickColumnContainer::setupHandlers (void) {
connect (this, &QQuickColumnContainer::verticalSpacingChanged, this, &QQuickColumnContainer::doLayout);
connect (this, &QQuickColumnContainer::verticalDirectionChanged, this, &QQuickColumnContainer::doLayout);
}
void QQuickColumnContainer::relayout (void) {
int maxImplicitWidth { 0 };
int totalFixedImplicitHeight { 0 };
int totalStretchedImplicitHeight { 0 };
int countFixedItems { 0 };
int countStretchedItems { 0 };
const QList<QQuickItem *> childItemsList { childItems () };
QVector<QQuickItem *> layoutItemsList { };
layoutItemsList.reserve (childItemsList.count ());
for (QQuickItem * childItem : childItemsList) {
const QQuickContainerAttachedObject * attached { getContainerAttachedObject (childItem) };
const int stretch { (attached ? attached->get_verticalStretch () : 0) };
const int forced { (attached ? attached->get_forcedHeight () : 0) };
const bool ignored { (attached && attached->get_ignored ()) };
if (!childItem->inherits (REPEATER_CLASSNAME)) {
if (!ignored) {
if (childItem->isVisible ()) {
layoutItemsList.append (childItem);
if (childItem->implicitWidth () > maxImplicitWidth) {
maxImplicitWidth = qCeil (childItem->implicitWidth ());
}
if (forced > 0) {
totalFixedImplicitHeight += forced;
++countFixedItems;
}
else if (stretch > 0) {
if (childItem->implicitHeight () > 0) {
totalStretchedImplicitHeight += qCeil (childItem->implicitHeight ());
}
countStretchedItems += stretch;
}
else {
if (childItem->implicitHeight () > 0) {
totalFixedImplicitHeight += qCeil (childItem->implicitHeight ());
}
++countFixedItems;
}
}
}
}
}
const int totalItemsCount { (countFixedItems + countStretchedItems) };
const int totalSpacing { (totalItemsCount > 1 ? ((totalItemsCount -1) * m_verticalSpacing) : 0) };
setImplicitHeight (totalFixedImplicitHeight + totalStretchedImplicitHeight + totalSpacing);
setImplicitWidth (maxImplicitWidth);
const int stretchedItemHeight { qFloor (qreal (qCeil (height ()) - totalFixedImplicitHeight - totalSpacing) / qreal (countStretchedItems)) };
int currentPosY { (m_verticalDirection == VerticalDirections::BOTTOM_TO_TOP ? qFloor (height ()) : 0) };
for (QQuickItem * childItem : layoutItemsList) {
const QQuickContainerAttachedObject * attached { getContainerAttachedObject (childItem) };
const int stretch { (attached ? attached->get_verticalStretch () : 0) };
const int forced { (attached ? attached->get_forcedHeight () : 0) };
if (attached && (forced > 0)) {
childItem->setHeight (forced);
}
else if (attached && (stretch > 0)) {
childItem->setHeight ((stretchedItemHeight * stretch) + (m_verticalSpacing * (stretch -1)));
}
else {
childItem->setHeight (qCeil (childItem->implicitHeight ()));
}
switch (m_verticalDirection) {
case VerticalDirections::TOP_TO_BOTTOM: {
childItem->setY (currentPosY);
currentPosY += childItem->height ();
currentPosY += m_verticalSpacing;
break;
}
case VerticalDirections::BOTTOM_TO_TOP: {
currentPosY -= childItem->height ();
childItem->setY (currentPosY);
currentPosY -= currentPosY;
break;
}
}
childItem->setX (0);
}
set_layoutItemsCount (layoutItemsList.count ());
}
#ifndef QQUICKCOLUMNCONTAINER_H
#define QQUICKCOLUMNCONTAINER_H
#include "QQuickAbstractContainerBase.h"
class QQuickColumnContainer : public QQuickAbstractContainerBase {
Q_OBJECT
QML_WRITABLE_VAR_PROPERTY (verticalSpacing, int)
QML_WRITABLE_VAR_PROPERTY (verticalDirection, int) // VerticalDirections::Type
// COMPATIBILITY ALIASES
Q_PROPERTY (int spacing READ get_verticalSpacing WRITE set_verticalSpacing NOTIFY verticalSpacingChanged)
public:
explicit QQuickColumnContainer (QQuickItem * parent = Q_NULLPTR);
virtual ~QQuickColumnContainer (void);
protected:
void setupHandlers (void) Q_DECL_FINAL;
void relayout (void) Q_DECL_FINAL;
};
#endif // QQUICKCOLUMNCONTAINER_H
#include "QQuickContainerAttachedObject.h"
QQuickContainerAttachedObject::QQuickContainerAttachedObject (QObject * parent)
: QObject { parent }
, m_forcedWidth { 0 }
, m_forcedHeight { 0 }
, m_verticalStretch { 0 }
, m_horizontalStretch { 0 }
, m_ignored { false }
{ }
QQuickContainerAttachedObject::~QQuickContainerAttachedObject (void) { }
QQuickContainerAttachedObject * QQuickContainerAttachedObject::qmlAttachedProperties (QObject * object) {
return new QQuickContainerAttachedObject { object };
}
#ifndef QQUICKCONTAINERATTACHEDOBJECT_H
#define QQUICKCONTAINERATTACHEDOBJECT_H
#include <QQuickItem>
#include "QmlPropertyHelpers.h"
class QQuickContainerAttachedObject : public QObject {
Q_OBJECT
QML_WRITABLE_VAR_PROPERTY (forcedWidth, int)
QML_WRITABLE_VAR_PROPERTY (forcedHeight, int)
QML_WRITABLE_VAR_PROPERTY (verticalStretch, int)
QML_WRITABLE_VAR_PROPERTY (horizontalStretch, int)
QML_WRITABLE_VAR_PROPERTY (ignored, bool)
public:
explicit QQuickContainerAttachedObject (QObject * parent = Q_NULLPTR);
virtual ~QQuickContainerAttachedObject (void);
static QQuickContainerAttachedObject * qmlAttachedProperties (QObject * object);
};
QML_DECLARE_TYPE (QQuickContainerAttachedObject)
QML_DECLARE_TYPEINFO (QQuickContainerAttachedObject, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKCONTAINERATTACHEDOBJECT_H
#include "QQuickGridContainer.h"
#include "QQuickContainerAttachedObject.h"
#include <QtMath>
QQuickGridContainer::QQuickGridContainer (QQuickItem * parent)
: QQuickAbstractContainerBase { parent }
, m_cols { 1 }
, m_rows { 1 }
, m_capacity { -1 }
, m_verticalSpacing { 0 }
, m_horizontalSpacing { 0 }
, m_verticalDirection { VerticalDirections::TOP_TO_BOTTOM }
, m_horizontalDirection { HorizontalDirections::LEFT_TO_RIGHT }
, m_flowDirection { FlowDirections::HORIZONTAL }
, m_fillEmpty { true }
{ }
void QQuickGridContainer::setupHandlers (void) {
connect (this, &QQuickGridContainer::colsChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::rowsChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::capacityChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::verticalSpacingChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::horizontalSpacingChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::verticalDirectionChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::horizontalDirectionChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::flowDirectionChanged, this, &QQuickGridContainer::doLayout);
connect (this, &QQuickGridContainer::fillEmptyChanged, this, &QQuickGridContainer::doLayout);
}
void QQuickGridContainer::relayout (void) {
int maxChildWidth { 0 }, maxChildHeight { 0 };
QVector<QQuickItem *> layoutItemsList { };
const QList<QQuickItem *> childrenList { childItems () };
layoutItemsList.reserve (childrenList.count ());
for (QQuickItem * childItem : childrenList) {
if (!childItem->inherits (REPEATER_CLASSNAME)) {
if (childItem->isVisible () || !m_fillEmpty) {
const QQuickContainerAttachedObject * attached { getContainerAttachedObject (childItem) };
const bool ignored { (attached && attached->get_ignored ()) };
if (!ignored) {
layoutItemsList.append (childItem);
if (qCeil (childItem->implicitWidth ()) > maxChildWidth) {
maxChildWidth = qCeil (childItem->implicitWidth ());
}
if (qCeil (childItem->implicitHeight ()) > maxChildHeight) {
maxChildHeight = qCeil (childItem->implicitHeight ());
}
}
}
}
}
switch (m_flowDirection) {
case FlowDirections::HORIZONTAL: {
if (m_cols > 0) {
if (m_capacity > 0) {
set_rows (qCeil (qreal (m_capacity) / qreal (m_cols)));
}
else if (layoutItemsList.count () > 0) {
set_rows (qCeil (qreal (layoutItemsList.count ()) / qreal (m_cols)));
}
else {
set_rows (0);
}
}
break;
}
case FlowDirections::VERTICAL: {
if (m_rows > 0) {
if (m_capacity > 0) {
set_cols (qCeil (qreal (m_capacity) / qreal (m_rows)));
}
else if (layoutItemsList.count () > 0) {
set_cols (qCeil (qreal (layoutItemsList.count ()) / qreal (m_rows)));
}
else {
set_cols (0);
}
}
break;
}
}
setImplicitWidth ((m_cols * maxChildWidth) + ((m_cols -1) * m_horizontalSpacing));
setImplicitHeight ((m_rows * maxChildHeight) + ((m_rows -1) * m_verticalSpacing));
if (m_rows > 0 && m_cols > 0) {
const qreal itemWidth { (qreal (width () - (m_horizontalSpacing * (m_cols -1))) / qreal (m_cols)) };
const qreal itemHeight { (qreal (height () - (m_verticalSpacing * (m_rows -1))) / qreal (m_rows)) };
int currentIdx { 0 };
for (QQuickItem * childItem : layoutItemsList) {
const int currentRow { (m_flowDirection == FlowDirections::HORIZONTAL ? (currentIdx / m_cols) : (currentIdx % m_rows)) };
const int currentCol { (m_flowDirection == FlowDirections::VERTICAL ? (currentIdx / m_rows) : (currentIdx % m_cols)) };
childItem->setWidth (itemWidth);
childItem->setHeight (itemHeight);
switch (m_horizontalDirection) {
case HorizontalDirections::LEFT_TO_RIGHT: {
childItem->setX (currentCol * (itemWidth + m_horizontalSpacing));
break;
}
case HorizontalDirections::RIGHT_TO_LEFT: {
childItem->setX (width () - (currentCol * (itemWidth + m_horizontalSpacing)) - itemWidth);
break;
}
}
switch (m_verticalDirection) {
case VerticalDirections::TOP_TO_BOTTOM: {
childItem->setY (currentRow * (itemHeight + m_verticalSpacing));
break;
}
case VerticalDirections::BOTTOM_TO_TOP: {
childItem->setY (height () - (currentRow * (itemHeight + m_verticalSpacing)) - itemHeight);
break;
}
}
++currentIdx;
}
}
set_layoutItemsCount (layoutItemsList.count ());
}
#ifndef QQUICKGRIDCONTAINER_H
#define QQUICKGRIDCONTAINER_H
#include "QQuickAbstractContainerBase.h"
class QQuickGridContainer : public QQuickAbstractContainerBase {
Q_OBJECT
QML_WRITABLE_VAR_PROPERTY (cols, int)
QML_WRITABLE_VAR_PROPERTY (rows, int)
QML_WRITABLE_VAR_PROPERTY (capacity, int)
QML_WRITABLE_VAR_PROPERTY (verticalSpacing, int)
QML_WRITABLE_VAR_PROPERTY (horizontalSpacing, int)
QML_WRITABLE_VAR_PROPERTY (verticalDirection, int) // VerticalDirections::Type
QML_WRITABLE_VAR_PROPERTY (horizontalDirection, int) // HorizontalDirections::Type
QML_WRITABLE_VAR_PROPERTY (flowDirection, int) // FlowDirections::Type
QML_WRITABLE_VAR_PROPERTY (fillEmpty, bool)
// COMPATIBILITY ALIASES
Q_PROPERTY (int colSpacing READ get_horizontalSpacing WRITE set_horizontalSpacing NOTIFY horizontalSpacingChanged)
Q_PROPERTY (int rowSpacing READ get_verticalSpacing WRITE set_verticalSpacing NOTIFY verticalSpacingChanged)
public:
explicit QQuickGridContainer (QQuickItem * parent = Q_NULLPTR);
protected:
void setupHandlers (void) Q_DECL_FINAL;
void relayout (void) Q_DECL_FINAL;
};
#endif // QQUICKGRIDCONTAINER_H
#include "QQuickRowContainer.h"
#include "QQuickContainerAttachedObject.h"
#include <QtMath>
QQuickRowContainer::QQuickRowContainer (QQuickItem * parent)
: QQuickAbstractContainerBase { parent }
, m_horizontalSpacing { 0 }
, m_horizontalDirection { HorizontalDirections::LEFT_TO_RIGHT }
{ }
QQuickRowContainer::~QQuickRowContainer (void) { }
void QQuickRowContainer::setupHandlers (void) {
connect (this, &QQuickRowContainer::horizontalSpacingChanged, this, &QQuickRowContainer::doLayout);
connect (this, &QQuickRowContainer::horizontalDirectionChanged, this, &QQuickRowContainer::doLayout);
}
void QQuickRowContainer::relayout (void) {
int maxImplicitHeight { 0 };
int totalFixedImplicitWidth { 0 };
int totalStretchedImplicitWidth { 0 };
int countFixedItems { 0 };
int countStretchedItems { 0 };
const QList<QQuickItem *> childItemsList { childItems () };
QVector<QQuickItem *> layoutItemsList { };
layoutItemsList.reserve (childItemsList.count ());
for (QQuickItem * childItem : childItemsList) {
const QQuickContainerAttachedObject * attached { getContainerAttachedObject (childItem) };
const int stretch { (attached ? attached->get_horizontalStretch () : 0) };
const int forced { (attached ? attached->get_forcedWidth () : 0) };
const bool ignored { (attached && attached->get_ignored ()) };
if (!childItem->inherits (REPEATER_CLASSNAME)) {
if (!ignored) {
if (childItem->isVisible ()) {
layoutItemsList.append (childItem);
if (childItem->implicitHeight () > maxImplicitHeight) {
maxImplicitHeight = qCeil (childItem->implicitHeight ());
}
if (forced > 0) {
totalFixedImplicitWidth += forced;
++countFixedItems;
}
else if (stretch > 0) {
if (childItem->implicitWidth () > 0) {
totalStretchedImplicitWidth += qCeil (childItem->implicitWidth ());
}
countStretchedItems += stretch;
}
else {
if (childItem->implicitWidth () > 0) {
totalFixedImplicitWidth += qCeil (childItem->implicitWidth ());
}
++countFixedItems;
}
}
}
}
}
const int totalItemsCount { (countFixedItems + countStretchedItems) };
const int totalSpacing { (totalItemsCount > 1 ? ((totalItemsCount -1) * m_horizontalSpacing) : 0) };
setImplicitWidth (totalFixedImplicitWidth + totalStretchedImplicitWidth + totalSpacing);
setImplicitHeight (maxImplicitHeight);
const int stretchedItemWidth { qFloor (qreal (qCeil (width ()) - totalFixedImplicitWidth - totalSpacing) / qreal (countStretchedItems)) };
int currentPosX { (m_horizontalDirection == HorizontalDirections::RIGHT_TO_LEFT ? qFloor (width ()) : 0) };
for (QQuickItem * childItem : layoutItemsList) {
const QQuickContainerAttachedObject * attached { getContainerAttachedObject (childItem) };
const int stretch { (attached ? attached->get_horizontalStretch () : 0) };
const int forced { (attached ? attached->get_forcedWidth () : 0) };
if (forced > 0) {
childItem->setWidth (forced);
}
else if (stretch > 0) {
childItem->setWidth ((stretchedItemWidth * stretch) + (m_horizontalSpacing * (stretch -1)));
}
else {
childItem->setWidth (qCeil (childItem->implicitWidth ()));
}
switch (m_horizontalDirection) {
case HorizontalDirections::LEFT_TO_RIGHT: {
childItem->setX (currentPosX);
currentPosX += childItem->width ();