Merging r730:732 from trunk to branches/0.3. Forwardports fancy bufferviews.
authorManuel Nickschas <sputnick@quassel-irc.org>
Sun, 13 Apr 2008 20:28:08 +0000 (20:28 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sun, 13 Apr 2008 20:28:08 +0000 (20:28 +0000)
95 files changed:
src/client/client.cpp
src/client/networkmodel.cpp
src/client/treemodel.cpp
src/client/treemodel.h
src/common/bufferviewconfig.cpp
src/common/bufferviewconfig.h
src/common/bufferviewmanager.cpp
src/common/bufferviewmanager.h
src/common/syncableobject.cpp
src/common/syncableobject.h
src/core/SQL/SQLite/10/setup_999_version.sql [deleted file]
src/core/SQL/SQLite/11/delete_backlog_by_uid.sql [moved from src/core/SQL/SQLite/10/delete_backlog_by_uid.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_backlog_for_buffer.sql [moved from src/core/SQL/SQLite/10/delete_backlog_for_buffer.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_backlog_for_network.sql [moved from src/core/SQL/SQLite/10/delete_backlog_for_network.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_buffer_for_bufferid.sql [moved from src/core/SQL/SQLite/10/delete_buffer_for_bufferid.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_buffers_by_uid.sql [moved from src/core/SQL/SQLite/10/delete_buffers_by_uid.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_buffers_for_network.sql [moved from src/core/SQL/SQLite/10/delete_buffers_for_network.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_ircservers_for_network.sql [moved from src/core/SQL/SQLite/10/delete_ircservers_for_network.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_network.sql [moved from src/core/SQL/SQLite/10/delete_network.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_networks_by_uid.sql [moved from src/core/SQL/SQLite/10/delete_networks_by_uid.sql with 100% similarity]
src/core/SQL/SQLite/11/delete_quasseluser.sql [moved from src/core/SQL/SQLite/10/delete_quasseluser.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_buffer.sql [moved from src/core/SQL/SQLite/10/insert_buffer.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_message.sql [moved from src/core/SQL/SQLite/10/insert_message.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_network.sql [moved from src/core/SQL/SQLite/10/insert_network.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_quasseluser.sql [moved from src/core/SQL/SQLite/10/insert_quasseluser.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_sender.sql [moved from src/core/SQL/SQLite/10/insert_sender.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_server.sql [moved from src/core/SQL/SQLite/10/insert_server.sql with 100% similarity]
src/core/SQL/SQLite/11/insert_user_setting.sql [new file with mode: 0644]
src/core/SQL/SQLite/11/select_authuser.sql [moved from src/core/SQL/SQLite/10/select_authuser.sql with 100% similarity]
src/core/SQL/SQLite/11/select_bufferByName.sql [moved from src/core/SQL/SQLite/10/select_bufferByName.sql with 100% similarity]
src/core/SQL/SQLite/11/select_bufferExists.sql [moved from src/core/SQL/SQLite/10/select_bufferExists.sql with 100% similarity]
src/core/SQL/SQLite/11/select_buffer_by_id.sql [moved from src/core/SQL/SQLite/10/select_buffer_by_id.sql with 100% similarity]
src/core/SQL/SQLite/11/select_buffer_lastseen_messages.sql [moved from src/core/SQL/SQLite/10/select_buffer_lastseen_messages.sql with 100% similarity]
src/core/SQL/SQLite/11/select_buffers.sql [moved from src/core/SQL/SQLite/10/select_buffers.sql with 100% similarity]
src/core/SQL/SQLite/11/select_connected_networks.sql [moved from src/core/SQL/SQLite/10/select_connected_networks.sql with 100% similarity]
src/core/SQL/SQLite/11/select_messageRange.sql [moved from src/core/SQL/SQLite/10/select_messageRange.sql with 100% similarity]
src/core/SQL/SQLite/11/select_messages.sql [moved from src/core/SQL/SQLite/10/select_messages.sql with 100% similarity]
src/core/SQL/SQLite/11/select_messagesOffset.sql [moved from src/core/SQL/SQLite/10/select_messagesOffset.sql with 100% similarity]
src/core/SQL/SQLite/11/select_messagesSince.sql [moved from src/core/SQL/SQLite/10/select_messagesSince.sql with 100% similarity]
src/core/SQL/SQLite/11/select_messagesSinceOffset.sql [moved from src/core/SQL/SQLite/10/select_messagesSinceOffset.sql with 100% similarity]
src/core/SQL/SQLite/11/select_networkExists.sql [moved from src/core/SQL/SQLite/10/select_networkExists.sql with 100% similarity]
src/core/SQL/SQLite/11/select_networks_for_user.sql [moved from src/core/SQL/SQLite/10/select_networks_for_user.sql with 100% similarity]
src/core/SQL/SQLite/11/select_persistent_channels.sql [moved from src/core/SQL/SQLite/10/select_persistent_channels.sql with 100% similarity]
src/core/SQL/SQLite/11/select_servers_for_network.sql [moved from src/core/SQL/SQLite/10/select_servers_for_network.sql with 100% similarity]
src/core/SQL/SQLite/11/select_user_setting.sql [new file with mode: 0644]
src/core/SQL/SQLite/11/select_userid.sql [moved from src/core/SQL/SQLite/10/select_userid.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_000_quasseluser.sql [moved from src/core/SQL/SQLite/10/setup_000_quasseluser.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_010_sender.sql [moved from src/core/SQL/SQLite/10/setup_010_sender.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_020_network.sql [moved from src/core/SQL/SQLite/10/setup_020_network.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_030_buffer.sql [moved from src/core/SQL/SQLite/10/setup_030_buffer.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_040_buffer_idx.sql [moved from src/core/SQL/SQLite/10/setup_040_buffer_idx.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_050_buffer_cname_idx.sql [moved from src/core/SQL/SQLite/10/setup_050_buffer_cname_idx.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_060_backlog.sql [moved from src/core/SQL/SQLite/10/setup_060_backlog.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_070_coreinfo.sql [moved from src/core/SQL/SQLite/10/setup_070_coreinfo.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_080_ircservers.sql [moved from src/core/SQL/SQLite/10/setup_080_ircservers.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_090_create_backlog_idx.sql [moved from src/core/SQL/SQLite/10/setup_090_create_backlog_idx.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_100_create_backlog_idx2.sql [moved from src/core/SQL/SQLite/10/setup_100_create_backlog_idx2.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_110_create_buffer_idx.sql [moved from src/core/SQL/SQLite/10/setup_110_create_buffer_idx.sql with 100% similarity]
src/core/SQL/SQLite/11/setup_120_create_user_setting.sql [new file with mode: 0644]
src/core/SQL/SQLite/11/setup_999_version.sql [new file with mode: 0644]
src/core/SQL/SQLite/11/update_buffer_lastseen.sql [moved from src/core/SQL/SQLite/10/update_buffer_lastseen.sql with 100% similarity]
src/core/SQL/SQLite/11/update_buffer_name.sql [moved from src/core/SQL/SQLite/10/update_buffer_name.sql with 100% similarity]
src/core/SQL/SQLite/11/update_buffer_persistent_channel.sql [moved from src/core/SQL/SQLite/10/update_buffer_persistent_channel.sql with 100% similarity]
src/core/SQL/SQLite/11/update_buffer_set_channel_key.sql [moved from src/core/SQL/SQLite/10/update_buffer_set_channel_key.sql with 100% similarity]
src/core/SQL/SQLite/11/update_network.sql [moved from src/core/SQL/SQLite/10/update_network.sql with 100% similarity]
src/core/SQL/SQLite/11/update_network_connected.sql [moved from src/core/SQL/SQLite/10/update_network_connected.sql with 100% similarity]
src/core/SQL/SQLite/11/update_user_setting.sql [new file with mode: 0644]
src/core/SQL/SQLite/11/update_username.sql [moved from src/core/SQL/SQLite/10/update_username.sql with 100% similarity]
src/core/SQL/SQLite/11/update_userpassword.sql [moved from src/core/SQL/SQLite/10/update_userpassword.sql with 100% similarity]
src/core/SQL/SQLite/11/upgrade_000_create_user_setting.sql [new file with mode: 0644]
src/core/SQL/SQLite/11/upgrade_999_version.sql [new file with mode: 0644]
src/core/SQL/upgradeSchema.sh [new file with mode: 0755]
src/core/core.cpp
src/core/core.h
src/core/corebufferviewconfig.cpp
src/core/corebufferviewconfig.h
src/core/corebufferviewmanager.cpp
src/core/corebufferviewmanager.h
src/core/sql.qrc
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.h
src/qtui/coreconnectdlg.cpp
src/qtui/mainwin.cpp
src/qtui/mainwin.h
src/qtui/settingspagedlg.cpp
src/qtui/settingspages/bufferviewsettingspage.cpp
src/qtui/settingspages/bufferviewsettingspage.h
src/qtui/settingspages/bufferviewsettingspage.ui
src/qtui/ui/mainwin.ui
src/uisupport/bufferview.cpp
src/uisupport/bufferview.h
src/uisupport/bufferviewfilter.cpp
src/uisupport/bufferviewfilter.h
version.inc

index c2cbb2f..5e472a1 100644 (file)
@@ -83,6 +83,7 @@ Client::~Client() {
 void Client::init() {
   _currentCoreAccount = 0;
   _networkModel = new NetworkModel(this);
+
   connect(this, SIGNAL(bufferUpdated(BufferInfo)),
           _networkModel, SLOT(bufferUpdated(BufferInfo)));
   connect(this, SIGNAL(networkRemoved(NetworkId)),
@@ -325,12 +326,12 @@ void Client::setSecuredConnection() {
 void Client::disconnectFromCore() {
   if(!isConnected())
     return;
+  _connectedToCore = false;
   
   if(socket) {
     socket->close();
     socket->deleteLater();
   }
-  _connectedToCore = false;
   _syncedToCore = false;
   setCurrentCoreAccount(0);
   emit disconnected();
@@ -346,7 +347,7 @@ void Client::disconnectFromCore() {
     _bufferViewManager->deleteLater();
     _bufferViewManager = 0;
   }
-  
+
   _networkModel->clear();
 
   QHash<BufferId, Buffer *>::iterator bufferIter =  _buffers.begin();
index 713198a..9a16ac1 100644 (file)
@@ -414,7 +414,9 @@ void NetworkItem::attachNetwork(Network *network) {
          this, SLOT(attachIrcChannel(QString)));
   connect(network, SIGNAL(connectedSet(bool)),
          this, SIGNAL(dataChanged()));
-
+  connect(network, SIGNAL(destroyed()),
+         this, SIGNAL(dataChanged()));
+  
   emit dataChanged();
 }
 
index 65310a6..9a91980 100644 (file)
@@ -147,8 +147,11 @@ AbstractTreeItem *AbstractTreeItem::childById(const quint64 &id) const {
   return 0;
 }
 
-int AbstractTreeItem::childCount() const {
-  return _childItems.count();
+int AbstractTreeItem::childCount(int column) const {
+  if(column > 0)
+    return 0;
+  else
+    return _childItems.count();
 }
 
 int AbstractTreeItem::row() const {
@@ -293,6 +296,8 @@ TreeModel::TreeModel(const QList<QVariant> &data, QObject *parent)
            this, SLOT(debug_rowsInserted(const QModelIndex &, int, int)));
     connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
            this, SLOT(debug_rowsRemoved(const QModelIndex &, int, int)));
+    connect(this, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
+           this, SLOT(debug_dataChanged(const QModelIndex &, const QModelIndex &)));
   }
 }
 
@@ -370,27 +375,23 @@ int TreeModel::rowCount(const QModelIndex &parent) const {
   else
     parentItem = static_cast<AbstractTreeItem*>(parent.internalPointer());
 
-  return parentItem->childCount();
+  return parentItem->childCount(parent.column());
 }
 
 int TreeModel::columnCount(const QModelIndex &parent) const {
   Q_UNUSED(parent)
+  return rootItem->columnCount();
   // since there the Qt Views don't draw more columns than the header has columns
   // we can be lazy and simply return the count of header columns
   // actually this gives us more freedom cause we don't have to ensure that a rows parent
   // has equal or more columns than that row
-  
-//   if(parent.isValid()) {
-//     AbstractTreeItem *child;
-//     if(child = static_cast<AbstractTreeItem *>(parent.internalPointer())->child(parent.column(), parent.row()))
-//       return child->columnCount();
-//     else
-//       return static_cast<AbstractTreeItem*>(parent.internalPointer())->columnCount();
-//   } else {
-//     return rootItem->columnCount();
-//   }
 
-  return rootItem->columnCount();
+//   AbstractTreeItem *parentItem;
+//   if(!parent.isValid())
+//     parentItem = rootItem;
+//   else
+//     parentItem = static_cast<AbstractTreeItem*>(parent.internalPointer());
+//   return parentItem->columnCount();
 }
 
 QVariant TreeModel::data(const QModelIndex &index, int role) const {
@@ -398,6 +399,9 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const {
     return QVariant();
 
   AbstractTreeItem *item = static_cast<AbstractTreeItem *>(index.internalPointer());
+  if(role == Qt::DisplayRole && !item->data(index.column(), role).isValid()) {
+    qDebug() << item->data(0, role) << item->columnCount();
+  }
   return item->data(index.column(), role);
 }
 
@@ -410,12 +414,12 @@ bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int rol
 }
 
 Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const {
-  AbstractTreeItem *item;
-  if(!index.isValid())
-    item = rootItem;
-  else
-    item = static_cast<AbstractTreeItem *>(index.internalPointer());
-  return item->flags();
+  if(!index.isValid()) {
+    return rootItem->flags() & Qt::ItemIsDropEnabled;
+  } else {
+    AbstractTreeItem *item = static_cast<AbstractTreeItem *>(index.internalPointer());
+    return item->flags();
+  }
 }
 
 QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
@@ -498,29 +502,37 @@ void TreeModel::beginRemoveChilds(int firstRow, int lastRow) {
     qWarning() << "TreeModel::beginRemoveChilds(): cannot append Childs to unknown parent";
     return;
   }
+
+  for(int i = firstRow; i <= lastRow; i++) {
+    disconnect(parentItem->child(i), 0, this, 0);
+  }
+  
+  // consitency checks
   QModelIndex parent = indexByItem(parentItem);
   Q_ASSERT(firstRow <= lastRow);
   Q_ASSERT(parentItem->childCount() > lastRow);
   Q_ASSERT(!_aboutToRemoveOrInsert);
-  
   _aboutToRemoveOrInsert = true;
   _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow);
+
   beginRemoveRows(parent, firstRow, lastRow);
 }
 
 void TreeModel::endRemoveChilds() {
   AbstractTreeItem *parentItem = qobject_cast<AbstractTreeItem *>(sender());
   if(!parentItem) {
-    qWarning() << "TreeModel::endRemoveChilds(): cannot append Childs to unknown parent";
+    qWarning() << "TreeModel::endRemoveChilds(): cannot remove Childs from unknown parent";
     return;
   }
+
+  // concistency checks
   Q_ASSERT(_aboutToRemoveOrInsert);
   ChildStatus cs = _childStatus;
   QModelIndex parent = indexByItem(parentItem);
   Q_ASSERT(cs.parent == parent);
   Q_ASSERT(rowCount(parent) == cs.childCount - cs.end + cs.start - 1);
-  
   _aboutToRemoveOrInsert = false;
+
   endRemoveRows();
 }
 
@@ -537,7 +549,7 @@ void TreeModel::debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start,
   parentItem = static_cast<AbstractTreeItem *>(parent.internalPointer());
   if(!parentItem)
     parentItem = rootItem;
-  qDebug() << "#" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end;
+  qDebug() << "debug_rowsAboutToBeRemoved" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end;
 
   QModelIndex child;
   AbstractTreeItem *childItem;
@@ -554,7 +566,7 @@ void TreeModel::debug_rowsInserted(const QModelIndex &parent, int start, int end
   parentItem = static_cast<AbstractTreeItem *>(parent.internalPointer());
   if(!parentItem)
     parentItem = rootItem;
-  qDebug() << "#" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end;
+  qDebug() << "debug_rowsInserted:" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end;
 
   QModelIndex child;
   AbstractTreeItem *childItem;
@@ -569,3 +581,15 @@ void TreeModel::debug_rowsInserted(const QModelIndex &parent, int start, int end
 void TreeModel::debug_rowsRemoved(const QModelIndex &parent, int start, int end) {
   qDebug() << "debug_rowsRemoved" << parent << parent.internalPointer() << parent.data().toString() << rowCount(parent) << start << end;
 }
+
+void TreeModel::debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) {
+  qDebug() << "debug_dataChanged" << topLeft << bottomRight;
+  QStringList displayData;
+  for(int row = topLeft.row(); row <= bottomRight.row(); row++) {
+    displayData = QStringList();
+    for(int column = topLeft.column(); column <= bottomRight.column(); column++) {
+      displayData << data(topLeft.sibling(row, column), Qt::DisplayRole).toString();
+    }
+    qDebug() << "  row:" << row << displayData;
+  }
+}
index 599956e..8caffdd 100644 (file)
@@ -52,7 +52,7 @@ public:
   AbstractTreeItem *child(int row) const;
   AbstractTreeItem *childById(const quint64 &id) const;
 
-  int childCount() const;
+  int childCount(int column = 0) const;
 
   virtual int columnCount() const = 0;
 
@@ -188,6 +188,7 @@ private slots:
   void debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
   void debug_rowsInserted(const QModelIndex &parent, int start, int end);
   void debug_rowsRemoved(const QModelIndex &parent, int start, int end);
+  void debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
 };
 
 #endif
index 7a893b3..2ffb3a7 100644 (file)
 
 #include "bufferviewconfig.h"
 
+#include "bufferinfo.h"
+
 BufferViewConfig::BufferViewConfig(int bufferViewId, QObject *parent)
+  : SyncableObject(parent),
+    _bufferViewId(bufferViewId),
+    _addNewBuffersAutomatically(true),
+    _sortAlphabetically(true),
+    _hideInactiveBuffers(false),
+    _allowedBufferTypes(BufferInfo::StatusBuffer | BufferInfo::ChannelBuffer | BufferInfo::QueryBuffer | BufferInfo::GroupBuffer),
+    _minimumActivity(0)
+{
+  setObjectName(QString::number(bufferViewId));
+}
+
+BufferViewConfig::BufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent)
   : SyncableObject(parent),
     _bufferViewId(bufferViewId)
 {
+  fromVariantMap(properties);
   setObjectName(QString::number(bufferViewId));
 }
 
@@ -58,3 +73,85 @@ void BufferViewConfig::setSortAlphabetically(bool sortAlphabetically) {
   _sortAlphabetically = sortAlphabetically;
   emit sortAlphabeticallySet(sortAlphabetically);
 }
+
+void BufferViewConfig::setAllowedBufferTypes(int bufferTypes) {
+  if(_allowedBufferTypes == bufferTypes)
+    return;
+
+  _allowedBufferTypes = bufferTypes;
+  emit allowedBufferTypesSet(bufferTypes);
+}
+
+void BufferViewConfig::setMinimumActivity(int activity) {
+  if(_minimumActivity == activity)
+    return;
+
+  _minimumActivity = activity;
+  emit minimumActivitySet(activity);
+}
+
+void BufferViewConfig::setHideInactiveBuffers(bool hideInactiveBuffers) {
+  if(_hideInactiveBuffers == hideInactiveBuffers)
+    return;
+
+  _hideInactiveBuffers = hideInactiveBuffers;
+  emit hideInactiveBuffersSet(hideInactiveBuffers);
+}
+
+QVariantList BufferViewConfig::initBufferList() const {
+  QVariantList buffers;
+
+  foreach(BufferId bufferId, _buffers) {
+    buffers << qVariantFromValue(bufferId);
+  }
+
+  return buffers;
+}
+
+void BufferViewConfig::initSetBufferList(const QVariantList &buffers) {
+  _buffers.clear();
+
+  foreach(QVariant buffer, buffers) {
+    _buffers << buffer.value<BufferId>();
+  }
+
+  emit bufferListSet();
+}
+
+void BufferViewConfig::initSetBufferList(const QList<BufferId> &buffers) {
+  _buffers.clear();
+
+  foreach(BufferId bufferId, buffers) {
+    _buffers << bufferId;
+  }
+
+  emit bufferListSet();
+}
+
+void BufferViewConfig::addBuffer(const BufferId &bufferId, int pos) {
+  qDebug() << "addBuffer" << bufferId;
+  if(_buffers.contains(bufferId))
+    return;
+  
+  _buffers.insert(pos, bufferId);
+  emit bufferAdded(bufferId, pos);
+}
+
+void BufferViewConfig::moveBuffer(const BufferId &bufferId, int pos) {
+  qDebug() << "moveeBuffer" << bufferId;
+  if(!_buffers.contains(bufferId))
+    return;
+
+  qDebug() << "lala" << bufferId << pos;
+  _buffers.move(_buffers.indexOf(bufferId), pos);
+  emit bufferMoved(bufferId, pos);
+}
+
+void BufferViewConfig::removeBuffer(const BufferId &bufferId) {
+  qDebug() << "removeBuffer" << bufferId;
+  if(!_buffers.contains(bufferId))
+    return;
+  
+  _buffers.removeAt(_buffers.indexOf(bufferId));
+  emit bufferRemoved(bufferId);
+}
index d728df5..2e2a9aa 100644 (file)
@@ -31,9 +31,14 @@ class BufferViewConfig : public SyncableObject {
   Q_PROPERTY(NetworkId networkId READ networkId WRITE setNetworkId)
   Q_PROPERTY(bool addNewBuffersAutomatically READ addNewBuffersAutomatically WRITE setAddNewBuffersAutomatically)
   Q_PROPERTY(bool sortAlphabetically READ sortAlphabetically WRITE setSortAlphabetically)
+  Q_PROPERTY(bool hideInactiveBuffers READ hideInactiveBuffers WRITE setHideInactiveBuffers)
+  Q_PROPERTY(int allowedBufferTypes READ allowedBufferTypes WRITE setAllowedBufferTypes)
+  Q_PROPERTY(int minimumActivity READ minimumActivity WRITE setMinimumActivity)
 
 public:
   BufferViewConfig(int bufferViewId, QObject *parent = 0);
+  BufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent = 0);
+
 
 public slots:
   inline int bufferViewId() const { return _bufferViewId; }
@@ -50,14 +55,46 @@ public slots:
   inline bool sortAlphabetically() const { return _sortAlphabetically; }
   void setSortAlphabetically(bool sortAlphabetically);
 
+  inline int allowedBufferTypes() const { return _allowedBufferTypes; }
+  void setAllowedBufferTypes(int bufferTypes);
+
+  inline int minimumActivity() const { return _minimumActivity; }
+  void setMinimumActivity(int activity);
+
+  inline bool hideInactiveBuffers() const { return _hideInactiveBuffers; }
+  void setHideInactiveBuffers(bool hideInactiveBuffers);
+  
   virtual inline void requestSetBufferViewName(const QString &bufferViewName) { emit setBufferViewNameRequested(bufferViewName); }
 
+  const QList<BufferId> &bufferList() const { return _buffers; }
+  QVariantList initBufferList() const;
+  void initSetBufferList(const QVariantList &buffers);
+  void initSetBufferList(const QList<BufferId> &buffers);
+
+  void addBuffer(const BufferId &bufferId, int pos);
+  virtual inline void requestAddBuffer(const BufferId &bufferId, int pos) { emit addBufferRequested(bufferId, pos); }
+  void moveBuffer(const BufferId &bufferId, int pos);
+  virtual inline void requestMoveBuffer(const BufferId &bufferId, int pos) { emit moveBufferRequested(bufferId, pos); }
+  void removeBuffer(const BufferId &bufferId);
+  virtual inline void requestRemoveBuffer(const BufferId &bufferId) { emit removeBufferRequested(bufferId); }
+  
 signals:
   void bufferViewNameSet(const QString &bufferViewName);
   void networkIdSet(const NetworkId &networkId);
   void addNewBuffersAutomaticallySet(bool addNewBuffersAutomatically);
   void sortAlphabeticallySet(bool sortAlphabetically);  
+  void allowedBufferTypesSet(int allowedBufferTypes);
+  void minimumActivitySet(int activity);
+  void hideInactiveBuffersSet(bool hideInactiveBuffers);
+  void bufferListSet();
 
+  void bufferAdded(const BufferId &bufferId, int pos);
+  void addBufferRequested(const BufferId &bufferId, int pos);
+  void bufferMoved(const BufferId &bufferId, int pos);
+  void moveBufferRequested(const BufferId &bufferId, int pos);
+  void bufferRemoved(const BufferId &bufferId);
+  void removeBufferRequested(const BufferId &bufferId);
+  
   void setBufferViewNameRequested(const QString &bufferViewName);
 
 private:
@@ -66,6 +103,10 @@ private:
   NetworkId _networkId;
   bool _addNewBuffersAutomatically;
   bool _sortAlphabetically;
+  bool _hideInactiveBuffers;
+  int _allowedBufferTypes;
+  int _minimumActivity;
+  QList<BufferId> _buffers;
 };
 
 #endif // BUFFERVIEWCONFIG_H
index 7ab9831..1046929 100644 (file)
@@ -53,6 +53,15 @@ void BufferViewManager::addBufferViewConfig(int bufferViewConfigId) {
   addBufferViewConfig(new BufferViewConfig(bufferViewConfigId, this));
 }
 
+void BufferViewManager::deleteBufferViewConfig(int bufferViewConfigId) {
+  if(!_bufferViewConfigs.contains(bufferViewConfigId))
+     return;
+
+  _bufferViewConfigs[bufferViewConfigId]->deleteLater();
+  _bufferViewConfigs.remove(bufferViewConfigId);
+  emit bufferViewConfigDeleted(bufferViewConfigId);
+}
+
 QVariantList BufferViewManager::initBufferViewIds() const {
   QVariantList bufferViewIds;
   BufferViewConfigHash::const_iterator iter = _bufferViewConfigs.constBegin();
index 143b400..8aef3da 100644 (file)
@@ -43,14 +43,23 @@ public slots:
   void addBufferViewConfig(int bufferViewConfigId);
   inline void newBufferViewConfig(int bufferViewConfigId)  { addBufferViewConfig(bufferViewConfigId); }
 
+  void deleteBufferViewConfig(int bufferViewConfigId);
+
   QVariantList initBufferViewIds() const;
   void initSetBufferViewIds(const QVariantList bufferViewIds);
 
-  virtual inline void requestCreateBufferView(const QString &bufferViewName) { emit createBufferViewRequested(bufferViewName); }
+  virtual inline void requestCreateBufferView(const QVariantMap &properties) { emit createBufferViewRequested(properties); }
+  virtual inline void requestCreateBufferViews(const QVariantList &properties) { emit createBufferViewsRequested(properties); }
+  virtual inline void requestDeleteBufferView(int bufferViewId) { emit deleteBufferViewRequested(bufferViewId); }
+  virtual inline void requestDeleteBufferViews(const QVariantList &bufferViews) { emit deleteBufferViewsRequested(bufferViews); }
 
 signals:
   void bufferViewConfigAdded(int bufferViewConfigId);
-  void createBufferViewRequested(const QString &bufferViewName);
+  void bufferViewConfigDeleted(int bufferViewConfigId);
+  void createBufferViewRequested(const QVariantMap &properties);
+  void createBufferViewsRequested(const QVariantList &properties);
+  void deleteBufferViewRequested(int bufferViewId);
+  void deleteBufferViewsRequested(const QVariantList &bufferViews);
 
 protected:
   typedef QHash<int, BufferViewConfig *> BufferViewConfigHash;
index 781dd15..426bc86 100644 (file)
 #include "signalproxy.h"
 #include "util.h"
 
-SyncableObject::SyncableObject(QObject *parent) : QObject(parent) {
-  _initialized = false;
+SyncableObject::SyncableObject(QObject *parent)
+  : QObject(parent),
+    _initialized(false),
+    _allowClientUpdates(false)
+{
 }
 
-SyncableObject::SyncableObject(const SyncableObject &other, QObject *parent) : QObject(parent) {
-  _initialized = other._initialized;
-
+SyncableObject::SyncableObject(const SyncableObject &other, QObject *parent)
+  : QObject(parent),
+    _initialized(other._initialized),
+    _allowClientUpdates(false)
+{
 }
 
 bool SyncableObject::isInitialized() const {
@@ -51,9 +56,14 @@ QVariantMap SyncableObject::toVariantMap() {
   const QMetaObject* meta = metaObject();
 
   // we collect data from properties
+  QMetaProperty prop;
+  QString propName;
   for(int i = 0; i < meta->propertyCount(); i++) {
-    QMetaProperty prop = meta->property(i);
-    properties[QString(prop.name())] = prop.read(this);
+    prop = meta->property(i);
+    propName = QString(prop.name());
+    if(propName == "objectName")
+      continue;
+    properties[propName] = prop.read(this);
   }
 
   // ...as well as methods, which have names starting with "init"
@@ -84,14 +94,20 @@ void SyncableObject::fromVariantMap(const QVariantMap &properties) {
   const QMetaObject *meta = metaObject();
 
   QVariantMap::const_iterator iterator = properties.constBegin();
+  QString propName;
   while(iterator != properties.constEnd()) {
-    QString name = iterator.key();
-    int propertyIndex = meta->indexOfProperty(name.toAscii());
+    propName = iterator.key();
+    if(propName == "objectName") {
+      iterator++;
+      continue;
+    }
+    
+    int propertyIndex = meta->indexOfProperty(propName.toAscii());
 
     if(propertyIndex == -1 || !meta->property(propertyIndex).isWritable())
-      setInitValue(name, iterator.value());
+      setInitValue(propName, iterator.value());
     else
-      setProperty(name.toAscii(), iterator.value());
+      setProperty(propName.toAscii(), iterator.value());
     // qDebug() << "<<< SYNC:" << name << iterator.value();
     iterator++;
   }
@@ -111,3 +127,15 @@ void SyncableObject::renameObject(const QString &newName) {
     emit objectRenamed(newName, oldName);
   }
 }
+
+void SyncableObject::update(const QVariantMap &properties) {
+  fromVariantMap(properties);
+  emit updated(properties);
+}
+
+void SyncableObject::requestUpdate(const QVariantMap &properties) {
+  if(allowClientUpdates()) {
+    update(properties);
+  }
+  emit updateRequested(properties);
+}
index 388ed90..61915cb 100644 (file)
@@ -49,27 +49,35 @@ public:
   //! Initialize the object's state from a given QVariantMap.
   /** \see toVariantMap() for important information concerning this method.
    */
-  virtual void fromVariantMap(const QVariantMap &map);
+  virtual void fromVariantMap(const QVariantMap &properties);
 
   virtual bool isInitialized() const;
 
   virtual const QMetaObject *syncMetaObject() const { return metaObject(); };
 
+  inline void setAllowClientUpdates(bool allow) { _allowClientUpdates = allow; }
+  inline bool allowClientUpdates() const { return _allowClientUpdates; }
+
 public slots:
   virtual void setInitialized();
+  void requestUpdate(const QVariantMap &properties);
+  void update(const QVariantMap &properties);
 
 protected:
   void renameObject(const QString &newName);
-  
+
 signals:
   void initDone();
   void updatedRemotely();
+  void updated(const QVariantMap &properties);
+  void updateRequested(const QVariantMap &properties);
   void objectRenamed(QString newName, QString oldName);
 
 private:
   bool setInitValue(const QString &property, const QVariant &value);
   
   bool _initialized;
+  bool _allowClientUpdates;
 
 };
 
diff --git a/src/core/SQL/SQLite/10/setup_999_version.sql b/src/core/SQL/SQLite/10/setup_999_version.sql
deleted file mode 100644 (file)
index 205c878..0000000
+++ /dev/null
@@ -1 +0,0 @@
-INSERT INTO coreinfo (key, value) VALUES ('schemaversion', 10)
diff --git a/src/core/SQL/SQLite/11/insert_user_setting.sql b/src/core/SQL/SQLite/11/insert_user_setting.sql
new file mode 100644 (file)
index 0000000..f85d340
--- /dev/null
@@ -0,0 +1,2 @@
+INSERT INTO user_setting (userid, settingname, settingvalue)
+VALUES (:userid, :settingname, :settingvalue)
diff --git a/src/core/SQL/SQLite/11/select_user_setting.sql b/src/core/SQL/SQLite/11/select_user_setting.sql
new file mode 100644 (file)
index 0000000..a5da306
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT settingvalue
+FROM user_setting
+WHERE userid = :userid AND settingname = :settingname
diff --git a/src/core/SQL/SQLite/11/setup_120_create_user_setting.sql b/src/core/SQL/SQLite/11/setup_120_create_user_setting.sql
new file mode 100644 (file)
index 0000000..fdfb4e0
--- /dev/null
@@ -0,0 +1,6 @@
+CREATE TABLE user_setting (
+    userid INTEGER NOT NULL,
+    settingname TEXT NOT NULL,
+    settingvalue BLOB,
+    PRIMARY KEY (userid, settingname)
+)
diff --git a/src/core/SQL/SQLite/11/setup_999_version.sql b/src/core/SQL/SQLite/11/setup_999_version.sql
new file mode 100644 (file)
index 0000000..6365de5
--- /dev/null
@@ -0,0 +1 @@
+INSERT INTO coreinfo (key, value) VALUES ('schemaversion', 11)
diff --git a/src/core/SQL/SQLite/11/update_user_setting.sql b/src/core/SQL/SQLite/11/update_user_setting.sql
new file mode 100644 (file)
index 0000000..3585fbc
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE user_setting
+SET settingvalue = :settingvalue
+WHERE userid = :userid AND settingname = :settingname
diff --git a/src/core/SQL/SQLite/11/upgrade_000_create_user_setting.sql b/src/core/SQL/SQLite/11/upgrade_000_create_user_setting.sql
new file mode 100644 (file)
index 0000000..fdfb4e0
--- /dev/null
@@ -0,0 +1,6 @@
+CREATE TABLE user_setting (
+    userid INTEGER NOT NULL,
+    settingname TEXT NOT NULL,
+    settingvalue BLOB,
+    PRIMARY KEY (userid, settingname)
+)
diff --git a/src/core/SQL/SQLite/11/upgrade_999_version.sql b/src/core/SQL/SQLite/11/upgrade_999_version.sql
new file mode 100644 (file)
index 0000000..68ec4b8
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE coreinfo
+SET value = 11
+WHERE key = 'schemaversion'
diff --git a/src/core/SQL/upgradeSchema.sh b/src/core/SQL/upgradeSchema.sh
new file mode 100755 (executable)
index 0000000..0fcb651
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+TARGET_DIR=$1
+if [ ! $TARGET_DIR ]; then
+    TARGET_DIR=`pwd`
+fi
+
+if [[ ! -d $TARGET_DIR ]]; then
+    echo "No such directory $TARGET_DIR"
+    exit 1
+fi
+
+cd $TARGET_DIR
+
+CURRENT_VERSION=`ls | sort -n | tail -n1`
+
+if [ ! $CURRENT_VERSION ]; then
+    echo "no previous schema found to upgrade from"
+    exit 2
+fi
+
+((NEW_VERSION=$CURRENT_VERSION + 1))
+
+mkdir $NEW_VERSION
+svn add $NEW_VERSION
+find $CURRENT_VERSION -depth 1 \! -name "upgrade_*" \! -name ".*" -exec svn mv {} $NEW_VERSION \;
+svn cp ${CURRENT_VERSION}/upgrade_999_version.sql $NEW_VERSION
index dad499a..1ad9fe2 100644 (file)
@@ -207,6 +207,16 @@ void Core::syncStorage() {
 }
 
 /*** Storage Access ***/
+void Core::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) {
+  QMutexLocker locker(&mutex);
+  instance()->storage->setUserSetting(userId, settingName, data);
+}
+
+QVariant Core::getUserSetting(UserId userId, const QString &settingName, const QVariant &data) {
+  QMutexLocker locker(&mutex);
+  return instance()->storage->getUserSetting(userId, settingName, data);
+}
+
 bool Core::createNetwork(UserId user, NetworkInfo &info) {
   QMutexLocker locker(&mutex);
   NetworkId networkId = instance()->storage->createNetwork(user, info);
index 5a125a4..8047598 100644 (file)
@@ -59,6 +59,24 @@ class Core : public QObject {
     /*** Storage access ***/
     // These methods are threadsafe.
 
+    //! Store a user setting persistently
+    /**
+     * \param userId       The users Id
+     * \param settingName  The Name of the Setting
+     * \param data         The Value
+     */
+    static void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
+  
+    //! Retrieve a persistent user setting
+    /**
+     * \param userId       The users Id
+     * \param settingName  The Name of the Setting
+     * \param default      Value to return in case it's unset.
+     * \return the Value of the Setting or the default value if it is unset.
+     */
+    static QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &data = QVariant());
+
+  
     //! Create a Network in the Storage and store it's Id in the given NetworkInfo
     /** \note This method is thredsafe.
      *
index 49686c1..47e3337 100644 (file)
 CoreBufferViewConfig::CoreBufferViewConfig(int bufferViewId, QObject *parent)
   : BufferViewConfig(bufferViewId, parent)
 {
+  setAllowClientUpdates(true);
 }
 
-void CoreBufferViewConfig::requestSetBufferViewName(const QString &bufferViewName) {
-  qDebug() << "requestSetBufferViewName" << bufferViewName;
-  setBufferViewName(bufferViewName);
+CoreBufferViewConfig::CoreBufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent)
+  : BufferViewConfig(bufferViewId, properties, parent)
+{
+  setAllowClientUpdates(true);
 }
index 06f15cf..b0d9e96 100644 (file)
@@ -28,11 +28,15 @@ class CoreBufferViewConfig : public BufferViewConfig {
 
 public:
   CoreBufferViewConfig(int bufferViewId, QObject *parent = 0);
-
+  CoreBufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent = 0);
+  
   virtual const QMetaObject *syncMetaObject() const { return &BufferViewConfig::staticMetaObject; }
 
 public slots:
-  virtual void requestSetBufferViewName(const QString &bufferViewName);
+  virtual inline void requestSetBufferViewName(const QString &bufferViewName) { setBufferViewName(bufferViewName); }
+  virtual inline void requestRemoveBuffer(const BufferId &bufferId) { removeBuffer(bufferId); }
+  virtual inline void requestAddBuffer(const BufferId &bufferId, int pos) { addBuffer(bufferId, pos); }
+  virtual inline void requestMoveBuffer(const BufferId &bufferId, int pos) { moveBuffer(bufferId, pos); }
 };
 
 #endif // COREBUFFERVIEWCONFIG_H
index a23a775..bf18fee 100644 (file)
 
 #include "corebufferviewconfig.h"
 
-CoreBufferViewManager::CoreBufferViewManager(SignalProxy *proxy, QObject *parent)
-  : BufferViewManager(proxy, parent)
+#include "core.h"
+#include "coresession.h"
+
+CoreBufferViewManager::CoreBufferViewManager(SignalProxy *proxy, CoreSession *parent)
+  : BufferViewManager(proxy, parent),
+    _coreSession(parent)
 {
-  return;
-  // fill in some demo views
+  QVariantMap views = Core::getUserSetting(_coreSession->user(), "BufferViews").toMap();
+  QVariantMap::iterator iter = views.begin();
+  QVariantMap::iterator iterEnd = views.end();
   CoreBufferViewConfig *config = 0;
-  for(int i = 0; i < 10; i++) {
-    config = new CoreBufferViewConfig(i);
-    config->setBufferViewName(QString("asdf%1").arg(i));
+  while(iter != iterEnd) {
+    config = new CoreBufferViewConfig(iter.key().toInt(), iter.value().toMap(), this);
     addBufferViewConfig(config);
+    iter++;
+  }
+}
+
+CoreBufferViewManager::~CoreBufferViewManager() {
+  QVariantMap views;
+
+  BufferViewConfigHash::const_iterator iter = bufferViewConfigHash().constBegin();
+  BufferViewConfigHash::const_iterator iterEnd = bufferViewConfigHash().constEnd();
+  while(iter != iterEnd) {
+    views[QString::number((*iter)->bufferViewId())] = (*iter)->toVariantMap();
+    iter++;
   }
+
+  Core::setUserSetting(_coreSession->user(), "BufferViews", views);
 }
 
-void CoreBufferViewManager::requestCreateBufferView(const QString &bufferViewName) {
-  // FIXME retreive new Id from database or whereever this stuff will be stored
+void CoreBufferViewManager::requestCreateBufferView(const QVariantMap &properties) {
+  QString bufferViewName = properties["bufferViewName"].toString();
   int maxId = -1;
   BufferViewConfigHash::const_iterator iter = bufferViewConfigHash().constBegin();
   BufferViewConfigHash::const_iterator iterEnd = bufferViewConfigHash().constEnd();
@@ -51,7 +69,25 @@ void CoreBufferViewManager::requestCreateBufferView(const QString &bufferViewNam
   }
   maxId++;
 
-  CoreBufferViewConfig *config = new CoreBufferViewConfig(maxId);
-  config->setBufferViewName(bufferViewName);
+  CoreBufferViewConfig *config = new CoreBufferViewConfig(maxId, properties);
   addBufferViewConfig(config);
 }
+
+void CoreBufferViewManager::requestCreateBufferViews(const QVariantList &properties) {
+  QVariantList::const_iterator iter = properties.constBegin();
+  QVariantList::const_iterator iterEnd = properties.constEnd();
+  while(iter != iterEnd) {
+    requestCreateBufferView((*iter).toMap());
+    iter++;
+  }
+}
+
+void CoreBufferViewManager::requestDeleteBufferView(int bufferViewId) {
+  deleteBufferViewConfig(bufferViewId);
+}
+
+void CoreBufferViewManager::requestDeleteBufferViews(const QVariantList &bufferViews) {
+  foreach(QVariant bufferView, bufferViews) {
+    deleteBufferViewConfig(bufferView.toInt());
+  }
+}
index 235c9dc..072b455 100644 (file)
 
 #include "bufferviewmanager.h"
 
+class CoreSession;
+
 class CoreBufferViewManager : public BufferViewManager {
   Q_OBJECT
 
 public:
-  CoreBufferViewManager(SignalProxy *proxy, QObject *parent = 0);
-
+  CoreBufferViewManager(SignalProxy *proxy, CoreSession *parent);
+  ~CoreBufferViewManager();
+  
   virtual const QMetaObject *syncMetaObject() const { return &BufferViewManager::staticMetaObject; }
 
 public slots:
-  virtual void requestCreateBufferView(const QString &bufferViewName);
+  virtual void requestCreateBufferView(const QVariantMap &properties);
+  virtual void requestCreateBufferViews(const QVariantList &properties);
+  virtual void requestDeleteBufferView(int bufferViewId);
+  virtual void requestDeleteBufferViews(const QVariantList &bufferViews);
+
+private:
+  CoreSession *_coreSession;
 };
 
 #endif // COREBUFFERVIEWMANAGER_H
+
index 2c806d4..8d38df0 100644 (file)
@@ -3,66 +3,72 @@
     <file>./SQL/SQLite/1/upgrade_000_drop_coreinfo.sql</file>
     <file>./SQL/SQLite/1/upgrade_010_create_coreinfo.sql</file>
     <file>./SQL/SQLite/1/upgrade_020_update_schemaversion.sql</file>
-    <file>./SQL/SQLite/10/delete_backlog_by_uid.sql</file>
-    <file>./SQL/SQLite/10/delete_backlog_for_buffer.sql</file>
-    <file>./SQL/SQLite/10/delete_backlog_for_network.sql</file>
-    <file>./SQL/SQLite/10/delete_buffer_for_bufferid.sql</file>
-    <file>./SQL/SQLite/10/delete_buffers_by_uid.sql</file>
-    <file>./SQL/SQLite/10/delete_buffers_for_network.sql</file>
-    <file>./SQL/SQLite/10/delete_ircservers_for_network.sql</file>
-    <file>./SQL/SQLite/10/delete_network.sql</file>
-    <file>./SQL/SQLite/10/delete_networks_by_uid.sql</file>
-    <file>./SQL/SQLite/10/delete_quasseluser.sql</file>
-    <file>./SQL/SQLite/10/insert_buffer.sql</file>
-    <file>./SQL/SQLite/10/insert_message.sql</file>
-    <file>./SQL/SQLite/10/insert_network.sql</file>
-    <file>./SQL/SQLite/10/insert_quasseluser.sql</file>
-    <file>./SQL/SQLite/10/insert_sender.sql</file>
-    <file>./SQL/SQLite/10/insert_server.sql</file>
-    <file>./SQL/SQLite/10/select_authuser.sql</file>
-    <file>./SQL/SQLite/10/select_buffer_by_id.sql</file>
-    <file>./SQL/SQLite/10/select_buffer_lastseen_messages.sql</file>
-    <file>./SQL/SQLite/10/select_bufferByName.sql</file>
-    <file>./SQL/SQLite/10/select_bufferExists.sql</file>
-    <file>./SQL/SQLite/10/select_buffers.sql</file>
-    <file>./SQL/SQLite/10/select_connected_networks.sql</file>
-    <file>./SQL/SQLite/10/select_messageRange.sql</file>
-    <file>./SQL/SQLite/10/select_messages.sql</file>
-    <file>./SQL/SQLite/10/select_messagesOffset.sql</file>
-    <file>./SQL/SQLite/10/select_messagesSince.sql</file>
-    <file>./SQL/SQLite/10/select_messagesSinceOffset.sql</file>
-    <file>./SQL/SQLite/10/select_networkExists.sql</file>
-    <file>./SQL/SQLite/10/select_networks_for_user.sql</file>
-    <file>./SQL/SQLite/10/select_persistent_channels.sql</file>
-    <file>./SQL/SQLite/10/select_servers_for_network.sql</file>
-    <file>./SQL/SQLite/10/select_userid.sql</file>
-    <file>./SQL/SQLite/10/setup_000_quasseluser.sql</file>
-    <file>./SQL/SQLite/10/setup_010_sender.sql</file>
-    <file>./SQL/SQLite/10/setup_020_network.sql</file>
-    <file>./SQL/SQLite/10/setup_030_buffer.sql</file>
-    <file>./SQL/SQLite/10/setup_040_buffer_idx.sql</file>
-    <file>./SQL/SQLite/10/setup_050_buffer_cname_idx.sql</file>
-    <file>./SQL/SQLite/10/setup_060_backlog.sql</file>
-    <file>./SQL/SQLite/10/setup_070_coreinfo.sql</file>
-    <file>./SQL/SQLite/10/setup_080_ircservers.sql</file>
-    <file>./SQL/SQLite/10/setup_090_create_backlog_idx.sql</file>
-    <file>./SQL/SQLite/10/setup_100_create_backlog_idx2.sql</file>
-    <file>./SQL/SQLite/10/setup_110_create_buffer_idx.sql</file>
-    <file>./SQL/SQLite/10/setup_999_version.sql</file>
-    <file>./SQL/SQLite/10/update_buffer_lastseen.sql</file>
-    <file>./SQL/SQLite/10/update_buffer_name.sql</file>
-    <file>./SQL/SQLite/10/update_buffer_persistent_channel.sql</file>
-    <file>./SQL/SQLite/10/update_buffer_set_channel_key.sql</file>
-    <file>./SQL/SQLite/10/update_network.sql</file>
-    <file>./SQL/SQLite/10/update_network_connected.sql</file>
-    <file>./SQL/SQLite/10/update_username.sql</file>
-    <file>./SQL/SQLite/10/update_userpassword.sql</file>
     <file>./SQL/SQLite/10/upgrade_000_switch_to_msgid.sql</file>
     <file>./SQL/SQLite/10/upgrade_010_rename_buffer_table.sql</file>
     <file>./SQL/SQLite/10/upgrade_020_create_buffer_table.sql</file>
     <file>./SQL/SQLite/10/upgrade_030_copy_buffer_table.sql</file>
     <file>./SQL/SQLite/10/upgrade_040_drop_buffer_old_table.sql</file>
     <file>./SQL/SQLite/10/upgrade_999_version.sql</file>
+    <file>./SQL/SQLite/11/delete_backlog_by_uid.sql</file>
+    <file>./SQL/SQLite/11/delete_backlog_for_buffer.sql</file>
+    <file>./SQL/SQLite/11/delete_backlog_for_network.sql</file>
+    <file>./SQL/SQLite/11/delete_buffer_for_bufferid.sql</file>
+    <file>./SQL/SQLite/11/delete_buffers_by_uid.sql</file>
+    <file>./SQL/SQLite/11/delete_buffers_for_network.sql</file>
+    <file>./SQL/SQLite/11/delete_ircservers_for_network.sql</file>
+    <file>./SQL/SQLite/11/delete_network.sql</file>
+    <file>./SQL/SQLite/11/delete_networks_by_uid.sql</file>
+    <file>./SQL/SQLite/11/delete_quasseluser.sql</file>
+    <file>./SQL/SQLite/11/insert_buffer.sql</file>
+    <file>./SQL/SQLite/11/insert_message.sql</file>
+    <file>./SQL/SQLite/11/insert_network.sql</file>
+    <file>./SQL/SQLite/11/insert_quasseluser.sql</file>
+    <file>./SQL/SQLite/11/insert_sender.sql</file>
+    <file>./SQL/SQLite/11/insert_server.sql</file>
+    <file>./SQL/SQLite/11/insert_user_setting.sql</file>
+    <file>./SQL/SQLite/11/select_authuser.sql</file>
+    <file>./SQL/SQLite/11/select_buffer_by_id.sql</file>
+    <file>./SQL/SQLite/11/select_buffer_lastseen_messages.sql</file>
+    <file>./SQL/SQLite/11/select_bufferByName.sql</file>
+    <file>./SQL/SQLite/11/select_bufferExists.sql</file>
+    <file>./SQL/SQLite/11/select_buffers.sql</file>
+    <file>./SQL/SQLite/11/select_connected_networks.sql</file>
+    <file>./SQL/SQLite/11/select_messageRange.sql</file>
+    <file>./SQL/SQLite/11/select_messages.sql</file>
+    <file>./SQL/SQLite/11/select_messagesOffset.sql</file>
+    <file>./SQL/SQLite/11/select_messagesSince.sql</file>
+    <file>./SQL/SQLite/11/select_messagesSinceOffset.sql</file>
+    <file>./SQL/SQLite/11/select_networkExists.sql</file>
+    <file>./SQL/SQLite/11/select_networks_for_user.sql</file>
+    <file>./SQL/SQLite/11/select_persistent_channels.sql</file>
+    <file>./SQL/SQLite/11/select_servers_for_network.sql</file>
+    <file>./SQL/SQLite/11/select_user_setting.sql</file>
+    <file>./SQL/SQLite/11/select_userid.sql</file>
+    <file>./SQL/SQLite/11/setup_000_quasseluser.sql</file>
+    <file>./SQL/SQLite/11/setup_010_sender.sql</file>
+    <file>./SQL/SQLite/11/setup_020_network.sql</file>
+    <file>./SQL/SQLite/11/setup_030_buffer.sql</file>
+    <file>./SQL/SQLite/11/setup_040_buffer_idx.sql</file>
+    <file>./SQL/SQLite/11/setup_050_buffer_cname_idx.sql</file>
+    <file>./SQL/SQLite/11/setup_060_backlog.sql</file>
+    <file>./SQL/SQLite/11/setup_070_coreinfo.sql</file>
+    <file>./SQL/SQLite/11/setup_080_ircservers.sql</file>
+    <file>./SQL/SQLite/11/setup_090_create_backlog_idx.sql</file>
+    <file>./SQL/SQLite/11/setup_100_create_backlog_idx2.sql</file>
+    <file>./SQL/SQLite/11/setup_110_create_buffer_idx.sql</file>
+    <file>./SQL/SQLite/11/setup_120_create_user_setting.sql</file>
+    <file>./SQL/SQLite/11/setup_999_version.sql</file>
+    <file>./SQL/SQLite/11/update_buffer_lastseen.sql</file>
+    <file>./SQL/SQLite/11/update_buffer_name.sql</file>
+    <file>./SQL/SQLite/11/update_buffer_persistent_channel.sql</file>
+    <file>./SQL/SQLite/11/update_buffer_set_channel_key.sql</file>
+    <file>./SQL/SQLite/11/update_network.sql</file>
+    <file>./SQL/SQLite/11/update_network_connected.sql</file>
+    <file>./SQL/SQLite/11/update_user_setting.sql</file>
+    <file>./SQL/SQLite/11/update_username.sql</file>
+    <file>./SQL/SQLite/11/update_userpassword.sql</file>
+    <file>./SQL/SQLite/11/upgrade_000_create_user_setting.sql</file>
+    <file>./SQL/SQLite/11/upgrade_999_version.sql</file>
     <file>./SQL/SQLite/2/upgrade_000_drop_buffergroup.sql</file>
     <file>./SQL/SQLite/2/upgrade_010_update_schemaversion.sql</file>
     <file>./SQL/SQLite/3/upgrade_000_update_backlog_flags.sql</file>
index b1d3d26..ea19ca9 100644 (file)
@@ -133,6 +133,49 @@ void SqliteStorage::delUser(UserId user) {
   emit userRemoved(user);
 }
 
+void SqliteStorage::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) {
+  QByteArray rawData;
+  QDataStream out(&rawData, QIODevice::WriteOnly);
+  out.setVersion(QDataStream::Qt_4_2);
+  out << data;
+
+  QSqlQuery query(logDb());
+  query.prepare(queryString("insert_user_setting"));
+  query.bindValue(":userid", userId.toInt());
+  query.bindValue(":settingname", settingName);
+  query.bindValue(":settingvalue", rawData);
+  query.exec();
+
+  if(query.lastError().isValid()) {
+    QSqlQuery updateQuery(logDb());
+    updateQuery.prepare(queryString("update_user_setting"));
+    updateQuery.bindValue(":userid", userId.toInt());
+    updateQuery.bindValue(":settingname", settingName);
+    updateQuery.bindValue(":settingvalue", rawData);
+    updateQuery.exec();
+  }
+                 
+}
+
+QVariant SqliteStorage::getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_user_setting"));
+  query.bindValue(":userid", userId.toInt());
+  query.bindValue(":settingname", settingName);
+  query.exec();
+
+  if(query.first()) {
+    QVariant data;
+    QByteArray rawData = query.value(0).toByteArray();
+    QDataStream in(&rawData, QIODevice::ReadOnly);
+    in.setVersion(QDataStream::Qt_4_2);
+    in >> data;
+    return data;
+  } else {
+    return defaultData;
+  }
+}
+
 NetworkId SqliteStorage::createNetwork(UserId user, const NetworkInfo &info) {
   NetworkId networkId;
   QSqlQuery query(logDb());
index 66d205f..597ca23 100644 (file)
@@ -50,6 +50,9 @@ public slots:
   virtual void renameUser(UserId user, const QString &newName);
   virtual UserId validateUser(const QString &user, const QString &password);
   virtual void delUser(UserId user);
+  virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
+  virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData = QVariant());
+
   
   /* Network handling */
   virtual NetworkId createNetwork(UserId user, const NetworkInfo &info);
index 1ce0079..964548d 100644 (file)
@@ -107,6 +107,23 @@ class Storage : public QObject {
      */
     virtual void delUser(UserId user) = 0;
 
+    //! Store a user setting persistently
+    /**
+     * \param userId       The users Id
+     * \param settingName  The Name of the Setting
+     * \param data         The Value
+     */
+    virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) = 0;
+  
+    //! Retrieve a persistent user setting
+    /**
+     * \param userId       The users Id
+     * \param settingName  The Name of the Setting
+     * \param default      Value to return in case it's unset.
+     * \return the Value of the Setting or the default value if it is unset.
+     */
+    virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &data = QVariant()) = 0;
+  
     /* Network handling */
 
     //! Create a new Network in the storage backend and return it unique Id
index 909592e..4811e2e 100644 (file)
 #include "clientsyncer.h"
 #include "coreconfigwizard.h"
 
-CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool autoconnect) : QDialog(parent) {
+CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool autoconnect)
+  : QDialog(parent)
+{
   ui.setupUi(this);
 
+  // make it look more native under Mac OS X:
+  setWindowFlags(Qt::Sheet);
+
   clientSyncer = new ClientSyncer(this);
   wizard = 0;
 
index cf7a6e0..36d7096 100644 (file)
@@ -22,6 +22,9 @@
 #include "aboutdlg.h"
 #include "chatwidget.h"
 #include "bufferview.h"
+#include "bufferviewconfig.h"
+#include "bufferviewfilter.h"
+#include "bufferviewmanager.h"
 #include "chatline.h"
 #include "chatline-old.h"
 #include "client.h"
@@ -165,39 +168,68 @@ void MainWin::setupMenus() {
   actionEditNetworks = new QAction(QIcon(":/22x22/actions/configure"), tr("Edit &Networks..."), this);
   ui.menuNetworks->addAction(actionEditNetworks);
   connect(actionEditNetworks, SIGNAL(triggered()), this, SLOT(showNetworkDlg()));
+  connect(ui.actionManageViews, SIGNAL(triggered()), this, SLOT(showManageViewsDlg()));
 }
 
 void MainWin::setupViews() {
-  BufferModel *model = Client::bufferModel();
-
-  addBufferView(tr("All Buffers"), model, BufferViewFilter::AllNets, QList<NetworkId>());
-  addBufferView(tr("All Channels"), model, BufferViewFilter::AllNets|BufferViewFilter::NoQueries|BufferViewFilter::NoServers, QList<NetworkId>());
-  addBufferView(tr("All Queries"), model, BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoServers, QList<NetworkId>());
-  addBufferView(tr("All Networks"), model, BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoQueries, QList<NetworkId>());
-  addBufferView(tr("Full Custom"), model, BufferViewFilter::FullCustom, QList<NetworkId>());
+  QAction *separator = ui.menuViews->addSeparator();
+  separator->setData("__EOBV__");
+  addBufferView();
+}
 
-  ui.menuViews->addSeparator();
+void MainWin::addBufferView(int bufferViewConfigId) {
+  addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewConfigId));
 }
 
-QDockWidget *MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model, const BufferViewFilter::Modes &mode, const QList<NetworkId> &nets) {
-  QDockWidget *dock = new QDockWidget(viewname, this);
-  dock->setObjectName(QString("ViewDock-" + viewname)); // should be unique for mainwindow state!
-  dock->setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
+void MainWin::addBufferView(BufferViewConfig *config) {
+  BufferViewDock *dock;
+  if(config)
+    dock = new BufferViewDock(config, this);
+  else
+    dock = new BufferViewDock(this);
 
   //create the view and initialize it's filter
   BufferView *view = new BufferView(dock);
+  view->setFilteredModel(Client::bufferModel(), config);
   view->show();
-  view->setFilteredModel(model, mode, nets);
+
   Client::bufferModel()->synchronizeView(view);
+
   dock->setWidget(view);
   dock->show();
 
   addDockWidget(Qt::LeftDockWidgetArea, dock);
 
-  ui.menuViews->addAction(dock->toggleViewAction());
+  QAction *endOfBufferViews = 0;
+  foreach(QAction *action, ui.menuViews->actions()) {
+    if(action->data().toString() == "__EOBV__") {
+      endOfBufferViews = action;
+      break;
+    }
+  }
+  Q_CHECK_PTR(endOfBufferViews);
+  ui.menuViews->insertAction(endOfBufferViews, dock->toggleViewAction());
 
-  netViews.append(dock);
-  return dock;
+  _netViews.append(dock);
+}
+
+void MainWin::removeBufferView(int bufferViewConfigId) {
+  QVariant actionData;
+  BufferViewDock *dock;
+  foreach(QAction *action, ui.menuViews->actions()) {
+    actionData = action->data();
+    if(!actionData.isValid())
+      continue;
+    
+    if(actionData.toString() == "__EOBV__")
+      break;
+
+    dock = qobject_cast<BufferViewDock *>(action->parent());
+    if(dock && actionData.toInt() != bufferViewConfigId) {
+      removeAction(action);
+      dock->deleteLater();
+    }
+  }
 }
 
 void MainWin::setupSettingsDlg() {
@@ -211,7 +243,17 @@ void MainWin::setupSettingsDlg() {
   //Category: General
   settingsDlg->registerSettingsPage(new IdentitiesSettingsPage(settingsDlg));
   settingsDlg->registerSettingsPage(new NetworksSettingsPage(settingsDlg));
-  // settingsDlg->registerSettingsPage(new BufferViewSettingsPage(settingsDlg));
+  settingsDlg->registerSettingsPage(new BufferViewSettingsPage(settingsDlg));
+}
+
+void MainWin::showNetworkDlg() {
+  SettingsPageDlg dlg(new NetworksSettingsPage(this), this);
+  dlg.exec();
+}
+
+void MainWin::showManageViewsDlg() {
+  SettingsPageDlg dlg(new BufferViewSettingsPage(this), this);
+  dlg.exec();
 }
 
 void MainWin::setupNickWidget() {
@@ -357,6 +399,11 @@ void MainWin::changeTopic(const QString &topic) {
 }
 
 void MainWin::connectedToCore() {
+  Q_CHECK_PTR(Client::bufferViewManager());
+  connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
+  connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int)));
+  connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout()));
+  
   foreach(BufferInfo id, Client::allBufferInfos()) {
     Client::backlogManager()->requestBacklog(id.bufferId(), 500, -1);
   }
@@ -374,6 +421,12 @@ void MainWin::connectedToCore() {
     sslLabel->setPixmap(QPixmap::fromImage(QImage(":/16x16/status/no-ssl")));
 }
 
+void MainWin::loadLayout() {
+  QtUiSettings s;
+  int accountId = Client::currentCoreAccount().toInt();
+  restoreState(s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(), accountId);
+}
+
 void MainWin::securedConnection() {
   // todo: make status bar entry
   qDebug() << "secured the connection";
@@ -382,6 +435,27 @@ void MainWin::securedConnection() {
 }
 
 void MainWin::disconnectedFromCore() {
+  // save core specific layout and remove bufferviews;
+  QtUiSettings s;
+  int accountId = Client::currentCoreAccount().toInt();
+  s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId));
+  QVariant actionData;
+  BufferViewDock *dock;
+  foreach(QAction *action, ui.menuViews->actions()) {
+    actionData = action->data();
+    if(!actionData.isValid())
+      continue;
+    
+    if(actionData.toString() == "__EOBV__")
+      break;
+
+    dock = qobject_cast<BufferViewDock *>(action->parent());
+    if(dock && actionData.toInt() != -1) {
+      removeAction(action);
+      dock->deleteLater();
+    }
+  }
+
   ui.menuViews->setEnabled(false);
   //ui.menuCore->setEnabled(false);
   ui.actionDisconnectCore->setEnabled(false);
@@ -527,11 +601,6 @@ void MainWin::makeTrayIconBlink() {
 }
 
 
-void MainWin::showNetworkDlg() {
-  SettingsPageDlg dlg(new NetworksSettingsPage(this), this);
-  dlg.exec();
-}
-
 void MainWin::clientNetworkCreated(NetworkId id) {
   const Network *net = Client::network(id);
   QAction *act = new QAction(net->networkName(), this);
index c2cdfce..0190345 100644 (file)
@@ -24,7 +24,6 @@
 #include "ui_mainwin.h"
 
 #include "qtui.h"
-#include "bufferviewfilter.h"
 
 #include <QSystemTrayIcon>
 #include <QTimer>
 class ServerListDlg;
 class CoreConnectDlg;
 class Buffer;
+class BufferViewConfig;
 class SettingsDlg;
 class QtUi;
 class Message;
 class NickListWidget;
 class DebugConsole;
 
+
 //!\brief The main window of Quassel's QtUi.
 class MainWin : public QMainWindow {
   Q_OBJECT
@@ -47,7 +48,7 @@ class MainWin : public QMainWindow {
     virtual ~MainWin();
 
     void init();
-    QDockWidget *addBufferView(const QString &, QAbstractItemModel *, const BufferViewFilter::Modes &, const QList<NetworkId> &);
+    void addBufferView(BufferViewConfig *config = 0);
 
     AbstractUiMsg *layoutMsg(const Message &);
     void displayTrayIconMessage(const QString &title, const QString &message);
@@ -68,9 +69,12 @@ class MainWin : public QMainWindow {
     void systrayActivated( QSystemTrayIcon::ActivationReason );
 
   private slots:
+    void addBufferView(int bufferViewConfigId);
+    void removeBufferView(int bufferViewConfigId);
     void receiveMessage(const Message &msg);
     void showSettingsDlg();
     void showNetworkDlg();
+    void showManageViewsDlg();
     void showAboutDlg();
     void showDebugConsole();
 
@@ -86,6 +90,8 @@ class MainWin : public QMainWindow {
     void makeTrayIconBlink();
     void saveStatusBarStatus(bool enabled);
 
+    void loadLayout();
+  
   signals:
     void connectToCore(const QVariantMap &connInfo);
     void disconnectFromCore();
@@ -127,7 +133,7 @@ class MainWin : public QMainWindow {
     BufferId currentBuffer;
     QString currentProfile;
 
-    QList<QDockWidget *> netViews;
+    QList<QDockWidget *> _netViews;
     NickListWidget *nickListWidget;
 
     QAction *actionEditNetworks;
index 2c817a9..7bac0ef 100644 (file)
 
 #include "settingspagedlg.h"
 
-SettingsPageDlg::SettingsPageDlg(SettingsPage *page, QWidget *parent) : QDialog(parent) {
+SettingsPageDlg::SettingsPageDlg(SettingsPage *page, QWidget *parent)
+  : QDialog(parent)
+{
   ui.setupUi(this);
   _currentPage = page;
   page->setParent(this);
+
+  // make it look more native under Mac OS X:
+  setWindowFlags(Qt::Sheet);
+
   ui.pageTitle->setText(page->title());
 
   // make the scrollarea behave sanely
index 3fe64df..9e95996 100644 (file)
 
 #include "bufferviewsettingspage.h"
 
+#include <QMessageBox>
+
 #include "client.h"
-#include "bufferviewmanager.h"
+#include "network.h"
 #include "bufferviewconfig.h"
+#include "bufferviewfilter.h"
+#include "bufferviewmanager.h"
+#include "buffermodel.h"
+#include "networkmodel.h"
 
 BufferViewSettingsPage::BufferViewSettingsPage(QWidget *parent)
-  : SettingsPage(tr("General"), tr("Buffer Views"), parent)
+  : SettingsPage(tr("General"), tr("Buffer Views"), parent),
+    _ignoreWidgetChanges(false)
 {
   ui.setupUi(this);
   reset();
+
+  ui.bufferViewList->setSortingEnabled(true);
+  ui.settingsGroupBox->setEnabled(false);
+  ui.bufferViewPreview->setEnabled(false);
+
   setEnabled(Client::isConnected());  // need a core connection!
   connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
+  connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+         this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &)));
+
+  connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
 }
 
 BufferViewSettingsPage::~BufferViewSettingsPage() {
@@ -39,14 +62,12 @@ BufferViewSettingsPage::~BufferViewSettingsPage() {
 
 void BufferViewSettingsPage::reset() {
   ui.bufferViewList->clear();
-  _viewToListPos.clear();
-  _listPosToView.clear();
 
   QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
   QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
   BufferViewConfig *config;
   while(changedConfigIter != changedConfigIterEnd) {
-    config = (*changedConfigIter);
+    config = changedConfigIter.value();
     changedConfigIter = _changedBufferViews.erase(changedConfigIter);
     config->deleteLater();
   }
@@ -59,6 +80,8 @@ void BufferViewSettingsPage::reset() {
     config->deleteLater();
   }
 
+  _deleteBufferViews.clear();
+  
   setChangedState(false);
 }
 
@@ -72,9 +95,62 @@ void BufferViewSettingsPage::load() {
   foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) {
     addBufferView(bufferViewConfig);
   }
+
+  _ignoreWidgetChanges = true;
+  // load network selector
+  ui.networkSelector->clear();
+  ui.networkSelector->addItem("All");
+  ui.networkSelector->setItemData(0, qVariantFromValue<NetworkId>(NetworkId()));
+  const Network *net;
+  foreach(NetworkId netId, Client::networkIds()) {
+    net = Client::network(netId);
+    ui.networkSelector->addItem(net->networkName());
+    ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue<NetworkId>(net->networkId()));
+  }
+  _ignoreWidgetChanges = false;
+  
+  ui.bufferViewList->setCurrentRow(0);
 }
 
 void BufferViewSettingsPage::save() {
+  setEnabled(false);
+  QVariantList newConfigs;
+  QVariantList deleteConfigs;
+  QVariantList changedConfigs;
+
+  foreach(int bufferId, _deleteBufferViews) {
+    deleteConfigs << bufferId;
+  }
+  _deleteBufferViews.clear();
+  if(Client::bufferViewManager()) {
+    Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs);
+  }
+  
+  QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
+  QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
+  BufferViewConfig *config, *changedConfig;
+  while(changedConfigIter != changedConfigIterEnd) {
+    config = changedConfigIter.key();
+    changedConfig = changedConfigIter.value();
+    changedConfigIter = _changedBufferViews.erase(changedConfigIter);
+    config->requestUpdate(changedConfig->toVariantMap());
+    changedConfig->deleteLater();
+  }
+
+  QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
+  QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
+  while(newConfigIter != newConfigIterEnd) {
+    config = *newConfigIter;
+    newConfigIter = _newBufferViews.erase(newConfigIter);
+    newConfigs << config->toVariantMap();
+    config->deleteLater();
+  }
+  if(Client::bufferViewManager()) {
+    Client::bufferViewManager()->requestCreateBufferViews(newConfigs);
+  }
+
+  load();
+  setEnabled(true);
 }
 
 void BufferViewSettingsPage::coreConnectionStateChanged(bool state) {
@@ -88,10 +164,10 @@ void BufferViewSettingsPage::coreConnectionStateChanged(bool state) {
 }
 
 void BufferViewSettingsPage::addBufferView(BufferViewConfig *config) {
-  _viewToListPos[config->bufferViewId()] = ui.bufferViewList->count();
-  _listPosToView[ui.bufferViewList->count()] = config->bufferViewId();
-  ui.bufferViewList->addItem(config->bufferViewName());
+  QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList);
+  item->setData(Qt::UserRole, qVariantFromValue<QObject *>(qobject_cast<QObject *>(config)));
   connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView()));
+  connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted()));
 }
 
 void BufferViewSettingsPage::addBufferView(int bufferViewId) {
@@ -99,27 +175,57 @@ void BufferViewSettingsPage::addBufferView(int bufferViewId) {
   addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId));
 }
 
+void BufferViewSettingsPage::bufferViewDeleted() {
+  BufferViewConfig *config = static_cast<BufferViewConfig *>(sender());
+  QObject *obj;
+  for(int i = 0; i < ui.bufferViewList->count(); i++) {
+    obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
+    if(config == static_cast<BufferViewConfig *>(obj)) {
+      QListWidgetItem *item = ui.bufferViewList->takeItem(i);
+      delete item;
+      return;
+    }
+  }
+}
+
 void BufferViewSettingsPage::newBufferView(const QString &bufferViewName) {
   // id's of newly created bufferviews are negative (-1, -2... -n)
   int fakeId = -1 * (_newBufferViews.count() + 1);
   BufferViewConfig *config = new BufferViewConfig(fakeId);
   config->setBufferViewName(bufferViewName);
+
+  QList<BufferId> bufferIds;
+  if(config->addNewBuffersAutomatically()) {
+    foreach(BufferInfo bufferInfo, Client::allBufferInfos()) {
+      bufferIds << bufferInfo.bufferId();
+    }
+    if(config->sortAlphabetically())
+      qSort(bufferIds.begin(), bufferIds.end(), bufferIdLessThan);
+  }
+  config->initSetBufferList(bufferIds);
+
   _newBufferViews << config;
   addBufferView(config);
+  ui.bufferViewList->setCurrentRow(listPos(config));
 }
       
 int BufferViewSettingsPage::listPos(BufferViewConfig *config) {
-  if(_viewToListPos.contains(config->bufferViewId()))
-    return _viewToListPos[config->bufferViewId()];
-  else
-    return -1;
+  QObject *obj;
+  for(int i = 0; i < ui.bufferViewList->count(); i++) {
+    obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
+    if(config == qobject_cast<BufferViewConfig *>(obj))
+      return i;
+  }
+  return -1;
 }
 
-int BufferViewSettingsPage::bufferViewId(int listPos) {
-  if(_listPosToView.contains(listPos))
-    return _listPosToView[listPos];
-  else
-    return -1;
+BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos) {
+  if(listPos < ui.bufferViewList->count() && listPos >= 0) {
+    QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value<QObject *>();
+    return qobject_cast<BufferViewConfig *>(obj);
+  } else {
+    return 0;
+  }
 }
 
 void BufferViewSettingsPage::updateBufferView() {
@@ -133,6 +239,8 @@ void BufferViewSettingsPage::updateBufferView() {
     return;
   }
   ui.bufferViewList->item(itemPos)->setText(config->bufferViewName());
+  if(itemPos == ui.bufferViewList->currentRow())
+    loadConfig(config);
 }
 
 void BufferViewSettingsPage::on_addBufferView_clicked() {
@@ -158,7 +266,7 @@ void BufferViewSettingsPage::on_renameBufferView_clicked() {
   if(!Client::bufferViewManager())
     return;
   
-  BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(bufferViewId(ui.bufferViewList->currentRow()));
+  BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow());
   if(!config)
     return;
 
@@ -171,16 +279,159 @@ void BufferViewSettingsPage::on_renameBufferView_clicked() {
   if(dlg.exec() == QDialog::Accepted) {
     BufferViewConfig *changedConfig = cloneConfig(config);
     changedConfig->setBufferViewName(dlg.bufferViewName());
+    ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName());
     changed();
   }
 }
 
+void BufferViewSettingsPage::on_deleteBufferView_clicked() {
+  if(ui.bufferViewList->selectedItems().isEmpty())
+    return;
+
+  QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow());
+  QString viewName = currentItem->text();
+  int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId();
+  int ret = QMessageBox::question(this, tr("Delete Buffer View?"),
+                                    tr("Do you really want to delete the buffer view \"%1\"?").arg(viewName),
+                                    QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+
+  if(ret == QMessageBox::Yes) {
+    ui.bufferViewList->removeItemWidget(currentItem);
+    delete currentItem;
+    if(viewId >= 0)
+      _deleteBufferViews << viewId;
+    changed();
+  }
+}
+
+void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection &current, const QItemSelection &previous) {
+  Q_UNUSED(previous)
+
+  if(!current.isEmpty()) {
+    ui.settingsGroupBox->setEnabled(true);
+    ui.bufferViewPreview->setEnabled(true);
+
+    loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow())));
+  } else {
+    ui.settingsGroupBox->setEnabled(false);
+    ui.bufferViewPreview->setEnabled(false);
+  }
+}
+
+void BufferViewSettingsPage::loadConfig(BufferViewConfig *config) {
+  if(!config)
+    return;
+  
+  _ignoreWidgetChanges = true;
+  ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes());
+  ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes());
+  ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes());
+  ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically());
+  ui.sortAlphabetically->setChecked(config->sortAlphabetically());
+  ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers());
+
+  int networkIndex = 0;
+  for(int i = 0; i < ui.networkSelector->count(); i++) {
+    if(ui.networkSelector->itemData(i).value<NetworkId>() == config->networkId()) {
+      networkIndex = i;
+      break;
+    }
+  }
+  ui.networkSelector->setCurrentIndex(networkIndex);
+
+  int activityIndex = 0;
+  int minimumActivity = config->minimumActivity();
+  while(minimumActivity) {
+    activityIndex++;
+    minimumActivity = minimumActivity >> 1;
+  }
+  ui.minimumActivitySelector->setCurrentIndex(activityIndex);
+
+  ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config);
+  
+  _ignoreWidgetChanges = false;
+}
+
+void BufferViewSettingsPage::saveConfig(BufferViewConfig *config) {
+  if(!config)
+    return;
+  
+  int allowedBufferTypes = 0;
+  if(ui.onlyStatusBuffers->isChecked())
+    allowedBufferTypes |= BufferInfo::StatusBuffer;
+  if(ui.onlyChannelBuffers->isChecked())
+    allowedBufferTypes |= BufferInfo::ChannelBuffer;
+  if(ui.onlyQueryBuffers->isChecked())
+    allowedBufferTypes |= BufferInfo::QueryBuffer;
+  config->setAllowedBufferTypes(allowedBufferTypes);
+
+  config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked());
+  config->setSortAlphabetically(ui.sortAlphabetically->isChecked());
+  config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked());
+  config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value<NetworkId>());
+
+  int minimumActivity = 0;
+  if(ui.minimumActivitySelector->currentIndex() > 0)
+    minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1);
+  config->setMinimumActivity(minimumActivity);
+
+  if(_newBufferViews.contains(config)) {
+    QList<BufferId> bufferIds;
+    if(config->addNewBuffersAutomatically()) {
+      foreach(BufferInfo bufferInfo, Client::allBufferInfos()) {
+       bufferIds << bufferInfo.bufferId();
+      }
+      if(config->sortAlphabetically())
+       qSort(bufferIds.begin(), bufferIds.end(), bufferIdLessThan);
+    }
+    config->initSetBufferList(bufferIds);
+  }
+}
+
+void BufferViewSettingsPage::widgetHasChanged() {
+  if(_ignoreWidgetChanges)
+    return;
+  setChangedState(testHasChanged());
+}
+
+bool BufferViewSettingsPage::testHasChanged() {
+  saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow())));
+
+  if(!_newBufferViews.isEmpty())
+    return true;
+
+  bool changed = false;
+  QHash<BufferViewConfig *, BufferViewConfig *>::iterator iter = _changedBufferViews.begin();
+  QHash<BufferViewConfig *, BufferViewConfig *>::iterator iterEnd = _changedBufferViews.end();
+  while(iter != iterEnd) {
+    if(&(iter.key()) == &(iter.value())) {
+      iter.value()->deleteLater();
+      _changedBufferViews.erase(iter);
+    } else {
+      changed = true;
+      iter++;
+    }
+  }
+  return changed;
+}
+
 BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config) {
+  if(!config || config->bufferViewId() < 0)
+    return config;
+  
   if(_changedBufferViews.contains(config))
     return _changedBufferViews[config];
 
   BufferViewConfig *changedConfig = new BufferViewConfig(-1, this);
   changedConfig->fromVariantMap(config->toVariantMap());
+  _changedBufferViews[config] = changedConfig;
+
+  // if this is the currently displayed view we have to change the config of the preview filter
+  BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(ui.bufferViewPreview->model());
+  if(filter && filter->config() == config)
+    filter->setConfig(changedConfig);
+  ui.bufferViewPreview->setConfig(changedConfig);
+
   return changedConfig;
 }
 
index 0c73358..bf08177 100644 (file)
@@ -25,6 +25,8 @@
 #include "ui_bufferviewsettingspage.h"
 #include "ui_buffervieweditdlg.h"
 
+#include <QItemSelection>
+
 class BufferViewConfig;
 
 class BufferViewSettingsPage : public SettingsPage {
@@ -44,29 +46,38 @@ private slots:
 
   void addBufferView(BufferViewConfig *config);
   void addBufferView(int bufferViewId);
+  void bufferViewDeleted();
   void newBufferView(const QString &bufferViewName);
   void updateBufferView();
 
   void on_addBufferView_clicked();
   void on_renameBufferView_clicked();
+  void on_deleteBufferView_clicked();
+  void bufferViewSelectionChanged(const QItemSelection &current, const QItemSelection &previous);
+
+  void widgetHasChanged();
   
 private:
   Ui::BufferViewSettingsPage ui;
-
-  // mappings for bufferViewId to position in the list and vice versa
-  QHash<int, int> _viewToListPos;
-  QHash<int, int> _listPosToView;
+  bool _ignoreWidgetChanges;
 
   // list of bufferviews to create
   QList<BufferViewConfig *> _newBufferViews;
 
+  // list of buferViews to delete
+  QList<int> _deleteBufferViews;
+  
   // Hash of pointers to cloned bufferViewConfigs holding the changes
   QHash<BufferViewConfig *, BufferViewConfig *> _changedBufferViews;
 
   int listPos(BufferViewConfig *config);
-  int bufferViewId(int listPos);
+  BufferViewConfig *bufferView(int listPos);
   BufferViewConfig *cloneConfig(BufferViewConfig *config);
   BufferViewConfig *configForDisplay(BufferViewConfig *config);
+
+  void loadConfig(BufferViewConfig *config);
+  void saveConfig(BufferViewConfig *config);
+  bool testHasChanged();
 };
 
 
index 161ecaa..0131e08 100644 (file)
@@ -5,8 +5,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>507</width>
-    <height>485</height>
+    <width>672</width>
+    <height>529</height>
    </rect>
   </property>
   <property name="windowTitle" >
@@ -75,7 +75,7 @@
     </layout>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox" >
+    <widget class="QGroupBox" name="settingsGroupBox" >
      <property name="title" >
       <string>Buffer View  Settings</string>
      </property>
         <item>
          <widget class="QLabel" name="label" >
           <property name="text" >
-           <string>Show only Buffers from:</string>
+           <string>Network:</string>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QComboBox" name="comboBox" />
+         <widget class="QComboBox" name="networkSelector" >
+          <item>
+           <property name="text" >
+            <string>All</string>
+           </property>
+          </item>
+         </widget>
         </item>
        </layout>
       </item>
         </property>
         <layout class="QVBoxLayout" >
          <item>
-          <widget class="QCheckBox" name="checkBox" >
+          <widget class="QCheckBox" name="onlyStatusBuffers" >
            <property name="text" >
             <string>Status Buffers</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QCheckBox" name="checkBox_2" >
+          <widget class="QCheckBox" name="onlyChannelBuffers" >
            <property name="text" >
             <string>Channel Buffers</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QCheckBox" name="checkBox_3" >
+          <widget class="QCheckBox" name="onlyQueryBuffers" >
            <property name="text" >
             <string>Query Buffers</string>
            </property>
        </widget>
       </item>
       <item>
-       <widget class="QCheckBox" name="checkBox_4" >
+       <widget class="QCheckBox" name="hideInactiveBuffers" >
+        <property name="text" >
+         <string>Hide inactive Buffers</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="addNewBuffersAutomatically" >
         <property name="text" >
          <string>Add new Buffers automatically</string>
         </property>
        </widget>
       </item>
       <item>
-       <widget class="QCheckBox" name="checkBox_5" >
+       <widget class="QCheckBox" name="sortAlphabetically" >
+        <property name="text" >
+         <string>Sort alphabetically</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="label_3" >
         <property name="text" >
-         <string>Sort Buffers alphabetically</string>
+         <string>Minimum Activity:</string>
         </property>
        </widget>
       </item>
+      <item>
+       <widget class="QComboBox" name="minimumActivitySelector" >
+        <item>
+         <property name="text" >
+          <string>No Activity</string>
+         </property>
+        </item>
+        <item>
+         <property name="text" >
+          <string>Other Activity</string>
+         </property>
+        </item>
+        <item>
+         <property name="text" >
+          <string>New Message</string>
+         </property>
+        </item>
+        <item>
+         <property name="text" >
+          <string>Highlight</string>
+         </property>
+        </item>
+       </widget>
+      </item>
       <item>
        <spacer>
         <property name="orientation" >
      </layout>
     </widget>
    </item>
+   <item>
+    <layout class="QVBoxLayout" >
+     <item>
+      <widget class="QLabel" name="label_2" >
+       <property name="text" >
+        <string>Preview:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="BufferView" name="bufferViewPreview" />
+     </item>
+    </layout>
+   </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>BufferView</class>
+   <extends>QTreeView</extends>
+   <header>bufferview.h</header>
+  </customwidget>
+ </customwidgets>
  <resources>
   <include location="../../icons/icons.qrc" />
  </resources>
index cd04808..3e49f7c 100644 (file)
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget" >
-   <property name="geometry" >
-    <rect>
-     <x>0</x>
-     <y>27</y>
-     <width>800</width>
-     <height>549</height>
-    </rect>
-   </property>
    <property name="sizePolicy" >
     <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
      <horstretch>0</horstretch>
     </sizepolicy>
    </property>
    <layout class="QVBoxLayout" >
-    <property name="spacing" >
-     <number>6</number>
+    <property name="leftMargin" >
+     <number>0</number>
+    </property>
+    <property name="topMargin" >
+     <number>0</number>
+    </property>
+    <property name="rightMargin" >
+     <number>0</number>
     </property>
-    <property name="margin" >
+    <property name="bottomMargin" >
      <number>0</number>
     </property>
     <item>
@@ -45,7 +43,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>27</height>
+     <height>22</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuFile" >
    <addaction name="menuDebug" />
    <addaction name="menuHelp" />
   </widget>
-  <widget class="QStatusBar" name="statusbar" >
-   <property name="geometry" >
-    <rect>
-     <x>0</x>
-     <y>576</y>
-     <width>800</width>
-     <height>24</height>
-    </rect>
-   </property>
-  </widget>
+  <widget class="QStatusBar" name="statusbar" />
   <action name="actionNetworkList" >
    <property name="enabled" >
     <bool>false</bool>
   </action>
   <action name="actionQuit" >
    <property name="icon" >
-    <iconset resource="../../icons/icons.qrc" >
-     <normaloff>:/22x22/actions/oxygen/22x22/actions/application-exit.png</normaloff>:/22x22/actions/oxygen/22x22/actions/application-exit.png</iconset>
+    <iconset resource="../../icons/icons.qrc" >:/22x22/actions/oxygen/22x22/actions/application-exit.png</iconset>
    </property>
    <property name="text" >
     <string>Quit...</string>
   </action>
   <action name="actionSettingsDlg" >
    <property name="icon" >
-    <iconset>
-     <normaloff/>
-    </iconset>
+    <iconset/>
    </property>
    <property name="text" >
     <string>Configure Quassel...</string>
   </action>
   <action name="actionManageViews" >
    <property name="enabled" >
-    <bool>false</bool>
+    <bool>true</bool>
    </property>
    <property name="text" >
     <string>Manage Views...</string>
     <bool>true</bool>
    </property>
    <property name="icon" >
-    <iconset resource="../../icons/icons.qrc" >
-     <normaloff>:/icons/quassel-icon.png</normaloff>:/icons/quassel-icon.png</iconset>
+    <iconset resource="../../icons/icons.qrc" >:/icons/quassel-icon.png</iconset>
    </property>
    <property name="text" >
     <string>About Quassel IRC...</string>
     <bool>false</bool>
    </property>
    <property name="icon" >
-    <iconset>
-     <normaloff/>
-    </iconset>
+    <iconset/>
    </property>
    <property name="text" >
     <string>Disconnect from Core</string>
     <bool>false</bool>
    </property>
    <property name="icon" >
-    <iconset>
-     <normaloff/>
-    </iconset>
+    <iconset/>
    </property>
    <property name="text" >
     <string>Connect to Core...</string>
index e922559..48e75ba 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#include "client.h"
-#include "buffersyncer.h"
 #include "bufferview.h"
-#include "networkmodel.h"
+
+#include "bufferviewfilter.h"
+#include "buffersyncer.h"
+#include "client.h"
 #include "network.h"
+#include "networkmodel.h"
 
 #include "uisettings.h"
 
 #include "global.h"
 
+#include <QAction>
+#include <QFlags>
+#include <QHeaderView>
+#include <QInputDialog>
+#include <QLineEdit>
+#include <QMenu>
+#include <QMessageBox>
+
 /*****************************************
 * The TreeView showing the Buffers
 *****************************************/
@@ -66,16 +76,12 @@ void BufferView::init() {
 #endif
 }
 
-void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QList<NetworkId> nets) {
-  BufferViewFilter *filter = new BufferViewFilter(model, mode, nets);
-  setModel(filter);
-  connect(this, SIGNAL(removeBuffer(const QModelIndex &)), filter, SLOT(removeBuffer(const QModelIndex &)));
-}
-
 void BufferView::setModel(QAbstractItemModel *model) {
   delete selectionModel();
   QTreeView::setModel(model);
   init();
+  if(!model)
+    return;
 
   // remove old Actions
   QList<QAction *> oldactions = header()->actions();
@@ -98,6 +104,59 @@ void BufferView::setModel(QAbstractItemModel *model) {
   
 }
 
+void BufferView::setFilteredModel(QAbstractItemModel *model_, BufferViewConfig *config) {
+  BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(model());
+  if(filter) {
+    filter->setConfig(config);
+    setConfig(config);
+    return;
+  }
+
+  if(model()) {
+    disconnect(this, 0, model(), 0);
+  }
+
+  if(!model_) {
+    setModel(model_);
+  } else {
+    BufferViewFilter *filter = new BufferViewFilter(model_, config);
+    setModel(filter);
+    connect(this, SIGNAL(removeBuffer(const QModelIndex &)), filter, SLOT(removeBuffer(const QModelIndex &)));
+  }
+  setConfig(config);
+}
+
+void BufferView::setConfig(BufferViewConfig *config) {
+  if(_config == config)
+    return;
+  
+  if(_config) {
+    disconnect(_config, 0, this, 0);
+  }
+
+  _config = config;
+  if(config) {
+    connect(config, SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(setRootIndexForNetworkId(const NetworkId &)));
+    setRootIndexForNetworkId(config->networkId());
+  } else {
+    setRootIndex(QModelIndex());
+  }
+}
+
+void BufferView::setRootIndexForNetworkId(const NetworkId &networkId) {
+  if(!networkId.isValid() || !model()) {
+    setRootIndex(QModelIndex());
+  } else {
+    int networkCount = model()->rowCount();
+    QModelIndex child;
+    for(int i = 0; i < networkCount; i++) {
+      child = model()->index(i, 0);
+      if(networkId == model()->data(child, NetworkModel::NetworkIdRole).value<NetworkId>())
+       setRootIndex(child);
+    }
+  }
+}
+
 void BufferView::joinChannel(const QModelIndex &index) {
   BufferInfo::Type bufferType = (BufferInfo::Type)index.data(NetworkModel::BufferTypeRole).value<int>();
 
@@ -304,7 +363,7 @@ void BufferView::wheelEvent(QWheelEvent* event) {
 
 
 QSize BufferView::sizeHint() const {
-  return QSize(120, 50);
+  return QTreeView::sizeHint();
   
   if(!model())
     return QTreeView::sizeHint();
@@ -319,3 +378,28 @@ QSize BufferView::sizeHint() const {
   }
   return QSize(columnSize, 50);
 }
+
+// ==============================
+//  BufferView Dock
+// ==============================
+BufferViewDock::BufferViewDock(BufferViewConfig *config, QWidget *parent)
+  : QDockWidget(config->bufferViewName(), parent)
+{
+  setObjectName("BufferViewDock-" + QString::number(config->bufferViewId()));
+  toggleViewAction()->setData(config->bufferViewId());
+  setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
+  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);
+}
index ae1bb37..0f1b502 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#ifndef _BUFFERVIEW_H_
-#define _BUFFERVIEW_H_
+#ifndef BUFFERVIEW_H_
+#define BUFFERVIEW_H_
 
-#include <QtGui>
-#include <QFlags>
+#include <QDockWidget>
+#include <QModelIndex>
+#include <QTreeView>
+#include <QPointer>
 
-#include "bufferviewfilter.h"
+#include "bufferviewconfig.h"
+
+#include "types.h"
 
 /*****************************************
  * The TreeView showing the Buffers
@@ -35,8 +39,15 @@ class BufferView : public QTreeView {
 public:
   BufferView(QWidget *parent = 0);
   void init();
+
   void setModel(QAbstractItemModel *model);
-  void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QList<NetworkId> nets);
+  void setFilteredModel(QAbstractItemModel *model, BufferViewConfig *config);
+
+  void setConfig(BufferViewConfig *config);
+  inline BufferViewConfig *config() { return _config; }
+
+public slots:
+  void setRootIndexForNetworkId(const NetworkId &networkId);
   
 signals:
   void removeBuffer(const QModelIndex &);
@@ -53,8 +64,24 @@ private slots:
   void toggleHeader(bool checked);
   void showContextMenu(const QPoint &);
 
+private:
+  QPointer<BufferViewConfig> _config;
 };
 
 
+// ==============================
+//  BufferView Dock
+// ==============================
+class BufferViewDock : public QDockWidget {
+  Q_OBJECT
+
+public:
+  BufferViewDock(BufferViewConfig *config, QWidget *parent);
+  BufferViewDock(QWidget *parent);
+
+public slots:
+  void bufferViewRenamed(const QString &newName);
+};
+
 #endif
 
index a4ece41..896bd11 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <QColor>
 
+#include "client.h"
 #include "networkmodel.h"
 
 #include "uisettings.h"
 /*****************************************
 * The Filter for the Tree View
 *****************************************/
-BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, const Modes &filtermode, const QList<NetworkId> &nets)
+BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, BufferViewConfig *config)
   : QSortFilterProxyModel(model),
-    mode(filtermode),
-    networks(QSet<NetworkId>::fromList(nets))
+    _config(0)
 {
+  setConfig(config);
   setSourceModel(model);
-  setSortCaseSensitivity(Qt::CaseInsensitive);
+  // setSortCaseSensitivity(Qt::CaseInsensitive);
+  setDynamicSortFilter(true);
+}
+
+void BufferViewFilter::setConfig(BufferViewConfig *config) {
+  if(_config == config)
+    return;
+  
+  if(_config) {
+    disconnect(_config, 0, this, 0);
+  }
+
+  _config = config;
+  if(config) {
+    connect(config, SIGNAL(bufferViewNameSet(const QString &)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(addNewBuffersAutomaticallySet(bool)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(sortAlphabeticallySet(bool)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(hideInactiveBuffersSet(bool)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(allowedBufferTypesSet(int)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(minimumActivitySet(int)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(bufferListSet()), this, SLOT(invalidate()));
+    connect(config, SIGNAL(bufferAdded(const BufferId &, int)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(bufferMoved(const BufferId &, int)), this, SLOT(invalidate()));
+    connect(config, SIGNAL(bufferRemoved(const BufferId &)), this, SLOT(invalidate()));
+  }
+  invalidate();
 }
 
 Qt::ItemFlags BufferViewFilter::flags(const QModelIndex &index) const {
   Qt::ItemFlags flags = mapToSource(index).flags();
-  if(mode & FullCustom) {
-    if(index == QModelIndex() || index.parent() == QModelIndex())
-      flags |= Qt::ItemIsDropEnabled;
-  }
+  if(_config && index == QModelIndex() || index.parent() == QModelIndex())
+    flags |= Qt::ItemIsDropEnabled;
   return flags;
 }
 
 bool BufferViewFilter::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
-  // drops have to occur in the open field
-  if(parent != QModelIndex())
+  if(!config() || !NetworkModel::mimeContainsBufferList(data))
     return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
 
-  if(!NetworkModel::mimeContainsBufferList(data))
-    return false;
+  NetworkId droppedNetworkId;
+  if(parent.data(NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType)
+    droppedNetworkId = parent.data(NetworkModel::NetworkIdRole).value<NetworkId>();
 
   QList< QPair<NetworkId, BufferId> > bufferList = NetworkModel::mimeDataToBufferList(data);
-
-  NetworkId netId;
   BufferId bufferId;
+  NetworkId networkId;
+  int pos;
   for(int i = 0; i < bufferList.count(); i++) {
-    netId = bufferList[i].first;
+    networkId = bufferList[i].first;
     bufferId = bufferList[i].second;
-    if(!networks.contains(netId)) {
-      networks << netId;
+    if(droppedNetworkId == networkId) {
+      if(row < rowCount(parent)) {
+       BufferId beforeBufferId = parent.child(row, 0).data(NetworkModel::BufferIdRole).value<BufferId>();
+       pos = config()->bufferList().indexOf(beforeBufferId);
+      } else {
+       pos = config()->bufferList().count();
+      }
+
+      if(config()->bufferList().contains(bufferId)) {
+       if(config()->bufferList().indexOf(bufferId) < pos)
+         pos--;
+       config()->requestMoveBuffer(bufferId, pos);
+      } else {
+       config()->requestAddBuffer(bufferId, pos);
+      }
+
+    } else {
+      addBuffer(bufferId);
     }
-    addBuffer(bufferId);
   }
   return true;
 }
 
-void BufferViewFilter::addBuffer(const BufferId &bufferuid) {
-  if(!buffers.contains(bufferuid)) {
-    buffers << bufferuid;
-    invalidateFilter();
-  }
-}
-
-void BufferViewFilter::removeBuffer(const QModelIndex &index) {
-  if(!(mode & FullCustom))
-    return; // only custom buffers can be customized... obviously... :)
+void BufferViewFilter::addBuffer(const BufferId &bufferId) {
+  if(config()->bufferList().contains(bufferId))
+    return;
   
-  if(index.parent() == QModelIndex())
-    return; // only child elements can be deleted
-
-  bool lastBuffer = (rowCount(index.parent()) == 1);
-  NetworkId netId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
-  BufferId bufferuid = index.data(NetworkModel::BufferIdRole).value<BufferId>();
-
-  if(buffers.contains(bufferuid)) {
-    buffers.remove(bufferuid);
+  int pos = config()->bufferList().count();
+  bool lt;
+  for(int i = 0; i < config()->bufferList().count(); i++) {
+    if(config() && config()->sortAlphabetically())
+      lt = bufferIdLessThan(bufferId, config()->bufferList()[i]);
+    else
+      lt = bufferId < config()->bufferList()[i];
     
-    if(lastBuffer) {
-      networks.remove(netId);
-      Q_ASSERT(!networks.contains(netId));
+    if(lt) {
+      pos = i;
+      break;
     }
-
-    invalidateFilter();
   }
+  config()->requestAddBuffer(bufferId, pos);
+}
+
+void BufferViewFilter::removeBuffer(const QModelIndex &index) {
+  if(!config())
+    return;
   
+  BufferId bufferId = data(index, NetworkModel::BufferIdRole).value<BufferId>();
+  config()->requestRemoveBuffer(bufferId);
 }
 
 
 bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const {
-  BufferInfo::Type bufferType = (BufferInfo::Type) source_bufferIndex.data(NetworkModel::BufferTypeRole).toInt();
+  if(!_config)
+    return true;
   
-  if((mode & NoChannels) && bufferType == BufferInfo::ChannelBuffer)
+  if(!(_config->allowedBufferTypes() & (BufferInfo::Type)source_bufferIndex.data(NetworkModel::BufferTypeRole).toInt()))
     return false;
-  if((mode & NoQueries) && bufferType == BufferInfo::QueryBuffer)
-    return false;
-  if((mode & NoServers) && bufferType == BufferInfo::StatusBuffer)
+
+  if(_config->hideInactiveBuffers() && !source_bufferIndex.data(NetworkModel::ItemActiveRole).toBool())
     return false;
 
-//   bool isActive = source_bufferIndex.data(NetworkModel::BufferActiveRole).toBool();
-//   if((mode & NoActive) && isActive)
-//     return false;
-//   if((mode & NoInactive) && !isActive)
-//     return false;
+   if(_config->minimumActivity() > source_bufferIndex.data(NetworkModel::BufferActivityRole).toInt())
+    return false;
 
-  if((mode & FullCustom)) {
-    BufferId bufferuid = source_bufferIndex.data(NetworkModel::BufferIdRole).value<BufferId>();
-    return buffers.contains(bufferuid);
-  }
-    
-  return true;
+   BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value<BufferId>();
+   return _config->bufferList().contains(bufferId);
 }
 
 bool BufferViewFilter::filterAcceptNetwork(const QModelIndex &source_index) const {
-  NetworkId net = source_index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
-  return !((mode & (SomeNets | FullCustom)) && !networks.contains(net));
+  if(!config())
+    return true;
+
+  if(!config()->networkId().isValid()) {
+    return true;
+  } else {
+    return config()->networkId() == sourceModel()->data(source_index, NetworkModel::NetworkIdRole).value<NetworkId>();
+  }
 }
 
 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";
+    qWarning() << "filterAcceptsRow has been called with an invalid Child";
     return false;
   }
 
@@ -145,14 +181,35 @@ bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &sourc
     return filterAcceptBuffer(child);
 }
 
-bool BufferViewFilter::lessThan(const QModelIndex &left, const QModelIndex &right) const {
-  int lefttype = left.data(NetworkModel::BufferTypeRole).toInt();
-  int righttype = right.data(NetworkModel::BufferTypeRole).toInt();
+bool BufferViewFilter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const {
+  int itemType = sourceModel()->data(source_left, NetworkModel::ItemTypeRole).toInt();
+  switch(itemType) {
+  case NetworkModel::NetworkItemType:
+    return networkLessThan(source_left, source_right);
+  case NetworkModel::BufferItemType:
+    return bufferLessThan(source_left, source_right);
+  default:
+    return QSortFilterProxyModel::lessThan(source_left, source_right);    
+  }
+}
 
-  if(lefttype != righttype)
-    return lefttype < righttype;
+bool BufferViewFilter::bufferLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const {
+  BufferId leftBufferId = sourceModel()->data(source_left, NetworkModel::BufferIdRole).value<BufferId>();
+  BufferId rightBufferId = sourceModel()->data(source_right, NetworkModel::BufferIdRole).value<BufferId>();
+  if(config()) {
+    return config()->bufferList().indexOf(leftBufferId) < config()->bufferList().indexOf(rightBufferId);
+  } else
+    return leftBufferId < rightBufferId;
+}
+
+bool BufferViewFilter::networkLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const {
+  NetworkId leftNetworkId = sourceModel()->data(source_left, NetworkModel::NetworkIdRole).value<NetworkId>();
+  NetworkId rightNetworkId = sourceModel()->data(source_right, NetworkModel::NetworkIdRole).value<NetworkId>();
+
+  if(config() && config()->sortAlphabetically())
+    return QSortFilterProxyModel::lessThan(source_left, source_right);
   else
-    return QSortFilterProxyModel::lessThan(left, right);
+    return leftNetworkId < rightNetworkId;
 }
 
 QVariant BufferViewFilter::data(const QModelIndex &index, int role) const {
@@ -185,3 +242,25 @@ QVariant BufferViewFilter::foreground(const QModelIndex &index) const {
   return noActivity;
 
 }
+
+
+// ******************************
+//  Helper
+// ******************************
+bool bufferIdLessThan(const BufferId &left, const BufferId &right) {
+  Q_CHECK_PTR(Client::networkModel());
+  if(!Client::networkModel())
+    return true;
+  
+  QModelIndex leftIndex = Client::networkModel()->bufferIndex(left);
+  QModelIndex rightIndex = Client::networkModel()->bufferIndex(right);
+
+  int leftType = Client::networkModel()->data(leftIndex, NetworkModel::BufferTypeRole).toInt();
+  int rightType = Client::networkModel()->data(rightIndex, NetworkModel::BufferTypeRole).toInt();
+
+  if(leftType != rightType)
+    return leftType < rightType;
+  else
+    return Client::networkModel()->data(leftIndex, Qt::DisplayRole).toString() < Client::networkModel()->data(rightIndex, Qt::DisplayRole).toString();
+}
+
index f27352e..581cd6c 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#ifndef _BUFFERVIEWFILTER_H_
-#define _BUFFERVIEWFILTER_H_
+#ifndef BUFFERVIEWFILTER_H_
+#define BUFFERVIEWFILTER_H_
 
-#include <QFlags>
 #include <QDropEvent>
-#include <QSortFilterProxyModel>
+#include <QFlags>
+#include <QPointer>
 #include <QSet>
-// #include "buffer.h"
+#include <QSortFilterProxyModel>
+
 #include "types.h"
+#include "bufferviewconfig.h"
 
 /*****************************************
  * Buffer View Filter
@@ -47,32 +49,35 @@ public:
   };
   Q_DECLARE_FLAGS(Modes, Mode);
 
-  BufferViewFilter(QAbstractItemModel *model, const Modes &mode, const QList<NetworkId> &nets);
+  BufferViewFilter(QAbstractItemModel *model, BufferViewConfig *config = 0);
   
   virtual Qt::ItemFlags flags(const QModelIndex &index) const;
   virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
 
   QVariant data(const QModelIndex &index, int role) const;
   QVariant foreground(const QModelIndex &index) const;
-                                                                          
+
+  void setConfig(BufferViewConfig *config);
+  inline BufferViewConfig *config() const { return _config; }
+
 public slots:
   void removeBuffer(const QModelIndex &);
   
 protected:
   bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
-  bool lessThan(const QModelIndex &, const QModelIndex &) const;
-  
+  bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
+  bool bufferLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
+  bool networkLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
+
 private:
-  Modes mode;
-  QSet<NetworkId> networks;
-  QSet<BufferId> buffers;
+  QPointer<BufferViewConfig> _config;
 
   bool filterAcceptBuffer(const QModelIndex &) const;
   bool filterAcceptNetwork(const QModelIndex &) const;
   void addBuffer(const BufferId &);
-
 };
 Q_DECLARE_OPERATORS_FOR_FLAGS(BufferViewFilter::Modes)    
 
-#endif
+bool bufferIdLessThan(const BufferId &, const BufferId &);
 
+#endif // BUFFERVIEWFILTER_H_
index a294d20..5104970 100644 (file)
@@ -5,14 +5,14 @@
 
   quasselVersion = "0.2.0-beta1-pre";
   quasselDate = "2008-04-13";
-  quasselBuild = 729;
+  quasselBuild = 733;
 
   //! Minimum client build number the core needs
-  clientBuildNeeded = 642;
+  clientBuildNeeded = 731;
   clientVersionNeeded = quasselVersion;
 
   //! Minimum core build number the client needs
-  coreBuildNeeded = 642;
+  coreBuildNeeded = 731;
   coreVersionNeeded = quasselVersion;
 
 }