[rkward/work/optionset_experiments] rkward: Implement drag-and-drop item reordering in accordion.
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Wed Oct 28 13:48:47 UTC 2015
Git commit 46b186da7766be3eec3284d87f2f5c2cc238d8f2 by Thomas Friedrichsmeier.
Committed on 28/10/2015 at 13:47.
Pushed by tfry into branch 'work/optionset_experiments'.
Implement drag-and-drop item reordering in accordion.
This should obsolete the per-row "add" buttons.
M +27 -7 rkward/misc/rkaccordiontable.cpp
M +61 -4 rkward/plugin/rkoptionset.cpp
M +7 -0 rkward/plugin/rkoptionset.h
M +1 -0 rkward/plugins/testing/optionset.js
http://commits.kde.org/rkward/46b186da7766be3eec3284d87f2f5c2cc238d8f2
diff --git a/rkward/misc/rkaccordiontable.cpp b/rkward/misc/rkaccordiontable.cpp
index 5aa0803..604ed2b 100644
--- a/rkward/misc/rkaccordiontable.cpp
+++ b/rkward/misc/rkaccordiontable.cpp
@@ -72,7 +72,7 @@ public:
Qt::ItemFlags flags (const QModelIndex& index) const {
if (isFake (index)) return (Qt::NoItemFlags);
- return QAbstractProxyModel::flags (index);
+ return (QAbstractProxyModel::flags (index));
}
int rowCount (const QModelIndex& parent = QModelIndex ()) const {
@@ -81,11 +81,23 @@ public:
return sourceModel ()->rowCount (mapToSource (parent)) + add_trailing_rows;
}
- QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const {
+ QVariant data (const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const {
if (isFake (proxyIndex)) return QVariant ();
return QAbstractProxyModel::data (proxyIndex, role);
}
+ bool dropMimeData (const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
+ // Ok, I don't understand why exactly, but something goes wrong while mapping this back to the source model. So we help it a bit:
+ Q_UNUSED (column);
+
+ if (isFake (parent)) {
+ RK_ASSERT (false);
+ return false;
+ }
+ if (parent.isValid ()) row = parent.row ();
+ return sourceModel ()->dropMimeData (data, action, row, 0, QModelIndex ());
+ }
+
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);
@@ -105,7 +117,7 @@ public:
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);
+ RK_ASSERT (parent.internalId () >= trailing_item_id);
return createIndex (row, column, parent.row ());
}
@@ -199,7 +211,12 @@ RKAccordionTable::RKAccordionTable (QWidget* parent) : QTreeView (parent) {
editor_widget = new KVBox (editor_widget_container);
layout->addWidget (editor_widget);
- setSelectionMode (NoSelection);
+ setSelectionMode (SingleSelection);
+ setDragEnabled (true);
+ setAcceptDrops (true);
+ setDragDropMode (InternalMove);
+ setDropIndicatorShown (false);
+ setDragDropOverwriteMode (false);
setIndentation (0);
setRootIsDecorated (false);
setExpandsOnDoubleClick (false); // we expand on single click, instead
@@ -274,8 +291,12 @@ void RKAccordionTable::rowClicked (QModelIndex row) {
RK_TRACE (MISC);
row = model ()->index (row.row (), 0, row.parent ()); // Fix up index to point to column 0, or isExpanded() will always return false
- if (!row.parent ().isValid ()) {
- setExpanded (row, !isExpanded (row));
+ if (isExpanded (row)) {
+ setExpanded (row, false);
+ } else {
+ if (!row.parent ().isValid ()) {
+ emit (activated (row.row ()));
+ }
}
}
@@ -293,7 +314,6 @@ void RKAccordionTable::rowExpanded (QModelIndex row) {
setCurrentIndex (row);
scrollTo (row, EnsureVisible); // yes, we want both scrolls: We want the header row above the widget, if possible at all,
scrollTo (model ()->index (0, 0, row), EnsureVisible); // but of course, having the header row visible without the widget is not enough...
- emit (activated (row.row ()));
}
void RKAccordionTable::updateWidget () {
diff --git a/rkward/plugin/rkoptionset.cpp b/rkward/plugin/rkoptionset.cpp
index 00fa92e..056c69d 100644
--- a/rkward/plugin/rkoptionset.cpp
+++ b/rkward/plugin/rkoptionset.cpp
@@ -23,6 +23,7 @@
#include <QPushButton>
#include <QStackedWidget>
#include <QLabel>
+#include <QMimeData>
#include <klocale.h>
#include <kvbox.h>
@@ -429,9 +430,9 @@ void RKOptionSet::addRow () {
void RKOptionSet::addRow (int row) {
RK_TRACE (PLUGIN);
-
+RK_DEBUG (MISC, DL_ERROR, "current row is now %d, %d", current_row->intValue (), active_row);
storeRowSerialization (active_row);
-
+RK_DEBUG (MISC, DL_ERROR, "current row is nows %d, %d", current_row->intValue (), active_row);
int nrows = rowCount ();
if (row < 0) row = nrows;
RK_ASSERT (!keycolumn);
@@ -456,7 +457,6 @@ void RKOptionSet::addRow (int row) {
rows.insert (row, ri);
++n_unfinished_rows;
++n_invalid_rows;
-
row_count->setIntValue (nrows + 1);
current_row->setIntValue (active_row = row);
setContentsForRow (active_row);
@@ -508,6 +508,31 @@ void RKOptionSet::removeRow (int row) {
changed ();
}
+void RKOptionSet::moveRow (int old_index, int new_index) {
+ RK_TRACE (PLUGIN);
+
+ int nrows = rowCount ();
+ if (old_index < 0 || old_index >= nrows) {
+ RK_ASSERT (false);
+ return;
+ }
+
+ if (new_index < 0 || new_index > nrows) {
+ new_index = nrows;
+ }
+
+ storeRowSerialization (active_row);
+ PropertyValueMap backup = rows[old_index].full_row_map;
+ removeRow (old_index);
+ if (new_index > old_index) new_index -= 1;
+ addRow (new_index);
+ rows[new_index].full_row_map = backup;
+ setContentsForRow (new_index);
+ updateCurrentRowInDisplay ();
+
+ changed ();
+}
+
QString getDefaultValue (const RKOptionSet::ColumnInfo& ci, int row) {
// let's not trace this simple helper fun
Q_UNUSED (row);
@@ -789,7 +814,7 @@ void RKOptionSet::currentRowChanged () {
void RKOptionSet::currentRowChanged (int row) {
RK_TRACE (PLUGIN);
- if (active_row != row) current_row->setIntValue (row);
+ current_row->setIntValue (row);
// --> currentRowPropertyChanged ()
}
@@ -836,6 +861,7 @@ RKOptionSetDisplayModel::RKOptionSetDisplayModel (RKOptionSet* parent) : QAbstra
connect (&reset_timer, SIGNAL (timeout()), this, SLOT (doResetNow()));
reset_timer.setInterval (0);
reset_timer.setSingleShot (true);
+ setSupportedDragActions (Qt::MoveAction);
}
RKOptionSetDisplayModel::~RKOptionSetDisplayModel () {
@@ -914,6 +940,37 @@ void RKOptionSetDisplayModel::triggerReset() {
}
}
+QString optionsetdisplaymodel_mt ("application/x-rkaccordiontableitem");
+QStringList RKOptionSetDisplayModel::mimeTypes () const {
+ return QStringList (optionsetdisplaymodel_mt);
+}
+
+QMimeData* RKOptionSetDisplayModel::mimeData (const QModelIndexList& indexes) const {
+ RK_ASSERT (indexes.length () >= 1);
+ QMimeData *ret = new QMimeData ();
+ ret->setData (optionsetdisplaymodel_mt, QByteArray (QString::number (indexes.first ().row ()).toAscii ()));
+ return (ret);
+}
+
+bool RKOptionSetDisplayModel::dropMimeData (const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
+ Q_UNUSED (column);
+ if (action == Qt::IgnoreAction) return true;
+ if (action == Qt::MoveAction) {
+ if (parent.isValid ()) return false;
+ int srow = QString::fromAscii (data->data (optionsetdisplaymodel_mt)).toInt ();
+ set->moveRow (srow, row);
+ }
+ return false;
+}
+
+Qt::ItemFlags RKOptionSetDisplayModel::flags (const QModelIndex& index) const {
+ return QAbstractItemModel::flags (index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
+}
+
+Qt::DropActions RKOptionSetDisplayModel::supportedDropActions () const {
+ return Qt::MoveAction;
+}
+
#include <QApplication>
RKOptionSetDelegate::RKOptionSetDelegate (RKOptionSet* parent) : QItemDelegate (parent) {
set = parent;
diff --git a/rkward/plugin/rkoptionset.h b/rkward/plugin/rkoptionset.h
index ad52247..48f5902 100644
--- a/rkward/plugin/rkoptionset.h
+++ b/rkward/plugin/rkoptionset.h
@@ -70,6 +70,7 @@ friend class RKOptionSetDisplayModel;
void setRowState (int row, bool finished, bool valid);
void storeRowSerialization (int row);
void applyContentsFromExternalColumn (RKComponentPropertyStringList* column, int row);
+ void moveRow (int old_index, int new_index);
RKComponentPropertyInt *current_row;
RKComponentPropertyInt *row_count;
@@ -161,6 +162,12 @@ friend class RKOptionSet;
QTimer reset_timer;
QStringList column_labels;
RKOptionSet *set;
+
+ QMimeData* mimeData (const QModelIndexList& indexes) const;
+ QStringList mimeTypes () const;
+ bool dropMimeData (const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
+ Qt::ItemFlags flags (const QModelIndex& index) const;
+ Qt::DropActions supportedDropActions () const;
private slots:
void doResetNow ();
};
diff --git a/rkward/plugins/testing/optionset.js b/rkward/plugins/testing/optionset.js
index c77e16b..5fbe270 100644
--- a/rkward/plugins/testing/optionset.js
+++ b/rkward/plugins/testing/optionset.js
@@ -7,6 +7,7 @@ function calculate () {
echo ("row_count <- " + getValue ("set.row_count") + "\n");
echo ("current_row <- " + getValue ("set.current_row") + "\n");
echo ("set.contents.enabled <- " + getValue ("set.contents.enabled") + "\n");
+ echo (getList ("mset.summary").join (",") + "\n");
var codeprops = getList ("set.plotoption_printout");
for (i = 0; i < codeprops.length; ++i) {
More information about the rkward-tracker
mailing list