X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fuisupport%2Fbufferview.cpp;h=addea42bce7876efb59c6bbf00efcd1e11bcb36d;hp=eadf8f7739f157130cba350597e0a5e17b5ca68a;hb=19eb49e171a5a39e1ba8d6c92fd97256aeb949e1;hpb=a7a8099ce2a9d8d25f963a8d297db498ecbc26a5 diff --git a/src/uisupport/bufferview.cpp b/src/uisupport/bufferview.cpp index eadf8f77..addea42b 100644 --- a/src/uisupport/bufferview.cpp +++ b/src/uisupport/bufferview.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-08 by the Quassel Project * + * Copyright (C) 2005-09 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -18,6 +18,9 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include "bufferview.h" + +#include #include #include #include @@ -26,8 +29,6 @@ #include #include -#include "bufferview.h" - #include "action.h" #include "buffermodel.h" #include "bufferviewfilter.h" @@ -35,30 +36,70 @@ #include "buffersyncer.h" #include "client.h" #include "iconloader.h" -#include "mappedselectionmodel.h" #include "network.h" #include "networkmodel.h" #include "networkmodelactionprovider.h" #include "quasselui.h" #include "uisettings.h" +bool TristateDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { + if(event->type() != QEvent::MouseButtonRelease) + return QStyledItemDelegate::editorEvent(event, model, option, index); + + if(!(model->flags(index) & Qt::ItemIsUserCheckable)) + return QStyledItemDelegate::editorEvent(event, model, option, index); + + QVariant value = index.data(Qt::CheckStateRole); + if(!value.isValid()) + return QStyledItemDelegate::editorEvent(event, model, option, index); + + QStyleOptionViewItemV4 viewOpt(option); + initStyleOption(&viewOpt, index); + + QRect checkRect = viewOpt.widget->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, viewOpt.widget); + QMouseEvent *me = static_cast(event); + + if(me->button() != Qt::LeftButton || !checkRect.contains(me->pos())) + return QStyledItemDelegate::editorEvent(event, model, option, index); + + Qt::CheckState state = static_cast(value.toInt()); + if(state == Qt::Unchecked) + state = Qt::PartiallyChecked; + else if(state == Qt::PartiallyChecked) + state = Qt::Checked; + else + state = Qt::Unchecked; + model->setData(index, state, Qt::CheckStateRole); + return true; +} + + + + /***************************************** * The TreeView showing the Buffers *****************************************/ // Please be carefull when reimplementing methods which are used to inform the view about changes to the data // to be on the safe side: call QTreeView's method aswell -BufferView::BufferView(QWidget *parent) : QTreeView(parent) { - connect(this, SIGNAL(collapsed(const QModelIndex &)), SLOT(on_collapse(const QModelIndex &))); - connect(this, SIGNAL(expanded(const QModelIndex &)), SLOT(on_expand(const QModelIndex &))); +BufferView::BufferView(QWidget *parent) + : QTreeView(parent) +{ + connect(this, SIGNAL(collapsed(const QModelIndex &)), SLOT(storeExpandedState(const QModelIndex &))); + connect(this, SIGNAL(expanded(const QModelIndex &)), SLOT(storeExpandedState(const QModelIndex &))); setSelectionMode(QAbstractItemView::ExtendedSelection); + + QAbstractItemDelegate *oldDelegate = itemDelegate(); + TristateDelegate *tristateDelegate = new TristateDelegate(this); + setItemDelegate(tristateDelegate); + delete oldDelegate; } void BufferView::init() { - setIndentation(10); header()->setContextMenuPolicy(Qt::ActionsContextMenu); hideColumn(1); hideColumn(2); + setIndentation(10); expandAll(); setAnimated(true); @@ -159,14 +200,17 @@ void BufferView::setConfig(BufferViewConfig *config) { connect(config, SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(setRootIndexForNetworkId(const NetworkId &))); setRootIndexForNetworkId(config->networkId()); } else { + setIndentation(10); setRootIndex(QModelIndex()); } } void BufferView::setRootIndexForNetworkId(const NetworkId &networkId) { if(!networkId.isValid() || !model()) { + setIndentation(10); setRootIndex(QModelIndex()); } else { + setIndentation(5); int networkCount = model()->rowCount(); QModelIndex child; for(int i = 0; i < networkCount; i++) { @@ -196,6 +240,46 @@ void BufferView::keyPressEvent(QKeyEvent *event) { QTreeView::keyPressEvent(event); } +void BufferView::dropEvent(QDropEvent *event) { + QModelIndex index = indexAt(event->pos()); + + QRect indexRect = visualRect(index); + QPoint cursorPos = event->pos(); + + // check if we're really _on_ the item and not indicating a move to just above or below the item + const int margin = 2; + if(cursorPos.y() - indexRect.top() < margin + || indexRect.bottom() - cursorPos.y() < margin) + return QTreeView::dropEvent(event); + + QList< QPair > bufferList = Client::networkModel()->mimeDataToBufferList(event->mimeData()); + if(bufferList.count() != 1) + return QTreeView::dropEvent(event); + + NetworkId networkId = bufferList[0].first; + BufferId bufferId2 = bufferList[0].second; + + if(index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) + return QTreeView::dropEvent(event); + + if(index.data(NetworkModel::BufferTypeRole) != BufferInfo::QueryBuffer) + return QTreeView::dropEvent(event); + + if(index.data(NetworkModel::NetworkIdRole).value() != networkId) + return QTreeView::dropEvent(event); + + BufferId bufferId1 = index.data(NetworkModel::BufferIdRole).value(); + if(bufferId1 == bufferId2) + return QTreeView::dropEvent(event); + + int res = QMessageBox::question(0, tr("Merge buffers permanently?"), + tr("Do you want to merge the buffer \"%1\" permanently into buffer \"%2\"?\n This cannot be reversed!").arg(Client::networkModel()->bufferName(bufferId2)).arg(Client::networkModel()->bufferName(bufferId1)), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if(res == QMessageBox::Yes) { + Client::mergeBuffersPermanently(bufferId1, bufferId2); + } +} + void BufferView::removeSelectedBuffers(bool permanently) { if(!config()) return; @@ -249,38 +333,49 @@ void BufferView::on_configChanged() { continue; update(networkIdx); - - bool expandNetwork = false; - if(_expandedState.contains(networkId)) - expandNetwork = _expandedState[networkId]; - else - expandNetwork = model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool(); - - if(expandNetwork) - expand(networkIdx); - else - collapse(networkIdx); + setExpandedState(networkIdx); } - // update selection to current one - MappedSelectionModel *mappedSelectionModel = qobject_cast(selectionModel()); - if(!config() || !mappedSelectionModel) - return; + if(config()) { + // update selection to current one + Client::bufferModel()->synchronizeView(this); + } - mappedSelectionModel->mappedSetCurrentIndex(Client::bufferModel()->standardSelectionModel()->currentIndex(), QItemSelectionModel::Current); - mappedSelectionModel->mappedSelect(Client::bufferModel()->standardSelectionModel()->selection(), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + return; } -void BufferView::on_collapse(const QModelIndex &index) { - storeExpandedState(index.data(NetworkModel::NetworkIdRole).value(), false); -} +void BufferView::storeExpandedState(const QModelIndex &networkIdx) { + NetworkId networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); + + int oldState = 0; + if(isExpanded(networkIdx)) + oldState |= WasExpanded; + if(model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool()) + oldState |= WasActive; -void BufferView::on_expand(const QModelIndex &index) { - storeExpandedState(index.data(NetworkModel::NetworkIdRole).value(), true); + _expandedState[networkId] = oldState; } -void BufferView::storeExpandedState(NetworkId networkId, bool expanded) { - _expandedState[networkId] = expanded; +void BufferView::setExpandedState(const QModelIndex &networkIdx) { + if(model()->data(networkIdx, NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) + return; + + if(model()->rowCount(networkIdx) == 0) + return; + + NetworkId networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); + + bool networkActive = model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool(); + bool expandNetwork = networkActive; + if(_expandedState.contains(networkId)) { + int oldState = _expandedState[networkId]; + if((bool)(oldState & WasActive) == networkActive) + expandNetwork = (bool)(oldState & WasExpanded); + } + + storeExpandedState(networkIdx); // this call is needed to keep track of the isActive state + if(expandNetwork != isExpanded(networkIdx)) + setExpanded(networkIdx, expandNetwork); } void BufferView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { @@ -293,15 +388,7 @@ void BufferView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bott for(int i = topLeft.row(); i <= bottomRight.row(); i++) { QModelIndex networkIdx = topLeft.sibling(i, 0); - if(model()->rowCount(networkIdx) == 0) - continue; - - bool isActive = networkIdx.data(NetworkModel::ItemActiveRole).toBool(); -#ifdef SPUTDEV - if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, true); -#else - if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, isActive); -#endif + setExpandedState(networkIdx); } } @@ -314,18 +401,39 @@ void BufferView::contextMenuEvent(QContextMenuEvent *event) { QModelIndex index = indexAt(event->pos()); if(!index.isValid()) index = rootIndex(); - if(!index.isValid()) - return; QMenu contextMenu(this); - addActionsToMenu(&contextMenu, index); + + if(index.isValid()) { + addActionsToMenu(&contextMenu, index); + } + + addFilterActions(&contextMenu, index); + if(!contextMenu.actions().isEmpty()) contextMenu.exec(QCursor::pos()); - } void BufferView::addActionsToMenu(QMenu *contextMenu, const QModelIndex &index) { - Client::mainUi()->actionProvider()->addActions(contextMenu, index, this, "menuActionTriggered", (bool)config()); + QModelIndexList indexList = selectedIndexes(); + // make sure the item we clicked on is first + indexList.removeAll(index); + indexList.prepend(index); + + Client::mainUi()->actionProvider()->addActions(contextMenu, indexList, this, "menuActionTriggered", (bool)config()); +} + +void BufferView::addFilterActions(QMenu *contextMenu, const QModelIndex &index) { + BufferViewFilter *filter = qobject_cast(model()); + if(filter) { + QList filterActions = filter->actions(index); + if(!filterActions.isEmpty()) { + contextMenu->addSeparator(); + foreach(QAction *action, filterActions) { + contextMenu->addAction(action); + } + } + } } void BufferView::menuActionTriggered(QAction *result) { @@ -398,14 +506,6 @@ BufferViewDock::BufferViewDock(BufferViewConfig *config, QWidget *parent) connect(config, SIGNAL(bufferViewNameSet(const QString &)), this, SLOT(bufferViewRenamed(const QString &))); } -BufferViewDock::BufferViewDock(QWidget *parent) - : QDockWidget(tr("All Buffers"), parent) -{ - setObjectName("BufferViewDock--1"); - toggleViewAction()->setData((int)-1); - setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea); -} - void BufferViewDock::bufferViewRenamed(const QString &newName) { setWindowTitle(newName); toggleViewAction()->setText(newName);