SET(gui_SRCS chatwidget.cpp channelwidgetinput.cpp tabcompleter.cpp mainwin.cpp serverlist.cpp buffer.cpp bufferwidget.cpp
- identities.cpp coreconnectdlg.cpp guiproxy.cpp bufferview.cpp style.cpp settingsdlg.cpp settingspages.cpp)
+ identities.cpp coreconnectdlg.cpp guiproxy.cpp bufferview.cpp bufferviewwidget.cpp style.cpp settingsdlg.cpp settingspages.cpp)
SET(gui_HDRS style.h)
SET(gui_MOCS chatwidget.h channelwidgetinput.h tabcompleter.h mainwin.h serverlist.h identities.h coreconnectdlg.h
- guiproxy.h bufferview.h buffer.h bufferwidget.h settingsdlg.h settingspages.h)
+ guiproxy.h bufferview.h buffer.h bufferwidget.h bufferviewwidget.h settingsdlg.h settingspages.h)
SET(gui_UICS identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui mainwin.ui
nickeditdlg.ui serverlistdlg.ui servereditdlg.ui coreconnectdlg.ui ircwidget.ui
- bufferview.ui bufferwidget.ui settingsdlg.ui
+ bufferviewwidget.ui bufferwidget.ui settingsdlg.ui
buffermgmntsettingspage.ui connectionsettingspage.ui)
# This prepends ui/ to the UIC names, so we don't have to do this ourselves.
}
+QString Buffer::displayName() {
+ if(bufferType() == ServerBuffer)
+ return tr("status");
+ else
+ return bufferName();
+}
+
void Buffer::setActive(bool a) {
if(a != active) {
active = a;
static void init();
enum Type { ServerBuffer, ChannelBuffer, QueryBuffer };
+
+ enum Activity {
+ NoActivity = 0x00,
+ OtherActivity = 0x01,
+ NewMessage = 0x02,
+ Highlight = 0x40
+ };
+ Q_DECLARE_FLAGS(ActivityLevel, Activity)
+
Type bufferType() { return type; }
bool isActive() { return active; }
QString networkName() { return _networkName; }
QString bufferName() { return _bufferName; }
+ QString displayName();
BufferId bufferId() { return id; }
QList<ChatLine *> contents() { return lines; }
VarMap nickList() { return nicks; }
QString topic() { return _topic; }
QString ownNick() { return _ownNick; }
+ bool isStatusBuffer() { return bufferType() == ServerBuffer; }
signals:
void userInput(BufferId, QString);
QList<ChatLine *> lines;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Buffer::ActivityLevel)
#endif
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#include "global.h"
#include "bufferview.h"
-
-BufferViewWidget::BufferViewWidget(QWidget *parent) : QWidget(parent) {
- ui.setupUi(this);
-
- //setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-}
-
-
-QSize BufferViewWidget::sizeHint() const {
- return QSize(150,100);
-
-}
-
-/**************************************************************************/
-
-BufferView::BufferView(QString n, int m, QStringList nets, QWidget *parent) : QDockWidget(parent) {
- setObjectName(QString("View-"+n)); // should be unique for mainwindow state!
- name = n; mode = m;
- setWindowTitle(name);
+#include "bufferviewwidget.h"
+
+/*****************************************
+* The TreeView showing the Buffers
+*****************************************/
+BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, Modes filtermode, QStringList nets, QObject *parent) : QSortFilterProxyModel(parent) {
+ setSourceModel(model);
+ mode = filtermode;
networks = nets;
- currentBuffer = 0;
- setWidget(new BufferViewWidget(this));
- tree = qobject_cast<BufferViewWidget*>(widget())->tree();
- tree->header()->hide();
- tree->setSortingEnabled(true);
- tree->setRootIsDecorated(true);
- tree->setIndentation(10);
- //tree->setAnimated(true);
- connect(tree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(itemClicked(QTreeWidgetItem*)));
- connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*)));
- connect(this, SIGNAL(fakeUserInput(BufferId, QString)), guiProxy, SLOT(gsUserInput(BufferId, QString)));
+ connect(model, SIGNAL(invalidateFilter()), this, SLOT(invalidateMe()));
+ connect(model, SIGNAL(updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags)), this, SLOT(select(const QModelIndex &, QItemSelectionModel::SelectionFlags)));
+
+ connect(this, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), model, SLOT(changeCurrent(const QModelIndex &, const QModelIndex &)));
+ connect(this, SIGNAL(doubleClicked(const QModelIndex &)), model, SLOT(doubleClickReceived(const QModelIndex &)));
}
-void BufferView::setBuffers(QList<Buffer *> buffers) {
- tree->clear(); bufitems.clear(); netitems.clear();
- foreach(Buffer *b, buffers) {
- bufferUpdated(b);
- }
+void BufferViewFilter::invalidateMe() {
+ invalidateFilter();
}
-void BufferView::bufferUpdated(Buffer *b) {
- if(bufitems.contains(b)) {
- // FIXME this looks ugly
- /*
- this is actually fugly! :) - EgS
- if anyone else wonders what this does: it takes the TreeItem related to the buffer out of the parents child list
- therefore we need to know the childs index
- */
- QTreeWidgetItem *item = bufitems[b]->parent()->takeChild(bufitems[b]->parent()->indexOfChild(bufitems[b]));
- delete item;
- bufitems.remove(b);
- }
- if(shouldShow(b)) {
- QString net = b->networkName();
- QString buf = b->bufferName();
- QTreeWidgetItem *item;
- QStringList label;
- if(b->bufferType() == Buffer::ServerBuffer) label << tr("Status");
- else label << buf;
- if((mode & SomeNets) || ( mode & AllNets)) {
- if(!netitems.contains(net)) {
- netitems[net] = new QTreeWidgetItem(tree, QStringList(net));
- netitems[net]->setFlags(Qt::ItemIsEnabled);
- }
- QTreeWidgetItem *ni = netitems[net];
- ni->setExpanded(true);
- ni->setFlags(Qt::ItemIsEnabled);
- item = new QTreeWidgetItem(ni, label);
- } else {
- item = new QTreeWidgetItem(label);
- }
- //item->setFlags(Qt::ItemIsEnabled);
- bufitems[b] = item;
- // TODO Use style engine!
- if(!b->isActive()) {
- item->setForeground(0, QColor("grey"));
- }
- if(b == currentBuffer) {
- // this fixes the multiple simultaneous selections
- emit bufferSelected(b);
- //item->setSelected(true);
- }
- }
- foreach(QString key, netitems.keys()) {
- if(!netitems[key]->childCount()) {
- delete netitems[key];
- QTreeWidgetItem *item = netitems[key]->parent()->takeChild(netitems[key]->parent()->indexOfChild(netitems[key]));
- delete item;
- netitems.remove(key);
- }
- }
+void BufferViewFilter::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) {
+ emit updateSelection(mapFromSource(index), command);
}
-void BufferView::bufferActivity(uint level, Buffer *b) {
- QColor c;
- if(bufitems.contains(b) and b != currentBuffer) {
- if(level & Highlight) {
- c = QColor(Qt::red);
- } else if(level & NewMessage) {
- c = QColor(Qt::darkYellow);
- } else if(level & OtherActivity) {
- c = QColor(Qt::darkGreen);
- }
- bufitems[b]->setForeground(0, c);
- }
+void BufferViewFilter::changeCurrent(const QModelIndex ¤t, const QModelIndex &previous) {
+ emit currentChanged(mapToSource(current), mapToSource(previous));
}
-void BufferView::clearActivity(Buffer *b) {
- QColor c;
- // it should be sane not to check if b is in bufitems since we just checked before calling this function
- if(b->isActive()) {
- c = QColor(Qt::black);
- } else {
- c = QColor(Qt::gray);
- }
- bufitems[b]->setForeground(0, c);
+void BufferViewFilter::doubleClickReceived(const QModelIndex &clicked) {
+ emit doubleClicked(mapToSource(clicked));
}
-bool BufferView::shouldShow(Buffer *b) {
- // bool f = false;
- if((mode & NoActive) && b->isActive()) return false;
- if((mode & NoInactive) && !b->isActive()) return false;
- if((mode & NoChannels) && b->bufferType() == Buffer::ChannelBuffer) return false;
- if((mode & NoQueries) && b->bufferType() == Buffer::QueryBuffer) return false;
- if((mode & NoServers) && b->bufferType() == Buffer::ServerBuffer) return false;
- if((mode & SomeNets) && !networks.contains(b->networkName())) return false;
+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 :)
+
+ Buffer::Type bufferType = (Buffer::Type) child.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();
+ 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;
+
return true;
}
-void BufferView::bufferDestroyed(Buffer *b) {
-
+/*****************************************
+* The TreeView showing the Buffers
+*****************************************/
+BufferView::BufferView(QWidget *parent) : QTreeView(parent) {
}
-void BufferView::itemClicked(QTreeWidgetItem *item) {
- Buffer *b = bufitems.key(item);
- if(b) {
- // there is a buffer associated with the item (aka: status/channel/query)
- emit bufferSelected(b);
- } else {
- // network item
- item->setExpanded(!item->isExpanded());
- }
+void BufferView::init() {
+ setIndentation(10);
+ header()->hide();
+ header()->hideSection(1);
+
+ setDragEnabled(true);
+ 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)));
}
-void BufferView::itemDoubleClicked(QTreeWidgetItem *item) {
- Buffer *b = bufitems.key(item);
- if(b && Buffer::ChannelBuffer == b->bufferType()) {
- emit fakeUserInput(b->bufferId(), QString("/join " + b->bufferName()));
- emit bufferSelected(b);
- }
+void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets) {
+ BufferViewFilter *filter = new BufferViewFilter(model, mode, nets);
+ setModel(filter);
}
-void BufferView::selectBuffer(Buffer *b) {
- QTreeWidgetItem *item = 0;
- if(bufitems.contains(b)) item = bufitems[b];
- QList<QTreeWidgetItem *> sel = tree->selectedItems();
- foreach(QTreeWidgetItem *i, sel) { if(i != item) i->setSelected(false); }
- if(item) {
- item->setSelected(true);
- clearActivity(b);
- currentBuffer = b;
- } else {
- currentBuffer = 0;
- }
-}
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#ifndef _BUFFERVIEW_H_
-#define _BUFFERVIEW_H_
+#ifndef _BUFFERVIEWWIDGET_H_
+#define _BUFFERVIEWWIDGET_H_
#include <QtGui>
-#include "ui_bufferview.h"
-#include "guiproxy.h"
+#include <QFlags>
#include "buffer.h"
-typedef QHash<QString, QHash<QString, Buffer*> > BufferHash;
-
-class BufferViewWidget : public QWidget {
+/*****************************************
+ * Buffer View Filter
+ *****************************************/
+class BufferViewFilter : public QSortFilterProxyModel {
Q_OBJECT
+
+public:
+ enum Mode {
+ NoActive = 0x01,
+ NoInactive = 0x02,
+ SomeNets = 0x04,
+ AllNets = 0x08,
+ NoChannels = 0x10,
+ NoQueries = 0x20,
+ NoServers = 0x40
+ };
+ Q_DECLARE_FLAGS(Modes, Mode)
+
+ BufferViewFilter(QAbstractItemModel *model, Modes mode, QStringList nets, QObject *parent = 0);
+
+public slots:
+ void invalidateMe();
+ void changeCurrent(const QModelIndex &, const QModelIndex &);
+ void doubleClickReceived(const QModelIndex &);
+ void select(const QModelIndex &, QItemSelectionModel::SelectionFlags);
+
+signals:
+ void currentChanged(const QModelIndex &, const QModelIndex &);
+ void doubleClicked(const QModelIndex &);
+ void updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags);
+
+private:
+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
- public:
- BufferViewWidget(QWidget *parent = 0);
-
- QTreeWidget *tree() { return ui.tree; }
-
- virtual QSize sizeHint () const;
-
- signals:
- void bufferSelected(QString net, QString buf);
-
- private slots:
-
-
- private:
- Ui::BufferViewWidget ui;
-
+ Modes mode;
+ QStringList networks;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(BufferViewFilter::Modes)
-class BufferView : public QDockWidget {
+/*****************************************
+ * The TreeView showing the Buffers
+ *****************************************/
+class BufferView : public QTreeView {
Q_OBJECT
-
- public:
- enum Mode {
- NoActive = 0x01, NoInactive = 0x02,
- SomeNets = 0x04, AllNets = 0x08,
- NoChannels = 0x10, NoQueries = 0x20, NoServers = 0x40
- };
- enum ActivityLevel {
- NoActivity = 0x00, OtherActivity = 0x01,
- NewMessage = 0x02, Highlight = 0x40
- };
-
- BufferView(QString name, int mode, QStringList nets = QStringList(), QWidget *parent = 0);
- void setMode(int mode, QStringList nets = QStringList());
- void setName(QString name);
-
-
- public slots:
- void bufferUpdated(Buffer *);
- void bufferActivity(uint, Buffer *);
- void bufferDestroyed(Buffer *);
- void setBuffers(QList<Buffer *>);
- void selectBuffer(Buffer *);
-
- signals:
- void bufferSelected(Buffer *);
- void fakeUserInput(BufferId, QString);
-
- private slots:
- void itemClicked(QTreeWidgetItem *item);
- void itemDoubleClicked(QTreeWidgetItem *item);
-
- private:
- int mode;
- QString name;
- QStringList networks;
- Buffer *currentBuffer;
- //QHash<QString, QHash<QString, Buffer*> > buffers;
- QHash<Buffer *, QTreeWidgetItem *> bufitems;
- QHash<QString, QTreeWidgetItem *> netitems;
- //QHash<QString, QHash<QString, QTreeWidgetItem *> > items;
- QTreeWidget *tree;
-
- bool shouldShow(Buffer *);
- void clearActivity(Buffer *);
+public:
+ BufferView(QWidget *parent = 0);
+ void init();
+ void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets);
+
};
-#endif
+#endif
\ No newline at end of file
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-07 by The Quassel Team *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "global.h"
+#include "bufferviewwidget.h"
+
+/*****************************************
+ * Buffer Items stored in the Tree Model
+ *****************************************/
+TreeItem::TreeItem(QList<QVariant> &data, TreeItem *parent) {
+ itemData = data;
+ parentItem = parent;
+ foreground = Qt::black;
+}
+
+TreeItem::TreeItem(TreeItem *parent) {
+ itemData = QList<QVariant>();
+ parentItem = parent;
+ foreground = Qt::black;
+}
+
+TreeItem::~TreeItem() {
+ qDeleteAll(childItems);
+}
+
+void TreeItem::appendChild(TreeItem *item) {
+ childItems.append(item);
+}
+
+void TreeItem::removeChild(int row) {
+ childItems.removeAt(row);
+}
+
+TreeItem *TreeItem::child(int row) {
+ return childItems.value(row);
+}
+
+int TreeItem::childCount() const {
+ return childItems.count();
+}
+
+int TreeItem::row() const {
+ if(parentItem)
+ return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
+ else
+ return 0;
+}
+
+TreeItem *TreeItem::parent() {
+ return parentItem;
+}
+
+int TreeItem::columnCount() const {
+ return itemData.count();
+}
+
+void TreeItem::setForeground(QColor newcolor) {
+ foreground = newcolor;
+}
+
+QVariant TreeItem::data(int column, int role) const {
+ switch(role) {
+ case Qt::DisplayRole:
+ if(column < itemData.count())
+ return itemData[column];
+ else
+ return QVariant();
+
+ case Qt::ForegroundRole:
+ return foreground;
+
+ default:
+ return QVariant();
+
+ }
+}
+
+/*****************************************
+* Fancy Buffer Items
+*****************************************/
+BufferTreeItem::BufferTreeItem(Buffer *buffer, TreeItem *parent) : TreeItem(parent) {
+ buf = buffer;
+ activity = Buffer::NoActivity;
+}
+
+void BufferTreeItem::setActivity(const Buffer::ActivityLevel &level) {
+ activity = level;
+}
+
+QString BufferTreeItem::text(int column) const {
+ switch(column) {
+ case 0:
+ return buf->displayName();
+ case 1:
+ return buf->networkName();
+ default:
+ return QString();
+ }
+}
+
+QColor BufferTreeItem::foreground(int column) const {
+ // for the time beeing we ignore the column :)
+ if(activity & Buffer::Highlight) {
+ return QColor(Qt::red);
+ } else if(activity & Buffer::NewMessage) {
+ return QColor(Qt::darkYellow);
+ } else if(activity & Buffer::OtherActivity) {
+ return QColor(Qt::darkGreen);
+ } else {
+ if(buf->isActive())
+ return QColor(Qt::black);
+ else
+ return QColor(Qt::gray);
+ }
+}
+
+
+QVariant BufferTreeItem::data(int column, int role) const {
+ switch(role) {
+ case Qt::DisplayRole:
+ return text(column);
+ case Qt::ForegroundRole:
+ return foreground(column);
+ case BufferTreeModel::BufferTypeRole:
+ return buf->bufferType();
+ case BufferTreeModel::BufferActiveRole:
+ return buf->isActive();
+ default:
+ return QVariant();
+ }
+}
+
+/*****************************************
+ * BufferTreeModel
+ *****************************************/
+BufferTreeModel::BufferTreeModel(QObject *parent) : QAbstractItemModel(parent) {
+ QList<QVariant> rootData;
+ rootData << "Buffer" << "Network";
+ rootItem = new TreeItem(rootData, 0);
+
+ connect(this, SIGNAL(fakeUserInput(BufferId, QString)), guiProxy, SLOT(gsUserInput(BufferId, QString)));
+}
+
+BufferTreeModel::~BufferTreeModel() {
+ delete rootItem;
+}
+
+QModelIndex BufferTreeModel::index(int row, int column, const QModelIndex &parent) const {
+ if(!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ TreeItem *parentItem;
+
+ if(!parent.isValid())
+ parentItem = rootItem;
+ else
+ parentItem = static_cast<TreeItem*>(parent.internalPointer());
+
+ TreeItem *childItem = parentItem->child(row);
+ if(childItem)
+ return createIndex(row, column, childItem);
+ else
+ return QModelIndex();
+}
+
+QModelIndex BufferTreeModel::parent(const QModelIndex &index) const {
+ if(!index.isValid())
+ return QModelIndex();
+
+ TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
+ TreeItem *parentItem = childItem->parent();
+
+ if(parentItem == rootItem)
+ return QModelIndex();
+
+ return createIndex(parentItem->row(), 0, parentItem);
+}
+
+int BufferTreeModel::rowCount(const QModelIndex &parent) const {
+ TreeItem *parentItem;
+ if(parent.column() > 0)
+ return 0;
+
+ if(!parent.isValid())
+ parentItem = rootItem;
+ else
+ parentItem = static_cast<TreeItem*>(parent.internalPointer());
+
+ return parentItem->childCount();
+}
+
+int BufferTreeModel::columnCount(const QModelIndex &parent) const {
+ if(parent.isValid())
+ return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
+ else
+ return rootItem->columnCount();
+}
+
+QVariant BufferTreeModel::data(const QModelIndex &index, int role) const {
+ if(!index.isValid())
+ return QVariant();
+
+ TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+ return item->data(index.column(), role);
+}
+
+Qt::ItemFlags BufferTreeModel::flags(const QModelIndex &index) const {
+ if(!index.isValid())
+ return 0;
+
+ // I think this is pretty ugly..
+ if(isBufferIndex(index)) {
+ Buffer *buffer = getBufferByIndex(index);
+ if(buffer->bufferType() == Buffer::QueryBuffer)
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
+ else
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ } else {
+ return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
+ }
+}
+
+QVariant BufferTreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ return rootItem->data(section, role);
+ else
+ return QVariant();
+}
+
+bool BufferTreeModel::removeRow(int row, const QModelIndex &parent) {
+ beginRemoveRows(parent, row, row);
+ TreeItem *item = static_cast<TreeItem*>(parent.internalPointer());
+ item->removeChild(row);
+ endRemoveRows();
+ return true;
+}
+
+bool BufferTreeModel::isBufferIndex(const QModelIndex &index) const {
+ return parent(index) != QModelIndex();
+}
+
+Buffer *BufferTreeModel::getBufferByIndex(const QModelIndex &index) const {
+ BufferTreeItem *item = static_cast<BufferTreeItem *>(index.internalPointer());
+ return item->buffer();
+}
+
+QModelIndex BufferTreeModel::getOrCreateNetworkItemIndex(Buffer *buffer) {
+ QString net = buffer->networkName();
+
+ if(networkItem.contains(net)) {
+ return index(networkItem[net]->row(), 0);
+ } else {
+ QList<QVariant> data;
+ data << net << "";
+
+ int nextRow = rootItem->childCount();
+
+ beginInsertRows(QModelIndex(), nextRow, nextRow);
+ rootItem->appendChild(new TreeItem(data, rootItem));
+ endInsertRows();
+
+ networkItem[net] = rootItem->child(nextRow);
+ return index(nextRow, 0);
+ }
+}
+
+QModelIndex BufferTreeModel::getOrCreateBufferItemIndex(Buffer *buffer) {
+ QModelIndex networkItemIndex = getOrCreateNetworkItemIndex(buffer);
+
+ if(bufferItem.contains(buffer)) {
+ return index(bufferItem[buffer]->row(), 0, networkItemIndex);
+ } else {
+ // first we determine the parent of the new Item
+ TreeItem *networkItem = static_cast<TreeItem*>(networkItemIndex.internalPointer());
+
+ int nextRow = networkItem->childCount();
+
+ beginInsertRows(networkItemIndex, nextRow, nextRow);
+ networkItem->appendChild(new BufferTreeItem(buffer, networkItem));
+ endInsertRows();
+
+ bufferItem[buffer] = static_cast<BufferTreeItem *>(networkItem->child(nextRow));
+ return index(nextRow, 0, networkItemIndex);
+ }
+}
+
+QStringList BufferTreeModel::mimeTypes() const {
+ QStringList types;
+ types << "application/Quassel/BufferItem/row"
+ << "application/Quassel/BufferItem/network";
+ return types;
+}
+
+QMimeData *BufferTreeModel::mimeData(const QModelIndexList &indexes) const {
+ QMimeData *mimeData = new QMimeData();
+
+ QModelIndex index = indexes.first();
+
+ mimeData->setData("application/Quassel/BufferItem/row", QByteArray::number(index.row()));
+ mimeData->setData("application/Quassel/BufferItem/network", getBufferByIndex(index)->networkName().toUtf8());
+ return mimeData;
+}
+
+bool BufferTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
+ 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<BufferTreeItem *>(networkItem[network]->child(sourcerow))->buffer();
+ Buffer *targetBuffer = getBufferByIndex(parent);
+
+ qDebug() << "merging" << sourceBuffer->bufferName() << "with" << targetBuffer->bufferName();
+ bufferItem.remove(getBufferByIndex(parent));
+ removeRow(parent.row(), BufferTreeModel::parent(parent));
+
+ return true;
+}
+
+void BufferTreeModel::bufferUpdated(Buffer *buffer) {
+ QModelIndex itemindex = getOrCreateBufferItemIndex(buffer);
+ emit invalidateFilter();
+ emit dataChanged(itemindex, itemindex);
+}
+
+// This Slot indicates that the user has selected a different buffer in the gui
+void BufferTreeModel::changeCurrent(const QModelIndex ¤t, const QModelIndex &previous) {
+ if(isBufferIndex(current)) {
+ currentBuffer = getBufferByIndex(current);
+ bufferActivity(Buffer::NoActivity, currentBuffer);
+ emit bufferSelected(currentBuffer);
+ }
+}
+
+// we received a double click on a buffer, so we're going to join it
+void BufferTreeModel::doubleClickReceived(const QModelIndex &clicked) {
+ if(isBufferIndex(clicked)) {
+ Buffer *buffer = getBufferByIndex(clicked);
+ if(!buffer->isStatusBuffer())
+ emit fakeUserInput(buffer->bufferId(), QString("/join " + buffer->bufferName()));
+ }
+
+}
+
+void BufferTreeModel::bufferActivity(Buffer::ActivityLevel level, Buffer *buffer) {
+ if(bufferItem.contains(buffer) and buffer != currentBuffer)
+ bufferItem[buffer]->setActivity(level);
+ else
+ bufferItem[buffer]->setActivity(Buffer::NoActivity);
+ bufferUpdated(buffer);
+}
+
+void BufferTreeModel::selectBuffer(Buffer *buffer) {
+ QModelIndex index = getOrCreateBufferItemIndex(buffer);
+ emit updateSelection(index, QItemSelectionModel::ClearAndSelect);
+}
+
+
+/*****************************************
+ * This Widget Contains the BufferView
+ *****************************************/
+BufferViewWidget::BufferViewWidget(QWidget *parent) : QWidget(parent) {
+ ui.setupUi(this);
+}
+
+QSize BufferViewWidget::sizeHint() const {
+ return QSize(150,100);
+}
+
+
+/*****************************************
+ * Dock and API for the BufferViews
+ *****************************************/
+BufferViewDock::BufferViewDock(QAbstractItemModel *model, QString viewname, BufferViewFilter::Modes mode, QStringList nets, QWidget *parent) : QDockWidget(parent) {
+ setObjectName(QString("View-" + viewname)); // should be unique for mainwindow state!
+ setWindowTitle(viewname);
+
+ BufferViewWidget *viewWidget = new BufferViewWidget(this);
+ viewWidget->treeView()->setFilteredModel(model, mode, nets);
+ viewWidget->treeView()->init();
+ setWidget(viewWidget);
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-07 by The Quassel Team *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _BUFFERVIEW_H_
+#define _BUFFERVIEW_H_
+
+#include <QtGui>
+#include <QtCore>
+
+#include "guiproxy.h"
+#include "buffer.h"
+#include "ui_bufferviewwidget.h"
+#include "bufferview.h"
+
+/*****************************************
+ * general item used in the Tree Model
+ *****************************************/
+class TreeItem {
+public:
+ TreeItem(QList<QVariant> &data, TreeItem *parent = 0);
+ TreeItem(TreeItem *parent = 0);
+ virtual ~TreeItem();
+
+ void appendChild(TreeItem *child);
+ void removeChild(int row);
+
+ TreeItem *child(int row);
+ int childCount() const;
+ int columnCount() const;
+ virtual QVariant data(int column, int role) const;
+ int row() const;
+ TreeItem *parent();
+
+ void setForeground(QColor);
+
+private:
+ QList<TreeItem*> childItems;
+ TreeItem *parentItem;
+ QList<QVariant> itemData;
+
+ QColor foreground;
+};
+
+
+/*****************************************
+ * Fancy Buffer Items
+ *****************************************/
+class BufferTreeItem : public TreeItem{
+public:
+ BufferTreeItem(Buffer *, TreeItem *parent = 0);
+ QVariant data(int column, int role) const;
+ Buffer *buffer() const { return buf; }
+ void setActivity(const Buffer::ActivityLevel &);
+
+private:
+ QString text(int column) const;
+ QColor foreground(int column) const;
+ Buffer *buf;
+ Buffer::ActivityLevel activity;
+};
+
+
+/*****************************************
+ * BufferTreeModel
+ *****************************************/
+class BufferTreeModel : public QAbstractItemModel {
+ Q_OBJECT
+
+public:
+ enum myRoles {
+ BufferTypeRole = Qt::UserRole,
+ BufferActiveRole
+ };
+
+
+ BufferTreeModel(QObject *parent = 0);
+ ~BufferTreeModel();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &index) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+ void clearActivity(Buffer *buffer);
+
+public slots:
+ void bufferUpdated(Buffer *);
+ void changeCurrent(const QModelIndex &, const QModelIndex &);
+ void selectBuffer(Buffer *buffer);
+ void doubleClickReceived(const QModelIndex &);
+ void bufferActivity(Buffer::ActivityLevel, Buffer *buffer);
+
+signals:
+ void bufferSelected(Buffer *);
+ void invalidateFilter();
+ void fakeUserInput(BufferId, QString);
+ void updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags);
+
+private:
+ bool isBufferIndex(const QModelIndex &) const;
+ Buffer *getBufferByIndex(const QModelIndex &) const;
+ QModelIndex getOrCreateNetworkItemIndex(Buffer *buffer);
+ QModelIndex getOrCreateBufferItemIndex(Buffer *buffer);
+
+ bool removeRow(int row, const QModelIndex &parent = QModelIndex());
+
+ QStringList mimeTypes() const;
+ QMimeData *mimeData(const QModelIndexList &) const;
+ bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &);
+ TreeItem *rootItem;
+
+ QHash<QString, TreeItem*> networkItem;
+ QHash<Buffer *, BufferTreeItem*> bufferItem;
+ Buffer *currentBuffer;
+};
+
+
+
+
+/*****************************************
+ * This Widget Contains the BufferView
+ *****************************************/
+class BufferViewWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ BufferViewWidget(QWidget *parent = 0);
+ virtual QSize sizeHint () const;
+ BufferView *treeView() { return ui.treeView; }
+
+private:
+ Ui::BufferViewWidget ui;
+
+};
+
+
+/*****************************************
+ * Dock and API for the BufferViews
+ *****************************************/
+class BufferViewDock : public QDockWidget {
+ Q_OBJECT
+
+public:
+ BufferViewDock(QAbstractItemModel *model, QString name, BufferViewFilter::Modes mode, QStringList nets = QStringList(), QWidget *parent = 0);
+};
+
+
+#endif
#include "mainwin.h"
#include "buffer.h"
-#include "bufferview.h"
+#include "bufferviewwidget.h"
#include "serverlist.h"
#include "coreconnectdlg.h"
#include "settingsdlg.h"
}
void MainWin::setupViews() {
- BufferView *all = new BufferView(tr("All Buffers"), BufferView::AllNets);
- registerBufferView(all);
- addDockWidget(Qt::LeftDockWidgetArea, all);
- BufferView *allchans = new BufferView(tr("All Channels"), BufferView::AllNets|BufferView::NoQueries|BufferView::NoServers);
- registerBufferView(allchans);
- addDockWidget(Qt::LeftDockWidgetArea, allchans);
- BufferView *allqrys = new BufferView(tr("All Queries"), BufferView::AllNets|BufferView::NoChannels|BufferView::NoServers);
- registerBufferView(allqrys);
- addDockWidget(Qt::RightDockWidgetArea, allqrys);
- BufferView *allnets = new BufferView(tr("All Networks"), BufferView::AllNets|BufferView::NoChannels|BufferView::NoQueries);
- registerBufferView(allnets);
- addDockWidget(Qt::RightDockWidgetArea, allnets);
+ BufferTreeModel *model = new BufferTreeModel();
+ connect(model, SIGNAL(bufferSelected(Buffer *)), this, SLOT(showBuffer(Buffer *)));
+ connect(this, SIGNAL(bufferSelected(Buffer *)), model, SLOT(selectBuffer(Buffer *)));
+ connect(this, SIGNAL(bufferUpdated(Buffer *)), model, SLOT(bufferUpdated(Buffer *)));
+ connect(this, SIGNAL(bufferActivity(Buffer::ActivityLevel, Buffer *)), model, SLOT(bufferActivity(Buffer::ActivityLevel, Buffer *)));
+
+ BufferViewDock *all = new BufferViewDock(model, tr("All Buffers"), BufferViewFilter::AllNets);
+ registerBufferViewDock(all);
+
+ BufferViewDock *allchans = new BufferViewDock(model, tr("All Channels"), BufferViewFilter::AllNets|BufferViewFilter::NoQueries|BufferViewFilter::NoServers);
+ registerBufferViewDock(allchans);
+
+ BufferViewDock *allqrys = new BufferViewDock(model, tr("All Queries"), BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoServers);
+ registerBufferViewDock(allqrys);
+
+
+ BufferViewDock *allnets = new BufferViewDock(model, tr("All Networks"), BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoQueries);
+ registerBufferViewDock(allnets);
+
ui.menuViews->addSeparator();
}
-void MainWin::registerBufferView(BufferView *view) {
+void MainWin::registerBufferViewDock(BufferViewDock *dock) {
+ addDockWidget(Qt::LeftDockWidgetArea, dock);
+ dock->setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
+ netViews.append(dock);
+ ui.menuViews->addAction(dock->toggleViewAction());
+
+ /*
connect(this, SIGNAL(bufferSelected(Buffer *)), view, SLOT(selectBuffer(Buffer *)));
- connect(this, SIGNAL(bufferUpdated(Buffer *)), view, SLOT(bufferUpdated(Buffer *)));
- connect(this, SIGNAL(bufferActivity(uint, Buffer *)), view, SLOT(bufferActivity(uint, Buffer *)));
connect(this, SIGNAL(bufferDestroyed(Buffer *)), view, SLOT(bufferDestroyed(Buffer *)));
connect(view, SIGNAL(bufferSelected(Buffer *)), this, SLOT(showBuffer(Buffer *)));
view->setBuffers(buffers.values());
- view->setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
- netViews.append(view);
- ui.menuViews->addAction(view->toggleViewAction());
+ */
}
void MainWin::showServerList() {
b = getBuffer(net, msg.target);
}
*/
+
+
Buffer *b = getBuffer(msg.buffer);
- uint level = BufferView::OtherActivity;
+ Buffer::ActivityLevel level = Buffer::OtherActivity;
if(msg.type == Message::Plain or msg.type == Message::Notice){
- level |= BufferView::NewMessage;
+ level |= Buffer::NewMessage;
}
if(msg.flags & Message::Highlight){
- level |= BufferView::Highlight;
+ level |= Buffer::Highlight;
}
-
emit bufferActivity(level, b);
+
//b->displayMsg(msg);
b->appendChatLine(new ChatLine(msg));
}
class ServerListDlg;
class CoreConnectDlg;
-class BufferView;
+class BufferViewDock;
class Buffer;
class BufferWidget;
class SettingsDlg;
~MainWin();
void init();
- void registerBufferView(BufferView *);
+ void registerBufferViewDock(BufferViewDock *);
protected:
void closeEvent(QCloseEvent *event);
void sendInput(BufferId, QString message);
void bufferSelected(Buffer *);
void bufferUpdated(Buffer *);
- void bufferActivity(uint, Buffer *);
+ void bufferActivity(Buffer::ActivityLevel, Buffer *);
void bufferDestroyed(Buffer *);
void backlogReceived(Buffer *, QList<Message>);
void requestBacklog(BufferId, QVariant, QVariant);
//QHash<QString, QList<Message> > coreBackLog;
QList<BufferId> coreBuffers;
- QList<BufferView *> netViews;
+ QList<BufferViewDock *> netViews;
QTimer *layoutTimer;
QList<Message> layoutQueue;
<number>0</number>
</property>
<item>
- <widget class="QTreeWidget" name="tree" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>5</hsizetype>
- <vsizetype>5</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize" >
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
+ <widget class="BufferView" name="treeView" >
<property name="rootIsDecorated" >
- <bool>false</bool>
+ <bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>BufferView</class>
+ <extends>QTreeView</extends>
+ <header>bufferview.h</header>
+ </customwidget>
+ </customwidgets>
<resources/>
<connections/>
</ui>