diff options
author | Thomas Zander <thomas.zander@trolltech.com> | 2009-05-12 11:02:54 +0200 |
---|---|---|
committer | Thomas Zander <thomas.zander@trolltech.com> | 2009-05-12 11:02:54 +0200 |
commit | 5a5c082b79d30dabd3cd0437ee692f9204ca156b (patch) | |
tree | 4fe9386c73f6b395ffaf301046b64a75eb2b1bfd | |
parent | 0181f56968fd1f7e4efb9033542bffe26309337a (diff) | |
parent | 0531abdb5231126baf0b989f3bf4e0d8c1d9f2a3 (diff) |
Merge branch 'master' into tableItemLayout
47 files changed, 3685 insertions, 1711 deletions
diff --git a/doc/classic.css b/doc/classic.css new file mode 100644 index 0000000..6cf7377 --- /dev/null +++ b/doc/classic.css @@ -0,0 +1,139 @@ +h3.fn,span.fn +{ + margin-left: 1cm; + text-indent: -1cm; +} + +a:link +{ + color: #004faf; + text-decoration: none +} + +a:visited +{ + color: #672967; + text-decoration: none +} + +a.obsolete +{ + color: #661100; + text-decoration: none +} + +a.compat +{ + color: #661100; + text-decoration: none +} + +a.obsolete:visited +{ + color: #995500; + text-decoration: none +} + +a.compat:visited +{ + color: #995500; + text-decoration: none +} + +td.postheader +{ + font-family: sans-serif +} + +tr.address +{ + font-family: sans-serif +} + +body +{ + background: #ffffff; + color: black +} + +table tr.odd { + background: #f0f0f0; + color: black; +} + +table tr.even { + background: #e4e4e4; + color: black; +} + +table.annotated th { + padding: 3px; + text-align: left +} + +table.annotated td { + padding: 3px; +} + +table tr pre +{ + padding-top: none; + padding-bottom: none; + padding-left: none; + padding-right: none; + border: none; + background: none +} + +tr.qt-style +{ + background: #96E066; + color: black +} + +body pre +{ + padding: 0.2em; + border: #e7e7e7 1px solid; + background: #f1f1f1; + color: black +} + +table tr.qt-code pre +{ + padding: 0.2em; + border: #e7e7e7 1px solid; + background: #f1f1f1; + color: black +} + +span.preprocessor, span.preprocessor a +{ + color: darkblue; +} + +span.comment +{ + color: darkred; + font-style: italic +} + +span.string,span.char +{ + color: darkgreen; +} + +.title +{ + text-align: center +} + +.subtitle +{ + font-size: 0.8em +} + +.small-subtitle +{ + font-size: 0.65em +} diff --git a/doc/itemviews-ng.qdoc b/doc/itemviews-ng.qdoc new file mode 100644 index 0000000..8e7227f --- /dev/null +++ b/doc/itemviews-ng.qdoc @@ -0,0 +1,4 @@ +/*! + \page itemviews-ng.html + \title Item Views Next Generation +*/ diff --git a/doc/itemviews-ng.qdocconf b/doc/itemviews-ng.qdocconf new file mode 100644 index 0000000..8ce6c2e --- /dev/null +++ b/doc/itemviews-ng.qdocconf @@ -0,0 +1,192 @@ +# Run qdoc from the directory that contains this file. + +project = itemviewsng +description = Item Views NG + +headerdirs = ../src +sourcedirs = ../src +imagedirs = src/images +outputdir = html + +extraimages.HTML = qt-logo + +headers.fileextesnions = "*.h" +sources.fileextensions = "*.cpp *.qdoc" + + +# macros.qdocconf + +macro.aring.HTML = "å" +macro.Auml.HTML = "Ä" +macro.author = "\\bold{Author:}" +macro.br.HTML = "<br />" +macro.BR.HTML = "<br />" +macro.aacute.HTML = "á" +macro.eacute.HTML = "é" +macro.iacute.HTML = "í" +macro.gui = "\\bold" +macro.hr.HTML = "<hr />" +macro.key = "\\bold" +macro.menu = "\\bold" +macro.note = "\\bold{Note:}" +macro.oslash.HTML = "ø" +macro.ouml.HTML = "ö" +macro.QA = "\\e{Qt Assistant}" +macro.QD = "\\e{Qt Designer}" +macro.QL = "\\e{Qt Linguist}" +macro.param = "\\e" +macro.raisedaster.HTML = "<sup>*</sup>" +macro.reg.HTML = "<sup>®</sup>" +macro.return = "Returns" +macro.starslash = "\\c{*/}" +macro.uuml.HTML = "ü" +macro.mdash.HTML = "—" + +# compat.qdocconf + +alias.i = e +alias.include = input + +macro.0 = "\\\\0" +macro.b = "\\\\b" +macro.n = "\\\\n" +macro.r = "\\\\r" +macro.i = "\\o" +macro.i11 = "\\o{1,1}" +macro.i12 = "\\o{1,2}" +macro.i13 = "\\o{1,3}" +macro.i14 = "\\o{1,4}" +macro.i15 = "\\o{1,5}" +macro.i16 = "\\o{1,6}" +macro.i17 = "\\o{1,7}" +macro.i18 = "\\o{1,8}" +macro.i19 = "\\o{1,9}" +macro.i21 = "\\o{2,1}" +macro.i31 = "\\o{3,1}" +macro.i41 = "\\o{4,1}" +macro.i51 = "\\o{5,1}" +macro.i61 = "\\o{6,1}" +macro.i71 = "\\o{7,1}" +macro.i81 = "\\o{8,1}" +macro.i91 = "\\o{9,1}" +macro.img = "\\image" +macro.endquote = "\\endquotation" + +spurious = "Missing comma in .*" \ + "Missing pattern .*" + +# Doxygen compatibility commands + +macro.see = "\\sa" +macro.function = "\\fn" + +# qt-cpp-ignore.qdocconf + +Cpp.ignoretokens = QAXFACTORY_EXPORT \ + QDESIGNER_COMPONENTS_LIBRARY \ + QDESIGNER_EXTENSION_LIBRARY \ + QDESIGNER_SDK_LIBRARY \ + QDESIGNER_SHARED_LIBRARY \ + QDESIGNER_UILIB_LIBRARY \ + QM_EXPORT_CANVAS \ + QM_EXPORT_DNS \ + QM_EXPORT_DOM \ + QM_EXPORT_FTP \ + QM_EXPORT_HTTP \ + QM_EXPORT_ICONVIEW \ + QM_EXPORT_NETWORK \ + QM_EXPORT_OPENGL \ + QM_EXPORT_SQL \ + QM_EXPORT_TABLE \ + QM_EXPORT_WORKSPACE \ + QM_EXPORT_XML \ + QT_ASCII_CAST_WARN \ + QT_ASCII_CAST_WARN_CONSTRUCTOR \ + QT_BEGIN_HEADER \ + QT_DESIGNER_STATIC \ + QT_END_HEADER \ + QT_FASTCALL \ + QT_WIDGET_PLUGIN_EXPORT \ + Q_COMPAT_EXPORT \ + Q_CORE_EXPORT \ + Q_EXPLICIT \ + Q_EXPORT \ + Q_EXPORT_CODECS_CN \ + Q_EXPORT_CODECS_JP \ + Q_EXPORT_CODECS_KR \ + Q_EXPORT_PLUGIN \ + Q_GFX_INLINE \ + Q_GUI_EXPORT \ + Q_GUI_EXPORT_INLINE \ + Q_GUI_EXPORT_STYLE_CDE \ + Q_GUI_EXPORT_STYLE_COMPACT \ + Q_GUI_EXPORT_STYLE_MAC \ + Q_GUI_EXPORT_STYLE_MOTIF \ + Q_GUI_EXPORT_STYLE_MOTIFPLUS \ + Q_GUI_EXPORT_STYLE_PLATINUM \ + Q_GUI_EXPORT_STYLE_POCKETPC \ + Q_GUI_EXPORT_STYLE_SGI \ + Q_GUI_EXPORT_STYLE_WINDOWS \ + Q_GUI_EXPORT_STYLE_WINDOWSXP \ + QHELP_EXPORT \ + Q_INLINE_TEMPLATE \ + Q_INTERNAL_WIN_NO_THROW \ + Q_NETWORK_EXPORT \ + Q_OPENGL_EXPORT \ + Q_OUTOFLINE_TEMPLATE \ + Q_SQL_EXPORT \ + Q_SVG_EXPORT \ + Q_SCRIPT_EXPORT \ + Q_TESTLIB_EXPORT \ + Q_TYPENAME \ + Q_XML_EXPORT \ + Q_XMLSTREAM_EXPORT \ + Q_XMLPATTERNS_EXPORT \ + QDBUS_EXPORT \ + QT_BEGIN_NAMESPACE \ + QT_BEGIN_INCLUDE_NAMESPACE \ + QT_END_NAMESPACE \ + QT_END_INCLUDE_NAMESPACE \ + PHONON_EXPORT \ + EXTENSIONSYSTEM_EXPORT +Cpp.ignoredirectives = Q_DECLARE_HANDLE \ + Q_DECLARE_INTERFACE \ + Q_DECLARE_METATYPE \ + Q_DECLARE_OPERATORS_FOR_FLAGS \ + Q_DECLARE_PRIVATE \ + Q_DECLARE_PUBLIC \ + Q_DECLARE_SHARED \ + Q_DECLARE_TR_FUNCTIONS \ + Q_DECLARE_TYPEINFO \ + Q_DISABLE_COPY \ + QT_FORWARD_DECLARE_CLASS \ + Q_DUMMY_COMPARISON_OPERATOR \ + Q_ENUMS \ + Q_FLAGS \ + Q_INTERFACES \ + __attribute__ \ + K_DECLARE_PRIVATE \ + PHONON_OBJECT \ + PHONON_HEIR + + + +HTML.stylesheets = classic.css +HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \ + "<tr>\n" \ + "<td align=\"left\" valign=\"top\" width=\"32\">" \ + "<img src=\"images/qt-logo.png\" align=\"left\" width=\"32\" height=\"32\" border=\"0\" />" \ + "</td>\n" \ + "<td width=\"1\"> </td>" \ + "<td class=\"postheader\" valign=\"center\">" \ + "<a href=\"qtcreator-manual.html\">" \ + "<font color=\"#004faf\">Home</font></a>" \ + "</td>\n" \ + "<td align=\"right\" valign=\"top\" width=\"230\"></td></tr></table><br>" + +HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ + "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ + "<td width=\"30%\" align=\"left\">Copyright © 2009 Nokia</td>\n" \ + "<td width=\"40%\" align=\"center\"> </td>\n" \ + "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt Creator 1.1.80</div></td>\n" \ + "</tr></table></div></address>" diff --git a/doc/src/images/itemviewdesign.png b/doc/src/images/itemviewdesign.png Binary files differnew file mode 100644 index 0000000..f3f529e --- /dev/null +++ b/doc/src/images/itemviewdesign.png diff --git a/examples/chat/main.cpp b/examples/chat/main.cpp index 34c8bf1..a57ce8c 100644 --- a/examples/chat/main.cpp +++ b/examples/chat/main.cpp @@ -24,26 +24,11 @@ #include <QtCore> #include <QtGui> -#include <qlistwidgetng.h> -#include <qlistcontroller.h> -#include <qgraphicslistview.h> #include <experimental/qkineticlistcontroller.h> #include "chatmodel.h" #include "chatview.h" - -class W : public QGraphicsWidget -{ -public: - W(QGraphicsWidget *parent = 0, Qt::WindowFlags wFlags = 0) : QGraphicsWidget(parent, wFlags) { - setCacheMode(QGraphicsItem::ItemCoordinateCache); - setMinimumSize(QSizeF(200, 30)); - setMaximumSize(QSizeF(200, 30)); - } - void paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*) { painter->fillRect(boundingRect(), Qt::green); } -}; - int main(int argc, char *argv[]) { QApplication app(argc, argv); diff --git a/examples/photoAlbum/main.cpp b/examples/photoAlbum/main.cpp index 940f238..a6942bd 100644 --- a/examples/photoAlbum/main.cpp +++ b/examples/photoAlbum/main.cpp @@ -53,7 +53,7 @@ void Photo::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWi { Q_UNUSED(option); Q_UNUSED(widget); - const QPixmap pixmap = qvariant_cast<QPixmap>(data().value(QtListModelInterface::IconRole)); + const QPixmap pixmap = qvariant_cast<QPixmap>(data().value(Qt::DecorationRole)); painter->drawPixmap(70, 52, pixmap); painter->drawRect(69, 51, 501, 376); } @@ -82,23 +82,23 @@ int main(int argc, char *argv[]) controller->setCenterOnItemEnabled(true); QtListDefaultItem *item = new QtListDefaultItem; - item->setData(QPixmap(":images/go.jpg"), QtListModelInterface::IconRole); + item->setData(QPixmap(":images/go.jpg"), Qt::DecorationRole); model->appendItem(item); item = new QtListDefaultItem; - item->setData(QPixmap(":images/contrast.jpg"), QtListModelInterface::IconRole); + item->setData(QPixmap(":images/contrast.jpg"), Qt::DecorationRole); model->appendItem(item); item = new QtListDefaultItem; - item->setData(QPixmap(":images/nightfall.jpg"), QtListModelInterface::IconRole); + item->setData(QPixmap(":images/nightfall.jpg"), Qt::DecorationRole); model->appendItem(item); item = new QtListDefaultItem; - item->setData(QPixmap(":images/flower.jpg"), QtListModelInterface::IconRole); + item->setData(QPixmap(":images/flower.jpg"), Qt::DecorationRole); model->appendItem(item); item = new QtListDefaultItem; - item->setData(QPixmap(":images/beach.jpg"), QtListModelInterface::IconRole); + item->setData(QPixmap(":images/beach.jpg"), Qt::DecorationRole); model->appendItem(item); widget.scene()->addItem(view); diff --git a/src/experimental/qgraphicsflowview.cpp b/src/experimental/qgraphicsflowview.cpp index 2300f67..23b7099 100644 --- a/src/experimental/qgraphicsflowview.cpp +++ b/src/experimental/qgraphicsflowview.cpp @@ -76,8 +76,8 @@ void QtGraphicsFlowViewItem::paint(QPainter *painter, const QStyleOptionGraphics d->view->initStyleOption(&d->option); d->view->initStyleOption(&d->option, d->index); - QHash<int, QVariant> itemData = d->view->model()->data(d->index, QList<int>() << QtListModelInterface::IconRole); - QVariant var = itemData.value(QtListModelInterface::IconRole); + QHash<int, QVariant> itemData = d->view->model()->data(d->index, QList<int>() << Qt::DecorationRole); + QVariant var = itemData.value(Qt::DecorationRole); if (var.isNull()) return; diff --git a/src/experimental/qgraphicspathview.cpp b/src/experimental/qgraphicspathview.cpp index 2a358b1..32bba08 100644 --- a/src/experimental/qgraphicspathview.cpp +++ b/src/experimental/qgraphicspathview.cpp @@ -154,7 +154,7 @@ void QtGraphicsPathView::doLayout() while (!path.isEmpty() && counter < count) { initStyleOption(&option, index); qreal c = qreal(counter) + progress; - QSizeF size = d->itemSize(&option, index); + QSizeF size = d->itemSizeHint(&option, index); //qreal scale = (qreal(count - qAbs(c - (count / 2))) / qreal(count)); qreal t = qBound(qreal(0), c / qreal(count), qreal(1)); QPointF pos = path.pointAtPercent(t); diff --git a/src/qgraphicslistview.cpp b/src/qgraphicslistview.cpp index 03321cb..09fcf55 100644 --- a/src/qgraphicslistview.cpp +++ b/src/qgraphicslistview.cpp @@ -432,7 +432,7 @@ QtGraphicsListViewItem *QtGraphicsListViewPrivate::viewItemAt(int index, int fir /*! \internal */ -QSizeF QtGraphicsListViewPrivate::itemSize(const QStyleOptionViewItemV4 *option, int index, const QSizeF &constraint) const +QSizeF QtGraphicsListViewPrivate::itemSizeHint(const QStyleOptionViewItemV4 *option, int index, const QSizeF &constraint) const { return viewItems.isEmpty() ? QSizeF() : viewItems.first()->sizeHint(index, option, Qt::PreferredSize, constraint); } @@ -628,7 +628,7 @@ int QtGraphicsListView::itemAt(const QPointF &position) const qreal y = -d->verticalOffset; while (y <= position.y() && index < count) { initStyleOption(&option, index); - QSizeF size = d->itemSize(&option, index, constraint); + QSizeF size = d->itemSizeHint(&option, index, constraint); y += size.height(); if (y >= position.y()) return index; @@ -638,7 +638,7 @@ int QtGraphicsListView::itemAt(const QPointF &position) const qreal x = -d->horizontalOffset; while (x <= position.x() && index < count) { initStyleOption(&option, index); - QSizeF size = d->itemSize(&option, index, constraint); + QSizeF size = d->itemSizeHint(&option, index, constraint); x += size.width(); if (x >= position.x()) return index; @@ -692,7 +692,7 @@ void QtGraphicsListView::doLayout() if (y < 0) { // the cached offset was above the visible area while (index < count) { initStyleOption(&option, index); - const qreal height = d->itemSize(&option, index, constraint).height(); + const qreal height = d->itemSizeHint(&option, index, constraint).height(); if (y + height > area.y()) break; y += height; @@ -701,7 +701,7 @@ void QtGraphicsListView::doLayout() } else if (y > 0) { // the cached offset was below while (index >= 0 && y > 0) { initStyleOption(&option, index); - const qreal height = d->itemSize(&option, index, constraint).height(); + const qreal height = d->itemSizeHint(&option, index, constraint).height(); y -= height; --index; } @@ -738,7 +738,7 @@ void QtGraphicsListView::doLayout() if (x < area.x()) { // the cached offset was left of the visible area while (index < count) { initStyleOption(&option, index); - const qreal width = d->itemSize(&option, index, constraint).width(); + const qreal width = d->itemSizeHint(&option, index, constraint).width(); if (x + width > area.x()) break; x += width; @@ -747,7 +747,7 @@ void QtGraphicsListView::doLayout() } else if (x > area.x()) { // the cached offset was to the right while (index >= 0 && x > area.x()) { initStyleOption(&option, index); - const qreal width = d->itemSize(&option, index, constraint).width(); + const qreal width = d->itemSizeHint(&option, index, constraint).width(); x -= width; --index; } @@ -798,7 +798,7 @@ int QtGraphicsListView::maximumFirstIndex() const qreal height = size().height() + d->verticalOffset; for (; index >= 0; --index) { initStyleOption(&option, index); - height -= d->itemSize(&option, index, constraint).height(); + height -= d->itemSizeHint(&option, index, constraint).height(); if (height < 0) break; } @@ -806,7 +806,7 @@ int QtGraphicsListView::maximumFirstIndex() const qreal width = size().width() + d->horizontalOffset; for (; index >= 0; --index) { initStyleOption(&option, index); - width -= d->itemSize(&option, index, constraint).width(); + width -= d->itemSizeHint(&option, index, constraint).width(); if (width < 0) break; } @@ -836,7 +836,7 @@ qreal QtGraphicsListView::maximumHorizontalOffset() const int count = (d->model ? d->model->count() : 0); for (int index = 0; index < count; ++index) { initStyleOption(&option, index); - QSizeF size = d->itemSize(&option, index, constraint); + QSizeF size = d->itemSizeHint(&option, index, constraint); max = qMax(max, size.width()); content += size.width(); } @@ -864,7 +864,7 @@ qreal QtGraphicsListView::maximumVerticalOffset() const int count = d->model ? d->model->count() : 0; for (int index = 0; index < count; ++index) { initStyleOption(&option, index); - QSizeF size = d->itemSize(&option, index, constraint); + QSizeF size = d->itemSizeHint(&option, index, constraint); content += size.height(); max = qMax(max, size.height()); } @@ -977,7 +977,7 @@ void QtGraphicsListView::setFirstIndexToEnsureIndexIsVisible(int index) qreal height = size().height() + d->verticalOffset; for (; index >= 0; --index) { initStyleOption(&option, index); - height -= d->itemSize(&option, index, constraint).height(); + height -= d->itemSizeHint(&option, index, constraint).height(); if (height < 0) break; } @@ -985,7 +985,7 @@ void QtGraphicsListView::setFirstIndexToEnsureIndexIsVisible(int index) qreal width = size().width() + d->horizontalOffset; for (; index >= 0; --index) { initStyleOption(&option, index); - width -= d->itemSize(&option, index, constraint).width(); + width -= d->itemSizeHint(&option, index, constraint).width(); if (width < 0) break; } diff --git a/src/qgraphicslistview.h b/src/qgraphicslistview.h index 23e26fd..31c80c8 100644 --- a/src/qgraphicslistview.h +++ b/src/qgraphicslistview.h @@ -53,7 +53,7 @@ public: int index() const; void setIndex(int index); - virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + virtual QSizeF sizeHint(Qt::SizeHint which = Qt::PreferredSize, const QSizeF &constraint = QSizeF()) const; virtual QSizeF sizeHint(int index, const QStyleOptionViewItemV4 *option, Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); @@ -146,14 +146,13 @@ Q_SIGNALS: void layoutChanged(); // ### ??? protected: - friend class QtPrinterListView; + friend class QtPrinterListView; // ### FIXME: should not be needed QtGraphicsListView(QtGraphicsListViewPrivate &, Qt::Orientation orientation, QGraphicsWidget *parent, Qt::WindowFlags wFlags = 0); // ### making them virtual allows the user to hook up to any signals they need virtual void setController(QtListController *control); virtual void setModel(QtListModelInterface *model); virtual void setSelectionManager(QtListSelectionManager *selectionManager); - virtual bool event(QEvent *event); QtGraphicsListViewPrivate *d_ptr; diff --git a/src/qgraphicslistview_p.h b/src/qgraphicslistview_p.h index 148891e..28153b0 100644 --- a/src/qgraphicslistview_p.h +++ b/src/qgraphicslistview_p.h @@ -83,7 +83,7 @@ public: void recycleViewItems(int firstVisibleIndex); void removeViewItemsFrom(int i); QtGraphicsListViewItem *viewItemAt(int index, int firstVisibleIndex); - QSizeF itemSize(const QStyleOptionViewItemV4 *option, int index, const QSizeF &constraints = QSizeF()) const; + QSizeF itemSizeHint(const QStyleOptionViewItemV4 *option, int index, const QSizeF &constraints = QSizeF()) const; QtGraphicsListView *q_ptr; QtListController *controller; diff --git a/src/qgraphicstableview.cpp b/src/qgraphicstableview.cpp index 4ddb7a4..f7937e3 100644 --- a/src/qgraphicstableview.cpp +++ b/src/qgraphicstableview.cpp @@ -214,13 +214,10 @@ void QtGraphicsTableViewPrivate::_q_cellsChanged(int firstRow, int firstColumn, checkCache(firstRow, firstColumn, rowCount, columnCount); } -void QtGraphicsTableViewPrivate::_q_selectionsChanged(int firstRow, int firstColumn, int rowCount, int columnCount) +void QtGraphicsTableViewPrivate::_q_selectionsChanged(const QList<QtTableSelectionRange> &changed) { -//qDebug() << "_q_selectionsChanged" << firstRow << firstColumn << rowCount << columnCount; - Q_UNUSED(firstRow); - Q_UNUSED(firstColumn); - Q_UNUSED(rowCount); - Q_UNUSED(columnCount); +//qDebug() << "_q_selectionsChanged" << changed; + Q_UNUSED(changed) // TODO Q_Q(QtGraphicsTableView); q->update(); @@ -550,8 +547,8 @@ void QtGraphicsTableView::setSelectionManager(QtTableSelectionManager *selection if (d->selectionManager) { disconnect(d->selectionManager, SIGNAL(destroyed()), this, SLOT(_q_selectionsDestroyed())); - disconnect(d->selectionManager, SIGNAL(selectionsChanged(int,int,int,int)), - this, SLOT(_q_selectionsChanged(int,int,int,int))); + disconnect(d->selectionManager, SIGNAL(selectionsChanged(const QList<QtTableSelectionRange>&)), + this, SLOT(_q_selectionsChanged(const QList<QtTableSelectionRange>&))); disconnect(d->selectionManager, SIGNAL(currentChanged(int,int,int,int)), this, SLOT(_q_currentChanged(int,int,int,int))); } @@ -559,8 +556,8 @@ void QtGraphicsTableView::setSelectionManager(QtTableSelectionManager *selection if (d->selectionManager) { connect(d->selectionManager, SIGNAL(destroyed()), this, SLOT(_q_selectionsDestroyed())); - connect(d->selectionManager, SIGNAL(selectionsChanged(int,int,int,int)), - this, SLOT(_q_selectionsChanged(int,int,int,int))); + connect(d->selectionManager, SIGNAL(selectionsChanged(const QList<QtTableSelectionRange>&)), + this, SLOT(_q_selectionsChanged(const QList<QtTableSelectionRange>&))); connect(d->selectionManager, SIGNAL(currentChanged(int,int,int,int)), this, SLOT(_q_currentChanged(int,int,int,int))); } diff --git a/src/qgraphicstableview.h b/src/qgraphicstableview.h index bef73b7..1f10a5b 100644 --- a/src/qgraphicstableview.h +++ b/src/qgraphicstableview.h @@ -39,6 +39,7 @@ class QtGraphicsHeader; class QtTableController; class QtTableModelInterface; class QtTableSelectionManager; +class QtTableSelectionRange; class QtGraphicsTableViewPrivate; class QtGraphicsTableViewItemPrivate; class QtTableOption; @@ -156,7 +157,6 @@ Q_SIGNALS: void verticalOffsetChanged(qreal offset); void horizontalHeaderChanged(QtGraphicsHeader*); void verticalHeaderChanged(QtGraphicsHeader*); - //void cursorChangeRequest(Qt::CursorShape shape); protected: QtGraphicsTableView(QtGraphicsTableViewPrivate&, QGraphicsWidget *parent = 0, Qt::WindowFlags wFlags = 0); @@ -180,7 +180,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_verticalHeaderDestroyed()) Q_PRIVATE_SLOT(d_func(), void _q_horizontalHeaderDestroyed()) Q_PRIVATE_SLOT(d_func(), void _q_cellsChanged(int firstRow, int firstColumn, int rowCount, int columnCount, const QList<int> &roles)) - Q_PRIVATE_SLOT(d_func(), void _q_selectionsChanged(int firstRow, int firstColumn, int rowCount, int columnCount)) + Q_PRIVATE_SLOT(d_func(), void _q_selectionsChanged(const QList<QtTableSelectionRange> &change)) Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)) Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(int row, int count)) Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(int row, int count)) diff --git a/src/qgraphicstableview_p.h b/src/qgraphicstableview_p.h index fb8a255..a38eee8 100644 --- a/src/qgraphicstableview_p.h +++ b/src/qgraphicstableview_p.h @@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE class QtTableModelInterface; class QtTableSelectionManager; +class QtTableSelectionRange; class QtTableController; class QtGraphicsHeader; @@ -73,7 +74,7 @@ public: void _q_horizontalHeaderDestroyed(); void _q_cellsChanged(int firstRow, int firstColumn, int rowCount, int columnCount, const QList<int> &roles); - void _q_selectionsChanged(int firstRow, int firstColumn, int rowCount, int columnCount); + void _q_selectionsChanged(const QList<QtTableSelectionRange> &changed); void _q_currentChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); void _q_rowsInserted(int row, int count); diff --git a/src/qlistcontroller.cpp b/src/qlistcontroller.cpp index 3327dfc..7bb8a50 100644 --- a/src/qlistcontroller.cpp +++ b/src/qlistcontroller.cpp @@ -107,21 +107,25 @@ void QtListControllerPrivate::_q_horizontalOffsetChanged(qreal offset) /*! \class QtListController - \brief provides a controller for model/view objects. + \brief provides a controller for list model and view objects. - QtListController represents a controller in model/view programming. It is - responsible for handling all user input and model changes. In other words, - QtListController accepts events and proceeds to make the requested changes - to the view, model, or selections. For example, when the user clicks on - the left mouse button, it is QtListController's responsibility to change - selection. + QtListController represents a controller in the model-view-controller (MFC) + design-pattern. - The actual widget to be used in an application is QtListWidgetNG. You can - install any QtListController object on a QtListWidgetNG. + It is used together with a sub-class of QtListModelInterface and QtGraphicsListView. + + QtListController is responsible for handling user input events and make the requested + changes to the view, model, or selections. + + For example, when the user clicks an item in the view, it is QtListController's + responsibility to change selection state of that item. + + QtListWidgetNG contains a QtListController, as well as a QtListDefaultModel + and a QtGraphicsListView. */ /*! - Constructs a new list controller with the given \a parent. + Constructs a list controller with the given \a parent. */ QtListController::QtListController(QObject *parent) : QObject(parent), d_ptr(new QtListControllerPrivate) @@ -130,6 +134,7 @@ QtListController::QtListController(QObject *parent) } /*! + \internal */ QtListController::QtListController(QtListControllerPrivate &dd, QObject *parent) : QObject(parent), d_ptr(&dd) @@ -272,6 +277,11 @@ void QtListController::setView(QtGraphicsListView *view) } /*! + Returns the scroll value of the view. + This value depends on the controller scroll mode and the + view orientation. + + \sa view() */ qreal QtListController::scrollValue() const { @@ -286,6 +296,11 @@ qreal QtListController::scrollValue() const } /*! + Sets the scroll value on the view. + The property this value is set on depends on the controller + scroll mode and the view orientation. + + \sa view() */ void QtListController::setScrollValue(qreal value) { @@ -301,6 +316,11 @@ void QtListController::setScrollValue(qreal value) } /*! + Returns the page step value of the view. + This value depends on the controller scroll mode and the + view orientation. + + \sa view() */ qreal QtListController::pageStepValue(qreal *maximumScrollValue) const { @@ -326,6 +346,11 @@ qreal QtListController::pageStepValue(qreal *maximumScrollValue) const /*! + Returns the maximum scroll value of the view. + This value depends on the controller scroll mode and the + view orientation. + + \sa view() */ qreal QtListController::maximumScrollValue() const { @@ -346,12 +371,23 @@ bool QtListController::keyPressEvent(QKeyEvent *event) Q_D(QtListController); if (d->model && d->selectionManager) { int index = d->selectionManager->currentItem(); - if (event->key() == Qt::Key_Up) { + switch (event->key()) { + case Qt::Key_Left: + case Qt::Key_Up: if (--index < 0) index = d->model->count() - 1; - } else if (event->key() == Qt::Key_Down) { + break; + case Qt::Key_Right: + case Qt::Key_Down: if (++index >= d->model->count()) index = 0; + break; + case Qt::Key_Tab: + case Qt::Key_Backtab: + case Qt::Key_Space: + // ### FIXME: implement + default: + break; } if (d->selectionManager->currentItem() != index) { if (event->modifiers() & Qt::ShiftModifier) { @@ -364,7 +400,6 @@ bool QtListController::keyPressEvent(QKeyEvent *event) } return true; } - // ### FIXME: Qt::Key_Space } return false; } @@ -505,7 +540,7 @@ bool QtListController::hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const QT } /*! -*/ + */ bool QtListController::wheelEvent(QGraphicsSceneWheelEvent *event, const QTransform &transform) { Q_UNUSED(transform); @@ -519,7 +554,7 @@ bool QtListController::wheelEvent(QGraphicsSceneWheelEvent *event, const QTransf } /*! -*/ + */ bool QtListController::resizeEvent(QGraphicsSceneResizeEvent *event, const QTransform &transform) { Q_UNUSED(event); @@ -532,8 +567,10 @@ bool QtListController::resizeEvent(QGraphicsSceneResizeEvent *event, const QTran } /*! - * This virtual function receives events to the list controller and should - * return true if the event \p event was recognized and processed. + Processes the given \a event, performing the appropriate changes to the, view + selections or model. The given \a transform is used to transform coordinates + and geometries if provided by the event. + Returns true if the event was recognized and processed, otherwise returns false. */ bool QtListController::processEvent(QEvent *event, const QTransform &transform) { diff --git a/src/qlistcontroller.h b/src/qlistcontroller.h index 6f530e6..784d89a 100644 --- a/src/qlistcontroller.h +++ b/src/qlistcontroller.h @@ -33,8 +33,8 @@ QT_BEGIN_NAMESPACE //QT_MODULE(Gui) class QEvent; -class QInputMethodEvent; class QKeyEvent; +class QInputMethodEvent; class QGraphicsSceneMouseEvent; class QGraphicsSceneDragDropEvent; class QGraphicsSceneHoverEvent; @@ -87,7 +87,6 @@ public: virtual bool hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform); virtual bool wheelEvent(QGraphicsSceneWheelEvent *event, const QTransform &transform); virtual bool resizeEvent(QGraphicsSceneResizeEvent *event, const QTransform &transform); - virtual bool processEvent(QEvent *event, const QTransform &transform); Q_SIGNALS: diff --git a/src/qlistdefaultmodel.cpp b/src/qlistdefaultmodel.cpp index b63bd63..5dc4888 100644 --- a/src/qlistdefaultmodel.cpp +++ b/src/qlistdefaultmodel.cpp @@ -165,12 +165,19 @@ void QtListDefaultModelPrivate::clear() // QtListDefaultModel /*! - \class QtListDefaultModel - \brief A list item model + \class QtListDefaultModel + \brief provides a default list item model. + + QtListDefaultModel implements QtListModelInterface so that you can get + started with a default list model, without having to do any subclassing + yourself. + + \sa QtListModelInterface */ /*! - */ + Constructs a list model with the given \a parent. +*/ QtListDefaultModel::QtListDefaultModel(QObject *parent) : QtListModelInterface(parent), d_ptr(new QtListDefaultModelPrivate) { @@ -178,7 +185,8 @@ QtListDefaultModel::QtListDefaultModel(QObject *parent) } /*! - */ + \internal +*/ QtListDefaultModel::QtListDefaultModel(QtListDefaultModelPrivate &dd, QObject *parent) : QtListModelInterface(parent), d_ptr(&dd) { @@ -186,14 +194,16 @@ QtListDefaultModel::QtListDefaultModel(QtListDefaultModelPrivate &dd, QObject *p } /*! - */ + Destroys the list model. +*/ QtListDefaultModel::~QtListDefaultModel() { delete d_ptr; } /*! - */ + Returns the index of the given \a item. +*/ int QtListDefaultModel::indexOf(const QtListDefaultItem *item) const { Q_D(const QtListDefaultModel); @@ -209,7 +219,8 @@ int QtListDefaultModel::indexOf(const QtListDefaultItem *item) const } /*! - */ + Returns the item for the given \a index. +*/ QtListDefaultItem *QtListDefaultModel::item(int index) const { Q_D(const QtListDefaultModel); @@ -219,7 +230,8 @@ QtListDefaultItem *QtListDefaultModel::item(int index) const } /*! - */ + Returns the number of items in the model. +*/ int QtListDefaultModel::count() const { Q_D(const QtListDefaultModel); @@ -227,7 +239,11 @@ int QtListDefaultModel::count() const } /*! - */ + Returns the data stored for the gievn \a index, according to the given + \a roles. + + \sa setData() +*/ QHash<int,QVariant> QtListDefaultModel::data(int index, const QList<int> &roles) const { if (const QtListDefaultItem *itm = item(index)) @@ -236,7 +252,11 @@ QHash<int,QVariant> QtListDefaultModel::data(int index, const QList<int> &roles) } /*! - */ + Sets the item at \a index to \a values. + \a values is a QHash role and data as the key-value pair. + + \sa data() +*/ bool QtListDefaultModel::setData(int index, const QHash<int,QVariant> &values) { Q_D(QtListDefaultModel); @@ -256,24 +276,32 @@ bool QtListDefaultModel::setData(int index, const QHash<int,QVariant> &values) } /*! - */ + Appends the given \a item to the model. +*/ void QtListDefaultModel::appendItem(QtListDefaultItem *item) { insertItem(count(), item); } /*! - */ + Inserts the given \a item at \a index. + + \sa removeItem() +*/ void QtListDefaultModel::insertItem(int index, QtListDefaultItem *item) { Q_D(QtListDefaultModel); + index = qBound(0, index, d->items.count()); d->insertItems(index, 1); d->items[index] = item; emit itemsInserted(index, 1); } /*! - */ + Removes the given \a item at \a index. + + \sa insertItem() +*/ void QtListDefaultModel::removeItem(int index) { Q_D(QtListDefaultModel); @@ -283,7 +311,10 @@ void QtListDefaultModel::removeItem(int index) } /*! - */ + \fn void QtListDefaultModel::moveItem(int a, int b) + + Moves the item from position \a a to \a b. +*/ void QtListDefaultModel::moveItem(int from, int to) { Q_D(QtListDefaultModel); @@ -292,7 +323,8 @@ void QtListDefaultModel::moveItem(int from, int to) } /*! - */ + Clears the model; all items will be deleted. +*/ void QtListDefaultModel::clear() { Q_D(QtListDefaultModel); @@ -302,7 +334,7 @@ void QtListDefaultModel::clear() } /*! - */ +*/ void QtListDefaultModel::itemChanged(QtListDefaultItem *item, const QList<int> &roles) { if (item) { @@ -312,7 +344,7 @@ void QtListDefaultModel::itemChanged(QtListDefaultItem *item, const QList<int> & } /*! - */ +*/ void QtListDefaultModel::itemDeleted(QtListDefaultItem *item) { Q_D(QtListDefaultModel); diff --git a/src/qlistmodelinterface.cpp b/src/qlistmodelinterface.cpp index 58cdfa9..f182478 100644 --- a/src/qlistmodelinterface.cpp +++ b/src/qlistmodelinterface.cpp @@ -24,43 +24,94 @@ #include "qlistmodelinterface.h" /*! - \class QtListModelInterface - \brief The QtListModelInterface is the interface class that data-models for - the QListViewNG implement. - - A QListViewNG is backed by two classes, a list control (QAbstractListControl) - and a model. Where the QAbstractListControl defines all the details on how to - show any sort of data, this class defines all the data that is shown in that list. - The default implementation of this interface is the QListItemModel. - - Each individual list item is addressed using an index in the form of an int. Each item - has multiple roles (QtListModelInterface::Roles) and those are requested by the control via - the data() method. -*/ + \class QtListModelInterface + \brief provides the abstract interface for list models. -/*! - \enum QtListModelInterface::Roles + \omit + A QtListWidgetNG is backed by four classes, a list controller + (QtListController) and a model. While QtListController is responsible for + handling all user input and model changes, QtListModelInterface is + responsible for displaying items on the list. + \endomit + + QtListModelInterface provides an abstract interface for list model classes. - Data roles for each of the items. + Each individual list item is referenced using an index, in the form of an + integer. Each item has multiple data roles, as specified by + Qt::DataRoles). Data can be requested using the data() method. + + \sa QtListController, QtListDefaultModel */ +/*! + */ QtListModelInterface::QtListModelInterface(QObject *parent) : QObject(parent) { } +/*! + \internal + */ QtListModelInterface::QtListModelInterface(QObjectPrivate &dd, QObject *parent) : QObject(dd, parent) { } - +/*! + */ QtListModelInterface::~QtListModelInterface() { } + + +/*! + \fn QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const + + Returns the data for a given \a index, according to the \a roles. +*/ + +/*! + \fn int count() const + + Returns the number of items in the list. +*/ + +/*! + \fn bool setData(int index, const QHash<int,QVariant> &values) + + Sets the data for the item at \a index to the given \a values. Returns true + if the data was set on the item; returns false otherwise. + + The default implementation does not set the data, and will always return + false. +*/ + +/*! + \fn void itemsInserted(int index, int count) + + This signal is emitted when \a count number of items were inserted in the + model beginning with \a index. +*/ + +/*! + \fn void itemsRemoved(int index, int count) + + This signal is emitted when \a count number of items were removed from the + model beginning with \a index. +*/ + +/*! + \fn void itemsMoved(int a, int b, int count) + + This signal is emitted when \a count number of items were moved in the + model from \a a to \a b. +*/ + /*! - \fd QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const; + \fn void itemsChanged(int index, int count, const QList<int> &roles) - return all the requested data roles for one specific index. + This signal is emitted when the data for \a roles in \a count number of + items were changed in the model beginning with \a index. */ diff --git a/src/qlistmodelinterface.h b/src/qlistmodelinterface.h index 243a934..71d5630 100644 --- a/src/qlistmodelinterface.h +++ b/src/qlistmodelinterface.h @@ -40,12 +40,6 @@ public: QtListModelInterface(QObject *parent = 0); virtual ~QtListModelInterface(); - enum Roles { - // ### move these into the Qt namespace - unless we remove the roles - TextRole = Qt::DisplayRole, - IconRole = Qt::DecorationRole - }; - virtual int count() const = 0; virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const = 0; virtual bool setData(int index, const QHash<int,QVariant> &values) { Q_UNUSED(index); Q_UNUSED(values); return false; } diff --git a/src/qlistselectionmanager.cpp b/src/qlistselectionmanager.cpp index cf3f97c..57226f8 100644 --- a/src/qlistselectionmanager.cpp +++ b/src/qlistselectionmanager.cpp @@ -318,8 +318,8 @@ void QtListSelectionManagerPrivate::_q_reset() const int count = model ? model->count() : 0; selections.resize(count); selections.fill(false); - current = model ? qBound(0, current, count - 1) : -1; - anchor = model ? qBound(0, anchor, count - 1) : -1; + current = count ? qBound(0, current, count - 1) : -1; + anchor = count ? qBound(0, anchor, count - 1) : -1; } /*! @@ -470,11 +470,11 @@ bool QtListSelectionManager::isSelected(int index) const /*! Sets the selected state of the items in the range indicated by the given \a index and \a count to be either true or false, depending on the given - \a selected value. + \a mode. \sa isSelected() */ -void QtListSelectionManager::setSelected(int index, bool selected, int count) +void QtListSelectionManager::setSelected(int index, int count, SelectionMode mode) { Q_D(QtListSelectionManager); if (index < 0) { @@ -484,12 +484,23 @@ void QtListSelectionManager::setSelected(int index, bool selected, int count) } if (count <= 0 || index >= d->selections.count()) return; - const int begin = index; + const int from = index; count = qMin(count, d->selections.count()); // this helps the usecase where count passed is INT_MAX - const int end = qMin(index + count, d->selections.count()); + const int to = qMin(index + count, d->selections.count()); // set selection const QBitArray old = d->selections; - d->selections.fill(selected, begin, end); + switch (mode) { + case Select: + d->selections.fill(true, from, to); + break; + case Deselect: + d->selections.fill(false, from, to); + break; + case Toggle: + for (int i = from; i <= to; ++i) + d->selections.toggleBit(i); + break; + } d->change.d->setSelections(old, d->selections); emit selectionsChanged(d->change); d->change.d->clear(); // avoid selections detach later @@ -545,12 +556,18 @@ void QtListSelectionManager::endAnchoredSelection() // commit anchored selection range if (d->current >= 0 && d->anchor >= 0) { const int from = qMin(d->anchor, d->current); - const int to = qMax(d->anchor, d->current); - if (d->mode == Toggle) { + const int to = qMax(d->anchor, d->current) + 1; + switch (d->mode) { + case Select: + d->selections.fill(true, from, to); + break; + case Deselect: + d->selections.fill(false, from, to); + break; + case Toggle: for (int i = from; i <= to; ++i) d->selections.toggleBit(i); - } else { - d->selections.fill(true, from, to + 1); + break; } } d->active = false; diff --git a/src/qlistselectionmanager.h b/src/qlistselectionmanager.h index 20fe985..6cd1e03 100644 --- a/src/qlistselectionmanager.h +++ b/src/qlistselectionmanager.h @@ -52,6 +52,8 @@ private: QSharedDataPointer<QtListSelectionChangeData> d; }; +Q_DECLARE_TYPEINFO(QtListSelectionChange, Q_MOVABLE_TYPE); + class Q_ITEMVIEWSNG_EXPORT QtListSelectionManager : public QObject { Q_OBJECT @@ -59,11 +61,12 @@ class Q_ITEMVIEWSNG_EXPORT QtListSelectionManager : public QObject public: enum SelectionMode { Select, + Deselect, Toggle }; QtListSelectionManager(QObject *parent = 0); - virtual ~QtListSelectionManager(); + ~QtListSelectionManager(); QtListModelInterface *model() const; @@ -79,7 +82,7 @@ public: public Q_SLOTS: void setCurrentItem(int current); void setAnchorItem(int anchor); - void setSelected(int index, bool selected = true, int count = 1); + void setSelected(int index, int count = 1, SelectionMode mode = Select); void clearSelections(); Q_SIGNALS: diff --git a/src/qtablecontroller.cpp b/src/qtablecontroller.cpp index c150ca0..4da536e 100644 --- a/src/qtablecontroller.cpp +++ b/src/qtablecontroller.cpp @@ -109,69 +109,73 @@ void QtTableControllerPrivate::_q_horizontalHeaderDestroyed() void QtTableControllerPrivate::_q_rowPressed(int row, Qt::KeyboardModifiers modifiers) { if (model && selectionManager) { - bool shift = modifiers & Qt::ShiftModifier; - bool ctrl = modifiers & Qt::ControlModifier; - if (!shift && !ctrl) + if (modifiers & Qt::ControlModifier) { + selectionManager->beginAnchoredSelection(row, 0, QtTableSelectionManager::Toggle); + selectionManager->setCurrentCell(row, model->columnCount() - 1); + } else if (modifiers & Qt::ShiftModifier) { selectionManager->clearSelections(); - selectionManager->setAnchorCell(row, 0); - selectionManager->setCurrentCell(row, model->columnCount() - 1); - selectionManager->setToggleCurrentAnchor(ctrl); + selectionManager->beginAnchoredSelection(selectionManager->anchorRow(), 0); + selectionManager->setCurrentCell(row, model->columnCount() - 1); + } else { // no modifiers + selectionManager->clearSelections(); + selectionManager->beginAnchoredSelection(row, 0); + selectionManager->setCurrentCell(row, model->columnCount() - 1); + } } } void QtTableControllerPrivate::_q_rowReleased(int row, Qt::KeyboardModifiers modifiers) { - Q_UNUSED(row); - if (model && selectionManager) { - if (modifiers & Qt::ControlModifier) - selectionManager->toggleSelection(selectionManager->currentAnchorRange()); - else - selectionManager->setSelected(selectionManager->currentAnchorRange()); - selectionManager->setToggleCurrentAnchor(false); - selectionManager->clearAnchorCell(); + Q_UNUSED(modifiers); + if (selectionManager) { + if (selectionManager->currentRow() != row) + selectionManager->setCurrentCell(row, selectionManager->currentColumn()); + selectionManager->endAnchoredSelection(); + //emit rowClicked(row, Qt::LeftButton); } } void QtTableControllerPrivate::_q_rowDragSelected(int row, Qt::KeyboardModifiers modifiers) { - if (model && selectionManager) { - selectionManager->setToggleCurrentAnchor(modifiers & Qt::ControlModifier); - selectionManager->setCurrentCell(row, model->columnCount() - 1); - } + Q_UNUSED(modifiers); + if (selectionManager && selectionManager->currentRow() != row) + selectionManager->setCurrentCell(row, selectionManager->currentColumn()); } void QtTableControllerPrivate::_q_columnPressed(int column, Qt::KeyboardModifiers modifiers) { if (model && selectionManager) { - bool shift = modifiers & Qt::ShiftModifier; - bool ctrl = modifiers & Qt::ControlModifier; - if (!shift && !ctrl) + if (modifiers & Qt::ControlModifier) { + selectionManager->beginAnchoredSelection(0, column, QtTableSelectionManager::Toggle); + selectionManager->setCurrentCell(model->rowCount() - 1, column); + } else if (modifiers & Qt::ShiftModifier) { selectionManager->clearSelections(); - selectionManager->setAnchorCell(0, column); - selectionManager->setCurrentCell(model->rowCount() - 1, column); - selectionManager->setToggleCurrentAnchor(ctrl); + selectionManager->beginAnchoredSelection(0, selectionManager->anchorColumn()); + selectionManager->setCurrentCell(model->rowCount() - 1, column); + } else { // no modifiers + selectionManager->clearSelections(); + selectionManager->beginAnchoredSelection(0, column); + selectionManager->setCurrentCell(model->rowCount() - 1, column); + } } } void QtTableControllerPrivate::_q_columnReleased(int column, Qt::KeyboardModifiers modifiers) { - Q_UNUSED(column); - if (model && selectionManager) { - if (modifiers & Qt::ControlModifier) - selectionManager->toggleSelection(selectionManager->currentAnchorRange()); - else - selectionManager->setSelected(selectionManager->currentAnchorRange()); - selectionManager->setToggleCurrentAnchor(false); - selectionManager->clearAnchorCell(); + Q_UNUSED(modifiers); + if (selectionManager) { + if (selectionManager->currentColumn() != column) + selectionManager->setCurrentCell(selectionManager->currentRow(), column); + selectionManager->endAnchoredSelection(); + //emit columnClicked(column, Qt::LeftButton); } } void QtTableControllerPrivate::_q_columnDragSelected(int column, Qt::KeyboardModifiers modifiers) { - if (model && selectionManager) { - selectionManager->setToggleCurrentAnchor(modifiers & Qt::ControlModifier); - selectionManager->setCurrentCell(model->rowCount() - 1, column); - } + Q_UNUSED(modifiers); + if (selectionManager && selectionManager->currentColumn() != column) + selectionManager->setCurrentCell(selectionManager->currentRow(), column); } void QtTableControllerPrivate::_q_firstRowChanged(int row) @@ -216,45 +220,41 @@ void QtTableControllerPrivate::_q_setVerticalHeader(QtGraphicsHeader* header) bool QtTableControllerPrivate::keyPressEvent(QKeyEvent *event) { - if (selectionManager && model) { + if (model && selectionManager) { int row = selectionManager->currentRow(); int column = selectionManager->currentColumn(); - bool shift = event->modifiers() & Qt::ShiftModifier; - bool ctrl = event->modifiers() & Qt::ControlModifier; - if (!shift && !ctrl) - selectionManager->clearSelections(); - selectionManager->setToggleCurrentAnchor(ctrl); switch (event->key()) { case Qt::Key_Left: column = qBound(0, column - 1, model->columnCount() - 1); - selectionManager->setCurrentCell(row, column); - if (!shift && !ctrl) - selectionManager->setAnchorCell(row, column); - return true; + break; case Qt::Key_Right: column = qBound(0, column + 1, model->columnCount() - 1); - selectionManager->setCurrentCell(row, column); - if (!shift && !ctrl) - selectionManager->setAnchorCell(row, column); - return true; + break; case Qt::Key_Up: row = qBound(0, row - 1, model->rowCount() - 1); - selectionManager->setCurrentCell(row, column); - if (!shift && !ctrl) - selectionManager->setAnchorCell(row, column); - return true; + break; case Qt::Key_Down: row = qBound(0, row + 1, model->rowCount() - 1); - selectionManager->setCurrentCell(row, column); - if (!shift && !ctrl) - selectionManager->setAnchorCell(row, column); - return true; + break; case Qt::Key_Tab: case Qt::Key_Backtab: - // ### implement + case Qt::Key_Space: + // ### FIXME: implement default: break; } + if (selectionManager->currentRow() != row || selectionManager->currentColumn() != column) { + if (event->modifiers() & Qt::ShiftModifier) { + selectionManager->beginAnchoredSelection(selectionManager->anchorRow(), selectionManager->anchorColumn()); + selectionManager->setCurrentCell(row, column); + } else { + selectionManager->endAnchoredSelection(); + selectionManager->clearSelections(); + selectionManager->setCurrentCell(row, column); + } + return true; + } + } return false; } @@ -267,20 +267,23 @@ bool QtTableControllerPrivate::inputMethodEvent(QInputMethodEvent *event) bool QtTableControllerPrivate::mousePressEvent(QMouseEvent *event, const QTransform &transform) { - const QPointF pos = transform.map(event->pos()); - // handle event if (sendMouseEditorEvent(event, transform)) return true; if (view && selectionManager && event->buttons() & Qt::LeftButton) { int row = view->rowAt(event->pos(), transform); int column = view->columnAt(event->pos(), transform); - bool shift = event->modifiers() & Qt::ShiftModifier; - bool ctrl = event->modifiers() & Qt::ControlModifier; - if (!shift && !ctrl) + if (event->modifiers() & Qt::ControlModifier) { + selectionManager->beginAnchoredSelection(row, column, QtTableSelectionManager::Toggle); + selectionManager->setCurrentCell(row, column); + } else if (event->modifiers() & Qt::ShiftModifier) { selectionManager->clearSelections(); - selectionManager->setCurrentCell(row, column); - selectionManager->setAnchorCell(row, column); - selectionManager->setToggleCurrentAnchor(ctrl); + selectionManager->beginAnchoredSelection(selectionManager->anchorRow(), selectionManager->anchorColumn()); + selectionManager->setCurrentCell(row, column); + } else { // no modifiers + selectionManager->clearSelections(); + selectionManager->beginAnchoredSelection(row, column); + selectionManager->setCurrentCell(row, column); + } return true; } return false; @@ -288,16 +291,16 @@ bool QtTableControllerPrivate::mousePressEvent(QMouseEvent *event, const QTransf bool QtTableControllerPrivate::mouseMoveEvent(QMouseEvent *event, const QTransform &transform) { - const QPointF pos = transform.map(event->pos()); - // handle event + //Q_Q(QtTableController); if (sendMouseEditorEvent(event, transform)) return true; if (view && selectionManager && event->buttons() & Qt::LeftButton) { - int row = view->rowAt(event->pos(), transform); - int column = view->columnAt(event->pos(), transform); - bool ctrl = event->modifiers() & Qt::ControlModifier; - selectionManager->setCurrentCell(row, column); - selectionManager->setToggleCurrentAnchor(ctrl); + const int row = view->rowAt(event->pos(), transform); + const int column = view->columnAt(event->pos(), transform); + if (selectionManager->currentRow() != row || selectionManager->currentColumn() != column) { + selectionManager->setCurrentCell(row, column); + return true; + } return true; } return false; @@ -305,17 +308,16 @@ bool QtTableControllerPrivate::mouseMoveEvent(QMouseEvent *event, const QTransfo bool QtTableControllerPrivate::mouseReleaseEvent(QMouseEvent *event, const QTransform &transform) { - const QPointF pos = transform.map(event->pos()); - // handle event + Q_Q(QtTableController); if (sendMouseEditorEvent(event, transform)) return true; - if (selectionManager && event->button() & Qt::LeftButton) { - if (event->modifiers() & Qt::ControlModifier) - selectionManager->toggleSelection(selectionManager->currentAnchorRange()); - else - selectionManager->setSelected(selectionManager->currentAnchorRange()); - selectionManager->setToggleCurrentAnchor(false); - selectionManager->clearAnchorCell(); + if (selectionManager && view && event->button() == Qt::LeftButton) { + const int row = view->rowAt(event->pos(), transform); + const int column = view->columnAt(event->pos(), transform); + if (selectionManager->currentRow() != row || selectionManager->currentColumn() != column) + selectionManager->setCurrentCell(row, column); + selectionManager->endAnchoredSelection(); + emit q->cellClicked(row, column, Qt::LeftButton); return true; } return false; @@ -323,7 +325,6 @@ bool QtTableControllerPrivate::mouseReleaseEvent(QMouseEvent *event, const QTran bool QtTableControllerPrivate::mouseDoubleClickEvent(QMouseEvent *event, const QTransform &transform) { - const QPointF pos = transform.map(event->pos()); if (sendMouseEditorEvent(event, transform)) return true; return false; @@ -483,8 +484,22 @@ bool QtTableControllerPrivate::sendMouseEditorEvent(QMouseEvent *event, const QT // QtTableController /*! - \class QtTableController - \brief A table control + \class QtTableController + \brief provides a controller for table model and view objects. + + QtTableController represents a controller in the model-view-controller (MFC) + design-pattern. + + It is used together with a sub-class of QtTableModelInterface and QtGraphicsTableView. + + QtTableController is responsible for handling user input events and make the requested + changes to the view, model, or selections. + + For example, when the user clicks a cell in the view, it is QtTableController's + responsibility to change selection state of that cell. + + QtTableWidgetNG contains a QtTableController, as well as a QtTableDefaultModel + and a QtGraphicsTableView. */ /*! diff --git a/src/qtableselectionmanager.cpp b/src/qtableselectionmanager.cpp index b93ad59..2ef58db 100644 --- a/src/qtableselectionmanager.cpp +++ b/src/qtableselectionmanager.cpp @@ -168,7 +168,7 @@ QtTableSelectionRange::~QtTableSelectionRange() */ bool QtTableSelectionRange::intersects(const QtTableSelectionRange &other) const { - // ### not be the most efficient intersection test + // ### may not be the most efficient intersection test if (QtTableSelectionRangePrivate::containedBy(*this, other)) return true; if (QtTableSelectionRangePrivate::contains(*this, other)) @@ -206,7 +206,7 @@ bool QtTableSelectionRange::intersects(const QtTableSelectionRange &other) const /*! */ -QList<QtTableSelectionRange> QtTableSelectionRange::subtract(const QtTableSelectionRange &other) const +QList<QtTableSelectionRange> QtTableSelectionRange::subtracted(const QtTableSelectionRange &other) const { if (QtTableSelectionRangePrivate::containedBy(*this, other)) return QList<QtTableSelectionRange>(); // nothing left @@ -305,16 +305,30 @@ QList<QtTableSelectionRange> QtTableSelectionRange::subtract(const QtTableSelect return QList<QtTableSelectionRange>(); } +/*! + */ bool QtTableSelectionRange::operator==(const QtTableSelectionRange &other) const { return other.top == top && other.left == left && other.bottom == bottom && other.right == right; } +/*! + */ bool QtTableSelectionRange::operator!=(const QtTableSelectionRange &other) const { return !operator==(other); } +/*! + */ +void QtTableSelectionRange::setRange(int topRow, int leftColumn, int bottomRow, int rightColumn) +{ + top = topRow; + left = leftColumn; + bottom = bottomRow; + right = rightColumn; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QtTableSelectionRange &range) { @@ -339,7 +353,8 @@ QtTableSelectionManagerPrivate::QtTableSelectionManagerPrivate() : q_ptr(0), model(0), currentRow(-1), currentColumn(-1), anchorRow(-1), anchorColumn(-1), - toggleCurrentAnchor(false) + active(false), + mode(QtTableSelectionManager::Select) { } @@ -355,255 +370,289 @@ void QtTableSelectionManagerPrivate::_q_modelDestroyed() void QtTableSelectionManagerPrivate::_q_rowsInserted(int row, int count) { Q_Q(QtTableSelectionManager); - // move the selection that is below it 'count' rows down. - QList<QtTableSelectionRange> newSelections; - int x1 = INT_MAX, y1 = INT_MAX, x2 = -1, y2 = -1; - foreach (const QtTableSelectionRange &range, selections) { - int top = range.topRow(); - int bottom = range.bottomRow(); - int left = range.leftColumn(); - int right = range.rightColumn(); - if (top < row && bottom >= row) { // range contains our insertion point, make bigger - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - bottom += count; - y2 = qMin(y2, bottom); - } else if (top >= row) { // range will be moved - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - top += count; - bottom += count; - y2 = qMin(y2, top); - } else { - newSelections << range; // cheap version. No change. - continue; + // update selections + QList<QtTableSelectionRange> changed; + QList<QtTableSelectionRange>::iterator it = selections.begin(); + for (;it != selections.end(); ++it) { + if (row < (*it).topRow()) { // move selection range + (*it).setRange((*it).topRow() + count, (*it).leftColumn(), (*it).bottomRow() + count, (*it).rightColumn()); + changed.append(*it); + } else if (row <= (*it).bottomRow()) { // increase selection range + (*it).setRange((*it).topRow(), (*it).leftColumn(), (*it).bottomRow() + count, (*it).rightColumn()); + changed.append(*it); } - newSelections << QtTableSelectionRange(top, left, bottom, right); } - selections = newSelections; - - int prevCurRow = currentRow; - if (currentRow > row) { - currentRow+= count; - emit q->currentChanged(currentRow, currentColumn, prevCurRow, currentColumn); + // update current + const int previousCurrentRow = currentRow; + if (row <= currentRow) { + currentRow += count; + emit q->currentChanged(currentRow, currentColumn, previousCurrentRow, currentColumn); } - if (anchorRow >= row) - anchorRow+= count; - - if (y1 != INT_MAX && x1 != INT_MAX && x2 != -1 && x2 != -1) - emit q->selectionsChanged(y1, x1, y2, x2); + // update anchor + const int previousAnchorRow = anchorRow; + if (row <= anchorRow) { + anchorRow += count; + emit q->anchorChanged(anchorRow, anchorColumn, previousAnchorRow, anchorColumn); + } + // update selections + if (active && (anchorRow != previousAnchorRow || currentRow != previousCurrentRow)) { + currentAnchorRange.setRange(qMin(anchorRow, currentRow), qMin(anchorColumn, currentColumn), + qMax(anchorRow, currentRow), qMax(anchorColumn, currentColumn)); + changed.append(currentAnchorRange); + } + if (!changed.isEmpty()) + emit q->selectionsChanged(changed); } void QtTableSelectionManagerPrivate::_q_rowsRemoved(int row, int count) { Q_Q(QtTableSelectionManager); - // move or shrink the selection that is below it 'count' rows up. - QList<QtTableSelectionRange> newSelections; - int x1 = INT_MAX, y1 = INT_MAX, x2 = -1, y2 = -1; - foreach (const QtTableSelectionRange &range, selections) { - int top = range.topRow(); - int bottom = range.bottomRow(); - int left = range.leftColumn(); - int right = range.rightColumn(); - if (top < row && bottom >= row) { // range contains our insertion point, make smaller - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - bottom -= count; - y2 = qMin(y2, bottom); - } else if (top >= row) { // range will be moved - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - top -= count; - bottom -= count; - y2 = qMin(y2, top); - } else { - newSelections << range; // cheap version. No change. - continue; + // update selections + QList<QtTableSelectionRange> changed; + QList<QtTableSelectionRange>::iterator it = selections.begin(); + while (it != selections.end()) { + if (row < (*it).topRow()) { // move selection range + changed.append(*it); + (*it).setRange((*it).topRow() - count, (*it).leftColumn(), (*it).bottomRow() - count, (*it).rightColumn()); + } else if (row <= (*it).bottomRow()) { + changed.append(*it); + if (count < ((*it).bottomRow() - (*it).topRow() + 1)) { // reduce the selection range + (*it).setRange((*it).topRow(), (*it).leftColumn(), (*it).bottomRow() - count, (*it).rightColumn()); + } else { // remove the selection range + it = selections.erase(it); + continue; + } } - if (bottom >= top) // it didn't shrink to non existence - newSelections << QtTableSelectionRange(top, left, bottom, right); + ++it; } - selections = newSelections; - - int prevCurRow = currentRow; - if (currentRow > row - count + 1) { + // update current + const int previousCurrentRow = currentRow; + if (row < currentRow) { currentRow -= count; - emit q->currentChanged(currentRow, currentColumn, prevCurRow, currentColumn); + emit q->currentChanged(currentRow, currentColumn, previousCurrentRow, currentColumn); } - if (anchorRow >= row - count) + // update anchor + const int previousAnchorRow = anchorRow; + if (row < anchorRow) { anchorRow -= count; - - if (y1 != INT_MAX && x1 != INT_MAX && x2 != -1 && x2 != -1) - emit q->selectionsChanged(y1, x1, y2, x2); + emit q->anchorChanged(anchorRow, anchorColumn, previousAnchorRow, anchorColumn); + } + // update selections + if (active && (anchorRow != previousAnchorRow || currentRow != previousCurrentRow)) { + currentAnchorRange.setRange(qMin(anchorRow, currentRow), qMin(anchorColumn, currentColumn), + qMax(anchorRow, currentRow), qMax(anchorColumn, currentColumn)); + changed.append(currentAnchorRange); + } + if (!changed.isEmpty()) + emit q->selectionsChanged(changed); } void QtTableSelectionManagerPrivate::_q_columnsInserted(int column, int count) { Q_Q(QtTableSelectionManager); - // move the selection that is below it 'count' rows down. - QList<QtTableSelectionRange> newSelections; - int x1 = INT_MAX, y1 = INT_MAX, x2 = -1, y2 = -1; - foreach (const QtTableSelectionRange &range, selections) { - int top = range.topRow(); - int bottom = range.bottomRow(); - int left = range.leftColumn(); - int right = range.rightColumn(); - if (left < column && right >= column) { // range contains our insertion point, make bigger - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - right += count; - y2 = qMin(y2, bottom); - } else if (top >= column) { // range will be moved - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - top += count; - right += count; - y2 = qMin(y2, top); - } else { - newSelections << range; // cheap version. No change. - continue; + // update selections + QList<QtTableSelectionRange> changed; + QList<QtTableSelectionRange>::iterator it = selections.begin(); + for (;it != selections.end(); ++it) { // move selection range + if (column < (*it).leftColumn()) { + (*it).setRange((*it).topRow(), (*it).leftColumn() + count, (*it).bottomRow(), (*it).rightColumn() + count); + changed.append(*it); + } else if (column <= (*it).rightColumn()) { // increase selection range + (*it).setRange((*it).topRow(), (*it).leftColumn(), (*it).bottomRow(), (*it).rightColumn() + count); + changed.append(*it); } - newSelections << QtTableSelectionRange(top, left, bottom, right); } - selections = newSelections; - - int prevCurCol = currentColumn; - if (currentColumn > column) { + // update current + const int previousCurrentColumn = currentColumn; + if (column <= currentColumn) { currentColumn += count; - emit q->currentChanged(currentRow, currentColumn, currentRow, prevCurCol); + emit q->currentChanged(currentRow, currentColumn, currentRow, previousCurrentColumn); } - if (anchorColumn >= column) + // update anchor + const int previousAnchorColumn = anchorColumn; + if (column <= anchorColumn) { anchorColumn += count; - - if (y1 != INT_MAX && x1 != INT_MAX && x2 != -1 && x2 != -1) - emit q->selectionsChanged(y1, x1, y2, x2); + emit q->anchorChanged(anchorRow, anchorColumn, anchorRow, previousAnchorColumn); + } + // update selections + if (active && (anchorColumn != previousAnchorColumn || currentColumn != previousCurrentColumn)) { + currentAnchorRange.setRange(qMin(anchorRow, currentRow), qMin(anchorColumn, currentColumn), + qMax(anchorRow, currentRow), qMax(anchorColumn, currentColumn)); + changed.append(currentAnchorRange); + } + if (!changed.isEmpty()) + emit q->selectionsChanged(changed); } void QtTableSelectionManagerPrivate::_q_columnsRemoved(int column, int count) { Q_Q(QtTableSelectionManager); - // move or shrink the selection that is below it 'count' rows up. - QList<QtTableSelectionRange> newSelections; - int x1 = INT_MAX, y1 = INT_MAX, x2 = -1, y2 = -1; - foreach (const QtTableSelectionRange &range, selections) { - int top = range.topRow(); - int bottom = range.bottomRow(); - int left = range.leftColumn(); - int right = range.rightColumn(); - if (left < column && right >= column) { // range contains our insertion point, make smaller - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - right -= count; - y2 = qMin(y2, bottom); - } else if (left >= column) { // range will be moved - x1 = qMin(left, x1); - x2 = qMax(right, x2); - y1 = qMin(y1, bottom); - left -= count; - right -= count; - y2 = qMin(y2, top); - } else { - newSelections << range; // cheap version. No change. - continue; + // update selections + QList<QtTableSelectionRange> changed; + QList<QtTableSelectionRange>::iterator it = selections.begin(); + while (it != selections.end()) { + if (column < (*it).leftColumn()) { // move selection range + changed.append(*it); + (*it).setRange((*it).topRow(), (*it).leftColumn() - count, (*it).bottomRow(), (*it).rightColumn() - count); + } else if (column <= (*it).rightColumn()) { + changed.append(*it); + if (count < ((*it).rightColumn() - (*it).leftColumn() + 1)) { // reduce the selection range + (*it).setRange((*it).topRow(), (*it).leftColumn(), (*it).bottomRow(), (*it).rightColumn() - count); + } else { // remove the selection range + it = selections.erase(it); + continue; + } } - if (right >= left) // it didn't shrink to non existence - newSelections << QtTableSelectionRange(top, left, bottom, right); + ++it; } - selections = newSelections; - - int prevCurCol = currentColumn; - if (currentColumn > column - count + 1) { + // update current + const int previousCurrentColumn = currentColumn; + if (column < currentColumn) { currentColumn -= count; - emit q->currentChanged(currentRow, currentColumn, currentRow, prevCurCol); + emit q->currentChanged(currentRow, currentColumn, currentRow, previousCurrentColumn); } - if (anchorColumn >= column - count) + // update anchor + const int previousAnchorColumn = anchorColumn; + if (column < anchorColumn) { anchorColumn -= count; - - if (y1 != INT_MAX && x1 != INT_MAX && x2 != -1 && x2 != -1) - emit q->selectionsChanged(y1, x1, y2, x2); + emit q->anchorChanged(anchorRow, anchorColumn, anchorRow, previousAnchorColumn); + } + // update selections + if (active && (anchorColumn != previousAnchorColumn || currentColumn != previousCurrentColumn)) { + currentAnchorRange.setRange(qMin(anchorRow, currentRow), qMin(anchorColumn, currentColumn), + qMax(anchorRow, currentRow), qMax(anchorColumn, currentColumn)); + changed.append(currentAnchorRange); + } + if (!changed.isEmpty()) + emit q->selectionsChanged(changed); } void QtTableSelectionManagerPrivate::_q_reset() { + const int rowCount = model ? model->rowCount() : 0; + const int columnCount = model ? model->columnCount() : 0; + currentRow = rowCount ? qBound(0, currentRow, rowCount - 1) : -1; + currentColumn = columnCount ? qBound(0, currentColumn, columnCount - 1) : -1; + anchorRow = rowCount ? qBound(0, anchorRow, rowCount - 1) : -1; + anchorColumn = columnCount ? qBound(0, anchorColumn, columnCount - 1) : -1; } bool QtTableSelectionManagerPrivate::isRowIntersected(int row) const { - bool selected = true; - if (currentAnchorRange.intersectsRow(row)) { - if (toggleCurrentAnchor) - selected = false; - else + bool toggle = false; + if (active && currentAnchorRange.intersectsRow(row)) { + switch (mode) { + case QtTableSelectionManager::Select: return true; + case QtTableSelectionManager::Deselect: + return false; + case QtTableSelectionManager::Toggle: + toggle = true; + default: + break; + } } for (int i = 0; i < selections.count(); ++i) if (selections.at(i).intersectsRow(row)) - return selected; - return !selected; + return !toggle; + return toggle; } bool QtTableSelectionManagerPrivate::isColumnIntersected(int column) const { - bool selected = true; - if (currentAnchorRange.intersectsColumn(column)) { - if (toggleCurrentAnchor) - selected = false; - else + bool toggle = false; + if (active && currentAnchorRange.intersectsColumn(column)) { + switch (mode) { + case QtTableSelectionManager::Select: return true; + case QtTableSelectionManager::Deselect: + return false; + case QtTableSelectionManager::Toggle: + toggle = true; + default: + break; + } } for (int i = 0; i < selections.count(); ++i) if (selections.at(i).intersectsColumn(column)) - return selected; - return !selected; + return !toggle; + return toggle; } bool QtTableSelectionManagerPrivate::isSelected(int row, int column) const { - bool selected = true; - if (currentAnchorRange.containsCell(row, column)) { - if (toggleCurrentAnchor) - selected = false; - else + bool toggle = false; + if (active && currentAnchorRange.containsCell(row, column)) { + switch (mode) { + case QtTableSelectionManager::Select: return true; + case QtTableSelectionManager::Deselect: + return false; + case QtTableSelectionManager::Toggle: + toggle = true; + default: + break; + } } for (int i = 0; i < selections.count(); ++i) if (selections.at(i).containsCell(row, column)) - return selected; - return !selected; + return !toggle; + return toggle; +} + +void QtTableSelectionManagerPrivate::selectRange(const QtTableSelectionRange &range) +{ + //changed.append(range); + selections.append(range); } -void QtTableSelectionManagerPrivate::updateCurrentAnchorRange() +void QtTableSelectionManagerPrivate::deselectRange(const QtTableSelectionRange &range) { - QtTableSelectionRange oldRange = currentAnchorRange; - int top = qMin<int>(anchorRow, currentRow); - int left = qMin<int>(anchorColumn, currentColumn); - int bottom = qMax<int>(anchorRow, currentRow); - int right = qMax<int>(anchorColumn, currentColumn); - currentAnchorRange = QtTableSelectionRange(top, left, bottom, right); + //QList<QtTableSelectionRange> changedRanges; + QList<QtTableSelectionRange> subtractedRanges; + QList<QtTableSelectionRange>::iterator it = selections.begin(); + while (it != selections.end()) { + if (range.intersects(*it)) { + //changedRanges.append(*it); + subtractedRanges += (*it).subtracted(range); + it = selections.erase(it); + continue; + } + ++it; + } + selections += subtractedRanges; + //return changedRanges; +} - if (oldRange.topRow() != -1 && oldRange.bottomRow() != -1 && oldRange.leftColumn() != -1 - && oldRange.rightColumn() != -1 && currentAnchorRange != oldRange) { - Q_Q(QtTableSelectionManager); - const int x1 = qMin(currentAnchorRange.leftColumn(), oldRange.leftColumn()); - const int x2 = qMax(currentAnchorRange.rightColumn(), oldRange.rightColumn()); - const int y1 = qMin(currentAnchorRange.topRow(), oldRange.topRow()); - const int y2 = qMax(currentAnchorRange.bottomRow(), oldRange.bottomRow()); - if (top != oldRange.topRow()) // some are at the top needs updating - emit q->selectionsChanged(y1, x1, qMax(top, oldRange.topRow())-1, x2); - if (bottom != oldRange.bottomRow()) // some cells on the bottom need updating. - emit q->selectionsChanged(qMin(bottom, oldRange.bottomRow())+1, x1, y2, x2); - if (left != oldRange.leftColumn()) - emit q->selectionsChanged(y1, x1, y2, qMax(left, oldRange.leftColumn())-1); // left side changed - if (right != oldRange.rightColumn()) - emit q->selectionsChanged(y1, qMin(right, oldRange.rightColumn())+1, y2, x2); // right side changed +void QtTableSelectionManagerPrivate::toggleRange(const QtTableSelectionRange &range) +{ + //QList<QtTableSelectionRange> changedRanges; + QList<QtTableSelectionRange> toggleRanges; + QList<QtTableSelectionRange> selectRanges; + toggleRanges.append(range); + for (int i = 0; i < selections.count(); ++i) { + const QtTableSelectionRange &selection = selections.at(i); + bool intersected = false; + // check for intersections with the toggle ranges + for (int j = 0; j < toggleRanges.count(); ++j) { + const QtTableSelectionRange &toggle = toggleRanges.at(j); + // if we have an intersecting range, remove the intersecting area + // then go on to check the remaining areas for intersections + if (selection.intersects(toggle)) { + selectRanges += selection.subtracted(toggle); + toggleRanges += toggle.subtracted(selection); + toggleRanges.removeAt(j--); + intersected = true; + } + } + // if the range was intersected, the remaining areas will + // be added to the selections; the old range is removed + if (intersected) + selections.removeAt(i--); } + // do the actual selection + selections += toggleRanges; + selections += selectRanges; } // QtTableSelectionManager @@ -637,6 +686,7 @@ QtTableSelectionManager::~QtTableSelectionManager() } /*! + Sets the model to be the given \a model. */ void QtTableSelectionManager::setModel(QtTableModelInterface *model) { @@ -658,10 +708,12 @@ void QtTableSelectionManager::setModel(QtTableModelInterface *model) connect(d->model, SIGNAL(columnsInserted(int,int)), this, SLOT(_q_columnsInserted(int,int))); connect(d->model, SIGNAL(columnsRemoved(int,int)), this, SLOT(_q_columnsRemoved(int,int))); } + d->_q_reset(); clearSelections(); } /*! + Returns a pointer to the model or null if no model is set. */ QtTableModelInterface *QtTableSelectionManager::model() const { @@ -670,37 +722,32 @@ QtTableModelInterface *QtTableSelectionManager::model() const } /*! - */ -void QtTableSelectionManager::setCurrentCell(int row, int column) -{ - Q_D(QtTableSelectionManager); - if (d->model) { - row = qBound(0, row, d->model->rowCount()-1); - column = qBound(0, column, d->model->columnCount()-1); - } - if (d->currentRow == row && d->currentColumn == column) - return; - int previousRow = d->currentRow; - int previousColumn = d->currentColumn; - d->currentRow = row; - d->currentColumn = column; + Sets the current cell to the given \a row and \a column. - d->updateCurrentAnchorRange(); - emit currentChanged(row, column, previousRow, previousColumn); -} - -/*! + \sa currentCell(), anchorCell() */ -void QtTableSelectionManager::clearCurrentCell() +void QtTableSelectionManager::setCurrentCell(int row, int column) { Q_D(QtTableSelectionManager); - if (d->currentRow == -1 && d->currentColumn == -1) + if (!d->model || !d->model->rowCount() || !d->model->columnCount()) return; - const int prevRow = d->currentRow; - const int prevCol = d->currentColumn; - d->currentRow = -1; - d->currentColumn = -1; - emit currentChanged(-1, -1, prevRow, prevCol); + row = qBound(0, row, d->model->rowCount() - 1); + column = qBound(0, column, d->model->columnCount() - 1); + if (d->currentRow != row || d->currentColumn != column) { + const int previousRow = d->currentRow; + const int previousColumn = d->currentColumn; + d->currentRow = row; + d->currentColumn = column; + emit currentChanged(row, column, previousRow, previousColumn); + d->currentAnchorRange.setRange(qMin(d->currentRow, d->anchorRow), + qMin(d->currentColumn, d->anchorColumn), + qMax(d->currentRow, d->anchorRow), + qMax(d->currentColumn, d->anchorColumn)); + // ### FIXME: check the mode + QList<QtTableSelectionRange> changed; + changed.append(d->currentAnchorRange); + emit selectionsChanged(changed); + } } /*! @@ -721,28 +768,29 @@ int QtTableSelectionManager::currentColumn() const /*! Sets the selection anchor to the given \a row and \a column. - - If the selection anchor is valid, the range comprized of the - anchor and the current cell is defined as selected. */ void QtTableSelectionManager::setAnchorCell(int row, int column) { Q_D(QtTableSelectionManager); - if (d->anchorRow == row && d->anchorColumn == column) + if (!d->model || !d->model->rowCount() || !d->model->columnCount()) return; - d->anchorRow = row; - d->anchorColumn = column; - d->updateCurrentAnchorRange(); -} - -/*! - */ -void QtTableSelectionManager::clearAnchorCell() -{ - Q_D(QtTableSelectionManager); - d->anchorRow = -1; - d->anchorColumn = -1; - d->updateCurrentAnchorRange(); + row = qBound(0, row, d->model->rowCount() - 1); + column = qBound(0, column, d->model->columnCount() - 1); + if (d->anchorRow != row || d->anchorColumn != column) { + const int previousRow = d->anchorRow; + const int previousColumn = d->anchorColumn; + d->anchorRow = row; + d->anchorColumn = column; + emit anchorChanged(row, column, previousRow, previousColumn); + d->currentAnchorRange.setRange(qMin(d->currentRow, d->anchorRow), + qMin(d->currentColumn, d->anchorColumn), + qMax(d->currentRow, d->anchorRow), + qMin(d->currentColumn, d->anchorColumn)); + // ### FIXME: check the mode + QList<QtTableSelectionRange> changed; + changed.append(d->currentAnchorRange); + emit selectionsChanged(changed); + } } /*! @@ -771,111 +819,87 @@ bool QtTableSelectionManager::isSelected(int row, int column) const /*! */ -const QList<QtTableSelectionRange> &QtTableSelectionManager::selectionRanges() const -{ - Q_D(const QtTableSelectionManager); - return d->selections; -} - -/*! - */ -const QtTableSelectionRange &QtTableSelectionManager::currentAnchorRange() const -{ - Q_D(const QtTableSelectionManager); - return d->currentAnchorRange; -} - -/*! - */ -void QtTableSelectionManager::setSelected(int top, int left, int bottom, int right) -{ - setSelected(QtTableSelectionRange(top, left, bottom, right)); -} - -/*! - */ -void QtTableSelectionManager::toggleSelection(int top, int left, int bottom, int right) -{ - toggleSelection(QtTableSelectionRange(top, left, bottom, right)); -} - -/*! - */ -void QtTableSelectionManager::setSelected(const QtTableSelectionRange &range) +void QtTableSelectionManager::beginAnchoredSelection(int anchorRow, int anchorColumn, SelectionMode mode) { Q_D(QtTableSelectionManager); - d->selections.append(range); - emit selectionsChanged(range.topRow(), range.leftColumn(), range.bottomRow(), range.rightColumn()); + if (d->active) + return; + d->active = true; + d->mode = mode; + setAnchorCell(anchorRow, anchorColumn); } /*! */ -void QtTableSelectionManager::toggleSelection(const QtTableSelectionRange &range) +void QtTableSelectionManager::endAnchoredSelection() { Q_D(QtTableSelectionManager); - QList<QtTableSelectionRange> toggleRanges; - QList<QtTableSelectionRange> selectRanges; - toggleRanges.append(range); - for (int i = 0; i < d->selections.count(); ++i) { - const QtTableSelectionRange &selection = d->selections.at(i); - bool intersected = false; - // check for intersections with the toggle ranges - for (int j = 0; j < toggleRanges.count(); ++j) { - const QtTableSelectionRange &toggle = toggleRanges.at(j); - // if we have an intersecting range, remove the intersecting area - // then go on to check the remaining areas for intersections - if (selection.intersects(toggle)) { - selectRanges += selection.subtract(toggle); - toggleRanges += toggle.subtract(selection); - toggleRanges.removeAt(j--); - intersected = true; - } + if (d->active) { + // commit anchored selection range + switch (d->mode) { + case Select: + d->selectRange(d->currentAnchorRange); + break; + case Deselect: + d->deselectRange(d->currentAnchorRange); + break; + case Toggle: + d->toggleRange(d->currentAnchorRange); + break; + default: + break; } - // if the range was intersected, the remaining areas will - // be added to the selections; the old range is removed - if (intersected) - d->selections.removeAt(i--); + d->active = false; + d->mode = Select; } - // do the actual selection - d->selections += toggleRanges; - d->selections += selectRanges; - emit selectionsChanged(range.topRow(), range.leftColumn(), range.bottomRow(), range.rightColumn()); } /*! */ -void QtTableSelectionManager::clearSelections() +QList<QtTableSelectionRange> QtTableSelectionManager::selectionRanges() const { - Q_D(QtTableSelectionManager); - d->currentAnchorRange = QtTableSelectionRange(); - QtTableSelectionRange max; - int x1 = INT_MAX, y1 = INT_MAX, x2 = -1, y2 = -1; - foreach (QtTableSelectionRange range, d->selections) { - x1 = qMin(x1, range.leftColumn()); - x2 = qMax(x1, range.rightColumn()); - y1 = qMin(x1, range.topRow()); - y2 = qMax(x1, range.bottomRow()); - } - d->selections.clear(); - - if (x1 < x2 && y1 < y2) - emit selectionsChanged(y1, x1, y2, x2); + Q_D(const QtTableSelectionManager); + QList<QtTableSelectionRange> ranges = d->selections; + if (d->active) + ranges += d->currentAnchorRange; + return ranges; } /*! */ -bool QtTableSelectionManager::toggleCurrentAnchor() const +void QtTableSelectionManager::setSelected(const QtTableSelectionRange &range, SelectionMode mode) { - Q_D(const QtTableSelectionManager); - return d->toggleCurrentAnchor; + Q_D(QtTableSelectionManager); + if (!d->model || !d->model->rowCount() || !d->model->columnCount()) + return; + QList<QtTableSelectionRange> changed; + switch (mode) { + case Select: + d->selectRange(range); + break; + case Deselect: + d->deselectRange(range); + break; + case Toggle: + d->toggleRange(range); + break; + default: + break; + } + if (!changed.isEmpty()) + emit selectionsChanged(changed); } /*! */ -void QtTableSelectionManager::setToggleCurrentAnchor(bool enable) +void QtTableSelectionManager::clearSelections() { Q_D(QtTableSelectionManager); - d->toggleCurrentAnchor = enable; + if (!d->selections.isEmpty()) { + QList<QtTableSelectionRange> changes = d->selections; + d->selections.clear(); + emit selectionsChanged(changes); + } } #include "moc_qtableselectionmanager.cpp" diff --git a/src/qtableselectionmanager.h b/src/qtableselectionmanager.h index 0282d8c..6cc8874 100644 --- a/src/qtableselectionmanager.h +++ b/src/qtableselectionmanager.h @@ -36,6 +36,7 @@ QT_BEGIN_NAMESPACE class QtTableModelInterface; class QtTableSelectionManagerPrivate; +// ### make shared ? class Q_ITEMVIEWSNG_EXPORT QtTableSelectionRange { public: @@ -56,20 +57,30 @@ public: inline bool containsCell(int row, int column) const { return intersectsRow(row) && intersectsColumn(column) && isValid(); } bool intersects(const QtTableSelectionRange &other) const; - QList<QtTableSelectionRange> subtract(const QtTableSelectionRange &other) const; + QList<QtTableSelectionRange> subtracted(const QtTableSelectionRange &other) const; bool operator==(const QtTableSelectionRange&) const; bool operator!=(const QtTableSelectionRange&) const; + void setRange(int topRow, int leftColumn, int bottomRow, int rightColumn); + private: int top, left, bottom, right; }; +Q_DECLARE_TYPEINFO(QtTableSelectionRange, Q_MOVABLE_TYPE); + class Q_ITEMVIEWSNG_EXPORT QtTableSelectionManager : public QObject { Q_OBJECT public: - explicit QtTableSelectionManager(QObject *parent = 0); + enum SelectionMode { + Select, + Deselect, + Toggle + }; + + QtTableSelectionManager(QObject *parent = 0); ~QtTableSelectionManager(); // ### do we even need the model here ? @@ -86,26 +97,21 @@ public: bool isSelected(int row, int column) const; - const QList<QtTableSelectionRange> &selectionRanges() const; // ### not needed to expose internals - const QtTableSelectionRange ¤tAnchorRange() const; // ### not needed to expose internals + void beginAnchoredSelection(int anchorRow, int anchorColumn, SelectionMode mode = Select); + void endAnchoredSelection(); - bool toggleCurrentAnchor() const; // editSelectionInverts - void setToggleCurrentAnchor(bool enable);// setEditSelectionInverts + QList<QtTableSelectionRange> selectionRanges() const; public Q_SLOTS: void setCurrentCell(int row, int column); void setAnchorCell(int row, int column); - void setSelected(int top, int left, int bottom, int right); - void toggleSelection(int top, int left, int bottom, int right); - void setSelected(const QtTableSelectionRange &range); - void toggleSelection(const QtTableSelectionRange &range); - void clearCurrentCell(); - void clearAnchorCell(); + void setSelected(const QtTableSelectionRange &range, SelectionMode mode = Select); void clearSelections(); Q_SIGNALS: void currentChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); - void selectionsChanged(int top, int left, int bottom, int right); + void anchorChanged(int anchorRow, int anchorColumn, int previousRow, int previousColumn); + void selectionsChanged(const QList<QtTableSelectionRange> &changed); protected: QtTableSelectionManager(QtTableSelectionManagerPrivate&, QObject *parent = 0); diff --git a/src/qtableselectionmanager_p.h b/src/qtableselectionmanager_p.h index 022303e..8b8ab7d 100644 --- a/src/qtableselectionmanager_p.h +++ b/src/qtableselectionmanager_p.h @@ -57,17 +57,20 @@ public: bool isColumnIntersected(int row) const; bool isSelected(int row, int column) const; - void updateCurrentAnchorRange(); + void selectRange(const QtTableSelectionRange &range); + void deselectRange(const QtTableSelectionRange &range); + void toggleRange(const QtTableSelectionRange &range); QtTableSelectionManager *q_ptr; QtTableModelInterface *model; + QList<QtTableSelectionRange> selections; int currentRow; int currentColumn; int anchorRow; int anchorColumn; + bool active; QtTableSelectionRange currentAnchorRange; - QList<QtTableSelectionRange> selections; - bool toggleCurrentAnchor; + QtTableSelectionManager::SelectionMode mode; }; QT_END_NAMESPACE diff --git a/src/qtreecontroller.cpp b/src/qtreecontroller.cpp index 8422271..6dcbb11 100644 --- a/src/qtreecontroller.cpp +++ b/src/qtreecontroller.cpp @@ -28,9 +28,10 @@ #include "qtreeselectionmanager.h" #include "qgraphicstreeview.h" -#include <qdebug.h> #include <qevent.h> #include <qgraphicssceneevent.h> +#include <qtransform.h> +#include <qdebug.h> // QTreeHeaderDataProvider @@ -154,160 +155,27 @@ bool QtTreeControllerPrivate::setCurrentItem(QtTreeModelBase::iterator_base &it) return false; } -bool QtTreeControllerPrivate::keyPressEvent(QKeyEvent *event) -{ - if (view && selectionManager) { - QtTreeModelBase::iterator_base it = selectionManager->currentItem(); - switch (event->key()) { - case Qt::Key_Down: - view->nextItem(it); - setCurrentItem(it); - return true; - case Qt::Key_Up: - view->previousItem(it); - setCurrentItem(it); - return true; - case Qt::Key_Left: - view->setItemExpanded(it, false); - return true; - case Qt::Key_Right: - view->setItemExpanded(it, true); - return true; - default: - break; - } - } - return false; -} - -bool QtTreeControllerPrivate::inputMethodEvent(QInputMethodEvent *event) -{ - Q_UNUSED(event); - return false; -} - -bool QtTreeControllerPrivate::mousePressEvent(QMouseEvent *event, const QTransform &transform) -{ - QPointF pos = transform.map(event->pos()); - //if (header && (!header->isIdle() || header->geometry().contains(pos))) - // return header->processEvent(event, transform); - if (view && event->buttons() & Qt::LeftButton) { - QRectF rect; // optimization; let itemAt get the rect too - QtTreeModelBase::iterator_base it = view->itemAt(pos, &rect); - if (it.hasChildren() && view->disclosureRect(rect).contains(pos)) { - if (view->isItemExpanded(it)) - view->setItemExpanded(it, false); - else - view->setItemExpanded(it, true); - return true; - } - return setCurrentItem(it); - } - return false; -} - -bool QtTreeControllerPrivate::mouseMoveEvent(QMouseEvent *event, const QTransform &transform) -{ - QPointF pos = transform.map(event->pos()); - if (view && event->buttons() & Qt::LeftButton) { - QtTreeModelBase::iterator_base it = view->itemAt(pos); - return setCurrentItem(it); - } - return false; -} - -bool QtTreeControllerPrivate::mouseReleaseEvent(QMouseEvent *event, const QTransform &transform) -{ - Q_Q(QtTreeController); - QPointF pos = transform.map(event->pos()); - if (view && event->button() == Qt::LeftButton) { - // ### make sure it is the same as pressed item - QtTreeModelBase::iterator_base it = view->itemAt(pos); - emit q->itemClicked(it, Qt::LeftButton); - return true; - } - return false; -} - -bool QtTreeControllerPrivate::mouseDoubleClickEvent(QMouseEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} - -bool QtTreeControllerPrivate::dragEnterEvent(QDragEnterEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} - -bool QtTreeControllerPrivate::dragLeaveEvent(QDragLeaveEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} - -bool QtTreeControllerPrivate::dragMoveEvent(QDragMoveEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} -bool QtTreeControllerPrivate::dropEvent(QDropEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} -bool QtTreeControllerPrivate::hoverEnterEvent(QHoverEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} +// QtTreeController -bool QtTreeControllerPrivate::hoverMoveEvent(QHoverEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} +/*! + \class QtTreeController + \brief provides a controller for tree model and view objects. -bool QtTreeControllerPrivate::hoverLeaveEvent(QHoverEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} + QtTreeController represents a controller in the model-view-controller (MFC) + design-pattern. -bool QtTreeControllerPrivate::wheelEvent(QWheelEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - return false; -} + It is used together with a sub-class of QtTreeModelInterface and QtGraphicsTreeView. -bool QtTreeControllerPrivate::resizeEvent(QResizeEvent *event, const QTransform &transform) -{ - Q_UNUSED(event); - Q_UNUSED(transform); - if (view) { - view->updateLayout(); - return true; - } - return false; -} + QtTreeController is responsible for handling user input events and make the requested + changes to the view, model, or selections. -// QtTreeController + For example, when the user clicks an item in the view, it is QtTreeController's + responsibility to change selection state of that item. -/*! - \class QtTreeController - \brief A tree controller + QtTreeWidgetNG contains a QtTreeController, as well as a QtTreeDefaultModel + and a QtGraphicsTreeView. */ /*! @@ -579,96 +447,227 @@ qreal QtTreeController::maximumHorizontalScrollValue() const /*! */ -bool QtTreeController::processEvent(QEvent *event, const QTransform &transform) +bool QtTreeController::keyPressEvent(QKeyEvent *event) { Q_D(QtTreeController); - Q_ASSERT(event); + if (d->view && d->selectionManager) { + QtTreeModelBase::iterator_base it = d->selectionManager->currentItem(); + switch (event->key()) { + case Qt::Key_Down: + d->view->nextItem(it); + d->setCurrentItem(it); + return true; + case Qt::Key_Up: + d->view->previousItem(it); + d->setCurrentItem(it); + return true; + case Qt::Key_Left: + d->view->setItemExpanded(it, false); + return true; + case Qt::Key_Right: + d->view->setItemExpanded(it, true); + return true; + default: + break; + } + } + return false; +} + +/*! + */ +bool QtTreeController::inputMethodEvent(QInputMethodEvent *event) +{ + Q_UNUSED(event); + return false; +} + +/*! + */ +bool QtTreeController::mousePressEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform) +{ + Q_D(QtTreeController); + QPointF pos = transform.map(event->pos()); + //if (header && (!header->isIdle() || header->geometry().contains(pos))) + // return header->processEvent(event, transform); + if (d->view && event->buttons() & Qt::LeftButton) { + QRectF rect; // optimization; let itemAt get the rect too + QtTreeModelBase::iterator_base it = d->view->itemAt(pos, &rect); + if (it.hasChildren() && d->view->disclosureRect(rect).contains(pos)) { + if (d->view->isItemExpanded(it)) + d->view->setItemExpanded(it, false); + else + d->view->setItemExpanded(it, true); + return true; + } + return d->setCurrentItem(it); + } + return false; +} + +/*! + */ +bool QtTreeController::mouseMoveEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform) +{ + Q_D(QtTreeController); + QPointF pos = transform.map(event->pos()); + if (d->view && event->buttons() & Qt::LeftButton) { + QtTreeModelBase::iterator_base it = d->view->itemAt(pos); + return d->setCurrentItem(it); + } + return false; +} + +/*! + */ +bool QtTreeController::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform) +{ + Q_D(QtTreeController); + QPointF pos = transform.map(event->pos()); + if (d->view && event->button() == Qt::LeftButton) { + // ### make sure it is the same as pressed item + QtTreeModelBase::iterator_base it = d->view->itemAt(pos); + emit itemClicked(it, Qt::LeftButton); + return true; + } + return false; +} + +/*! + */ +bool QtTreeController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::dragEnterEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::dragLeaveEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::dragMoveEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} +/*! + */ +bool QtTreeController::dropEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::hoverEnterEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::hoverMoveEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::wheelEvent(QGraphicsSceneWheelEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + return false; +} + +/*! + */ +bool QtTreeController::resizeEvent(QGraphicsSceneResizeEvent *event, const QTransform &transform) +{ + Q_UNUSED(event); + Q_UNUSED(transform); + Q_D(QtTreeController); + if (d->view) { + d->view->updateLayout(); + return true; + } + return false; +} + +/*! + */ +bool QtTreeController::processEvent(QEvent *event, const QTransform &transform) +{ + Q_ASSERT(event); + Q_ASSERT(event); switch(event->type()) { -// case QEvent::FocusIn: -// case QEvent::FocusOut: -// return d->focusEvent(static_cast<QFocusEvent*>(event)); +// case QEvent::FocusIn: +// case QEvent::FocusOut: +// return focusEvent(static_cast<QFocusEvent*>(event)); case QEvent::KeyPress: - return d->keyPressEvent(static_cast<QKeyEvent*>(event)); + return keyPressEvent(static_cast<QKeyEvent*>(event)); case QEvent::InputMethod: - return d->inputMethodEvent(static_cast<QInputMethodEvent*>(event)); - case QEvent::MouseButtonPress: - return d->mousePressEvent(static_cast<QMouseEvent*>(event), transform); - case QEvent::MouseMove: - return d->mouseMoveEvent(static_cast<QMouseEvent*>(event), transform); - case QEvent::MouseButtonRelease: - return d->mouseReleaseEvent(static_cast<QMouseEvent*>(event), transform); - case QEvent::MouseButtonDblClick: - return d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(event), transform); -#ifndef QT_NO_DRAGANDDROP - case QEvent::DragEnter: - return d->dragEnterEvent(static_cast<QDragEnterEvent*>(event), transform); - case QEvent::DragLeave: - return d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(event), transform); - case QEvent::DragMove: - return d->dragMoveEvent(static_cast<QDragMoveEvent*>(event), transform); - case QEvent::Drop: - return d->dropEvent(static_cast<QDropEvent*>(event), transform); -#endif - case QEvent::HoverEnter: - return d->hoverEnterEvent(static_cast<QHoverEvent*>(event), transform); - case QEvent::HoverMove: - return d->hoverMoveEvent(static_cast<QHoverEvent*>(event), transform); - case QEvent::HoverLeave: - return d->hoverLeaveEvent(static_cast<QHoverEvent*>(event), transform); - case QEvent::Resize: - return d->resizeEvent(static_cast<QResizeEvent*>(event), transform); - // ### converting graphics scene events - case QEvent::GraphicsSceneMousePress: { - QGraphicsSceneMouseEvent *ge = static_cast<QGraphicsSceneMouseEvent*>(event); - QMouseEvent me(QEvent::MouseButtonPress, ge->pos().toPoint(), ge->button(), ge->buttons(), ge->modifiers()); - return d->mousePressEvent(&me, QTransform()); } // ### - case QEvent::GraphicsSceneMouseMove: { - QGraphicsSceneMouseEvent *ge = static_cast<QGraphicsSceneMouseEvent*>(event); - QMouseEvent me(QEvent::MouseMove, ge->pos().toPoint(), ge->button(), ge->buttons(), ge->modifiers()); - return d->mouseMoveEvent(&me, QTransform()); } // ### - case QEvent::GraphicsSceneMouseRelease: { - QGraphicsSceneMouseEvent *ge = static_cast<QGraphicsSceneMouseEvent*>(event); - QMouseEvent me(QEvent::MouseButtonRelease, ge->pos().toPoint(), ge->button(), ge->buttons(), ge->modifiers()); - return d->mouseReleaseEvent(&me, QTransform()); } // ### + return inputMethodEvent(static_cast<QInputMethodEvent*>(event)); + case QEvent::GraphicsSceneMousePress: + return mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform()); + case QEvent::GraphicsSceneMouseMove: + return mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform()); + case QEvent::GraphicsSceneMouseRelease: + return mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform()); #ifndef QT_NO_WHEELEVENT - case QEvent::GraphicsSceneWheel: { - QGraphicsSceneWheelEvent *ge = static_cast<QGraphicsSceneWheelEvent*>(event); - QWheelEvent we(ge->pos().toPoint(), ge->delta(), ge->buttons(), ge->modifiers(), ge->orientation()); - return d->wheelEvent(&we, QTransform()); } // ### + case QEvent::GraphicsSceneWheel: + return wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(event), QTransform()); #endif - case QEvent::GraphicsSceneDragEnter: { - QGraphicsSceneDragDropEvent *ge = static_cast<QGraphicsSceneDragDropEvent*>(event); - QDragEnterEvent de(ge->pos().toPoint(), ge->dropAction(), ge->mimeData(), ge->buttons(), ge->modifiers()); - return d->dragEnterEvent(&de, QTransform()); } - case QEvent::GraphicsSceneDragLeave: { - //QGraphicsSceneDragDropEvent *ge = static_cast<QGraphicsSceneDragDropEvent*>(event); - QDragLeaveEvent de;//(ge->pos().toPoint(), ge->dropAction(), ge->mimeData(), ge->buttons(), ge->modifiers()); - return d->dragLeaveEvent(&de, QTransform()); } - case QEvent::GraphicsSceneDragMove: { - QGraphicsSceneDragDropEvent *ge = static_cast<QGraphicsSceneDragDropEvent*>(event); - QDragMoveEvent de(ge->pos().toPoint(), ge->dropAction(), ge->mimeData(), ge->buttons(), ge->modifiers()); - return d->dragMoveEvent(&de, QTransform()); } - case QEvent::GraphicsSceneDrop: { - QGraphicsSceneDragDropEvent *ge = static_cast<QGraphicsSceneDragDropEvent*>(event); - QDropEvent de(ge->pos().toPoint(), ge->dropAction(), ge->mimeData(), ge->buttons(), ge->modifiers()); - return d->dropEvent(&de, QTransform()); } - case QEvent::GraphicsSceneHoverEnter: { - QGraphicsSceneHoverEvent *ge = static_cast<QGraphicsSceneHoverEvent*>(event); - QHoverEvent he(ge->type(), ge->pos().toPoint(), ge->lastPos().toPoint()); - return d->hoverEnterEvent(&he, QTransform()); } - case QEvent::GraphicsSceneHoverMove: { - QGraphicsSceneHoverEvent *ge = static_cast<QGraphicsSceneHoverEvent*>(event); - QHoverEvent he(ge->type(), ge->pos().toPoint(), ge->lastPos().toPoint()); - return d->hoverMoveEvent(&he, QTransform()); } - case QEvent::GraphicsSceneHoverLeave: { - QGraphicsSceneHoverEvent *ge = static_cast<QGraphicsSceneHoverEvent*>(event); - QHoverEvent he(ge->type(), ge->pos().toPoint(), ge->lastPos().toPoint()); - return d->hoverLeaveEvent(&he, QTransform()); } - case QEvent::GraphicsSceneResize: { - QGraphicsSceneResizeEvent *ge = static_cast<QGraphicsSceneResizeEvent*>(event); - QResizeEvent re(ge->newSize().toSize(), ge->oldSize().toSize()); - return d->resizeEvent(&re, QTransform()); } + case QEvent::GraphicsSceneDragEnter: + return dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform()); + case QEvent::GraphicsSceneDragLeave: + return dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform()); + case QEvent::GraphicsSceneDragMove: + return dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform()); + case QEvent::GraphicsSceneDrop: + return dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform()); + case QEvent::GraphicsSceneHoverEnter: + return hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform()); + case QEvent::GraphicsSceneHoverMove: + return hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform()); + case QEvent::GraphicsSceneHoverLeave: + return hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform()); + case QEvent::GraphicsSceneResize: + return resizeEvent(static_cast<QGraphicsSceneResizeEvent*>(event), transform); default: break; } diff --git a/src/qtreecontroller.h b/src/qtreecontroller.h index 1b5dee1..d1dc7fd 100644 --- a/src/qtreecontroller.h +++ b/src/qtreecontroller.h @@ -25,7 +25,6 @@ #define QTTREECONTROLLER_H #include <QtCore/qobject.h> -#include <QtGui/qtransform.h> #include "qtreemodelinterface.h" QT_BEGIN_HEADER @@ -35,13 +34,22 @@ QT_BEGIN_NAMESPACE //QT_MODULE(Gui) class QEvent; +class QKeyEvent; +class QInputMethodEvent; +class QGraphicsSceneMouseEvent; +class QGraphicsSceneDragDropEvent; +class QGraphicsSceneHoverEvent; +class QGraphicsSceneWheelEvent; +class QGraphicsSceneResizeEvent; class QTransform; + class QtTreeControllerPrivate; class QtTreeSelectionManager; class QtTreeModelBase; class QtGraphicsTreeView; class QtGraphicsHeader; + class Q_ITEMVIEWSNG_EXPORT QtTreeController : public QObject { Q_OBJECT @@ -71,7 +79,22 @@ public: virtual qreal maximumVerticalScrollValue() const; virtual qreal maximumHorizontalScrollValue() const; - virtual bool processEvent(QEvent *event, const QTransform &transform = QTransform()); + virtual bool keyPressEvent(QKeyEvent *event); + virtual bool inputMethodEvent(QInputMethodEvent *event); + virtual bool mousePressEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform); + virtual bool mouseMoveEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform); + virtual bool mouseReleaseEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform); + virtual bool mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform); + virtual bool dragEnterEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform); + virtual bool dragLeaveEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform); + virtual bool dragMoveEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform); + virtual bool dropEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform); + virtual bool hoverEnterEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform); + virtual bool hoverMoveEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform); + virtual bool hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const QTransform &transform); + virtual bool wheelEvent(QGraphicsSceneWheelEvent *event, const QTransform &transform); + virtual bool resizeEvent(QGraphicsSceneResizeEvent *event, const QTransform &transform); + virtual bool processEvent(QEvent *event, const QTransform &transform); Q_SIGNALS: void itemClicked(QtTreeModelIterator &it, Qt::MouseButton button); diff --git a/src/qtreecontroller_p.h b/src/qtreecontroller_p.h index cfd0883..b57f36b 100644 --- a/src/qtreecontroller_p.h +++ b/src/qtreecontroller_p.h @@ -77,22 +77,6 @@ public: QtTreeModelBase::iterator_base currentItem() const; bool setCurrentItem(QtTreeModelBase::iterator_base &it); - - bool keyPressEvent(QKeyEvent *event); - bool inputMethodEvent(QInputMethodEvent *event); - bool mousePressEvent(QMouseEvent *event, const QTransform &transform); - bool mouseMoveEvent(QMouseEvent *event, const QTransform &transform); - bool mouseReleaseEvent(QMouseEvent *event, const QTransform &transform); - bool mouseDoubleClickEvent(QMouseEvent *event, const QTransform &transform); - bool dragEnterEvent(QDragEnterEvent *event, const QTransform &transform); - bool dragLeaveEvent(QDragLeaveEvent *event, const QTransform &transform); - bool dragMoveEvent(QDragMoveEvent *event, const QTransform &transform); - bool dropEvent(QDropEvent *event, const QTransform &transform); - bool hoverEnterEvent(QHoverEvent *event, const QTransform &transform); - bool hoverMoveEvent(QHoverEvent *event, const QTransform &transform); - bool hoverLeaveEvent(QHoverEvent *event, const QTransform &transform); - bool wheelEvent(QWheelEvent *event, const QTransform &transform); - bool resizeEvent(QResizeEvent *event, const QTransform &transform); QtTreeController *q_ptr; QtGraphicsTreeView *view; diff --git a/src/qtreedefaultmodel.cpp b/src/qtreedefaultmodel.cpp index 914e516..8523171 100644 --- a/src/qtreedefaultmodel.cpp +++ b/src/qtreedefaultmodel.cpp @@ -28,7 +28,7 @@ struct QtTreeDefaultItemPrivate { QtTreeDefaultItemPrivate() : parent(0), previous(0), next(0), model(0) {} - QList<QHash<int,QVariant> > data; + QVector<QHash<int,QVariant> > data; QtTreeDefaultItem *parent; QtTreeDefaultItem *previous; QtTreeDefaultItem *next; @@ -126,6 +126,19 @@ int QtTreeDefaultItem::columnCount() const } /*! + Sets the items column count to be the given \a count. + \sa columnCount() + */ +void QtTreeDefaultItem::setColumnCount(int count) +{ + if (d_ptr->data.count() != count) { + d_ptr->data.resize(count); + if (d_ptr->model) + d_ptr->model->itemChanged(this, QList<int>()); + } +} + +/*! Returns the item's children. \sa parent() */ @@ -135,16 +148,17 @@ const QList<QtTreeDefaultItem*> &QtTreeDefaultItem::children() const } /*! - Inserts the \a child at \a i in teh list of children. + Inserts the \a child at \a i in the list of children. \sa appendChild(), takeChild(), removeChild() */ void QtTreeDefaultItem::insertChild(int i, QtTreeDefaultItem *child) { - QtTreeDefaultItem *previous = d_ptr->children.value(i); + i = qBound(0, i, d_ptr->children.count()); + QtTreeDefaultItem *previous = i > 0 ? d_ptr->children.value(i - 1) : 0; child->d_ptr->previous = previous; if (previous) previous->d_ptr->next = child; - QtTreeDefaultItem *next = d_ptr->children.value(i + 1); + QtTreeDefaultItem *next = i < d_ptr->children.count() ? d_ptr->children.value(i) : 0; child->d_ptr->next = next; if (next) next->d_ptr->previous = child; @@ -165,6 +179,7 @@ void QtTreeDefaultItem::appendChild(QtTreeDefaultItem *child) if (previous) previous->d_ptr->next = child; child->d_ptr->model = d_ptr->model; + child->d_ptr->next = 0; d_ptr->children.append(child); if (d_ptr->model) d_ptr->model->itemInserted(child); @@ -176,6 +191,8 @@ void QtTreeDefaultItem::appendChild(QtTreeDefaultItem *child) */ QtTreeDefaultItem *QtTreeDefaultItem::takeChild(int i) { + if (i < 0 || i >= d_ptr->children.count()) + return 0; QtTreeDefaultItem *previous = d_ptr->children.value(i - 1); QtTreeDefaultItem *next = d_ptr->children.value(i + 1); if (previous) @@ -314,7 +331,16 @@ QtTreeDefaultModel::~QtTreeDefaultModel() */ QtTreeDefaultModel::iterator QtTreeDefaultModel::itemIterator(QtTreeDefaultItem *item) { - return QtTreeDefaultModel::iterator(item, this); + Q_D(const QtTreeDefaultModel); + return QtTreeDefaultModel::iterator(item != d->root ? item : 0, this); +} + +/*! + Returns the item for the given \a iterator. + */ +QtTreeDefaultItem *QtTreeDefaultModel::item(iterator &iterator) +{ + return (*iterator); } /*! diff --git a/src/qtreedefaultmodel.h b/src/qtreedefaultmodel.h index ae913fe..aae5b0d 100644 --- a/src/qtreedefaultmodel.h +++ b/src/qtreedefaultmodel.h @@ -21,8 +21,8 @@ ** ****************************************************************************/ -#ifndef QTTREEDefaultModel_H -#define QTTREEDefaultModel_H +#ifndef QTTREEDEFAULTMODEL_H +#define QTTREEDEFAULTMODEL_H #include "qtreemodelinterface.h" #include <QtGui/qicon.h> @@ -53,6 +53,7 @@ public: QtTreeDefaultItem *previous() const; int columnCount() const; + void setColumnCount(int count); const QList<QtTreeDefaultItem*> &children() const; void insertChild(int i, QtTreeDefaultItem *child); @@ -67,46 +68,46 @@ public: // data functions virtual QHash<int,QVariant> data(int column, const QList<int> &roles) const; - virtual QVariant data(int column, int role) const; + virtual QVariant data(int column, int role) const; // ### virtual void setData(const QVariant &data, int column, int role); // ### is the order of args ok ? // ### we should add // Qt::TextRole == Qt::DisplayRole // Qt::IconRole == Qt::DecorationRole - inline QString text(int column) const { return qvariant_cast<QString>(data(column, Qt::DisplayRole)); } - inline void setText(int column, const QString &text) { setData(text, column, Qt::DisplayRole); } + inline QString text(int column = 0) const { return qvariant_cast<QString>(data(column, Qt::DisplayRole)); } + inline void setText(const QString &text, int column = 0) { setData(text, column, Qt::DisplayRole); } - inline QIcon icon(int column) const { return qvariant_cast<QIcon>(data(column, Qt::DecorationRole)); } - inline void setIcon(int column, const QIcon &icon) { setData(icon, column, Qt::DecorationRole); } + inline QIcon icon(int column = 0) const { return qvariant_cast<QIcon>(data(column, Qt::DecorationRole)); } + inline void setIcon(const QIcon &icon, int column = 0) { setData(icon, column, Qt::DecorationRole); } - inline QString statusTip(int column) const { return qvariant_cast<QString>(data(column, Qt::StatusTipRole)); } - inline void setStatusTip(int column, const QString &tip) { setData(tip, column, Qt::StatusTipRole); } + inline QString statusTip(int column = 0) const { return qvariant_cast<QString>(data(column, Qt::StatusTipRole)); } + inline void setStatusTip(const QString &tip, int column = 0) { setData(tip, column, Qt::StatusTipRole); } #ifndef QT_NO_TOOLTIP - inline QString toolTip(int column) const { return qvariant_cast<QString>(data(column, Qt::ToolTipRole)); } - inline void setToolTip(int column, const QString &tip) { setData(tip, column, Qt::ToolTipRole); } + inline QString toolTip(int column = 0) const { return qvariant_cast<QString>(data(column, Qt::ToolTipRole)); } + inline void setToolTip(const QString &tip, int column = 0) { setData(tip, column, Qt::ToolTipRole); } #endif #ifndef QT_NO_WHATSTHIS - inline QString whatsThis(int column) const { return qvariant_cast<QString>(data(column, Qt::WhatsThisRole)); } - inline void setWhatsThis(int column, const QString &what) { setData(what, column, Qt::WhatsThisRole); } + inline QString whatsThis(int column = 0) const { return qvariant_cast<QString>(data(column, Qt::WhatsThisRole)); } + inline void setWhatsThis(const QString &what, int column = 0) { setData(what, column, Qt::WhatsThisRole); } #endif - inline QFont font(int column) const { return qvariant_cast<QFont>(data(column, Qt::FontRole)); } - inline void setFont(int column, const QFont &font) { setData(font, column, Qt::FontRole); } + inline QFont font(int column = 0) const { return qvariant_cast<QFont>(data(column, Qt::FontRole)); } + inline void setFont(const QFont &font, int column = 0) { setData(font, column, Qt::FontRole); } - inline int textAlignment(int column) const { return qvariant_cast<int>(data(column, Qt::TextAlignmentRole)); } - inline void setTextAlignment(int column, int alignment) { setData(alignment, column, Qt::TextAlignmentRole); } + inline int textAlignment(int column = 0) const { return qvariant_cast<int>(data(column, Qt::TextAlignmentRole)); } + inline void setTextAlignment(int alignment, int column = 0) { setData(alignment, column, Qt::TextAlignmentRole); } - inline QBrush background(int column) const { return qvariant_cast<QBrush>(data(column, Qt::BackgroundRole)); } - inline void setBackground(int column, const QBrush &brush) { setData(brush, column, Qt::BackgroundRole); } + inline QBrush background(int column = 0) const { return qvariant_cast<QBrush>(data(column, Qt::BackgroundRole)); } + inline void setBackground(const QBrush &brush, int column = 0) { setData(brush, column, Qt::BackgroundRole); } - inline QBrush foreground(int column) const { return qvariant_cast<QBrush>(data(column, Qt::ForegroundRole)); } - inline void setForeground(int column, const QBrush &brush) { setData(brush, column, Qt::ForegroundRole); } + inline QBrush foreground(int column = 0) const { return qvariant_cast<QBrush>(data(column, Qt::ForegroundRole)); } + inline void setForeground(const QBrush &brush, int column = 0) { setData(brush, column, Qt::ForegroundRole); } - inline Qt::CheckState checkState(int column) const { return static_cast<Qt::CheckState>(data(column, Qt::CheckStateRole).toInt()); } - inline void setCheckState(int column, Qt::CheckState state) { setData(state, column, Qt::CheckStateRole); } + inline Qt::CheckState checkState(int column = 0) const { return static_cast<Qt::CheckState>(data(column, Qt::CheckStateRole).toInt()); } + inline void setCheckState(Qt::CheckState state, int column = 0) { setData(state, column, Qt::CheckStateRole); } - inline QSizeF sizeHint(int column) const { return qvariant_cast<QSizeF>(data(column, Qt::SizeHintRole)); } - inline void setSizeHint(int column, const QSizeF &size) { setData(size, column, Qt::SizeHintRole); } + inline QSizeF sizeHint(int column = 0) const { return qvariant_cast<QSizeF>(data(column, Qt::SizeHintRole)); } + inline void setSizeHint(const QSizeF &size, int column = 0) { setData(size, column, Qt::SizeHintRole); } private: QtTreeDefaultItemPrivate *d_ptr; @@ -123,6 +124,7 @@ public: virtual ~QtTreeDefaultModel(); QtTreeDefaultModel::iterator itemIterator(QtTreeDefaultItem *item); // ### + QtTreeDefaultItem *item(iterator &iterator); QtTreeDefaultItem *rootItem() const; protected: @@ -160,4 +162,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif//QTTREEDefaultModel_H +#endif//QTTREEDEFAULTMODEL_H diff --git a/tests/README.tests b/tests/README.tests index bfe6161..c3aa125 100644 --- a/tests/README.tests +++ b/tests/README.tests @@ -5,7 +5,7 @@ How to run all tests and only show the relevant output: function qtestitemviews { (cd $HOME/work/itemview/tests && for i in *; do - (cb && if test -d $i; then + (if test -d $i; then (cd $i && testrunner) fi) done diff --git a/tests/qgraphicsflowview/tst_qgraphicsflowview.cpp b/tests/qgraphicsflowview/tst_qgraphicsflowview.cpp index 284d0be..5837db2 100644 --- a/tests/qgraphicsflowview/tst_qgraphicsflowview.cpp +++ b/tests/qgraphicsflowview/tst_qgraphicsflowview.cpp @@ -232,4 +232,4 @@ void tst_QListFlowLayout::layoutPositioningVertical() // vertical } QTEST_MAIN(tst_QListFlowLayout) -#include <tst_qgraphicsflowview.moc> +#include "tst_qgraphicsflowview.moc" diff --git a/tests/qgraphicsgridview/tst_qgraphicsgridview.cpp b/tests/qgraphicsgridview/tst_qgraphicsgridview.cpp index 70be5e9..3e0d588 100644 --- a/tests/qgraphicsgridview/tst_qgraphicsgridview.cpp +++ b/tests/qgraphicsgridview/tst_qgraphicsgridview.cpp @@ -73,4 +73,4 @@ void tst_QtGraphicsGridView::getSetCheck() } QTEST_MAIN(tst_QtGraphicsGridView) -#include <tst_qgraphicsgridview.moc> +#include "tst_qgraphicsgridview.moc" diff --git a/tests/qgraphicslistview/tst_qgraphicslistview.cpp b/tests/qgraphicslistview/tst_qgraphicslistview.cpp index f18e29f..bcf5d3c 100644 --- a/tests/qgraphicslistview/tst_qgraphicslistview.cpp +++ b/tests/qgraphicslistview/tst_qgraphicslistview.cpp @@ -29,15 +29,22 @@ #include <qlistdefaultmodel.h> #include <qlistcontroller.h> -class MockView : public QtGraphicsListView +class GraphicsListView : public QtGraphicsListView { public: - MockView() { } - + GraphicsListView() { } void setController(QtListController *c) { QtGraphicsListView::setController(c); } void setModel(QtListModelInterface *m) { QtGraphicsListView::setModel(m); } }; +class GraphicsListViewItem : public QtGraphicsListViewItem +{ +public: + GraphicsListViewItem(int index, QtGraphicsListView *view) : QtGraphicsListViewItem(index, view) { } + QSizeF sizeHint(int, const QStyleOptionViewItemV4 *, Qt::SizeHint, const QSizeF&) const { return QSize(20, 20); } +}; + + class tst_QtGraphicsListView : public QObject { Q_OBJECT @@ -56,15 +63,18 @@ private slots: void getSetCheck(); void maximumFirstIndex_data(); void maximumFirstIndex(); - void itemAtVertical(); - void itemAtHorizontal(); - void layoutPositioningVertical(); - void layoutPositioningHorizontal(); + void itemAt_data(); + void itemAt(); + void layout_data(); + void layout(); protected: - MockView *listView; + GraphicsListView *view; }; +Q_DECLARE_METATYPE(QList<int>) +Q_DECLARE_METATYPE(QList<QRectF>) + tst_QtGraphicsListView::tst_QtGraphicsListView() { } @@ -83,380 +93,497 @@ void tst_QtGraphicsListView::cleanupTestCase() void tst_QtGraphicsListView::init() { - listView = new MockView(); + view = new GraphicsListView(); } void tst_QtGraphicsListView::cleanup() { - delete listView; + delete view; } void tst_QtGraphicsListView::getSetCheck() { - QCOMPARE(listView->horizontalOffset(), 0.); // default - QCOMPARE(listView->firstIndex(), 0); // default - QCOMPARE(listView->orientation(), Qt::Vertical); // default - QCOMPARE(listView->verticalOffset(), 0.); // default - - listView->setFirstIndex(9); - QCOMPARE(listView->firstIndex(), 9); - listView->setFirstIndex(0); - QCOMPARE(listView->firstIndex(), 0); - - QCOMPARE(listView->horizontalOffset(), 0.); - listView->setHorizontalOffset(0); - QCOMPARE(listView->horizontalOffset(), 0.); - listView->setHorizontalOffset(0.123); - QCOMPARE(listView->horizontalOffset(), 0.123); - listView->setHorizontalOffset(123.4); - QCOMPARE(listView->horizontalOffset(), 123.4); - - QCOMPARE(listView->verticalOffset(), 0.); - listView->setVerticalOffset(0); - QCOMPARE(listView->verticalOffset(), 0.); - listView->setVerticalOffset(0.123); - QCOMPARE(listView->verticalOffset(), 0.123); - listView->setVerticalOffset(123.4); - QCOMPARE(listView->verticalOffset(), 123.4); - - QCOMPARE(listView->orientation(), Qt::Vertical); - listView->setOrientation(Qt::Horizontal); - QCOMPARE(listView->orientation(), Qt::Horizontal); - - QVERIFY(listView->model() == 0); - QtListDefaultModel *model = new QtListDefaultModel(listView); - listView->setModel(model); - QCOMPARE(listView->model(), model); - - QSignalSpy deleted1(model, SIGNAL(destroyed(QObject*))); - listView->setModel(0); - QVERIFY(deleted1.isEmpty()); // check that the model is *not* deleted. Views don't own models ;) - listView->setModel(model); - - QVERIFY(listView->controller() == 0); + QCOMPARE(view->horizontalOffset(), 0.); // default + QCOMPARE(view->firstIndex(), 0); // default + QCOMPARE(view->orientation(), Qt::Vertical); // default + QCOMPARE(view->verticalOffset(), 0.); // default + + view->setFirstIndex(9); + QCOMPARE(view->firstIndex(), 9); + view->setFirstIndex(0); + QCOMPARE(view->firstIndex(), 0); + + QCOMPARE(view->horizontalOffset(), 0.); + view->setHorizontalOffset(0); + QCOMPARE(view->horizontalOffset(), 0.); + view->setHorizontalOffset(0.123); + QCOMPARE(view->horizontalOffset(), 0.123); + view->setHorizontalOffset(123.4); + QCOMPARE(view->horizontalOffset(), 123.4); + + QCOMPARE(view->verticalOffset(), 0.); + view->setVerticalOffset(0); + QCOMPARE(view->verticalOffset(), 0.); + view->setVerticalOffset(0.123); + QCOMPARE(view->verticalOffset(), 0.123); + view->setVerticalOffset(123.4); + QCOMPARE(view->verticalOffset(), 123.4); + + QCOMPARE(view->orientation(), Qt::Vertical); + view->setOrientation(Qt::Horizontal); + QCOMPARE(view->orientation(), Qt::Horizontal); + + QVERIFY(view->model() == 0); + QtListDefaultModel *model = new QtListDefaultModel(view); + view->setModel(model); + QCOMPARE(view->model(), model); + + // check that the model is not deleted + QSignalSpy modelDeleted(model, SIGNAL(destroyed(QObject*))); + view->setModel(0); + QVERIFY(modelDeleted.isEmpty()); + view->setModel(model); + + QVERIFY(view->controller() == 0); QtListController *controller = new QtListController(); - listView->setController(controller); - QCOMPARE(listView->controller(), controller); - QCOMPARE(listView->model(), model); // controller and model are independent - - QSignalSpy deleted2(controller, SIGNAL(destroyed(QObject*))); - listView->setController(0); - QVERIFY(listView->controller() == 0); - QVERIFY(deleted1.isEmpty()); - QVERIFY(deleted2.isEmpty()); + view->setController(controller); + QCOMPARE(view->controller(), controller); + QCOMPARE(view->model(), model); + + // check that the controller is not deleted + QSignalSpy controllerDeleted(controller, SIGNAL(destroyed(QObject*))); + view->setController(0); + QVERIFY(view->controller() == 0); + QVERIFY(modelDeleted.isEmpty()); + QVERIFY(controllerDeleted.isEmpty()); + + delete controller; + delete model; } void tst_QtGraphicsListView::maximumFirstIndex_data() { - QTest::addColumn<QStringList>("items"); - QTest::addColumn<int>("wholeVisibleItems"); - QTest::addColumn<int>("additionalVisibleSpace"); - QTest::addColumn<int>("expectedMaximum"); - - QTest::newRow("4 items fully visible") << (QStringList() - << "First" - << "Second" - << "Third" - << "Fourth") - << 4 << 0 << 0; - - QTest::newRow("3 items fully visible") << (QStringList() - << "First" - << "Second" - << "Third") - << 3 << 0 << 0; + QTest::addColumn<int>("count"); + QTest::addColumn<int>("orientation"); + QTest::addColumn<QSizeF>("size"); + QTest::addColumn<int>("maximumFirstIndex"); + + QTest::newRow("no items, vertical, all visible") + << 0 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0; + + QTest::newRow("one item, vertical, all visible") + << 5 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0; + + QTest::newRow("five items, vertical, all visible") + << 5 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0; + + QTest::newRow("six items, vertical") + << 6 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 1; + + QTest::newRow("ten items, vertical") + << 10 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 5; + + QTest::newRow("no items, horizontal, all visible") + << 0 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0; + + QTest::newRow("one item, horizontal, all visible") + << 5 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0; + + QTest::newRow("five items, horizontal, all visible") + << 5 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0; + + QTest::newRow("six items, horizontal") + << 6 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 1; + + QTest::newRow("ten items, horizontal") + << 10 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 5; } void tst_QtGraphicsListView::maximumFirstIndex() { - QFETCH(QStringList, items); - QFETCH(int, wholeVisibleItems); - QFETCH(int, additionalVisibleSpace); - QFETCH(int, expectedMaximum); + QFETCH(int, count); + QFETCH(int, orientation); + QFETCH(QSizeF, size); + QFETCH(int, maximumFirstIndex); QtListDefaultModel model; - for (int i = 0; i < items.count(); ++i) - model.insertItem(i, new QtListDefaultItem(items.at(i))); + for (int i = 0; i < count; ++i) + model.insertItem(i, new QtListDefaultItem()); - listView->setModel(&model); - listView->doLayout(); + view->setOrientation(static_cast<Qt::Orientation>(orientation)); + view->setGeometry(QRectF(QPointF(0, 0), size)); + view->setViewItemCreator(new QtGraphicsListViewItemCreator<GraphicsListViewItem>()); + view->setModel(&model); + view->doLayout(); - int width = 200; - int height = listView->viewItems().first()->preferredSize().height() * wholeVisibleItems + additionalVisibleSpace; - listView->setGeometry(QRectF(0, 0, width, height)); - QCOMPARE(listView->maximumFirstIndex(), expectedMaximum); + QCOMPARE(view->maximumFirstIndex(), maximumFirstIndex); } -void tst_QtGraphicsListView::itemAtVertical() +void tst_QtGraphicsListView::itemAt_data() { - QtListDefaultModel model; - for (int i = 0; i < 10; ++i) { - QtListDefaultItem *item = new QtListDefaultItem(QString("Item %1").arg(i)); - item->setSizeHint(QSizeF(100, 50+i)); // provide for some nice sizing hints ;) - model.insertItem(i, item); - } - listView->setModel(&model); - // this generates row-bottoms as follows; - // row: 0 50 - // row: 1 101 - // row: 2 153 - // row: 3 206 - // row: 4 260 - // row: 5 315 - // row: 6 371 - // row: 7 428 - // row: 8 486 - // row: 9 545 - - - listView->doLayout(); - QCOMPARE(listView->itemAt(QPointF(0, 0)), 0); - QCOMPARE(listView->itemAt(QPointF(99, 50)), 0); - QCOMPARE(listView->itemAt(QPointF(100, 50)), 0); - QCOMPARE(listView->itemAt(QPointF(100, 51)), 1); - QCOMPARE(listView->itemAt(QPointF(170, 51)), 1); - QCOMPARE(listView->itemAt(QPointF(10, 545)), 9); - QCOMPARE(listView->itemAt(QPointF(10, 546)), -1); - - // setting the firstIndex will make the itemAt be repositioned to the new baseline. - // meaning all y positions are offset by -153 - int expectedYOffset = 153; - listView->setFirstIndex(3); - QCOMPARE(listView->itemAt(QPointF(0, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(99, 206-expectedYOffset)), 3); - QCOMPARE(listView->itemAt(QPointF(100, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(170, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(10, 545-expectedYOffset)), 9); - QCOMPARE(listView->itemAt(QPointF(10, 546-expectedYOffset)), -1); - - listView->setHorizontalOffset(10); // should have no effect. - QCOMPARE(listView->itemAt(QPointF(0, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(99, 206-expectedYOffset)), 3); - QCOMPARE(listView->itemAt(QPointF(100, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(170, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(10, 545-expectedYOffset)), 9); - QCOMPARE(listView->itemAt(QPointF(10, 546-expectedYOffset)), -1); - - // vertical offset has an effect too - listView->setVerticalOffset(21); - expectedYOffset += 21; - QCOMPARE(listView->itemAt(QPointF(0, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(99, 206-expectedYOffset)), 3); - QCOMPARE(listView->itemAt(QPointF(100, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(170, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(10, 545-expectedYOffset)), 9); - QCOMPARE(listView->itemAt(QPointF(10, 546-expectedYOffset)), -1); - - listView->setVerticalOffset(-21); - expectedYOffset -= 21 * 2; - // a negative offset means we move the items down in the view and thus some white space - // appears above. The listView does not show any items that come before the firstIndex! - QCOMPARE(listView->itemAt(QPointF(0, 0)), -1); - QCOMPARE(listView->itemAt(QPointF(0, 21)), 3); - QCOMPARE(listView->itemAt(QPointF(99, 206-expectedYOffset)), 3); - QCOMPARE(listView->itemAt(QPointF(100, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(170, 207-expectedYOffset)), 4); - QCOMPARE(listView->itemAt(QPointF(10, 545-expectedYOffset)), 9); - QCOMPARE(listView->itemAt(QPointF(10, 546-expectedYOffset)), -1); + QTest::addColumn<int>("count"); + QTest::addColumn<int>("orientation"); + QTest::addColumn<QSizeF>("size"); + QTest::addColumn<int>("firstIndex"); + QTest::addColumn<qreal>("horizontalOffset"); + QTest::addColumn<qreal>("verticalOffset"); + QTest::addColumn<QPointF>("position"); + QTest::addColumn<int>("expectedIndex"); + + QTest::newRow("no items, vertical") + << 0 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QPointF() + << -1; + + QTest::newRow("one item, vertical, all visible") + << 1 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QPointF(50, 10) + << 0; + + QTest::newRow("five items, vertical, all visible") + << 5 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QPointF(50, 90) + << 4; + + QTest::newRow("ten items, vertical, first index five") + << 10 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 5 + << 0. << 0. + << QPointF(50, 90) + << 9; + + QTest::newRow("ten items, vertical, vertical offset") + << 10 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 100. + << QPointF(50, 90) + << 9; + + QTest::newRow("no items, horizontal") + << 0 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QPointF() + << -1; + + QTest::newRow("one item, horizontal, all visible") + << 1 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QPointF(10, 50) + << 0; + + QTest::newRow("five items, horizontal, all visible") + << 5 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QPointF(90, 50) + << 4; + + QTest::newRow("ten items, horizontal, first index five") + << 10 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 5 + << 0. << 0. + << QPointF(90, 50) + << 9; + + QTest::newRow("ten items, horizontal, horizontal offset") + << 10 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 100. << 0. + << QPointF(90, 50) + << 9; + } -void tst_QtGraphicsListView::itemAtHorizontal() +void tst_QtGraphicsListView::itemAt() { - listView->setOrientation(Qt::Horizontal); + QFETCH(int, count); + QFETCH(int, orientation); + QFETCH(QSizeF, size); + QFETCH(int, firstIndex); + QFETCH(qreal, horizontalOffset); + QFETCH(qreal, verticalOffset); + QFETCH(QPointF, position); + QFETCH(int, expectedIndex); + QtListDefaultModel model; - for (int i = 0; i < 10; ++i) { - QtListDefaultItem *item = new QtListDefaultItem(QString("Item %1").arg(i)); - item->setSizeHint(QSizeF(50+i, 100)); // provide for some nice sizing hints ;) - model.insertItem(i, item); - } - listView->setModel(&model); - // this generates row-right-edges as follows; - // column: 0 50 - // column: 1 101 - // column: 2 153 - // column: 3 206 - // column: 4 260 - // column: 5 315 - // column: 6 371 - // column: 7 428 - // column: 8 486 - // column: 9 545 - - listView->doLayout(); - QCOMPARE(listView->itemAt(QPointF(0, 0)), 0); - QCOMPARE(listView->itemAt(QPointF(50, 99)), 0); - QCOMPARE(listView->itemAt(QPointF(50, 100)), 0); - QCOMPARE(listView->itemAt(QPointF(51, 100)), 1); - QCOMPARE(listView->itemAt(QPointF(51, 170)), 1); - QCOMPARE(listView->itemAt(QPointF(545, 10)), 9); - QCOMPARE(listView->itemAt(QPointF(546, 10)), -1); - - // setting the firstIndex will make the itemAt be repositioned to the new baseline. - // meaning all y positions are offset by -153 - int expectedXOffset = 153; - listView->setFirstIndex(3); - QCOMPARE(listView->itemAt(QPointF(0, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(206-expectedXOffset, 99)), 3); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 100)), 4); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 170)), 4); - QCOMPARE(listView->itemAt(QPointF(545-expectedXOffset, 10)), 9); - QCOMPARE(listView->itemAt(QPointF(546-expectedXOffset, 10)), -1); - - listView->setVerticalOffset(10); // should have no effect. - QCOMPARE(listView->itemAt(QPointF(0, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(206-expectedXOffset, 99)), 3); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 100)), 4); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 170)), 4); - QCOMPARE(listView->itemAt(QPointF(545-expectedXOffset, 10)), 9); - QCOMPARE(listView->itemAt(QPointF(546-expectedXOffset, 10)), -1); - - // horizontalOffset offset has an effect too - listView->setHorizontalOffset(21); - expectedXOffset += 21; - QCOMPARE(listView->itemAt(QPointF(0, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(206-expectedXOffset, 99)), 3); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 100)), 4); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 170)), 4); - QCOMPARE(listView->itemAt(QPointF(545-expectedXOffset, 10)), 9); - QCOMPARE(listView->itemAt(QPointF(546-expectedXOffset, 10)), -1); - - listView->setHorizontalOffset(-21); - expectedXOffset -= 21 * 2; - // a negative offset means we move the items right in the view and thus some white space - // appears left of them. The listView does not show any items that come before the firstIndex! - QCOMPARE(listView->itemAt(QPointF(0, 0)), -1); - QCOMPARE(listView->itemAt(QPointF(21, 0)), 3); - QCOMPARE(listView->itemAt(QPointF(206-expectedXOffset, 99)), 3); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 100)), 4); - QCOMPARE(listView->itemAt(QPointF(207-expectedXOffset, 170)), 4); - QCOMPARE(listView->itemAt(QPointF(545-expectedXOffset, 10)), 9); - QCOMPARE(listView->itemAt(QPointF(546-expectedXOffset, 10)), -1); + for (int i = 0; i < count; ++i) + model.insertItem(i, new QtListDefaultItem()); + + view->setOrientation(static_cast<Qt::Orientation>(orientation)); + view->setGeometry(QRectF(QPointF(0, 0), size)); + view->setViewItemCreator(new QtGraphicsListViewItemCreator<GraphicsListViewItem>()); + view->setModel(&model); + view->setFirstIndex(firstIndex); + view->setHorizontalOffset(horizontalOffset); + view->setVerticalOffset(verticalOffset); + view->doLayout(); + + QCOMPARE(view->itemAt(position), expectedIndex); } -void tst_QtGraphicsListView::layoutPositioningVertical() +void tst_QtGraphicsListView::layout_data() { - QtListDefaultModel model; - for (int i = 0; i < 10; ++i) { - QtListDefaultItem *item = new QtListDefaultItem(QString("Item %1").arg(i)); - item->setSizeHint(QSizeF(100, 50+i)); // provide for some nice sizing hints ;) - model.insertItem(i, item); - } - listView->setModel(&model); - listView->setGeometry(0, 0, 200, 206); - QVERIFY(listView->children().isEmpty()); - listView->doLayout(); - - QCOMPARE(listView->childItems().count(), 4); - QList<int> visibleItems; - visibleItems << 0 << 1 << 2 << 3; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } - - listView->setFirstIndex(2); - listView->setGeometry(0, 0, 200, 260); - listView->doLayout(); - QCOMPARE(listView->childItems().count(), 5); // would fit 0 till 4, but not 2 till 6 ;) - visibleItems.clear(); - visibleItems << 2 << 3 << 4 << 5 << 6; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } - - listView->setFirstIndex(1); - listView->doLayout(); - QCOMPARE(listView->childItems().count(), 5); - visibleItems.clear(); - visibleItems << 1 << 2 << 3 << 4 << 5; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } - - listView->setFirstIndex(7); - listView->setGeometry(0, 0, 200, 115); - listView->doLayout(); - QCOMPARE(listView->childItems().count(), 2); - visibleItems.clear(); - visibleItems << 7 << 8; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } + QTest::addColumn<int>("count"); + QTest::addColumn<int>("orientation"); + QTest::addColumn<QSizeF>("size"); + QTest::addColumn<int>("firstIndex"); + QTest::addColumn<qreal>("horizontalOffset"); + QTest::addColumn<qreal>("verticalOffset"); + QTest::addColumn<QList<QRectF> >("expectedGeometries"); + QTest::addColumn<QList<int> >("expectedIndexes"); + + QTest::newRow("no items, vertical") + << 0 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QList<QRectF>() + << QList<int>(); + + + QTest::newRow("one item, vertical, all visible") + << 1 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << (QList<QRectF>() << QRectF(0, 0, 20, 20)) + << (QList<int>() << 0); + + + QTest::newRow("five items, vertical, all visible") + << 5 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << (QList<QRectF>() + << QRectF(0, 0, 20, 20) + << QRectF(0, 20, 20, 20) + << QRectF(0, 40, 20, 20) + << QRectF(0, 60, 20, 20) + << QRectF(0, 80, 20, 20)) + << (QList<int>() + << 0 << 1 << 2 << 3 << 4); + + QTest::newRow("ten items, vertical, five visible") + << 10 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << (QList<QRectF>() + << QRectF(0, 0, 20, 20) + << QRectF(0, 20, 20, 20) + << QRectF(0, 40, 20, 20) + << QRectF(0, 60, 20, 20) + << QRectF(0, 80, 20, 20)) + << (QList<int>() + << 0 << 1 << 2 << 3 << 4); + + QTest::newRow("ten items, vertical, five visible, first item five") + << 10 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 5 + << 0. << 0. + << (QList<QRectF>() + << QRectF(0, 0, 20, 20) + << QRectF(0, 20, 20, 20) + << QRectF(0, 40, 20, 20) + << QRectF(0, 60, 20, 20) + << QRectF(0, 80, 20, 20)) + << (QList<int>() + << 5 << 6 << 7 << 8 << 9); + + QTest::newRow("ten items, vertical, five visible, vertical offset") + << 10 + << int(Qt::Vertical) + << QSizeF(100, 100) + << 0 + << 0. << 10. + << (QList<QRectF>() + << QRectF(0, -10, 20, 20) + << QRectF(0, 10, 20, 20) + << QRectF(0, 30, 20, 20) + << QRectF(0, 50, 20, 20) + << QRectF(0, 70, 20, 20) + << QRectF(0, 90, 20, 20)) + << (QList<int>() + << 0 << 1 << 2 << 3 << 4 << 5); + + QTest::newRow("no items, horizontal") + << 0 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << QList<QRectF>() + << QList<int>(); + + + QTest::newRow("one item, horizontal, all visible") + << 1 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << (QList<QRectF>() << QRectF(0, 0, 20, 20)) + << (QList<int>() << 0); + + + QTest::newRow("five items, horizontal, all visible") + << 5 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << (QList<QRectF>() + << QRectF(0, 0, 20, 20) + << QRectF(20, 0, 20, 20) + << QRectF(40, 0, 20, 20) + << QRectF(60, 0, 20, 20) + << QRectF(80, 0, 20, 20)) + << (QList<int>() + << 0 << 1 << 2 << 3 << 4); + + QTest::newRow("ten items, horizontal, five visible") + << 10 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 0. << 0. + << (QList<QRectF>() + << QRectF(0, 0, 20, 20) + << QRectF(20, 0, 20, 20) + << QRectF(40, 0, 20, 20) + << QRectF(60, 0, 20, 20) + << QRectF(80, 0, 20, 20)) + << (QList<int>() + << 0 << 1 << 2 << 3 << 4); + + QTest::newRow("ten items, horizontal, five visible, first item five") + << 10 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 5 + << 0. << 0. + << (QList<QRectF>() + << QRectF(0, 0, 20, 20) + << QRectF(20, 0, 20, 20) + << QRectF(40, 0, 20, 20) + << QRectF(60, 0, 20, 20) + << QRectF(80, 0, 20, 20)) + << (QList<int>() + << 5 << 6 << 7 << 8 << 9); + + QTest::newRow("ten items, horizontal, five visible, horizontal offset") + << 10 + << int(Qt::Horizontal) + << QSizeF(100, 100) + << 0 + << 10. << 0. + << (QList<QRectF>() + << QRectF(-10, 0, 20, 20) + << QRectF(10, 0, 20, 20) + << QRectF(30, 0, 20, 20) + << QRectF(50, 0, 20, 20) + << QRectF(70, 0, 20, 20) + << QRectF(90, 0, 20, 20)) + << (QList<int>() + << 0 << 1 << 2 << 3 << 4 << 5); } -void tst_QtGraphicsListView::layoutPositioningHorizontal() +void tst_QtGraphicsListView::layout() { - QtListDefaultModel model; - listView->setOrientation(Qt::Horizontal); - for (int i = 0; i < 10; ++i) { - QtListDefaultItem *item = new QtListDefaultItem(QString("Item %1").arg(i)); - item->setSizeHint(QSizeF(50+i, 100)); // provide for some nice sizing hints ;) - model.insertItem(i, item); - } - listView->setModel(&model); - listView->setGeometry(0, 0, 206, 200); - QVERIFY(listView->children().isEmpty()); - listView->updateLayout(); - - QCOMPARE(listView->childItems().count(), 4); - QList<int> visibleItems; - visibleItems << 0 << 1 << 2 << 3; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } - - listView->setFirstIndex(2); - listView->setGeometry(0, 0, 260, 200); - listView->doLayout(); - QCOMPARE(listView->childItems().count(), 5); - visibleItems.clear(); - visibleItems << 2 << 3 << 4 << 5 << 6; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } + QFETCH(int, count); + QFETCH(int, orientation); + QFETCH(QSizeF, size); + QFETCH(int, firstIndex); + QFETCH(qreal, horizontalOffset); + QFETCH(qreal, verticalOffset); + QFETCH(QList<QRectF>, expectedGeometries); + QFETCH(QList<int>, expectedIndexes); - listView->setFirstIndex(1); - listView->doLayout(); - QCOMPARE(listView->childItems().count(), 5); - visibleItems.clear(); - visibleItems << 1 << 2 << 3 << 4 << 5; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); - } - - listView->setFirstIndex(7); - listView->setGeometry(0, 0, 115, 200); - listView->doLayout(); - QCOMPARE(listView->childItems().count(), 2); - visibleItems.clear(); - visibleItems << 7 << 8; - foreach (QGraphicsItem *child, listView->childItems()) { - QtGraphicsListViewItem *item = dynamic_cast<QtGraphicsListViewItem*>(child); - QVERIFY(item); - //qDebug() << item->index(); - QVERIFY(visibleItems.contains(item->index())); + QtListDefaultModel model; + for (int i = 0; i < count; ++i) + model.insertItem(i, new QtListDefaultItem()); + + view->setOrientation(static_cast<Qt::Orientation>(orientation)); + view->setGeometry(QRectF(QPointF(0, 0), size)); + view->setViewItemCreator(new QtGraphicsListViewItemCreator<GraphicsListViewItem>()); + view->setModel(&model); + view->setFirstIndex(firstIndex); + view->setHorizontalOffset(horizontalOffset); + view->setVerticalOffset(verticalOffset); + view->doLayout(); + + QCOMPARE(view->viewItems().count(), expectedGeometries.count()); + QCOMPARE(view->viewItems().count(), expectedIndexes.count()); + for (int j = 0; j < expectedGeometries.count(); ++j) { + QCOMPARE(view->viewItems().at(j)->geometry(), expectedGeometries.at(j)); + QCOMPARE(view->viewItems().at(j)->index(), expectedIndexes.at(j)); } } QTEST_MAIN(tst_QtGraphicsListView) -#include <tst_qgraphicslistview.moc> +#include "tst_qgraphicslistview.moc" diff --git a/tests/qgraphicspathview/tst_qgraphicspathview.cpp b/tests/qgraphicspathview/tst_qgraphicspathview.cpp index 4b74f3f..4cc8e10 100644 --- a/tests/qgraphicspathview/tst_qgraphicspathview.cpp +++ b/tests/qgraphicspathview/tst_qgraphicspathview.cpp @@ -73,4 +73,4 @@ void tst_QtGraphicsPathView::getSetCheck() } QTEST_MAIN(tst_QtGraphicsPathView) -#include <tst_qgraphicspathview.moc> +#include "tst_qgraphicspathview.moc" diff --git a/tests/qgraphicstableview/tst_qgraphicstableview.cpp b/tests/qgraphicstableview/tst_qgraphicstableview.cpp index 437cb46..b2928ad 100644 --- a/tests/qgraphicstableview/tst_qgraphicstableview.cpp +++ b/tests/qgraphicstableview/tst_qgraphicstableview.cpp @@ -73,4 +73,4 @@ void tst_QtGraphicsTableView::getSetCheck() } QTEST_MAIN(tst_QtGraphicsTableView) -#include <tst_qgraphicstableview.moc> +#include "tst_qgraphicstableview.moc" diff --git a/tests/qgraphicstreeview/tst_qgraphicstreeview.cpp b/tests/qgraphicstreeview/tst_qgraphicstreeview.cpp index 8e1864e..920e1d7 100644 --- a/tests/qgraphicstreeview/tst_qgraphicstreeview.cpp +++ b/tests/qgraphicstreeview/tst_qgraphicstreeview.cpp @@ -73,4 +73,4 @@ void tst_QtGraphicsTreeView::getSetCheck() } QTEST_MAIN(tst_QtGraphicsTreeView) -#include <tst_qgraphicstreeview.moc> +#include "tst_qgraphicstreeview.moc" diff --git a/tests/qlistdefaultmodel/tst_qlistdefaultmodel.cpp b/tests/qlistdefaultmodel/tst_qlistdefaultmodel.cpp index f3d9a34..e910a06 100644 --- a/tests/qlistdefaultmodel/tst_qlistdefaultmodel.cpp +++ b/tests/qlistdefaultmodel/tst_qlistdefaultmodel.cpp @@ -39,12 +39,24 @@ public slots: void cleanup(); private slots: - void signalsCheck(); + void getSetCheck(); + void appendItems_data(); + void appendItems(); + void insertItems_data(); + void insertItems(); + void removeItems_data(); + void removeItems(); + void moveItems_data(); + void moveItems(); + void setData_data(); + void setData(); protected: QtListDefaultModel *model; }; +Q_DECLARE_METATYPE(QList<int>) + tst_QtListDefaultModel::tst_QtListDefaultModel() { } @@ -71,85 +83,396 @@ void tst_QtListDefaultModel::cleanup() delete model; } -void tst_QtListDefaultModel::signalsCheck() -{ - QSignalSpy inserted(model, SIGNAL(itemsInserted(int, int))); - QVERIFY(inserted.isValid()); - QSignalSpy removed(model, SIGNAL(itemsRemoved(int, int))); - QVERIFY(removed.isValid()); - QSignalSpy moved(model, SIGNAL(itemsMoved(int, int, int))); - QVERIFY(moved.isValid()); - QSignalSpy changed(model, SIGNAL(itemsChanged(int, int, const QList<int>&))); - QVERIFY(changed.isValid()); - - QtListDefaultItem *item1 = new QtListDefaultItem("foo"); - model->appendItem(item1); - QCOMPARE(inserted.count(), 1); - QCOMPARE(removed.count(), 0); - QCOMPARE(moved.count(), 0); - QCOMPARE(changed.count(), 0); - QCOMPARE(model->count(), 1); - - inserted.clear(); - QtListDefaultItem *item2 = new QtListDefaultItem("bar"); - model->insertItem(0, item2); - QCOMPARE(inserted.count(), 1); - QCOMPARE(removed.count(), 0); - QCOMPARE(moved.count(), 0); - QCOMPARE(changed.count(), 0); - QCOMPARE(model->count(), 2); - QCOMPARE(model->item(0), item2); - QCOMPARE(model->item(1), item1); - - QList<int> roles; - roles << QtListModelInterface::TextRole << 19284; - QHash<int, QVariant> answer = model->data(0, roles); - QCOMPARE(answer.count(), 1); - QVERIFY(answer.contains(QtListModelInterface::TextRole)); - QCOMPARE(answer[QtListModelInterface::TextRole].toString(), QString("bar")); - - answer = model->data(2, roles); - QCOMPARE(answer.count(), 0); - - inserted.clear(); - QHash<int,QVariant> ignoreMe; - ignoreMe.insert(QtListModelInterface::TextRole, "ignoreMe"); - model->setData(3, ignoreMe); // index out of range - QCOMPARE(inserted.count(), 0); - QCOMPARE(removed.count(), 0); - QCOMPARE(moved.count(), 0); - QCOMPARE(changed.count(), 0); - - QHash<int,QVariant> newTitle; - newTitle.insert(QtListModelInterface::TextRole, "newTitle"); - model->setData(0, newTitle); - QCOMPARE(inserted.count(), 0); - QCOMPARE(removed.count(), 0); - QCOMPARE(moved.count(), 0); - QCOMPARE(changed.count(), 1); - QList<QVariant> change = changed.at(0); - QCOMPARE(change.count(), 3); - QCOMPARE(change.at(0).toInt(), 0); - QCOMPARE(change.at(1).toInt(), 1); - - model->moveItem(0, 1); - changed.clear(); - QCOMPARE(inserted.count(), 0); - QCOMPARE(removed.count(), 0); - QCOMPARE(moved.count(), 1); - QCOMPARE(changed.count(), 0); - - moved.clear(); - model->clear(); - QCOMPARE(inserted.count(), 0); - QCOMPARE(removed.count(), 1); - QCOMPARE(moved.count(), 0); - QCOMPARE(changed.count(), 0); - QList<QVariant> removedEmit = removed.at(0); - QCOMPARE(removedEmit.count(), 2); - QCOMPARE(removedEmit.at(0).toInt(), 0); - QCOMPARE(removedEmit.at(1).toInt(), 2); +void tst_QtListDefaultModel::getSetCheck() +{ +} + +void tst_QtListDefaultModel::appendItems_data() +{ + QTest::addColumn<QStringList>("appendItems"); + QTest::addColumn<QStringList>("expectedItems"); + QTest::addColumn<int>("signalCount"); + QTest::addColumn<QList<int> >("signalArgs"); + + QTest::newRow("no items") + << QStringList() + << QStringList() + << 0 + << QList<int>(); + + QTest::newRow("one item") + << (QStringList() << "one") + << (QStringList() << "one") + << 1 + << (QList<int>() << 0 << 1); // index, count + + QTest::newRow("three items") + << (QStringList() << "one" << "two" << "three") + << (QStringList() << "one" << "two" << "three") + << 3 + << (QList<int>() + << 0 << 1 // index, count + << 1 << 1 + << 2 << 1); +} + +void tst_QtListDefaultModel::appendItems() +{ + QFETCH(QStringList, appendItems); + QFETCH(QStringList, expectedItems); + QFETCH(int, signalCount); + QFETCH(QList<int>, signalArgs); + + QSignalSpy itemsInserted(model, SIGNAL(itemsInserted(int,int))); + + for (int i = 0; i < appendItems.count(); ++i) + model->appendItem(new QtListDefaultItem(appendItems.at(i))); + + QCOMPARE(model->count(), expectedItems.count()); + for (int j = 0; j < expectedItems.count(); ++j) { + QtListDefaultItem *item = model->item(j); + QVERIFY(!!item); + QCOMPARE(item->text(), expectedItems.at(j)); + } + + QCOMPARE(itemsInserted.count(), signalCount); + for (int k = 0; k < signalCount; ++k) { + QList<QVariant> args = itemsInserted.at(k); + for (int l = 0; l < args.count(); ++l) { + int signalArgCount = signalArgs.count()/signalCount; + int m = (k * signalArgCount) + l; + QCOMPARE(args.at(l).toInt(), signalArgs.at(m)); + } + } +} + +void tst_QtListDefaultModel::insertItems_data() +{ + QTest::addColumn<QStringList>("initialItems"); + QTest::addColumn<int>("insertAt"); + QTest::addColumn<QStringList>("insertItems"); + QTest::addColumn<QStringList>("expectedItems"); + QTest::addColumn<int>("signalCount"); + QTest::addColumn<QList<int> >("signalArgs"); + + QTest::newRow("no items") + << QStringList() + << 0 + << QStringList() + << QStringList() + << 0 + << QList<int>(); + + QTest::newRow("no items, insert one") + << QStringList() + << 0 + << (QStringList() << "one") + << (QStringList() << "one") + << 1 + << (QList<int>() << 0 << 1); // index, count + + QTest::newRow("no items, insert one at -1") + << QStringList() + << -1 + << (QStringList() << "one") + << (QStringList() << "one") + << 1 + << (QList<int>() << 0 << 1); + + QTest::newRow("no items, insert one at INT_MAX") + << QStringList() + << INT_MAX + << (QStringList() << "one") + << (QStringList() << "one") + << 1 + << (QList<int>() << 0 << 1); + + QTest::newRow("two items, insert one before") + << (QStringList() << "two" << "three") + << 0 + << (QStringList() << "one") + << (QStringList() << "one" << "two" << "three") + << 3 + << (QList<int>() + << 0 << 1 // index, count + << 1 << 1 + << 0 << 1); + + QTest::newRow("two items, insert one in the middle") + << (QStringList() << "one" << "three") + << 1 + << (QStringList() << "two") + << (QStringList() << "one" << "two" << "three") + << 3 + << (QList<int>() + << 0 << 1 + << 1 << 1 + << 1 << 1); + + QTest::newRow("two items, insert one after") + << (QStringList() << "one" << "two") + << 2 + << (QStringList() << "three") + << (QStringList() << "one" << "two" << "three") + << 3 + << (QList<int>() + << 0 << 1 + << 1 << 1 + << 2 << 1); +} + +void tst_QtListDefaultModel::insertItems() +{ + QFETCH(QStringList, initialItems); + QFETCH(int, insertAt); + QFETCH(QStringList, insertItems); + QFETCH(QStringList, expectedItems); + QFETCH(int, signalCount); + QFETCH(QList<int>, signalArgs); + + QSignalSpy itemsInserted(model, SIGNAL(itemsInserted(int,int))); + + for (int i = 0; i < initialItems.count(); ++i) + model->appendItem(new QtListDefaultItem(initialItems.at(i))); + QCOMPARE(model->count(), initialItems.count()); + + for (int j = 0; j < insertItems.count(); ++j) + model->insertItem(insertAt + j, new QtListDefaultItem(insertItems.at(j))); + + QCOMPARE(model->count(), expectedItems.count()); + for (int k = 0; k < expectedItems.count(); ++k) { + QtListDefaultItem *item = model->item(k); + QVERIFY(!!item); + QCOMPARE(item->text(), expectedItems.at(k)); + } + + QCOMPARE(itemsInserted.count(), signalCount); + for (int k = 0; k < signalCount; ++k) { + QList<QVariant> args = itemsInserted.at(k); + for (int l = 0; l < args.count(); ++l) { + int signalArgCount = signalArgs.count()/signalCount; + int m = (k * signalArgCount) + l; + QCOMPARE(args.at(l).toInt(), signalArgs.at(m)); + } + } +} + +void tst_QtListDefaultModel::removeItems_data() +{ + QTest::addColumn<QStringList>("initialItems"); + QTest::addColumn<int>("removeAt"); + QTest::addColumn<int>("removeCount"); + QTest::addColumn<QStringList>("expectedItems"); + QTest::addColumn<int>("signalCount"); + QTest::addColumn<QList<int> >("signalArgs"); + + QTest::newRow("no items") + << QStringList() + << 0 + << 0 + << QStringList() + << 0 + << QList<int>(); + + QTest::newRow("one item, remove one") + << (QStringList() << "one") + << 0 + << 1 + << QStringList() + << 1 + << (QList<int>() << 0 << 1); + + QTest::newRow("two items, remove first") + << (QStringList() << "one" << "two") + << 0 + << 1 + << (QStringList() << "two") + << 1 + << (QList<int>() << 0 << 1); + + QTest::newRow("two items, remove second") + << (QStringList() << "one" << "two") + << 1 + << 1 + << (QStringList() << "one") + << 1 + << (QList<int>() << 1 << 1); + + QTest::newRow("three items, remove middle") + << (QStringList() << "one" << "two" << "three") + << 1 + << 1 + << (QStringList() << "one" << "three") + << 1 + << (QList<int>() << 1 << 1); + + QTest::newRow("three items, remove first two") + << (QStringList() << "one" << "two" << "three") + << 0 + << 2 + << (QStringList() << "three") + << 2 + << (QList<int>() + << 0 << 1 + << 0 << 1); + + QTest::newRow("three items, remove last two") + << (QStringList() << "one" << "two" << "three") + << 1 + << 2 + << (QStringList() << "one") + << 2 + << (QList<int>() + << 1 << 1 + << 1 << 1); +} + +void tst_QtListDefaultModel::removeItems() +{ + QFETCH(QStringList, initialItems); + QFETCH(int, removeAt); + QFETCH(int, removeCount); + QFETCH(QStringList, expectedItems); + QFETCH(int, signalCount); + QFETCH(QList<int>, signalArgs); + + QSignalSpy itemsRemoved(model, SIGNAL(itemsRemoved(int,int))); + + for (int i = 0; i < initialItems.count(); ++i) + model->appendItem(new QtListDefaultItem(initialItems.at(i))); + QCOMPARE(model->count(), initialItems.count()); + + for (int j = 0; j < removeCount; ++j) + model->removeItem(removeAt); + + QCOMPARE(model->count(), expectedItems.count()); + for (int k = 0; k < expectedItems.count(); ++k) { + QtListDefaultItem *item = model->item(k); + QVERIFY(!!item); + QCOMPARE(item->text(), expectedItems.at(k)); + } + + QCOMPARE(itemsRemoved.count(), signalCount); + for (int k = 0; k < signalCount; ++k) { + QList<QVariant> args = itemsRemoved.at(k); + for (int l = 0; l < args.count(); ++l) { + int signalArgCount = signalArgs.count()/signalCount; + int m = (k * signalArgCount) + l; + QCOMPARE(args.at(l).toInt(), signalArgs.at(m)); + } + } +} + +void tst_QtListDefaultModel::moveItems_data() +{ + QTest::addColumn<QStringList>("initialItems"); + QTest::addColumn<int>("moveFrom"); + QTest::addColumn<int>("moveTo"); + QTest::addColumn<int>("moveCount"); + QTest::addColumn<QStringList>("expectedItems"); + QTest::addColumn<int>("signalCount"); + QTest::addColumn<QList<int> >("signalArgs"); + + QTest::newRow("no items") + << QStringList() + << 0 + << 0 + << 0 + << QStringList() + << 0 + << QList<int>(); + + QTest::newRow("three items, move one") + << (QStringList() << "one" << "two" << "three") + << 0 + << 1 + << 1 + << (QStringList() << "two" << "one" << "three") + << 1 + << (QList<int>() << 0 << 1 << 1); + + QTest::newRow("three items, move two") + << (QStringList() << "one" << "two" << "three") + << 0 + << 1 + << 2 + << (QStringList() << "one" << "two" << "three") + << 2 + << (QList<int>() + << 0 << 1 << 1 + << 0 << 1 << 1); + + QTest::newRow("three items, move three back") + << (QStringList() << "one" << "two" << "three") + << 0 + << 2 + << 3 + << (QStringList() << "one" << "two" << "three") + << 3 + << (QList<int>() + << 0 << 2 << 1 + << 0 << 2 << 1 + << 0 << 2 << 1); + + QTest::newRow("three items, move three front") + << (QStringList() << "one" << "two" << "three") + << 2 + << 0 + << 3 + << (QStringList() << "one" << "two" << "three") + << 3 + << (QList<int>() + << 2 << 0 << 1 + << 2 << 0 << 1 + << 2 << 0 << 1); +} + +void tst_QtListDefaultModel::moveItems() +{ + QFETCH(QStringList, initialItems); + QFETCH(int, moveFrom); + QFETCH(int, moveTo); + QFETCH(int, moveCount); + QFETCH(QStringList, expectedItems); + QFETCH(int, signalCount); + QFETCH(QList<int>, signalArgs); + + QSignalSpy itemsRemoved(model, SIGNAL(itemsMoved(int,int,int))); + + for (int i = 0; i < initialItems.count(); ++i) + model->appendItem(new QtListDefaultItem(initialItems.at(i))); + QCOMPARE(model->count(), initialItems.count()); + + for (int j = 0; j < moveCount; ++j) + model->moveItem(moveFrom, moveTo); + + QCOMPARE(model->count(), expectedItems.count()); + for (int k = 0; k < expectedItems.count(); ++k) { + QtListDefaultItem *item = model->item(k); + QVERIFY(!!item); + QCOMPARE(item->text(), expectedItems.at(k)); + } + + QCOMPARE(itemsRemoved.count(), signalCount); + for (int k = 0; k < signalCount; ++k) { + QList<QVariant> args = itemsRemoved.at(k); + for (int l = 0; l < args.count(); ++l) { + int signalArgCount = signalArgs.count()/signalCount; + int m = (k * signalArgCount) + l; + QCOMPARE(args.at(l).toInt(), signalArgs.at(m)); + } + } +} + +void tst_QtListDefaultModel::setData_data() +{ + // ### FIXME : add data +} + +void tst_QtListDefaultModel::setData() +{ + // ### FIXME: add test } QTEST_MAIN(tst_QtListDefaultModel) -#include <tst_qlistdefaultmodel.moc> +#include "tst_qlistdefaultmodel.moc" diff --git a/tests/qlistmodeladaptor/tst_qlistmodeladaptor.cpp b/tests/qlistmodeladaptor/tst_qlistmodeladaptor.cpp index b7d53ca..d148d5a 100644 --- a/tests/qlistmodeladaptor/tst_qlistmodeladaptor.cpp +++ b/tests/qlistmodeladaptor/tst_qlistmodeladaptor.cpp @@ -21,58 +21,10 @@ ** ****************************************************************************/ #include <QtTest/QtTest> +#include <QtGui/qstandarditemmodel.h> #include <qlistmodeladaptor.h> -class MockOldListModel : public QAbstractListModel -{ -public: - int rowCount(const QModelIndex &parent=QModelIndex()) const - { - if (parent.isValid()) - return 0; - if (m_data.isEmpty()) - return 0; - QList<QVariant> data = m_data.value(m_data.keys().first()); - return data.count(); - } - - QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const - { - const_cast<MockOldListModel*>(this)->m_lastRequestedIndex = index; - if (!index.isValid() || index.parent().isValid() || index.model() != this) - return QVariant(); - if (index.column() != 0) - return QVariant(); - if (!m_data.contains(role)) - return QVariant(); - QList<QVariant> data = m_data.value(role); - if (index.row() < 0 || data.count() <= index.row()) - return QVariant(); - return QVariant(data.at(index.row())); - } - - void insertStuff(int role, QList<QVariant> data) { - if (! m_data.isEmpty()) { - QList<QVariant> existingData = m_data.value(m_data.keys().first()); - QCOMPARE(data.count(), existingData.count()); - } - QVERIFY(role >= 0 && role <= 13); // only allow valid roles - m_data.insert(role, data); - } - - void insertStrings(QStringList data) { - QList<QVariant> var; - foreach(const QString &string, data) - var << QVariant(string); - insertStuff(Qt::DisplayRole, var); - } - - QHash<int, QList<QVariant> > m_data; - - QModelIndex m_lastRequestedIndex; -}; - class tst_QtListModelAdaptor : public QObject { Q_OBJECT @@ -88,15 +40,23 @@ public slots: void cleanup(); private slots: - void checkGetData(); + void count_data(); + void count(); + void getData_data(); + void getData(); + void setData_data(); + void setData(); protected: - MockOldListModel *oldModel; - QtListModelAdaptor *model; + QStandardItemModel *source; + QtListModelAdaptor *adaptor; }; +Q_DECLARE_METATYPE(QList<int>) + tst_QtListModelAdaptor::tst_QtListModelAdaptor() { + qRegisterMetaType<QList<int> >(); } tst_QtListModelAdaptor::~tst_QtListModelAdaptor() @@ -105,16 +65,14 @@ tst_QtListModelAdaptor::~tst_QtListModelAdaptor() void tst_QtListModelAdaptor::initTestCase() { - oldModel = new MockOldListModel(); - model = new QtListModelAdaptor(oldModel); + source = new QStandardItemModel(); + adaptor = new QtListModelAdaptor(source); } void tst_QtListModelAdaptor::cleanupTestCase() { - delete oldModel; - oldModel = 0; - delete model; - model = 0; + delete source; + delete adaptor; } void tst_QtListModelAdaptor::init() @@ -123,41 +81,125 @@ void tst_QtListModelAdaptor::init() void tst_QtListModelAdaptor::cleanup() { + source->clear(); +} + +void tst_QtListModelAdaptor::count_data() +{ + QTest::addColumn<int>("itemCount"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no items") << 0 << 0; + QTest::newRow("one items") << 1 << 1; + QTest::newRow("two items") << 2 << 1; + QTest::newRow("many items") << 10000 << 1; +} + +void tst_QtListModelAdaptor::count() +{ + QFETCH(int, itemCount); + QFETCH(int, signalCount); + + QSignalSpy itemsInserted(adaptor, SIGNAL(itemsInserted(int,int))); + source->setRowCount(itemCount); + QCOMPARE(adaptor->count(), itemCount); + QCOMPARE(itemsInserted.count(), signalCount); +} + +void tst_QtListModelAdaptor::getData_data() +{ + QTest::addColumn<QStringList>("items"); + QTest::addColumn<int>("role"); + QTest::addColumn<QStringList>("data"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no items") + << QStringList() + << int(Qt::DisplayRole) + << QStringList() + << 0; + + QTest::newRow("three items") + << (QStringList() << "one" << "two" << "three") + << int(Qt::DisplayRole) + << (QStringList() << "four" << "five" << "six") + << 3; +} + +void tst_QtListModelAdaptor::getData() +{ + QFETCH(QStringList, items); + QFETCH(int, role); + QFETCH(QStringList, data); + QFETCH(int, signalCount); + + QSignalSpy itemsChanged(adaptor, SIGNAL(itemsChanged(int,int,const QList<int>&))); + + for (int i = 0; i < items.count(); ++i) + source->appendRow(new QStandardItem(items.at(i))); + + QCOMPARE(adaptor->count(), items.count()); + for (int j = 0; j < items.count(); ++j) + QCOMPARE(adaptor->data(j, QList<int>() << role).value(role).toString(), items.at(j)); + + for (int k = 0; k < data.count(); ++k) + source->setData(source->index(k, 0), data.at(k), role); + + for (int l = 0; l < data.count(); ++l) + QCOMPARE(adaptor->data(l, QList<int>() << role).value(role).toString(), data.at(l)); + + QCOMPARE(itemsChanged.count(), signalCount); +} + +void tst_QtListModelAdaptor::setData_data() +{ + QTest::addColumn<QStringList>("items"); + QTest::addColumn<int>("role"); + QTest::addColumn<QStringList>("data"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no items") + << QStringList() + << int(Qt::DisplayRole) + << QStringList() + << 0; + + QTest::newRow("three items") + << (QStringList() << "one" << "two" << "three") + << int(Qt::DisplayRole) + << (QStringList() << "four" << "five" << "six") + << 3; } -void tst_QtListModelAdaptor::checkGetData() +void tst_QtListModelAdaptor::setData() { - QStringList data; - data << "One" << "two" << "Mad" << "Cow" << "Flies"; - oldModel->insertStrings(data); - QCOMPARE(model->model(), oldModel); - QVERIFY(!model->rootIndex().parent().isValid()); - QCOMPARE(model->column(), 0); - QCOMPARE(model->count(), 5); - - QHash<int, QVariant> answer; - QList<int> roles; - roles << QtListModelInterface::TextRole; - answer = model->data(4, roles); - QCOMPARE(answer.count(), 1); - QVERIFY(answer.contains(QtListModelInterface::TextRole)); - QCOMPARE(answer.value(QtListModelInterface::TextRole).toString(), data[4]); - answer = model->data(5, roles); - QCOMPARE(answer.count(), 1); - QVERIFY(answer.contains(QtListModelInterface::TextRole)); - QVERIFY(!answer.value(QtListModelInterface::TextRole).isValid()); - - roles << QtListModelInterface::IconRole; - - answer = model->data(2, roles); - QCOMPARE(answer.count(), 2); - QVERIFY(answer.contains(QtListModelInterface::TextRole)); - QVERIFY(answer.contains(QtListModelInterface::IconRole)); - QCOMPARE(answer.value(QtListModelInterface::TextRole).toString(), data[2]); - QVERIFY(!answer.value(QtListModelInterface::IconRole).isValid()); + QFETCH(QStringList, items); + QFETCH(int, role); + QFETCH(QStringList, data); + QFETCH(int, signalCount); + + QSignalSpy itemsChanged(adaptor, SIGNAL(itemsChanged(int,int,const QList<int>&))); + + for (int i = 0; i < items.count(); ++i) + source->appendRow(new QStandardItem(items.at(i))); + + QCOMPARE(adaptor->count(), items.count()); + for (int j = 0; j < items.count(); ++j) + QCOMPARE(adaptor->data(j, QList<int>() << role).value(role).toString(), items.at(j)); + + for (int k = 0; k < data.count(); ++k) { + QHash<int, QVariant> hash; + hash.insert(role, data.at(k)); + adaptor->setData(k, hash); + } + + for (int l = 0; l < data.count(); ++l) + QCOMPARE(source->data(source->index(l, 0), role).toString(), data.at(l)); + + QCOMPARE(itemsChanged.count(), signalCount); } QTEST_MAIN(tst_QtListModelAdaptor) -#include <tst_qlistmodeladaptor.moc> +#include "tst_qlistmodeladaptor.moc" diff --git a/tests/qlistselectionmanager/tst_qlistselectionmanager.cpp b/tests/qlistselectionmanager/tst_qlistselectionmanager.cpp index 998a5cb..4821aa0 100644 --- a/tests/qlistselectionmanager/tst_qlistselectionmanager.cpp +++ b/tests/qlistselectionmanager/tst_qlistselectionmanager.cpp @@ -40,6 +40,12 @@ class tst_QtListSelectionManager : public QObject Q_OBJECT public: + enum SelectionMode { + Select = QtListSelectionManager::Select, + Deselect = QtListSelectionManager::Deselect, + Toggle = QtListSelectionManager::Toggle + }; + tst_QtListSelectionManager(); virtual ~tst_QtListSelectionManager(); @@ -126,7 +132,7 @@ void tst_QtListSelectionManager::currentItem_data() QTest::addColumn<int>("changedCurrent"); QTest::addColumn<int>("signalCount"); - QTest::newRow("no data") + QTest::newRow("no model") << false << 0 // model << -1 << 0 // initial << 0 << -1 // set/get @@ -135,6 +141,15 @@ void tst_QtListSelectionManager::currentItem_data() << 0 << 0 << 0 // move << -1 << 0; // changed/signals + QTest::newRow("no data") + << true << 0 + << -1 << 0 + << 0 << -1 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << -1 << 0; + QTest::newRow("before first") << true << 10 << 0 << 0 @@ -244,7 +259,7 @@ void tst_QtListSelectionManager::anchorItem_data() QTest::addColumn<int>("changedAnchor"); QTest::addColumn<int>("signalCount"); - QTest::newRow("no data") + QTest::newRow("no model") << false << 0 // model << -1 << 0 // initial << 0 << -1 // set/get @@ -253,6 +268,15 @@ void tst_QtListSelectionManager::anchorItem_data() << 0 << 0 << 0 // move << -1 << 0; // changed/signals + QTest::newRow("no data") + << true << 0 + << -1 << 0 + << 0 << -1 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << -1 << 0; + QTest::newRow("before first") << true << 10 << 0 << 0 @@ -348,7 +372,7 @@ void tst_QtListSelectionManager::selections_data() QTest::addColumn<bool>("useModel"); QTest::addColumn<int>("itemCount"); QTest::addColumn<QList<int> >("newSelectionIndexes"); - QTest::addColumn<QList<bool> >("newSelectionStates"); + QTest::addColumn<QList<int> >("newSelectionModes"); QTest::addColumn<QList<int> >("expectedSelectionIndexes"); QTest::addColumn<int>("insertAt"); QTest::addColumn<int>("insertCount"); @@ -360,18 +384,36 @@ void tst_QtListSelectionManager::selections_data() QTest::addColumn<QList<int> >("changedSelectionIndexes"); QTest::addColumn<int>("signalCount"); - QTest::newRow("no data") + QTest::newRow("no model") << false << 0 // model - << QList<int>() << QList<bool>() << QList<int>() // initial + << QList<int>() << QList<int>() << QList<int>() // initial << 0 << 0 // insert << 0 << 0 // remove << 0 << 0 << 0 // move << QList<int>() // changed - << 0; // signal + << 0; // signal - QTest::newRow("no data, one selection") + QTest::newRow("no model, one selection") << false << 0 - << (QList<int>() << 3) << (QList<bool>() << true) << QList<int>() + << (QList<int>() << 3) << (QList<int>() << int(Select)) << QList<int>() + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << QList<int>() + << 0; + + QTest::newRow("no data") + << true << 0 + << QList<int>() << QList<int>() << QList<int>() + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << QList<int>() + << 0; + + QTest::newRow("no data, one selection") + << true << 0 + << (QList<int>() << 3) << (QList<int>() << int(Select)) << QList<int>() << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -380,7 +422,7 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("no selections") << true << 10 - << QList<int>() << QList<bool>() << QList<int>() + << QList<int>() << QList<int>() << QList<int>() << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -389,7 +431,7 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("one selection") << true << 10 - << (QList<int>() << 3) << (QList<bool>() << true) << (QList<int>() << 3) + << (QList<int>() << 3) << (QList<int>() << int(Select)) << (QList<int>() << 3) << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -398,7 +440,7 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("two selections") << true << 10 - << (QList<int>() << 3 << 5) << (QList<bool>() << true << true) << (QList<int>() << 3 << 5) + << (QList<int>() << 3 << 5) << (QList<int>() << int(Select) << int(Select)) << (QList<int>() << 3 << 5) << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -407,7 +449,7 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("one selection, one de-selection") << true << 10 - << (QList<int>() << 3 << 3) << (QList<bool>() << true << false) << QList<int>() + << (QList<int>() << 3 << 3) << (QList<int>() << int(Select) << int(Deselect)) << QList<int>() << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -416,7 +458,7 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("two selections, one de-selection") << true << 10 - << (QList<int>() << 3 << 5 << 3) << (QList<bool>() << true << true << false) << (QList<int>() << 5) + << (QList<int>() << 3 << 5 << 3) << (QList<int>() << int(Select) << int(Select) << int(Deselect)) << (QList<int>() << 5) << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -425,7 +467,7 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("two out of range selections") << true << 10 - << (QList<int>() << -1 << INT_MAX) << (QList<bool>() << true << true) << QList<int>() + << (QList<int>() << -1 << INT_MAX) << (QList<int>() << int(Select) << int(Select)) << QList<int>() << 0 << 0 << 0 << 0 << 0 << 0 << 0 @@ -434,43 +476,43 @@ void tst_QtListSelectionManager::selections_data() QTest::newRow("no selections, one insertion") << true << 10 - << QList<int>() << QList<bool>() << QList<int>() + << QList<int>() << QList<int>() << QList<int>() << 4 << 1 << 0 << 0 << 0 << 0 << 0 << QList<int>() << 0; - QTest::newRow("one selections, one insertion before") + QTest::newRow("one selection, one insertion before") << true << 10 - << (QList<int>() << 3) << (QList<bool>() << true) << (QList<int>() << 3) + << (QList<int>() << 3) << (QList<int>() << int(Select)) << (QList<int>() << 3) << 2 << 1 << 0 << 0 << 0 << 0 << 0 << (QList<int>() << 4) << 2; // selection and insertion - QTest::newRow("one selections, one insertion after") + QTest::newRow("one selection, one insertion after") << true << 10 - << (QList<int>() << 3) << (QList<bool>() << true) << (QList<int>() << 3) + << (QList<int>() << 3) << (QList<int>() << int(Select)) << (QList<int>() << 3) << 4 << 1 << 0 << 0 << 0 << 0 << 0 << (QList<int>() << 3) << 1; // selection - QTest::newRow("one selections, one removal before") + QTest::newRow("one selection, one removal before") << true << 10 - << (QList<int>() << 3) << (QList<bool>() << true) << (QList<int>() << 3) + << (QList<int>() << 3) << (QList<int>() << int(Select)) << (QList<int>() << 3) << 0 << 0 << 2 << 1 << 0 << 0 << 0 << (QList<int>() << 2) << 2; // selection and removal - QTest::newRow("one selections, one removal after") + QTest::newRow("one selection, one removal after") << true << 10 - << (QList<int>() << 3) << (QList<bool>() << true) << (QList<int>() << 3) + << (QList<int>() << 3) << (QList<int>() << int(Select)) << (QList<int>() << 3) << 0 << 0 << 4 << 1 << 0 << 0 << 0 @@ -483,7 +525,7 @@ void tst_QtListSelectionManager::selections() QFETCH(bool, useModel); QFETCH(int, itemCount); QFETCH(QList<int>, newSelectionIndexes); - QFETCH(QList<bool>, newSelectionStates); + QFETCH(QList<int>, newSelectionModes); QFETCH(QList<int>, expectedSelectionIndexes); QFETCH(int, insertAt); QFETCH(int, insertCount); @@ -510,7 +552,7 @@ void tst_QtListSelectionManager::selections() // set and check selection for (int a = 0; a < newSelectionIndexes.count(); ++a) - manager->setSelected(newSelectionIndexes.at(a), newSelectionStates.at(a)); + manager->setSelected(newSelectionIndexes.at(a), 1, QtListSelectionManager::SelectionMode(newSelectionModes.at(a))); QList<int> selectedItems = manager->selectedItems(); QCOMPARE(selectedItems.count(), expectedSelectionIndexes.count()); for (int b = 0; b < expectedSelectionIndexes.count(); ++b) @@ -543,7 +585,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::addColumn<bool>("useModel"); QTest::addColumn<int>("itemCount"); QTest::addColumn<QList<int> >("initialSelectionIndexes"); - QTest::addColumn<bool>("toggle"); + QTest::addColumn<int>("mode"); QTest::addColumn<int>("anchorIndex"); QTest::addColumn<int>("currentIndex"); QTest::addColumn<QList<int> >("expectedSelectionIndexes"); @@ -558,22 +600,22 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::addColumn<QList<int> >("commitedSelectionIndexes"); QTest::addColumn<int>("signalCount"); - QTest::newRow("no data") - << false << 0 // model - << QList<int>() // initial - << false << 0 << 0 // range - << QList<int>() // expected - << 0 << 0 // insert - << 0 << 0 // remove - << 0 << 0 << 0 // move - << QList<int>() // changed - << QList<int>() // commited - << 0; // signals + QTest::newRow("no model") + << false << 0 // model + << QList<int>() // initial + << int(Select) << 0 << 0 // range + << QList<int>() // expected + << 0 << 0 // insert + << 0 << 0 // remove + << 0 << 0 << 0 // move + << QList<int>() // changed + << QList<int>() // commited + << 0; // signals QTest::newRow("valid range") << true << 10 << QList<int>() - << false << 4 << 7 + << int(Select) << 4 << 7 << (QList<int>() << 4 << 5 << 6 << 7) << 0 << 0 << 0 << 0 @@ -585,7 +627,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("reversed valid range") << true << 10 << QList<int>() - << false << 7 << 4 + << int(Select) << 7 << 4 << (QList<int>() << 4 << 5 << 6 << 7) << 0 << 0 << 0 << 0 @@ -597,7 +639,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("invalid anchor") << true << 10 << QList<int>() - << false << -1 << 3 + << int(Select) << -1 << 3 << (QList<int>() << 0 << 1 << 2 << 3) << 0 << 0 << 0 << 0 @@ -609,7 +651,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("invalid current") << true << 10 << QList<int>() - << false << 6 << INT_MAX + << int(Select) << 6 << INT_MAX << (QList<int>() << 6 << 7 << 8 << 9) << 0 << 0 << 0 << 0 @@ -621,7 +663,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("same anchor and current") << true << 10 << QList<int>() - << false << 4 << 4 + << int(Select) << 4 << 4 << (QList<int>() << 4) << 0 << 0 << 0 << 0 @@ -633,7 +675,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("valid range, one insert above") << true << 10 << QList<int>() - << false << 4 << 7 + << int(Select) << 4 << 7 << (QList<int>() << 4 << 5 << 6 << 7) << 1 << 1 << 0 << 0 @@ -645,7 +687,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("valid range, one insert below") << true << 10 << QList<int>() - << false << 4 << 7 + << int(Select) << 4 << 7 << (QList<int>() << 4 << 5 << 6 << 7) << 8 << 1 << 0 << 0 @@ -657,7 +699,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("valid range, one removal above") << true << 10 << QList<int>() - << false << 4 << 7 + << int(Select) << 4 << 7 << (QList<int>() << 4 << 5 << 6 << 7) << 0 << 0 << 1 << 1 @@ -669,7 +711,7 @@ void tst_QtListSelectionManager::anchoredSelections_data() QTest::newRow("valid range, one removal below") << true << 10 << QList<int>() - << false << 4 << 7 + << int(Select) << 4 << 7 << (QList<int>() << 4 << 5 << 6 << 7) << 0 << 0 << 8 << 1 @@ -684,7 +726,7 @@ void tst_QtListSelectionManager::anchoredSelections() QFETCH(bool, useModel); QFETCH(int, itemCount); QFETCH(QList<int>, initialSelectionIndexes); - QFETCH(bool, toggle); + QFETCH(int, mode); QFETCH(int, anchorIndex); QFETCH(int, currentIndex); QFETCH(QList<int>, expectedSelectionIndexes); @@ -714,10 +756,10 @@ void tst_QtListSelectionManager::anchoredSelections() // set initial selection for (int a = 0; a < initialSelectionIndexes.count(); ++a) - manager->setSelected(initialSelectionIndexes.at(a), true); + manager->setSelected(initialSelectionIndexes.at(a), 1, QtListSelectionManager::Select); // set anchor and mode - manager->beginAnchoredSelection(anchorIndex, toggle ? QtListSelectionManager::Toggle : QtListSelectionManager::Select); + manager->beginAnchoredSelection(anchorIndex, QtListSelectionManager::SelectionMode(mode)); // set current to make a selected range manager->setCurrentItem(currentIndex); diff --git a/tests/qsectionspans/tst_qsectionspans.cpp b/tests/qsectionspans/tst_qsectionspans.cpp index e7178e0..7e3515f 100644 --- a/tests/qsectionspans/tst_qsectionspans.cpp +++ b/tests/qsectionspans/tst_qsectionspans.cpp @@ -93,12 +93,13 @@ void tst_QSectionSpans::setValue_data() QTest::addColumn<QList<int> >("spanCounts"); QTest::addColumn<QList<int> >("expectedValues"); - QTest::newRow("-") << 0 - << (QList<int>() << 2 << 5 << 7 << 8 << 9) - << (QList<int>() << 10 << 100 << 1000 << 1000 << 1000) - << (QList<int>() << 0 << 10 << 0 << 100 << 0 << 1000) - << (QList<int>() << 2 << 1 << 2 << 1 << 1 << 3) - << (QList<int>() << 0 << 0 << 10 << 0 << 0 << 100 << 0 << 1000 << 1000 << 1000); + QTest::newRow("-") + << 0 + << (QList<int>() << 2 << 5 << 7 << 8 << 9) + << (QList<int>() << 10 << 100 << 1000 << 1000 << 1000) + << (QList<int>() << 0 << 10 << 0 << 100 << 0 << 1000) + << (QList<int>() << 2 << 1 << 2 << 1 << 1 << 3) + << (QList<int>() << 0 << 0 << 10 << 0 << 0 << 100 << 0 << 1000 << 1000 << 1000); } void tst_QSectionSpans::setValue() @@ -179,13 +180,14 @@ void tst_QSectionSpans::removeSectionsAt_data() QTest::addColumn<QList<int> >("spanCounts"); QTest::addColumn<QList<int> >("expectedValues"); - QTest::newRow("-") << 0 - << (QList<int>() << 2 << 5 << 7 << 8 << 9) - << (QList<int>() << 10 << 100 << 1000 << 1000 << 1000) - << (QList<int>() << 2 << 5 << 8) - << (QList<int>() << 0 << 1000) - << (QList<int>() << 5 << 2) - << (QList<int>() << 0 << 0 << 0 << 0 << 0 << 1000 << 1000); + QTest::newRow("-") + << 0 + << (QList<int>() << 2 << 5 << 7 << 8 << 9) + << (QList<int>() << 10 << 100 << 1000 << 1000 << 1000) + << (QList<int>() << 2 << 5 << 8) + << (QList<int>() << 0 << 1000) + << (QList<int>() << 5 << 2) + << (QList<int>() << 0 << 0 << 0 << 0 << 0 << 1000 << 1000); } void tst_QSectionSpans::removeSectionsAt() diff --git a/tests/qtablemodeladaptor/tst_qtablemodeladaptor.cpp b/tests/qtablemodeladaptor/tst_qtablemodeladaptor.cpp index 5b4ba4e..c708501 100644 --- a/tests/qtablemodeladaptor/tst_qtablemodeladaptor.cpp +++ b/tests/qtablemodeladaptor/tst_qtablemodeladaptor.cpp @@ -71,5 +71,5 @@ void tst_QtTableModelAdaptor::checkGetData() QTEST_MAIN(tst_QtTableModelAdaptor) -#include <tst_qtablemodeladaptor.moc> +#include "tst_qtablemodeladaptor.moc" diff --git a/tests/qtableselectionmanager/tst_qtableselectionmanager.cpp b/tests/qtableselectionmanager/tst_qtableselectionmanager.cpp index 56b92f6..be314fa 100644 --- a/tests/qtableselectionmanager/tst_qtableselectionmanager.cpp +++ b/tests/qtableselectionmanager/tst_qtableselectionmanager.cpp @@ -25,10 +25,13 @@ #include <qtableselectionmanager.h> #include <qtabledefaultmodel.h> -class MockTableSelectionManager : public QtTableSelectionManager +class TableSelectionManager : public QtTableSelectionManager { public: - void setModel(QtTableModelInterface *model) {QtTableSelectionManager::setModel(model); } + inline void setModel(QtTableModelInterface *model) + { + QtTableSelectionManager::setModel(model); + } }; class tst_QtTableSelectionManager : public QObject @@ -36,6 +39,12 @@ class tst_QtTableSelectionManager : public QObject Q_OBJECT public: + enum SelectionMode { + Select = QtTableSelectionManager::Select, + Deselect = QtTableSelectionManager::Deselect, + Toggle = QtTableSelectionManager::Toggle + }; + tst_QtTableSelectionManager(); virtual ~tst_QtTableSelectionManager(); @@ -47,21 +56,29 @@ public slots: private slots: void getSetCheck(); - void setSelection(); - void toggleSelection(); - void testSignals(); - void modelChanges(); - void setAnchorCell(); + void currentCell_data(); + void currentCell(); + void anchorCell_data(); + void anchorCell(); + void selections_data(); + void selections(); + void anchoredSelections_data(); + void anchoredSelections(); private: - MockTableSelectionManager *sm; + TableSelectionManager *manager; QtTableDefaultModel *model; }; Q_DECLARE_METATYPE(QList<int>) +Q_DECLARE_METATYPE(QList<bool>) +Q_DECLARE_METATYPE(QtTableSelectionRange) +Q_DECLARE_METATYPE(QList<QtTableSelectionRange>) tst_QtTableSelectionManager::tst_QtTableSelectionManager() + : manager(0), model(0) { + qRegisterMetaType<QtTableSelectionRange>("QtTableSelectionRange"); } tst_QtTableSelectionManager::~tst_QtTableSelectionManager() @@ -78,323 +95,611 @@ void tst_QtTableSelectionManager::cleanupTestCase() void tst_QtTableSelectionManager::init() { + manager = new TableSelectionManager(); model = new QtTableDefaultModel(); - model->setRowCount(5); - model->setColumnCount(8); - sm = new MockTableSelectionManager(); - sm->setModel(model); + manager->setModel(model); } void tst_QtTableSelectionManager::cleanup() { + delete manager; delete model; - delete sm; - sm = 0; - model = 0; } void tst_QtTableSelectionManager::getSetCheck() { - QCOMPARE(sm->model(), model); - QCOMPARE(sm->currentRow(), -1); - QCOMPARE(sm->currentColumn(), -1); - QCOMPARE(sm->currentCell().first, -1); - QCOMPARE(sm->currentCell().second, -1); - for (int x = 0; x < 9; ++x) { - for (int y = 0; y < 6; ++y) { - QCOMPARE(sm->isSelected(y, x), false); - } - } +} - sm->setCurrentCell(1, 0); - QCOMPARE(sm->currentRow(), 1); - QCOMPARE(sm->currentColumn(), 0); - QCOMPARE(sm->isSelected(1, 0), false); - - sm->setCurrentCell(10, 3); - QCOMPARE(sm->currentRow(), 4); - QCOMPARE(sm->currentColumn(), 3); - QCOMPARE(sm->isSelected(1, 0), false); - QCOMPARE(sm->isSelected(10, 3), false); - QCOMPARE(sm->isSelected(5, 3), false); - - sm->setCurrentCell(2, 7); - QCOMPARE(sm->currentRow(), 2); - QCOMPARE(sm->currentColumn(), 7); - - sm->setCurrentCell(4, 8); - QCOMPARE(sm->currentRow(), 4); - QCOMPARE(sm->currentColumn(), 7); +/* + Note that current cell and anchor cell should behave the same. + So if you modify one test, make sure you also modify the other. + */ +void tst_QtTableSelectionManager::currentCell_data() +{ + QTest::addColumn<bool>("useModel"); + QTest::addColumn<int>("rowCount"); + QTest::addColumn<int>("columnCount"); + QTest::addColumn<int>("initialCurrentRow"); + QTest::addColumn<int>("initialCurrentColumn"); + QTest::addColumn<int>("newCurrentRow"); + QTest::addColumn<int>("newCurrentColumn"); + QTest::addColumn<int>("expectedCurrentRow"); + QTest::addColumn<int>("expectedCurrentColumn"); + QTest::addColumn<int>("insertRowsAt"); + QTest::addColumn<int>("insertRowCount"); + QTest::addColumn<int>("insertColumnsAt"); + QTest::addColumn<int>("insertColumnCount"); + QTest::addColumn<int>("removeRowsAt"); + QTest::addColumn<int>("removeRowCount"); + QTest::addColumn<int>("removeColumnsAt"); + QTest::addColumn<int>("removeColumnCount"); + QTest::addColumn<int>("moveRowsFrom"); + QTest::addColumn<int>("moveRowsTo"); + QTest::addColumn<int>("moveRowCount"); + QTest::addColumn<int>("moveColumnsFrom"); + QTest::addColumn<int>("moveColumnsTo"); + QTest::addColumn<int>("moveColumnCount"); + QTest::addColumn<int>("changedCurrentRow"); + QTest::addColumn<int>("changedCurrentColumn"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no model") + << false // use model + << 0 << 0 // cell count + << -1 << -1 // current cell + << 0 << 0 // new current + << -1 << -1 // expected current + << 0 << 0 // insert rows + << 0 << 0 // insert columns + << 0 << 0 // remove rows + << 0 << 0 // remove columns + << 0 << 0 << 0 // move rows + << 0 << 0 << 0 // move columns + << -1 << -1 // changed current + << 0; // signals + + QTest::newRow("no data") + << true + << 0 << 0 + << -1 << -1 + << 0 << 0 + << -1 << -1 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << -1 << -1 + << 0; + + QTest::newRow("before first row") + << true + << 10 << 10 + << 0 << 0 + << -1 << -1 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 + << 0; + + QTest::newRow("valid") + << true + << 10 << 10 + << 0 << 0 + << 4 << 4 + << 4 << 4 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << 4 << 4 + << 1; + + QTest::newRow("after last row") + << true + << 10 << 10 + << 0 << 0 + << 10 << 10 + << 9 << 9 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << 9 << 9 + << 1; } -void tst_QtTableSelectionManager::setSelection() +void tst_QtTableSelectionManager::currentCell() { - // we start with no selection - for (int col = 0; col < 8; ++col) - for (int row = 0; row < 5; ++row) - QCOMPARE(sm->isSelected(row, col), false); - - QtTableSelectionRange range(1, 1, 3, 3); - sm->setSelected(range); - - QCOMPARE(sm->isSelected(0, 0), false); - QCOMPARE(sm->isSelected(1, 0), false); - QCOMPARE(sm->isSelected(0, 1), false); - QCOMPARE(sm->isSelected(1, 1), true); - QCOMPARE(sm->isSelected(3, 3), true); - QCOMPARE(sm->isSelected(4, 3), false); - QCOMPARE(sm->isSelected(3, 4), false); - QCOMPARE(sm->isSelected(4, 4), false); - QCOMPARE(sm->isSelected(14, 14), false); - - sm->setSelected(0, 3, 5, 10); - for (int i=0; i < 3; ++i) - QCOMPARE(sm->isSelected(0, i), false); - for (int y = 0; y < 5; ++y) { - for (int x=3; x < 8; ++x) { - //qDebug() << "isSelected" << y << x; - QCOMPARE(sm->isSelected(y, x), true); - } - } - QCOMPARE(sm->isSelected(3, 0), false); - QCOMPARE(sm->isSelected(3, 1), true); - QCOMPARE(sm->isSelected(4, 1), false); - - sm->toggleSelection(0, 1, 4, 1); - QCOMPARE(sm->isSelected(0, 1), true); - QCOMPARE(sm->isSelected(1, 1), false); - QCOMPARE(sm->isSelected(2, 1), false); - QCOMPARE(sm->isSelected(3, 1), false); - QCOMPARE(sm->isSelected(4, 1), true); - QCOMPARE(sm->isSelected(5, 1), false); + QFETCH(bool, useModel); + QFETCH(int, rowCount); + QFETCH(int, columnCount); + QFETCH(int, initialCurrentRow); + QFETCH(int, initialCurrentColumn); + QFETCH(int, newCurrentRow); + QFETCH(int, newCurrentColumn); + QFETCH(int, expectedCurrentRow); + QFETCH(int, expectedCurrentColumn); + QFETCH(int, insertRowsAt); + QFETCH(int, insertRowCount); + QFETCH(int, insertColumnsAt); + QFETCH(int, insertColumnCount); + QFETCH(int, removeRowsAt); + QFETCH(int, removeRowCount); + QFETCH(int, removeColumnsAt); + QFETCH(int, removeColumnCount); + QFETCH(int, moveRowsFrom); + QFETCH(int, moveRowsTo); + QFETCH(int, moveRowCount); + QFETCH(int, moveColumnsFrom); + QFETCH(int, moveColumnsTo); + QFETCH(int, moveColumnCount); + QFETCH(int, changedCurrentRow); + QFETCH(int, changedCurrentColumn); + QFETCH(int, signalCount); + + QSignalSpy currentChanged(manager, SIGNAL(currentChanged(int,int,int,int))); + + // start without model + manager->setModel(0); + + // setup the model row and column count + model->setRowCount(rowCount); + model->setColumnCount(columnCount); + + // with or without data model + manager->setModel(useModel ? model : 0); + QCOMPARE(manager->model(), (useModel ? model : 0)); + + // check initial current item and selection + QCOMPARE(manager->currentRow(), initialCurrentRow); + QCOMPARE(manager->currentColumn(), initialCurrentColumn); + //QCOMPARE(manager->selectionRanges().count(), selectionRangesCount); + + // set current cell + manager->setCurrentCell(newCurrentRow, newCurrentColumn); + QCOMPARE(manager->currentRow(), expectedCurrentRow); + QCOMPARE(manager->currentColumn(), expectedCurrentColumn); + //QCOMPARE(manager->selectionRanges().count(), selectionRangesCount); + + // insert rows + for (int i = insertRowsAt; i < insertRowCount; ++i) + model->insertRow(i); + + // insert columns + for (int j = insertColumnsAt; j < insertColumnCount; ++j) + model->insertColumn(j); + + // remove rows + for (int k = removeRowsAt; k < removeRowCount; ++k) + model->removeRow(k); + + // remove columns + for (int l = removeColumnsAt; l < removeColumnCount; ++l) + model->removeColumn(l); + + // move rows + for (int m = 0; m < moveRowCount; ++m) + model->moveRow(moveRowsFrom, moveRowsTo + m); + + // move columns + for (int n = 0; n < moveColumnCount; ++n) + model->moveColumn(moveColumnsFrom, moveColumnsTo + n); + + // check again + QCOMPARE(manager->currentRow(), changedCurrentRow); + QCOMPARE(manager->currentColumn(), changedCurrentColumn); + + // check signals + QCOMPARE(currentChanged.count(), signalCount); } -void tst_QtTableSelectionManager::toggleSelection() +/* + Note that current cell and anchor cell should behave the same. + So if you modify one test, make sure you also modify the other. + */ +void tst_QtTableSelectionManager::anchorCell_data() { - sm->setSelected(2, 0, 2, 8); // select one horizontal row (row=2) - for (int col = 0; col < 8; ++col) { - //qDebug() << col; - QCOMPARE(sm->isSelected(0, col), false); - QCOMPARE(sm->isSelected(1, col), false); - QCOMPARE(sm->isSelected(2, col), true); - QCOMPARE(sm->isSelected(4, col), false); - QCOMPARE(sm->isSelected(5, col), false); - } + QTest::addColumn<bool>("useModel"); + QTest::addColumn<int>("rowCount"); + QTest::addColumn<int>("columnCount"); + QTest::addColumn<int>("initialAnchorRow"); + QTest::addColumn<int>("initialAnchorColumn"); + QTest::addColumn<int>("newAnchorRow"); + QTest::addColumn<int>("newAnchorColumn"); + QTest::addColumn<int>("expectedAnchorRow"); + QTest::addColumn<int>("expectedAnchorColumn"); + QTest::addColumn<int>("insertRowsAt"); + QTest::addColumn<int>("insertRowCount"); + QTest::addColumn<int>("insertColumnsAt"); + QTest::addColumn<int>("insertColumnCount"); + QTest::addColumn<int>("removeRowsAt"); + QTest::addColumn<int>("removeRowCount"); + QTest::addColumn<int>("removeColumnsAt"); + QTest::addColumn<int>("removeColumnCount"); + QTest::addColumn<int>("moveRowsFrom"); + QTest::addColumn<int>("moveRowsTo"); + QTest::addColumn<int>("moveRowCount"); + QTest::addColumn<int>("moveColumnsFrom"); + QTest::addColumn<int>("moveColumnsTo"); + QTest::addColumn<int>("moveColumnCount"); + QTest::addColumn<int>("changedAnchorRow"); + QTest::addColumn<int>("changedAnchorColumn"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no model") + << false + << 0 << 0 // cell count + << -1 << -1 // anchor cell + << 0 << 0 // new anchor + << -1 << -1 // expected anchor + << 0 << 0 // insert rows + << 0 << 0 // insert columns + << 0 << 0 // remove rows + << 0 << 0 // remove columns + << 0 << 0 << 0 // move rows + << 0 << 0 << 0 // move columns + << -1 << -1 // changed anchor + << 0; // signals + + QTest::newRow("no data") + << true + << 0 << 0 + << -1 << -1 + << 0 << 0 + << -1 << -1 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << -1 << -1 + << 0; + + QTest::newRow("before first row") + << true + << 10 << 10 + << 0 << 0 + << -1 << -1 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 + << 0; + + QTest::newRow("valid") + << true + << 10 << 10 + << 0 << 0 + << 4 << 4 + << 4 << 4 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << 4 << 4 + << 1; + + QTest::newRow("after last row") + << true + << 10 << 10 + << 0 << 0 + << 10 << 10 + << 9 << 9 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << 9 << 9 + << 1; +} - sm->toggleSelection(0, 3, 5, 3); // toggle one vertical column (col=3). - QCOMPARE(sm->isSelected(0, 1), false); - for (int col = 0; col < 8; ++col) { - //qDebug() << col; - QCOMPARE(sm->isSelected(0, col), col == 3); - QCOMPARE(sm->isSelected(1, col), col == 3); - QCOMPARE(sm->isSelected(2, col), col != 3); - QCOMPARE(sm->isSelected(4, col), col == 3); - QCOMPARE(sm->isSelected(5, col), col == 3); - } +void tst_QtTableSelectionManager::anchorCell() +{ + QFETCH(bool, useModel); + QFETCH(int, rowCount); + QFETCH(int, columnCount); + QFETCH(int, initialAnchorRow); + QFETCH(int, initialAnchorColumn); + QFETCH(int, newAnchorRow); + QFETCH(int, newAnchorColumn); + QFETCH(int, expectedAnchorRow); + QFETCH(int, expectedAnchorColumn); + QFETCH(int, insertRowsAt); + QFETCH(int, insertRowCount); + QFETCH(int, insertColumnsAt); + QFETCH(int, insertColumnCount); + QFETCH(int, removeRowsAt); + QFETCH(int, removeRowCount); + QFETCH(int, removeColumnsAt); + QFETCH(int, removeColumnCount); + QFETCH(int, moveRowsFrom); + QFETCH(int, moveRowsTo); + QFETCH(int, moveRowCount); + QFETCH(int, moveColumnsFrom); + QFETCH(int, moveColumnsTo); + QFETCH(int, moveColumnCount); + QFETCH(int, changedAnchorRow); + QFETCH(int, changedAnchorColumn); + QFETCH(int, signalCount); + + QSignalSpy anchorChanged(manager, SIGNAL(anchorChanged(int,int,int,int))); + + // start without model + manager->setModel(0); + + // setup the model row and column count + model->setRowCount(rowCount); + model->setColumnCount(columnCount); + + // with or without data model + manager->setModel(useModel ? model : 0); + QCOMPARE(manager->model(), (useModel ? model : 0)); + + // check initial anchor item and selection + QCOMPARE(manager->anchorRow(), initialAnchorRow); + QCOMPARE(manager->anchorColumn(), initialAnchorColumn); + //QCOMPARE(manager->selectionRanges().count(), selectionRangesCount); + + // set anchor cell + manager->setAnchorCell(newAnchorRow, newAnchorColumn); + QCOMPARE(manager->anchorRow(), expectedAnchorRow); + QCOMPARE(manager->anchorColumn(), expectedAnchorColumn); + //QCOMPARE(manager->selectionRanges().count(), selectionRangesCount); + + // insert rows + for (int i = insertRowsAt; i < insertRowCount; ++i) + model->insertRow(i); + + // insert columns + for (int j = insertColumnsAt; j < insertColumnCount; ++j) + model->insertColumn(j); + + // remove rows + for (int k = removeRowsAt; k < removeRowCount; ++k) + model->removeRow(k); + + // remove columns + for (int l = removeColumnsAt; l < removeColumnCount; ++l) + model->removeColumn(l); + + // move rows + for (int m = 0; m < moveRowCount; ++m) + model->moveRow(moveRowsFrom, moveRowsTo + m); + + // move columns + for (int n = 0; n < moveColumnCount; ++n) + model->moveColumn(moveColumnsFrom, moveColumnsTo + n); + + // check again + QCOMPARE(manager->anchorRow(), changedAnchorRow); + QCOMPARE(manager->anchorColumn(), changedAnchorColumn); + + // check signals + QCOMPARE(anchorChanged.count(), signalCount); } -void tst_QtTableSelectionManager::testSignals() +void tst_QtTableSelectionManager::selections_data() { - QSignalSpy current(sm, SIGNAL(currentChanged(int,int,int,int))); - QSignalSpy selection(sm, SIGNAL(selectionsChanged(int,int,int,int))); - - // we start with no selection - for (int col = 0; col < 8; ++col) - for (int row = 0; row < 5; ++row) - QCOMPARE(sm->isSelected(row, col), false); - - sm->setCurrentCell(4, 3); - QCOMPARE(sm->currentRow(), 4); - QCOMPARE(sm->currentColumn(), 3); - for (int col = 0; col < 8; ++col) // current doesn't affect selection - for (int row = 0; row < 5; ++row) - QCOMPARE(sm->isSelected(row, col), false); - - QVERIFY(selection.isEmpty()); - QCOMPARE(current.count(), 1); - sm->setCurrentCell(4, 3); // no change - QCOMPARE(current.count(), 1); - sm->setCurrentCell(0, 0); - QCOMPARE(current.count(), 2); - - current.clear(); - sm->setCurrentCell(INT_MAX, INT_MAX); - QCOMPARE(sm->currentRow(), 4); - QCOMPARE(sm->currentColumn(), 7); - QCOMPARE(current.count(), 1); - sm->setCurrentCell(4, 7); - QCOMPARE(current.count(), 1); - sm->setCurrentCell(INT_MAX, INT_MAX); - QCOMPARE(current.count(), 1); - - QVERIFY(selection.isEmpty()); - sm->setSelected(0, 0, 2, 2); - QCOMPARE(selection.count(), 1); - QCOMPARE(current.count(), 1); - sm->clearSelections(); - QCOMPARE(selection.count(), 2); - - selection.clear(); - sm->setSelected(3, 3, 3, 3); - QCOMPARE(selection.count(), 1); - sm->setSelected(1, 3, 1, 3); - QCOMPARE(selection.count(), 2); - sm->setSelected(2, 3, 2, 3); - QCOMPARE(selection.count(), 3); // merge - - selection.clear(); - sm->toggleSelection(1, 3, 3, 3); // deselects all. - QCOMPARE(selection.count(), 1); + QTest::addColumn<bool>("useModel"); + QTest::addColumn<int>("rowCount"); + QTest::addColumn<int>("columnCount"); + QTest::addColumn<QList<QtTableSelectionRange> >("newSelections"); + QTest::addColumn<QList<int> >("newSelectionModes"); + QTest::addColumn<QList<QtTableSelectionRange> >("expectedSelections"); + QTest::addColumn<int>("insertRowsAt"); + QTest::addColumn<int>("insertRowCount"); + QTest::addColumn<int>("insertColumnsAt"); + QTest::addColumn<int>("insertColumnCount"); + QTest::addColumn<int>("removeRowsAt"); + QTest::addColumn<int>("removeRowCount"); + QTest::addColumn<int>("removeColumnsAt"); + QTest::addColumn<int>("removeColumnCount"); + QTest::addColumn<int>("moveRowsFrom"); + QTest::addColumn<int>("moveRowsTo"); + QTest::addColumn<int>("moveRowCount"); + QTest::addColumn<int>("moveColumnsFrom"); + QTest::addColumn<int>("moveColumnsTo"); + QTest::addColumn<int>("moveColumnCount"); + QTest::addColumn<QList<QtTableSelectionRange> >("changedSelections"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no model") + << false // use model + << 0 << 0 // cell count + << QList<QtTableSelectionRange>() + << QList<int>() // modes + << QList<QtTableSelectionRange>() + << 0 << 0 // insert rows + << 0 << 0 // insert columns + << 0 << 0 // remove rows + << 0 << 0 // remove columns + << 0 << 0 << 0 // move rows + << 0 << 0 << 0 // move columns + << QList<QtTableSelectionRange>() + << 0; // signals + + QTest::newRow("no model, one selection") + << false + << 0 << 0 + << (QList<QtTableSelectionRange>() << QtTableSelectionRange(0, 0, 1, 1)) + << (QList<int>() << int(Select)) + << QList<QtTableSelectionRange>() + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << QList<QtTableSelectionRange>() + << 0; + + QTest::newRow("no data") + << true + << 0 << 0 + << QList<QtTableSelectionRange>() + << QList<int>() + << QList<QtTableSelectionRange>() + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << QList<QtTableSelectionRange>() + << 0; + + QTest::newRow("no data, one selection") + << true + << 0 << 0 + << (QList<QtTableSelectionRange>() << QtTableSelectionRange(0, 0, 1, 1)) + << (QList<int>() << int(Select)) + << QList<QtTableSelectionRange>() + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << QList<QtTableSelectionRange>() + << 0; + + QTest::newRow("no selections") + << true + << 10 << 10 + << QList<QtTableSelectionRange>() + << QList<int>() + << QList<QtTableSelectionRange>() + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << QList<QtTableSelectionRange>() + << 0; + + QTest::newRow("one selection") + << true + << 10 << 10 + << (QList<QtTableSelectionRange>() << QtTableSelectionRange(0, 0, 1, 1)) + << (QList<int>() << int(Select)) + << (QList<QtTableSelectionRange>() << QtTableSelectionRange(0, 0, 1, 1)) + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 + << 0 << 0 << 0 + << 0 << 0 << 0 + << (QList<QtTableSelectionRange>() << QtTableSelectionRange(0, 0, 1, 1)) + << 0; } -void tst_QtTableSelectionManager::modelChanges() +void tst_QtTableSelectionManager::selections() { - QSignalSpy current(sm, SIGNAL(currentChanged(int,int,int,int))); - QSignalSpy selection(sm, SIGNAL(selectionsChanged(int,int,int,int))); - - sm->setCurrentCell(1,0); - QCOMPARE(sm->currentRow(), 1); - QCOMPARE(sm->currentColumn(), 0); - QCOMPARE(current.count(), 1); - model->insertRow(0); - QCOMPARE(current.count(), 2); - QCOMPARE(sm->currentRow(), 2); - QCOMPARE(sm->currentColumn(), 0); - - model->insertRow(3); - // should not change anything. - QCOMPARE(current.count(), 2); - QCOMPARE(sm->currentRow(), 2); - QCOMPARE(sm->currentColumn(), 0); - - model->removeRow(2); // removes our current cell. - // should not change anything. - QCOMPARE(current.count(), 2); - QCOMPARE(sm->currentRow(), 2); - QCOMPARE(sm->currentColumn(), 0); - - model->removeRow(0); - // should not change anything. - QCOMPARE(current.count(), 3); - QCOMPARE(sm->currentRow(), 1); - QCOMPARE(sm->currentColumn(), 0); - - // column next - current.clear(); - sm->setCurrentCell(0,1); - QCOMPARE(sm->currentRow(), 0); - QCOMPARE(sm->currentColumn(), 1); - QCOMPARE(current.count(), 1); - model->insertColumn(0); - QCOMPARE(current.count(), 2); - QCOMPARE(sm->currentRow(), 0); - QCOMPARE(sm->currentColumn(), 2); - - model->insertColumn(3); - // should not change anything. - QCOMPARE(current.count(), 2); - QCOMPARE(sm->currentRow(), 0); - QCOMPARE(sm->currentColumn(), 2); - - model->removeColumn(2); // removes our current cell. - // should not change anything. - QCOMPARE(current.count(), 2); - QCOMPARE(sm->currentRow(), 0); - QCOMPARE(sm->currentColumn(), 2); - - model->removeColumn(0); - // should not change anything. - QCOMPARE(current.count(), 3); - QCOMPARE(sm->currentRow(), 0); - QCOMPARE(sm->currentColumn(), 1); + QFETCH(bool, useModel); + QFETCH(int, rowCount); + QFETCH(int, columnCount); + QFETCH(QList<QtTableSelectionRange>, newSelections); + QFETCH(QList<int>, newSelectionModes); + QFETCH(QList<QtTableSelectionRange>, expectedSelections); + QFETCH(int, insertRowsAt); + QFETCH(int, insertRowCount); + QFETCH(int, insertColumnsAt); + QFETCH(int, insertColumnCount); + QFETCH(int, removeRowsAt); + QFETCH(int, removeRowCount); + QFETCH(int, removeColumnsAt); + QFETCH(int, removeColumnCount); + QFETCH(int, moveRowsFrom); + QFETCH(int, moveRowsTo); + QFETCH(int, moveRowCount); + QFETCH(int, moveColumnsFrom); + QFETCH(int, moveColumnsTo); + QFETCH(int, moveColumnCount); + QFETCH(QList<QtTableSelectionRange>, changedSelections); + QFETCH(int, signalCount); + + QSignalSpy selectionsChanged(manager, SIGNAL(selectionsChanged(const QList<QtTableSelectionRange>&))); + + // start without model + manager->setModel(0); + + // setup the model item count + model->setRowCount(rowCount); + model->setColumnCount(columnCount); + + // with or without data model + manager->setModel(useModel ? model : 0); + QCOMPARE(manager->model(), (useModel ? model : 0)); + + // set and check selection + for (int a = 0; a < newSelections.count(); ++a) + manager->setSelected(newSelections.at(a), QtTableSelectionManager::SelectionMode(newSelectionModes.at(a))); + QList<QtTableSelectionRange> selectionRanges = manager->selectionRanges(); + QCOMPARE(selectionRanges.count(), expectedSelections.count()); + for (int b = 0; b < expectedSelections.count(); ++b) + QCOMPARE(selectionRanges.at(b), expectedSelections.at(b)); + + // insert rows + for (int j = insertRowsAt; j < insertRowsAt + insertRowCount; ++j) + model->insertRow(j); + + // insert columns + for (int k = insertColumnsAt; k < insertColumnsAt + insertColumnCount; ++k) + model->insertColumn(k); + + // remove rows + for (int l = removeRowsAt; l < removeRowsAt + removeRowCount; ++l) + model->removeRow(l); + + // remove columns + for (int m = removeColumnsAt; m < removeColumnsAt + removeColumnCount; ++m) + model->removeColumn(m); + + // move rows + for (int n = 0; n < moveRowCount; ++n) + model->moveRow(moveRowsFrom, moveRowsTo + n); + + // move columns + for (int o = 0; o < moveColumnCount; ++o) + model->moveColumn(moveColumnsFrom, moveColumnsTo + o); + + // check selection again + selectionRanges = manager->selectionRanges(); + QCOMPARE(selectionRanges.count(), changedSelections.count()); + for (int p = 0; p < changedSelections.count(); ++p) + QCOMPARE(selectionRanges.at(p), changedSelections.at(p)); + + // check signals + QCOMPARE(selectionsChanged.count(), signalCount); +} +void tst_QtTableSelectionManager::anchoredSelections_data() +{ } -void tst_QtTableSelectionManager::setAnchorCell() +void tst_QtTableSelectionManager::anchoredSelections() { - QCOMPARE(sm->anchorRow(), -1); - QCOMPARE(sm->anchorColumn(), -1); - sm->setCurrentCell(2, 1); - QCOMPARE(sm->anchorRow(), -1); - QCOMPARE(sm->anchorColumn(), -1); - sm->setAnchorCell(4, 2); - QCOMPARE(sm->anchorRow(), 4); - QCOMPARE(sm->anchorColumn(), 2); - sm->clearCurrentCell(); - QCOMPARE(sm->anchorRow(), 4); // actually, can we have *no* current cell? - QCOMPARE(sm->anchorColumn(), 2); - - sm->setCurrentCell(2, 1); - sm->clearAnchorCell(); - QCOMPARE(sm->anchorRow(), -1); // or should this be the same as the current cell? - QCOMPARE(sm->anchorColumn(), -1); - - sm->setCurrentCell(2, 1); - sm->setAnchorCell(4, 2); - QCOMPARE(sm->isSelected(0, 0), false); - QCOMPARE(sm->isSelected(1, 1), false); - QCOMPARE(sm->isSelected(2, 1), true); - QCOMPARE(sm->isSelected(2, 2), true); - QCOMPARE(sm->isSelected(3, 2), true); - QCOMPARE(sm->isSelected(4, 2), true); - QCOMPARE(sm->isSelected(4, 3), false); - QSignalSpy current(sm, SIGNAL(currentChanged(int,int,int,int))); - QSignalSpy selection(sm, SIGNAL(selectionsChanged(int,int,int,int))); - sm->setAnchorCell(2,2); - QCOMPARE(current.count(), 0); - QCOMPARE(selection.count(), 1); - QList<QVariant> signal = selection.at(0); - QCOMPARE(signal.count(), 4); - QCOMPARE(signal.at(0).toInt(), 3); - QCOMPARE(signal.at(1).toInt(), 1); - QCOMPARE(signal.at(2).toInt(), 4); - QCOMPARE(signal.at(3).toInt(), 2); - - sm->setAnchorCell(3,3); - QCOMPARE(current.count(), 0); - QCOMPARE(selection.count(), 3); - // ordering of the signals is not important, as long as we get them. - signal = selection.at(1); - QCOMPARE(signal.at(0).toInt(), 3); - QCOMPARE(signal.at(1).toInt(), 1); - QCOMPARE(signal.at(2).toInt(), 3); - QCOMPARE(signal.at(3).toInt(), 3); - signal = selection.at(2); - QCOMPARE(signal.at(0).toInt(), 2); - QCOMPARE(signal.at(1).toInt(), 3); - QCOMPARE(signal.at(2).toInt(), 3); - QCOMPARE(signal.at(3).toInt(), 3); - - sm->setCurrentCell(3, 2); - QCOMPARE(current.count(), 1); - QCOMPARE(selection.count(), 5); - // ordering of the signals is not important, as long as we get them. - signal = selection.at(3); - QCOMPARE(signal.at(0).toInt(), 2); - QCOMPARE(signal.at(1).toInt(), 1); - QCOMPARE(signal.at(2).toInt(), 2); - QCOMPARE(signal.at(3).toInt(), 3); - signal = selection.at(4); - QCOMPARE(signal.at(0).toInt(), 2); - QCOMPARE(signal.at(1).toInt(), 1); - QCOMPARE(signal.at(2).toInt(), 3); - QCOMPARE(signal.at(3).toInt(), 1); - - selection.clear(); - current.clear(); - sm->setAnchorCell(0, 0); - QCOMPARE(current.count(), 0); - QCOMPARE(selection.count(), 3); - signal = selection.at(0); // top/right changed - QCOMPARE(signal.at(0).toInt(), 0); - QCOMPARE(signal.at(1).toInt(), 0); - QCOMPARE(signal.at(2).toInt(), 2); - QCOMPARE(signal.at(3).toInt(), 3); - signal = selection.at(1); // left - QCOMPARE(signal.at(0).toInt(), 0); - QCOMPARE(signal.at(1).toInt(), 0); - QCOMPARE(signal.at(2).toInt(), 3); - QCOMPARE(signal.at(3).toInt(), 1); } QTEST_MAIN(tst_QtTableSelectionManager) diff --git a/tests/qtableselectionrange/tst_qtableselectionrange.cpp b/tests/qtableselectionrange/tst_qtableselectionrange.cpp index 31963bf..4a968cc 100644 --- a/tests/qtableselectionrange/tst_qtableselectionrange.cpp +++ b/tests/qtableselectionrange/tst_qtableselectionrange.cpp @@ -42,8 +42,8 @@ private slots: void getSetCheck(); void intersects_data(); void intersects(); - void subtract_data(); - void subtract(); + void subtracted_data(); + void subtracted(); }; Q_DECLARE_METATYPE(QList<int>) @@ -147,7 +147,7 @@ void tst_QtTableSelectionRange::intersects() { } -void tst_QtTableSelectionRange::subtract_data() +void tst_QtTableSelectionRange::subtracted_data() { QTest::addColumn<int>("rangeTop"); QTest::addColumn<int>("rangeLeft"); @@ -312,7 +312,7 @@ void tst_QtTableSelectionRange::subtract_data() << (QList<int>() << 0 << 2); // results right } -void tst_QtTableSelectionRange::subtract() +void tst_QtTableSelectionRange::subtracted() { QFETCH(int, rangeTop); QFETCH(int, rangeLeft); @@ -333,7 +333,7 @@ void tst_QtTableSelectionRange::subtract() QtTableSelectionRange range(rangeTop, rangeLeft, rangeBottom, rangeRight); QtTableSelectionRange subtract(subtractTop, subtractLeft, subtractBottom, subtractRight); - QList<QtTableSelectionRange> results = range.subtract(subtract); + QList<QtTableSelectionRange> results = range.subtracted(subtract); QCOMPARE(results.count(), resultsCount); for (int i = 0; i < resultsCount; ++i) { diff --git a/tests/qtreedefaultmodel/tst_qtreedefaultmodel.cpp b/tests/qtreedefaultmodel/tst_qtreedefaultmodel.cpp index bcc7006..a1bd857 100644 --- a/tests/qtreedefaultmodel/tst_qtreedefaultmodel.cpp +++ b/tests/qtreedefaultmodel/tst_qtreedefaultmodel.cpp @@ -22,6 +22,7 @@ ****************************************************************************/ #include <QtTest/QtTest> +#include <qtreemodelinterface.h> #include <qtreedefaultmodel.h> class tst_QtTreeDefaultModel : public QObject @@ -40,14 +41,28 @@ public slots: private slots: void getSetCheck(); + void insertChild_data(); + void insertChild(); + void appendChild_data(); + void appendChild(); + void takeChild_data(); + void takeChild(); + void removeChild_data(); + void removeChild(); + void setData_data(); + void setData(); protected: QtTreeDefaultModel *model; }; +Q_DECLARE_METATYPE(QList<int>) +Q_DECLARE_METATYPE(QList<bool>) +Q_DECLARE_METATYPE(QtTreeModelBase::iterator_base) tst_QtTreeDefaultModel::tst_QtTreeDefaultModel() { + qRegisterMetaType<QtTreeModelBase::iterator_base>("QtTreeModelBase::iterator_base"); } tst_QtTreeDefaultModel::~tst_QtTreeDefaultModel() @@ -76,5 +91,565 @@ void tst_QtTreeDefaultModel::getSetCheck() { } +void tst_QtTreeDefaultModel::insertChild_data() +{ + QTest::addColumn<QStringList>("initialChildren"); + QTest::addColumn<QStringList>("insertChildren"); + QTest::addColumn<int>("insertChildrenAt"); + QTest::addColumn<QStringList>("expectedChildren"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no children") + << QStringList() + << QStringList() + << 0 + << QStringList() + << 0; + + QTest::newRow("one initial child") + << (QStringList() << "one") + << QStringList() + << 0 + << (QStringList() << "one") + << 1; + + QTest::newRow("two initial children") + << (QStringList() << "one" << "two") + << QStringList() + << 0 + << (QStringList() << "one" << "two") + << 2; + + QTest::newRow("no initial children, one insert") + << QStringList() + << (QStringList() << "one") + << 0 + << (QStringList() << "one") + << 1; + + QTest::newRow("no initial children, one insert at illegal index") + << QStringList() + << (QStringList() << "one") + << -1 + << (QStringList() << "one") + << 1; + + QTest::newRow("two initial children, two inserts before") + << (QStringList() << "three" << "four") + << (QStringList() << "one" << "two") + << 0 + << (QStringList() << "one" << "two" << "three" << "four") + << 4; + + QTest::newRow("two initial children, two inserts after") + << (QStringList() << "one" << "two") + << (QStringList() << "three" << "four") + << 2 + << (QStringList() << "one" << "two" << "three" << "four") + << 4; + + QTest::newRow("two initial children, two inserts in the middle") + << (QStringList() << "one" << "four") + << (QStringList() << "two" << "three") + << 1 + << (QStringList() << "one" << "two" << "three" << "four") + << 4; +} + +void tst_QtTreeDefaultModel::insertChild() +{ + QFETCH(QStringList, initialChildren); + QFETCH(QStringList, insertChildren); + QFETCH(int, insertChildrenAt); + QFETCH(QStringList, expectedChildren); + QFETCH(int, signalCount); + + Q_UNUSED(signalCount); + //QSignalSpy itemsInserted(model, SIGNAL(itemsInserted(QtTreeModelBase::iterator_base&,int))); + + QVERIFY(model->rootItem()); + + // add initial children + for (int i = 0; i < initialChildren.count(); ++i) + new QtTreeDefaultItem(initialChildren.at(i), model->rootItem()); + QCOMPARE(model->rootItem()->children().count(), initialChildren.count()); + + // check children + QtTreeDefaultItem *previous = 0; + for (int j = 0; j < initialChildren.count(); ++j) { + QtTreeDefaultItem *item = model->rootItem()->children().at(j); + QCOMPARE(item->text(), initialChildren.at(j)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // insert children + for (int k = 0; k < insertChildren.count(); ++k) + model->rootItem()->insertChild(insertChildrenAt + k, new QtTreeDefaultItem(insertChildren.at(k))); + + // check children + previous = 0; + QCOMPARE(model->rootItem()->children().count(), expectedChildren.count()); + for (int l = 0; l < expectedChildren.count(); ++l) { + QtTreeDefaultItem *item = model->rootItem()->children().at(l); + QCOMPARE(item->text(), expectedChildren.at(l)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // check signals + //QCOMPARE(itemsInserted.count(), signalCount); +} + +void tst_QtTreeDefaultModel::appendChild_data() +{ + QTest::addColumn<QStringList>("initialChildren"); + QTest::addColumn<QStringList>("appendChildren"); + QTest::addColumn<QStringList>("expectedChildren"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no children") + << QStringList() + << QStringList() + << QStringList() + << 0; + + QTest::newRow("one initial child") + << (QStringList() << "one") + << QStringList() + << (QStringList() << "one") + << 1; + + QTest::newRow("two initial children") + << (QStringList() << "one" << "two") + << QStringList() + << (QStringList() << "one" << "two") + << 2; + + QTest::newRow("no initial children, one append") + << QStringList() + << (QStringList() << "one") + << (QStringList() << "one") + << 1; + + QTest::newRow("one initial child, one append") + << (QStringList() << "one") + << (QStringList() << "two") + << (QStringList() << "one" << "two") + << 2; + + QTest::newRow("two initial children, one append") + << (QStringList() << "one" << "two") + << (QStringList() << "three") + << (QStringList() << "one" << "two" << "three") + << 3; + + QTest::newRow("one initial child, two appends") + << (QStringList() << "one") + << (QStringList() << "two" << "three") + << (QStringList() << "one" << "two" << "three") + << 2; +} + +void tst_QtTreeDefaultModel::appendChild() +{ + QFETCH(QStringList, initialChildren); + QFETCH(QStringList, appendChildren); + QFETCH(QStringList, expectedChildren); + QFETCH(int, signalCount); + + Q_UNUSED(signalCount); + //QSignalSpy itemsInserted(model, SIGNAL(itemsInserted(QtTreeModelBase::iterator_base&,int))); + + QVERIFY(model->rootItem()); + + // add initial children + for (int i = 0; i < initialChildren.count(); ++i) + new QtTreeDefaultItem(initialChildren.at(i), model->rootItem()); + QCOMPARE(model->rootItem()->children().count(), initialChildren.count()); + + // check children + QtTreeDefaultItem *previous = 0; + for (int j = 0; j < initialChildren.count(); ++j) { + QtTreeDefaultItem *item = model->rootItem()->children().at(j); + QCOMPARE(item->text(), initialChildren.at(j)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // append children + for (int k = 0; k < appendChildren.count(); ++k) + model->rootItem()->appendChild(new QtTreeDefaultItem(appendChildren.at(k))); + + // check children + previous = 0; + QCOMPARE(model->rootItem()->children().count(), expectedChildren.count()); + for (int l = 0; l < expectedChildren.count(); ++l) { + QtTreeDefaultItem *item = model->rootItem()->children().at(l); + QCOMPARE(model->rootItem()->children().at(l)->text(), expectedChildren.at(l)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // check signals + //QCOMPARE(itemsInserted.count(), signalCount); +} + +void tst_QtTreeDefaultModel::takeChild_data() +{ + QTest::addColumn<QStringList>("initialChildren"); + QTest::addColumn<int>("takeChildrenAt"); + QTest::addColumn<int>("takeChildrenCount"); + QTest::addColumn<QList<bool> >("takeChildrenExist"); + QTest::addColumn<QStringList>("expectedChildren"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no children") + << QStringList() + << 0 + << 0 + << QList<bool>() + << QStringList() + << 0; + + QTest::newRow("no children, take one") + << QStringList() + << 0 + << 1 + << (QList<bool>() << false) + << QStringList() + << 0; + + QTest::newRow("one child, take one") + << (QStringList() << "one") + << 0 + << 1 + << (QList<bool>() << true) + << QStringList() + << 1; + + QTest::newRow("one child, take two") + << (QStringList() << "one") + << 0 + << 1 + << (QList<bool>() << true << false) + << QStringList() + << 1; + + QTest::newRow("three children, take first") + << (QStringList() << "one" << "two" << "three") + << 0 + << 1 + << (QList<bool>() << true) + << (QStringList() << "two" << "three") + << 1; + + QTest::newRow("three children, take middle") + << (QStringList() << "one" << "two" << "three") + << 1 + << 1 + << (QList<bool>() << true) + << (QStringList() << "one" << "three") + << 1; + + QTest::newRow("three children, take last") + << (QStringList() << "one" << "two" << "three") + << 2 + << 1 + << (QList<bool>() << true) + << (QStringList() << "one" << "two") + << 1; + + QTest::newRow("two children, take -1") + << (QStringList() << "one" << "two") + << -1 + << 1 + << (QList<bool>() << false) + << (QStringList() << "one" << "two") + << 0; + + QTest::newRow("two children, take INT_MAX") + << (QStringList() << "one" << "two") + << INT_MAX + << 1 + << (QList<bool>() << false) + << (QStringList() << "one" << "two") + << 0; +} + +void tst_QtTreeDefaultModel::takeChild() +{ + QFETCH(QStringList, initialChildren); + QFETCH(int, takeChildrenAt); + QFETCH(int, takeChildrenCount); + QFETCH(QList<bool>, takeChildrenExist); + QFETCH(QStringList, expectedChildren); + QFETCH(int, signalCount); + + Q_UNUSED(signalCount); + //QSignalSpy itemsRemoved(model, SIGNAL(itemsInserted(QtTreeModelBase::iterator_base&,int))); + + QVERIFY(model->rootItem()); + + // add initial children + for (int i = 0; i < initialChildren.count(); ++i) + new QtTreeDefaultItem(initialChildren.at(i), model->rootItem()); + QCOMPARE(model->rootItem()->children().count(), initialChildren.count()); + + // check children + QtTreeDefaultItem *previous = 0; + for (int j = 0; j < initialChildren.count(); ++j) { + QtTreeDefaultItem *item = model->rootItem()->children().at(j); + QCOMPARE(item->text(), initialChildren.at(j)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // take children + for (int k = 0; k < takeChildrenCount; ++k) { + QtTreeDefaultItem *item = model->rootItem()->takeChild(takeChildrenAt); + QCOMPARE(!!item, takeChildrenExist.at(k)); + delete item; + } + + // check children + previous = 0; + QCOMPARE(model->rootItem()->children().count(), expectedChildren.count()); + for (int l = 0; l < expectedChildren.count(); ++l) { + QtTreeDefaultItem *item = model->rootItem()->children().at(l); + QCOMPARE(model->rootItem()->children().at(l)->text(), expectedChildren.at(l)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // check signals + //QCOMPARE(itemsRemoved.count(), signalCount); +} + +void tst_QtTreeDefaultModel::removeChild_data() +{ + QTest::addColumn<QStringList>("initialChildren"); + QTest::addColumn<int>("removeChildrenAt"); + QTest::addColumn<int>("removeChildrenCount"); + QTest::addColumn<QStringList>("expectedChildren"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no children") + << QStringList() + << 0 + << 0 + << QStringList() + << 0; + + QTest::newRow("no children, remove one") + << QStringList() + << 0 + << 1 + << QStringList() + << 0; + + QTest::newRow("one child, remove one") + << (QStringList() << "one") + << 0 + << 1 + << QStringList() + << 1; + + QTest::newRow("one child, remove two") + << (QStringList() << "one") + << 0 + << 1 + << QStringList() + << 1; + + QTest::newRow("three children, remove first") + << (QStringList() << "one" << "two" << "three") + << 0 + << 1 + << (QStringList() << "two" << "three") + << 1; + + QTest::newRow("three children, remove middle") + << (QStringList() << "one" << "two" << "three") + << 1 + << 1 + << (QStringList() << "one" << "three") + << 1; + + QTest::newRow("three children, remove last") + << (QStringList() << "one" << "two" << "three") + << 2 + << 1 + << (QStringList() << "one" << "two") + << 1; + + QTest::newRow("two children, remove -1") + << (QStringList() << "one" << "two") + << -1 + << 1 + << (QStringList() << "one" << "two") + << 0; + + QTest::newRow("two children, remove INT_MAX") + << (QStringList() << "one" << "two") + << INT_MAX + << 1 + << (QStringList() << "one" << "two") + << 0; +} + +void tst_QtTreeDefaultModel::removeChild() +{ + QFETCH(QStringList, initialChildren); + QFETCH(int, removeChildrenAt); + QFETCH(int, removeChildrenCount); + QFETCH(QStringList, expectedChildren); + QFETCH(int, signalCount); + + Q_UNUSED(signalCount); + //QSignalSpy itemsRemoved(model, SIGNAL(itemsInserted(QtTreeModelBase::iterator_base&,int))); + + QVERIFY(model->rootItem()); + + // add initial children + for (int i = 0; i < initialChildren.count(); ++i) + new QtTreeDefaultItem(initialChildren.at(i), model->rootItem()); + QCOMPARE(model->rootItem()->children().count(), initialChildren.count()); + + // check children + QtTreeDefaultItem *previous = 0; + for (int j = 0; j < initialChildren.count(); ++j) { + QtTreeDefaultItem *item = model->rootItem()->children().at(j); + QCOMPARE(item->text(), initialChildren.at(j)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // remove children + for (int k = 0; k < removeChildrenCount; ++k) { + QtTreeDefaultItem *item = model->rootItem()->children().value(removeChildrenAt); + model->rootItem()->removeChild(item); + delete item; + } + + // check children + previous = 0; + QCOMPARE(model->rootItem()->children().count(), expectedChildren.count()); + for (int l = 0; l < expectedChildren.count(); ++l) { + QtTreeDefaultItem *item = model->rootItem()->children().at(l); + QCOMPARE(model->rootItem()->children().at(l)->text(), expectedChildren.at(l)); + QCOMPARE(item->previous(), previous); + if (previous) + QCOMPARE(previous->next(), item); + previous = item; + } + + // check signals + //QCOMPARE(itemsRemoved.count(), signalCount); +} + +void tst_QtTreeDefaultModel::setData_data() +{ + QTest::addColumn<QStringList>("initialChildren"); + QTest::addColumn<QList<int> >("columns"); + QTest::addColumn<QList<int> >("roles"); + QTest::addColumn<QList<QVariant> >("data"); + QTest::addColumn<int>("signalCount"); + + QTest::newRow("no children") + << QStringList() + << QList<int>() + << QList<int>() + << QList<QVariant>() + << 0; + + QTest::newRow("one child, no data") + << (QStringList() << "one") + << QList<int>() + << QList<int>() + << QList<QVariant>() + << 0; + + QTest::newRow("one child, one column, one text") + << (QStringList() << "one") + << (QList<int>() << 0) + << (QList<int>() << int(Qt::DisplayRole)) + << (QList<QVariant>() << QVariant("text")) + << 1; + + QTest::newRow("one child, two columns, one role") + << (QStringList() << "one") + << (QList<int>() << 0 << 1) + << (QList<int>() << int(Qt::DisplayRole)) + << (QList<QVariant>() << QVariant("text") << QVariant("text")) + << 2; + + QTest::newRow("one child, one column, two roles") + << (QStringList() << "one") + << (QList<int>() << 0) + << (QList<int>() << int(Qt::DisplayRole) << int(Qt::EditRole)) + << (QList<QVariant>() << QVariant("text") << QVariant("edit")) + << 2; + + QTest::newRow("one child, two columns, two roles") + << (QStringList() << "one") + << (QList<int>() << 0 << 1) + << (QList<int>() << int(Qt::DisplayRole) << int(Qt::EditRole)) + << (QList<QVariant>() // for each column and for each role + << QVariant("text") << QVariant("edit") + << QVariant("text") << QVariant("edit")) + << 2; +} + +void tst_QtTreeDefaultModel::setData() +{ + QFETCH(QStringList, initialChildren); + QFETCH(QList<int>, columns); + QFETCH(QList<int>, roles); + QFETCH(QList<QVariant>, data); + QFETCH(int, signalCount); + + Q_UNUSED(signalCount); + //QSignalSpy itemsChanged(model, SIGNAL(itemsInserted(QtTreeModelBase::iterator_base&,int,const QList<int>&))); + + QVERIFY(model->rootItem()); + + // add initial children + for (int i = 0; i < initialChildren.count(); ++i) + new QtTreeDefaultItem(initialChildren.at(i), model->rootItem()); + QCOMPARE(model->rootItem()->children().count(), initialChildren.count()); + + // change data and check + for (int j = 0; j < model->rootItem()->children().count(); ++j) { + QtTreeDefaultItem *item = model->rootItem()->children().value(j); + item->setColumnCount(columns.count()); + QCOMPARE(item->columnCount(), columns.count()); + for (int k = 0; k < columns.count(); ++k) { + for (int l = 0; l < roles.count(); ++l) { + int m = k * roles.count() + l; + item->setData(data.at(m), columns.at(k), roles.at(l)); + QCOMPARE(item->data(columns.at(k), roles.at(l)), data.at(m)); + } + } + } + + // check signals + //QCOMPARE(itemsChanged.count(), signalCount); +} + QTEST_MAIN(tst_QtTreeDefaultModel) #include "tst_qtreedefaultmodel.moc" diff --git a/tests/qtreemodeladaptor/tst_qtreemodeladaptor.cpp b/tests/qtreemodeladaptor/tst_qtreemodeladaptor.cpp index a2d107e..d6c04a5 100644 --- a/tests/qtreemodeladaptor/tst_qtreemodeladaptor.cpp +++ b/tests/qtreemodeladaptor/tst_qtreemodeladaptor.cpp @@ -71,5 +71,5 @@ void tst_QtTreeModelAdaptor::checkGetData() QTEST_MAIN(tst_QtTreeModelAdaptor) -#include <tst_qtreemodeladaptor.moc> +#include "tst_qtreemodeladaptor.moc" diff --git a/tests/qtreeselectionmanager/tst_qtreeselectionmanager.cpp b/tests/qtreeselectionmanager/tst_qtreeselectionmanager.cpp index a6873db..9422265 100644 --- a/tests/qtreeselectionmanager/tst_qtreeselectionmanager.cpp +++ b/tests/qtreeselectionmanager/tst_qtreeselectionmanager.cpp @@ -22,7 +22,8 @@ ****************************************************************************/ #include <QtTest/QtTest> -#include "qtreeselectionmanager.h" +#include <qtreeselectionmanager.h> +#include <qtreedefaultmodel.h> class tst_QtTreeSelectionManager : public QObject { @@ -40,13 +41,23 @@ public slots: private slots: void getSetCheck(); - void setSelection_data(); - void setSelection(); - void toggleSelection_data(); - void toggleSelection(); + void currentItem_data(); + void currentItem(); + void anchorItem_data(); + void anchorItem(); + void selections_data(); + void selections(); + void anchoredSelections_data(); + void anchoredSelections(); + +private: + QtTreeSelectionManager *manager; + QtTreeDefaultModel *model; }; Q_DECLARE_METATYPE(QList<int>) +Q_DECLARE_METATYPE(QList<bool>) +Q_DECLARE_METATYPE(QtTreeModelBase::iterator_base) tst_QtTreeSelectionManager::tst_QtTreeSelectionManager() { @@ -76,19 +87,34 @@ void tst_QtTreeSelectionManager::getSetCheck() { } -void tst_QtTreeSelectionManager::setSelection_data() +void tst_QtTreeSelectionManager::currentItem_data() { } -void tst_QtTreeSelectionManager::setSelection() +void tst_QtTreeSelectionManager::currentItem() +{ +} +void tst_QtTreeSelectionManager::anchorItem_data() +{ +} + +void tst_QtTreeSelectionManager::anchorItem() +{ +} + +void tst_QtTreeSelectionManager::selections_data() +{ +} + +void tst_QtTreeSelectionManager::selections() { } -void tst_QtTreeSelectionManager::toggleSelection_data() +void tst_QtTreeSelectionManager::anchoredSelections_data() { } -void tst_QtTreeSelectionManager::toggleSelection() +void tst_QtTreeSelectionManager::anchoredSelections() { } |