Dropped plugins now retain their selection so you can see where they went

pull/21/head
Pieter van der Kloet 14 years ago
parent 8b50cd48f5
commit 410229e521

@ -7,6 +7,9 @@ set(LAUNCHER
graphicspage.cpp
naturalsort.cpp
pluginsmodel.cpp
pluginsview.cpp
datafilespage.hpp
lineedit.hpp
maindialog.hpp
@ -14,6 +17,9 @@ set(LAUNCHER
combobox.hpp
graphicspage.hpp
naturalsort.hpp
pluginsmodel.hpp
pluginsview.hpp
)
set(MOC_HDRS
@ -24,6 +30,8 @@ set(MOC_HDRS
combobox.hpp
graphicspage.hpp
pluginsmodel.hpp
pluginsview.hpp
)
find_package(Qt4 REQUIRED)

@ -10,6 +10,8 @@
#include "datafilespage.hpp"
#include "lineedit.hpp"
#include "naturalsort.hpp"
#include "pluginsmodel.hpp"
#include "pluginsview.hpp"
using namespace ESM;
using namespace std;
@ -17,7 +19,7 @@ using namespace std;
DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent)
{
mDataFilesModel = new QStandardItemModel(); // Contains all plugins with masters
mPluginsModel = new QStandardItemModel(); // Contains selectable plugins
mPluginsModel = new PluginsModel(); // Contains selectable plugins
mPluginsProxyModel = new QSortFilterProxyModel();
mPluginsProxyModel->setDynamicSortFilter(true);
@ -34,8 +36,6 @@ DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent)
topLayout->addWidget(filterLineEdit);
mMastersWidget = new QTableWidget(this); // Contains the available masters
mPluginsTable = new QTableView(this);
mMastersWidget->setObjectName("MastersWidget");
mMastersWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
mMastersWidget->setSelectionMode(QAbstractItemView::MultiSelection);
@ -46,11 +46,9 @@ DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent)
mMastersWidget->verticalHeader()->hide();
mMastersWidget->insertColumn(0);
mPluginsTable = new PluginsView(this);
mPluginsTable->setModel(mPluginsProxyModel);
mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
mPluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
mPluginsTable->setAlternatingRowColors(true);
mPluginsTable->horizontalHeader()->setStretchLastSection(true);
mPluginsTable->horizontalHeader()->hide();
@ -60,14 +58,6 @@ DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent)
mPluginsTable->verticalHeader()->setDefaultSectionSize(height);
mPluginsTable->setDragEnabled(true);
mPluginsTable->setDragDropMode(QAbstractItemView::InternalMove);
mPluginsTable->setDropIndicatorShown(true);
mPluginsTable->setDragDropOverwriteMode(false);
mPluginsTable->viewport()->setAcceptDrops(true);
mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
// Add both tables to a splitter
QSplitter *splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);

@ -6,8 +6,6 @@
#include "combobox.hpp"
class QTableWidget;
class QTableView;
class ComboBox;
class QStandardItemModel;
class QItemSelection;
class QItemSelectionModel;
@ -17,6 +15,9 @@ class QSettings;
class QAction;
class QToolBar;
class QMenu;
class PluginsModel;
class PluginsView;
class ComboBox;
class DataFilesPage : public QWidget
{
@ -58,10 +59,10 @@ public slots:
private:
QTableWidget *mMastersWidget;
QTableView *mPluginsTable;
PluginsView *mPluginsTable;
QStandardItemModel *mDataFilesModel;
QStandardItemModel *mPluginsModel;
PluginsModel *mPluginsModel;
QSortFilterProxyModel *mPluginsProxyModel;
QItemSelectionModel *mPluginsSelectModel;

@ -0,0 +1,148 @@
#include <QMimeData>
#include <QBitArray>
#include <QDebug>
#include "pluginsmodel.hpp"
PluginsModel::PluginsModel(QObject *parent) : QStandardItemModel(parent)
{
}
void decodeDataRecursive(QDataStream &stream, QStandardItem *item)
{
int colCount, childCount;
stream >> *item;
stream >> colCount >> childCount;
item->setColumnCount(colCount);
int childPos = childCount;
while(childPos > 0) {
childPos--;
QStandardItem *child = new QStandardItem();
decodeDataRecursive(stream, child);
item->setChild( childPos / colCount, childPos % colCount, child);
}
}
bool PluginsModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
// Code largely based on QStandardItemModel::dropMimeData
// check if the action is supported
if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
return false;
// check if the format is supported
QString format = QLatin1String("application/x-qstandarditemmodeldatalist");
if (!data->hasFormat(format))
return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
if (row > rowCount(parent))
row = rowCount(parent);
if (row == -1)
row = rowCount(parent);
if (column == -1)
column = 0;
// decode and insert
QByteArray encoded = data->data(format);
QDataStream stream(&encoded, QIODevice::ReadOnly);
//code based on QAbstractItemModel::decodeData
// adapted to work with QStandardItem
int top = INT_MAX;
int left = INT_MAX;
int bottom = 0;
int right = 0;
QVector<int> rows, columns;
QVector<QStandardItem *> items;
while (!stream.atEnd()) {
int r, c;
QStandardItem *item = new QStandardItem();
stream >> r >> c;
decodeDataRecursive(stream, item);
rows.append(r);
columns.append(c);
items.append(item);
top = qMin(r, top);
left = qMin(c, left);
bottom = qMax(r, bottom);
right = qMax(c, right);
}
// insert the dragged items into the table, use a bit array to avoid overwriting items,
// since items from different tables can have the same row and column
int dragRowCount = 0;
int dragColumnCount = right - left + 1;
// Compute the number of continuous rows upon insertion and modify the rows to match
QVector<int> rowsToInsert(bottom + 1);
for (int i = 0; i < rows.count(); ++i)
rowsToInsert[rows.at(i)] = 1;
for (int i = 0; i < rowsToInsert.count(); ++i) {
if (rowsToInsert[i] == 1){
rowsToInsert[i] = dragRowCount;
++dragRowCount;
}
}
for (int i = 0; i < rows.count(); ++i)
rows[i] = top + rowsToInsert[rows[i]];
QBitArray isWrittenTo(dragRowCount * dragColumnCount);
// make space in the table for the dropped data
int colCount = columnCount(parent);
if (colCount < dragColumnCount + column) {
insertColumns(colCount, dragColumnCount + column - colCount, parent);
colCount = columnCount(parent);
}
insertRows(row, dragRowCount, parent);
row = qMax(0, row);
column = qMax(0, column);
QStandardItem *parentItem = itemFromIndex (parent);
if (!parentItem)
parentItem = invisibleRootItem();
QVector<QPersistentModelIndex> newIndexes(items.size());
// set the data in the table
for (int j = 0; j < items.size(); ++j) {
int relativeRow = rows.at(j) - top;
int relativeColumn = columns.at(j) - left;
int destinationRow = relativeRow + row;
int destinationColumn = relativeColumn + column;
int flat = (relativeRow * dragColumnCount) + relativeColumn;
// if the item was already written to, or we just can't fit it in the table, create a new row
if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
destinationColumn = qBound(column, destinationColumn, colCount - 1);
destinationRow = row + dragRowCount;
insertRows(row + dragRowCount, 1, parent);
flat = (dragRowCount * dragColumnCount) + relativeColumn;
isWrittenTo.resize(++dragRowCount * dragColumnCount);
}
if (!isWrittenTo.testBit(flat)) {
newIndexes[j] = index(destinationRow, destinationColumn, parentItem->index());
isWrittenTo.setBit(flat);
}
}
for(int k = 0; k < newIndexes.size(); k++) {
if (newIndexes.at(k).isValid()) {
parentItem->setChild(newIndexes.at(k).row(), newIndexes.at(k).column(), items.at(k));
} else {
delete items.at(k);
}
}
// The important part, tell the view what is dropped
emit indexesDropped(newIndexes);
return true;
}

@ -0,0 +1,21 @@
#ifndef PLUGINSMODEL_H
#define PLUGINSMODEL_H
#include <QStandardItemModel>
class PluginsModel : public QStandardItemModel
{
Q_OBJECT
public:
PluginsModel(QObject *parent = 0);
~PluginsModel() {};
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
signals:
void indexesDropped(QVector<QPersistentModelIndex> indexes);
};
#endif

@ -0,0 +1,56 @@
#include "pluginsview.hpp"
#include <QDebug>
#include <QSortFilterProxyModel>
PluginsView::PluginsView(QWidget *parent) : QTableView(parent)
{
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setAlternatingRowColors(true);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::InternalMove);
setDropIndicatorShown(true);
setDragDropOverwriteMode(false);
//viewport()->setAcceptDrops(true);
setContextMenuPolicy(Qt::CustomContextMenu);
}
void PluginsView::startDrag(Qt::DropActions supportedActions)
{
selectionModel()->select( selectionModel()->selection(),
QItemSelectionModel::Select | QItemSelectionModel::Rows );
QAbstractItemView::startDrag( supportedActions );
}
void PluginsView::setModel(PluginsModel *model)
{
/*QTableView::setModel(model);
qRegisterMetaType< QVector<QPersistentModelIndex> >();
connect(model, SIGNAL(indexesDropped(QVector<QPersistentModelIndex>)),
this, SLOT(selectIndexes(QVector<QPersistentModelIndex>)), Qt::QueuedConnection);*/
}
void PluginsView::setModel(QSortFilterProxyModel *model)
{
QTableView::setModel(model);
qRegisterMetaType< QVector<QPersistentModelIndex> >();
connect(model->sourceModel(), SIGNAL(indexesDropped(QVector<QPersistentModelIndex>)),
this, SLOT(selectIndexes(QVector<QPersistentModelIndex>)), Qt::QueuedConnection);
}
void PluginsView::selectIndexes( QVector<QPersistentModelIndex> aIndexes )
{
selectionModel()->clearSelection();
foreach( QPersistentModelIndex pIndex, aIndexes )
selectionModel()->select( pIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows );
}

@ -0,0 +1,30 @@
#ifndef PLUGINSVIEW_H
#define PLUGINSVIEW_H
#include <QTableView>
#include "pluginsmodel.hpp"
class QSortFilterProxyModel;
class PluginsView : public QTableView
{
Q_OBJECT
public:
PluginsView(QWidget *parent = 0);
PluginsModel* model() const
{ return qobject_cast<PluginsModel*>(QAbstractItemView::model()); }
void startDrag(Qt::DropActions supportedActions);
void setModel(PluginsModel *model);
void setModel(QSortFilterProxyModel *model);
public slots:
void selectIndexes(QVector<QPersistentModelIndex> aIndexes);
};
Q_DECLARE_METATYPE(QVector<QPersistentModelIndex>);
#endif
Loading…
Cancel
Save