From 64ff44560cc13569ab4968e3d974b0b7e9820607 Mon Sep 17 00:00:00 2001 From: Marcus Eggenberger Date: Fri, 22 Jun 2007 15:06:11 +0000 Subject: [PATCH 1/1] Implemented Custom Views (configurable via drag and drop) --- src/client/buffertreemodel.cpp | 36 ++++++++++++++---- src/client/buffertreemodel.h | 5 ++- src/qtgui/bufferview.cpp | 28 +++++++++++--- src/qtgui/bufferview.h | 19 ++++++---- src/qtgui/bufferviewfilter.cpp | 67 ++++++++++++++++++++++++++++++---- src/qtgui/bufferviewfilter.h | 10 ++++- src/qtgui/mainwin.cpp | 2 + 7 files changed, 138 insertions(+), 29 deletions(-) diff --git a/src/client/buffertreemodel.cpp b/src/client/buffertreemodel.cpp index 2d51d85c..43f624ea 100644 --- a/src/client/buffertreemodel.cpp +++ b/src/client/buffertreemodel.cpp @@ -69,10 +69,14 @@ QVariant BufferTreeItem::data(int column, int role) const { return text(column); case Qt::ForegroundRole: return foreground(column); + case BufferTreeModel::BufferNameRole: + return buf->bufferName(); case BufferTreeModel::BufferTypeRole: return buf->bufferType(); case BufferTreeModel::BufferActiveRole: return buf->isActive(); + case BufferTreeModel::BufferIdRole: + return buf->bufferId().uid(); default: return QVariant(); } @@ -94,7 +98,8 @@ QListBufferTreeModel::defaultHeader() { Qt::ItemFlags BufferTreeModel::flags(const QModelIndex &index) const { if(!index.isValid()) - return 0; + return Qt::ItemIsDropEnabled; + //return 0; // I think this is pretty ugly.. if(isBufferIndex(index)) { @@ -102,7 +107,7 @@ Qt::ItemFlags BufferTreeModel::flags(const QModelIndex &index) const { if(buffer->bufferType() == Buffer::QueryBuffer) return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; else - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; } else { return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; } @@ -160,7 +165,8 @@ QModelIndex BufferTreeModel::getOrCreateBufferItemIndex(Buffer *buffer) { QStringList BufferTreeModel::mimeTypes() const { QStringList types; types << "application/Quassel/BufferItem/row" - << "application/Quassel/BufferItem/network"; + << "application/Quassel/BufferItem/network" + << "application/Quassel/BufferItem/bufferId"; return types; } @@ -171,25 +177,41 @@ QMimeData *BufferTreeModel::mimeData(const QModelIndexList &indexes) const { mimeData->setData("application/Quassel/BufferItem/row", QByteArray::number(index.row())); mimeData->setData("application/Quassel/BufferItem/network", getBufferByIndex(index)->networkName().toUtf8()); + mimeData->setData("application/Quassel/BufferItem/bufferId", QByteArray::number(getBufferByIndex(index)->bufferId().uid())); return mimeData; } bool BufferTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { + if(!(data->hasFormat("application/Quassel/BufferItem/row") + && data->hasFormat("application/Quassel/BufferItem/network") + && data->hasFormat("application/Quassel/BufferItem/bufferId"))) + return false; // whatever the drop is... it's not a buffer... + int sourcerow = data->data("application/Quassel/BufferItem/row").toInt(); QString network = QString::fromUtf8(data->data("application/Quassel/BufferItem/network")); if(!networkItem.contains(network)) return false; - if(!isBufferIndex(parent)) // dropping at a network -> no merging needed - return false; - + Buffer *sourceBuffer = static_cast(networkItem[network]->child(sourcerow))->buffer(); + + if(parent == QModelIndex()) { // droping into empty space + emit addBuffer(sourceBuffer->bufferId().uid(), network); + return true; + } + + if(!isBufferIndex(parent)) { // dropping at a network + emit addBuffer(sourceBuffer->bufferId().uid(), network); + return true; + } + + Buffer *targetBuffer = getBufferByIndex(parent); if(sourceBuffer == targetBuffer) // we won't merge with ourself :) return false; - + /* if(QMessageBox::warning(static_cast(QObject::parent()), tr("Merge Buffers?"), diff --git a/src/client/buffertreemodel.h b/src/client/buffertreemodel.h index 9d71dee7..f8490180 100644 --- a/src/client/buffertreemodel.h +++ b/src/client/buffertreemodel.h @@ -58,7 +58,9 @@ class BufferTreeModel : public TreeModel { public: enum myRoles { BufferTypeRole = Qt::UserRole, - BufferActiveRole + BufferActiveRole, + BufferNameRole, + BufferIdRole }; //BufferTreeModel(const QList &, QObject *parent = 0); @@ -81,6 +83,7 @@ signals: void invalidateFilter(); void fakeUserInput(BufferId, QString); void updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags); + void addBuffer(const uint &, const QString &); private: bool isBufferIndex(const QModelIndex &) const; diff --git a/src/qtgui/bufferview.cpp b/src/qtgui/bufferview.cpp index f8054189..33eab930 100644 --- a/src/qtgui/bufferview.cpp +++ b/src/qtgui/bufferview.cpp @@ -30,7 +30,7 @@ BufferView::BufferView(QWidget *parent) : QTreeView(parent) { void BufferView::init() { setIndentation(10); - header()->hide(); + //header()->hide(); header()->hideSection(1); expandAll(); @@ -38,15 +38,25 @@ void BufferView::init() { setAcceptDrops(true); setDropIndicatorShown(true); - connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), model(), SLOT(changeCurrent(const QModelIndex &, const QModelIndex &))); - connect(this, SIGNAL(doubleClicked(const QModelIndex &)), model(), SLOT(doubleClickReceived(const QModelIndex &))); - connect(model(), SIGNAL(updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags)), selectionModel(), SLOT(select(const QModelIndex &, QItemSelectionModel::SelectionFlags))); + setSortingEnabled(true); + sortByColumn(0, Qt::AscendingOrder); + + connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + model(), SLOT(changeCurrent(const QModelIndex &, const QModelIndex &))); + + connect(this, SIGNAL(doubleClicked(const QModelIndex &)), + model(), SLOT(doubleClickReceived(const QModelIndex &))); + + connect(model(), SIGNAL(updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags)), + selectionModel(), SLOT(select(const QModelIndex &, QItemSelectionModel::SelectionFlags))); } void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets) { BufferViewFilter *filter = new BufferViewFilter(model, mode, nets); setModel(filter); + connect(this, SIGNAL(dragEnter()), filter, SLOT(enterDrag())); + connect(this, SIGNAL(dragLeave()), filter, SLOT(leaveDrag())); } void BufferView::setModel(QAbstractItemModel *model) { @@ -54,11 +64,19 @@ void BufferView::setModel(QAbstractItemModel *model) { init(); } +// dragEnterEvent and dragLeaveEvent are needed to keep track of the active +// view when customizing them via drag and drop void BufferView::dragEnterEvent(QDragEnterEvent *event) { - // not yet needed... this will be usefull to keep track of the active view when customizing them with drag and drop + emit dragEnter(); QTreeView::dragEnterEvent(event); } +void BufferView::dragLeaveEvent(QDragLeaveEvent *event) { + emit dragLeave(); + QTreeView::dragLeaveEvent(event); +} + +// ensure that newly inserted network nodes are expanded per default void BufferView::rowsInserted(const QModelIndex & parent, int start, int end) { if(parent.parent() == QModelIndex()) setExpanded(parent, true); QTreeView::rowsInserted(parent, start, end); diff --git a/src/qtgui/bufferview.h b/src/qtgui/bufferview.h index 561cae72..1cb09869 100644 --- a/src/qtgui/bufferview.h +++ b/src/qtgui/bufferview.h @@ -32,14 +32,19 @@ class BufferView : public QTreeView { Q_OBJECT - public: - BufferView(QWidget *parent = 0); - void init(); - void setModel(QAbstractItemModel *model); - void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets); +public: + BufferView(QWidget *parent = 0); + void init(); + void setModel(QAbstractItemModel *model); + void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets); + + void dragEnterEvent(QDragEnterEvent *); + void dragLeaveEvent(QDragLeaveEvent *); + +signals: + void dragEnter(); + void dragLeave(); - void dragEnterEvent(QDragEnterEvent *); - protected: void rowsInserted (const QModelIndex & parent, int start, int end); }; diff --git a/src/qtgui/bufferviewfilter.cpp b/src/qtgui/bufferviewfilter.cpp index caa1fb38..57155ea0 100644 --- a/src/qtgui/bufferviewfilter.cpp +++ b/src/qtgui/bufferviewfilter.cpp @@ -25,6 +25,9 @@ *****************************************/ BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, Modes filtermode, QStringList nets, QObject *parent) : QSortFilterProxyModel(parent) { setSourceModel(model); + setSortRole(BufferTreeModel::BufferNameRole); + setSortCaseSensitivity(Qt::CaseInsensitive); + mode = filtermode; networks = nets; @@ -51,22 +54,70 @@ void BufferViewFilter::doubleClickReceived(const QModelIndex &clicked) { emit doubleClicked(mapToSource(clicked)); } -bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - QModelIndex child = source_parent.child(source_row, 0); - if(!child.isValid()) - return true; // can't imagine this case but true sounds good :) +void BufferViewFilter::enterDrag() { + connect(sourceModel(), SIGNAL(addBuffer(const uint &, const QString &)), + this, SLOT(addBuffer(const uint &, const QString &))); +} + +void BufferViewFilter::leaveDrag() { + disconnect(sourceModel(), SIGNAL(addBuffer(const uint &, const QString &)), + this, SLOT(addBuffer(const uint &, const QString &))); +} - Buffer::Type bufferType = (Buffer::Type) child.data(BufferTreeModel::BufferTypeRole).toInt(); +void BufferViewFilter::addBuffer(const uint &bufferuid, const QString &network) { + if(!networks.contains(network)) { + networks << network; + } + + if(!customBuffers.contains(bufferuid)) { + customBuffers << bufferuid; + invalidateFilter(); + } + +} + +bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const { + Buffer::Type bufferType = (Buffer::Type) source_bufferIndex.data(BufferTreeModel::BufferTypeRole).toInt(); if((mode & NoChannels) && bufferType == Buffer::ChannelBuffer) return false; if((mode & NoQueries) && bufferType == Buffer::QueryBuffer) return false; if((mode & NoServers) && bufferType == Buffer::ServerBuffer) return false; - bool isActive = child.data(BufferTreeModel::BufferActiveRole).toBool(); + bool isActive = source_bufferIndex.data(BufferTreeModel::BufferActiveRole).toBool(); if((mode & NoActive) && isActive) return false; if((mode & NoInactive) && !isActive) return false; - QString net = child.data(Qt::DisplayRole).toString(); - if((mode & SomeNets) && !networks.contains(net)) return false; + if((mode & FullCustom)) { + uint bufferuid = source_bufferIndex.data(BufferTreeModel::BufferIdRole).toUInt(); + if(!customBuffers.contains(bufferuid)) + return false; + } return true; } + +bool BufferViewFilter::filterAcceptNetwork(const QModelIndex &source_index) const { + QString net = source_index.data(Qt::DisplayRole).toString(); + if((mode & SomeNets) && !networks.contains(net)) + return false; + else + return true; +} + +bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { + QModelIndex child = sourceModel()->index(source_row, 0, source_parent); + + if(!child.isValid()) { + qDebug() << "filterAcceptsRow has been called with an invalid Child"; + return false; + } + + if(source_parent == QModelIndex()) + return filterAcceptNetwork(child); + else + return filterAcceptBuffer(child); +} + +bool BufferViewFilter::lessThan(const QModelIndex &left, const QModelIndex &right) { + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/src/qtgui/bufferviewfilter.h b/src/qtgui/bufferviewfilter.h index 8bce1439..cd93a220 100644 --- a/src/qtgui/bufferviewfilter.h +++ b/src/qtgui/bufferviewfilter.h @@ -40,7 +40,8 @@ public: AllNets = 0x08, NoChannels = 0x10, NoQueries = 0x20, - NoServers = 0x40 + NoServers = 0x40, + FullCustom = 0x80 }; Q_DECLARE_FLAGS(Modes, Mode) @@ -51,6 +52,9 @@ public slots: void changeCurrent(const QModelIndex &, const QModelIndex &); void doubleClickReceived(const QModelIndex &); void select(const QModelIndex &, QItemSelectionModel::SelectionFlags); + void enterDrag(); + void leaveDrag(); + void addBuffer(const uint &, const QString &); signals: void currentChanged(const QModelIndex &, const QModelIndex &); @@ -58,10 +62,14 @@ signals: void updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags); private: + bool filterAcceptBuffer(const QModelIndex &) const; + bool filterAcceptNetwork(const QModelIndex &) const; bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + bool lessThan(const QModelIndex &, const QModelIndex &); Modes mode; QStringList networks; + QList customBuffers; }; Q_DECLARE_OPERATORS_FOR_FLAGS(BufferViewFilter::Modes) diff --git a/src/qtgui/mainwin.cpp b/src/qtgui/mainwin.cpp index 0ef57c18..f4f0c7e9 100644 --- a/src/qtgui/mainwin.cpp +++ b/src/qtgui/mainwin.cpp @@ -141,6 +141,8 @@ void MainWin::setupViews() { BufferViewDock *allnets = new BufferViewDock(model, tr("All Networks"), BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoQueries); registerBufferViewDock(allnets); + BufferViewDock *fullCustom = new BufferViewDock(model, tr("Full Custom"), BufferViewFilter::FullCustom|BufferViewFilter::SomeNets); + registerBufferViewDock(fullCustom); ui.menuViews->addSeparator(); } -- 2.20.1