[rkward/work/optionset_experiments] rkward/misc: Add some more flexibility to the Accordion table:
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Tue Oct 27 19:53:19 UTC 2015
Git commit aa34ef9333cf5bd324d5d37511dcbda39fcf7982 by Thomas Friedrichsmeier.
Committed on 27/10/2015 at 19:52.
Pushed by tfry into branch 'work/optionset_experiments'.
Add some more flexibility to the Accordion table:
- Button columns optional
- Optionally strip leading columns
- Optional trailing row
M +65 -20 rkward/misc/rkaccordiontable.cpp
M +2 -3 rkward/misc/rkaccordiontable.h
http://commits.kde.org/rkward/aa34ef9333cf5bd324d5d37511dcbda39fcf7982
diff --git a/rkward/misc/rkaccordiontable.cpp b/rkward/misc/rkaccordiontable.cpp
index 7383919..5aa0803 100644
--- a/rkward/misc/rkaccordiontable.cpp
+++ b/rkward/misc/rkaccordiontable.cpp
@@ -22,6 +22,7 @@
#include <QAbstractProxyModel>
#include <QToolButton>
#include <QHBoxLayout>
+#include <QLabel>
#include <kvbox.h>
#include <klocale.h>
@@ -37,21 +38,35 @@
class RKAccordionDummyModel : public QAbstractProxyModel {
Q_OBJECT
public:
- RKAccordionDummyModel (QObject *parent) : QAbstractProxyModel (parent) {};
+ RKAccordionDummyModel (QObject *parent) : QAbstractProxyModel (parent) {
+ add_leading_columns = 1;
+ strip_leading_columns = 0;
+ add_trailing_rows = 1;
+ };
QModelIndex mapFromSource (const QModelIndex& sindex) const {
if (!sindex.isValid ()) return QModelIndex ();
// we're using Source row as "Internal ID", here. This _would_ fall on our feet when removing rows, _if_ we'd actually
// have to be able to map the dummy rows back to their real parents.
- return (createIndex (sindex.row (), sindex.column (), real_item_id));
+ return (createIndex (sindex.row (), mapColumnFromSource (sindex.column ()), real_item_id));
+ }
+
+ inline int mapColumnFromSource (int column) const {
+ return qMax (0, column + add_leading_columns - strip_leading_columns);
+ }
+
+ inline int mapColumnToSource (int column) const {
+ return qMax (0, column - add_leading_columns + strip_leading_columns);
}
QModelIndex mapToSource (const QModelIndex& pindex) const {
if (!pindex.isValid ()) return QModelIndex ();
- if (pindex.internalId () != real_item_id) {
- return sourceModel ()->index (pindex.internalId (), pindex.column ());
+ if (pindex.internalId () == real_item_id) {
+ return sourceModel ()->index (pindex.row (), mapColumnToSource (pindex.column ()));
+ } else if (pindex.internalId () == trailing_item_id) {
+ return QModelIndex ();
} else {
- return sourceModel ()->index (pindex.row (), pindex.column ());
+ return sourceModel ()->index (pindex.internalId (), 0);
}
}
@@ -60,10 +75,10 @@ public:
return QAbstractProxyModel::flags (index);
}
- int rowCount (const QModelIndex& parent) const {
+ int rowCount (const QModelIndex& parent = QModelIndex ()) const {
if (isFake (parent)) return 0;
if (parent.isValid ()) return 1;
- return sourceModel ()->rowCount (mapToSource (parent));
+ return sourceModel ()->rowCount (mapToSource (parent)) + add_trailing_rows;
}
QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const {
@@ -71,23 +86,32 @@ public:
return QAbstractProxyModel::data (proxyIndex, role);
}
+ QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const {
+ if ((orientation == Qt::Horizontal) && (section < add_leading_columns) && (role == Qt::DisplayRole)) return QVariant ();
+ return QAbstractProxyModel::headerData (section, orientation, role);
+ }
+
bool hasChildren (const QModelIndex& parent) const {
return (!isFake (parent));
}
- int columnCount (const QModelIndex& parent) const {
+ int columnCount (const QModelIndex& parent = QModelIndex ()) const {
if (isFake (parent)) return 1;
- return sourceModel ()->columnCount (mapToSource (parent));
+ return mapColumnFromSource (sourceModel ()->columnCount (mapToSource (parent)));
}
- QModelIndex index (int row, int column, const QModelIndex& parent) const {
- if (!parent.isValid ()) return createIndex (row, column, real_item_id);
+ QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex ()) const {
+ if (!parent.isValid ()) {
+ if (row == sourceModel ()->rowCount ()) return createIndex (row, column, trailing_item_id);
+ return createIndex (row, column, real_item_id);
+ }
RK_ASSERT (parent.internalId () == real_item_id);
return createIndex (row, column, parent.row ());
}
QModelIndex parent (const QModelIndex& child) const {
if (child.internalId () == real_item_id) return QModelIndex ();
+ else if (child.internalId () == trailing_item_id) return QModelIndex ();
return createIndex (child.internalId (), 0, real_item_id);
}
@@ -105,6 +129,10 @@ public:
}
static const quint32 real_item_id = 0xFFFFFFFF;
+ static const quint32 trailing_item_id = 0xFFFFFFFE;
+ int add_leading_columns;
+ int strip_leading_columns;
+ int add_trailing_rows;
public slots:
void r_rowsInserted (const QModelIndex& parent, int start, int end) {
RK_TRACE (MISC);
@@ -173,10 +201,11 @@ RKAccordionTable::RKAccordionTable (QWidget* parent) : QTreeView (parent) {
setSelectionMode (NoSelection);
setIndentation (0);
+ setRootIsDecorated (false);
setExpandsOnDoubleClick (false); // we expand on single click, instead
setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setViewportMargins (20, 0, 0, 0);
- pmodel = new RKAccordionDummyModel (this);
+ pmodel = new RKAccordionDummyModel (0);
connect (this, SIGNAL (expanded(QModelIndex)), this, SLOT (rowExpanded(QModelIndex)));
connect (this, SIGNAL (clicked(QModelIndex)), this, SLOT (rowClicked(QModelIndex)));
}
@@ -184,7 +213,11 @@ RKAccordionTable::RKAccordionTable (QWidget* parent) : QTreeView (parent) {
RKAccordionTable::~RKAccordionTable () {
RK_TRACE (MISC);
- delete editor_widget;
+ // Qt 4.8.6: The model must _not_ be a child of this view, and must _not_ be deleted along with it, or else there will be a crash
+ // on destruction _if_ (and only if) there are any trailing dummy rows. (Inside QAbstractItemModelPrivate::removePersistentIndexData())
+ // No, I do not understand this, yes, this is worrysome, but no idea, what could be the actual cause.
+ pmodel->deleteLater ();
+ delete editor_widget_container;
}
QSize RKAccordionTable::sizeHintWithoutEditor () const {
@@ -286,17 +319,26 @@ void RKAccordionTable::updateWidget () {
RKCommonFunctions::setTips (i18n ("Add a row / element"), add_button);
layout->addWidget (add_button);
- QToolButton *remove_button = new QToolButton (display_buttons);
- connect (remove_button, SIGNAL (clicked(bool)), this, SLOT (removeClicked()));
- remove_button->setIcon (RKStandardIcons::getIcon (RKStandardIcons::ActionDeleteRow));
- RKCommonFunctions::setTips (i18n ("Remove a row / element"), remove_button);
- layout->addWidget (remove_button);
+ if (i < (model ()->rowCount () - 1)) {
+ QToolButton *remove_button = new QToolButton (display_buttons);
+ connect (remove_button, SIGNAL (clicked(bool)), this, SLOT (removeClicked()));
+ remove_button->setIcon (RKStandardIcons::getIcon (RKStandardIcons::ActionDeleteRow));
+ RKCommonFunctions::setTips (i18n ("Remove this row / element"), remove_button);
+ layout->addWidget (remove_button);
+ } else {
+ QLabel *label = new QLabel (i18n ("Click to add new row / element"), display_buttons);
+ layout->addWidget (label);
+ setFirstColumnSpanned (i, QModelIndex (), true);
+ }
setIndexWidget (row, display_buttons);
+
+ if (i == 0) {
+ header ()->resizeSection (0, 2*rowHeight (row));
+ header ()->setResizeMode (0, QHeaderView::Fixed);
+ }
}
}
-
- if (show_add_remove_buttons) header ()->setResizeMode (0, QHeaderView::ResizeToContents);
}
int RKAccordionTable::rowOfButton (QObject* button) const {
@@ -350,15 +392,18 @@ void RKAccordionTable::setModel (QAbstractItemModel* model) {
if (pmodel->rowCount () > 0) expand (pmodel->index (0, 0));
+ updateWidget ();
updateGeometry (); // TODO: Not so clean to call this, here. But at this point we know the display_widget has been constructed, too
}
// TODO
// - insertion when now row is available, yet
+// - index column, and sets without manual add / remove
// - expand / collapse indicator?
// - drag-reordering?
// - will this make per-item add buttons obsolete?
+// - improve scrolling behavior
// KF5 TODO: remove:
#include "rkaccordiontable.moc"
diff --git a/rkward/misc/rkaccordiontable.h b/rkward/misc/rkaccordiontable.h
index b4af29c..031579d 100644
--- a/rkward/misc/rkaccordiontable.h
+++ b/rkward/misc/rkaccordiontable.h
@@ -21,8 +21,7 @@
#include <QWidget>
#include <QTreeView>
-class QAbstractItemModel;
-class QAbstractProxyModel;
+class RKAccordionDummyModel;
class RKAccordionTable : public QTreeView {
Q_OBJECT
@@ -57,7 +56,7 @@ private:
bool show_add_remove_buttons;
QWidget *editor_widget;
QWidget *editor_widget_container;
- QAbstractProxyModel *pmodel;
+ RKAccordionDummyModel *pmodel;
};
#endif
More information about the rkward-tracker
mailing list