Buffer activity levels are now synced between clients, meaning that seeing a buffer...
authorManuel Nickschas <sputnick@quassel-irc.org>
Mon, 18 Feb 2008 00:33:29 +0000 (00:33 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 18 Feb 2008 00:33:29 +0000 (00:33 +0000)
will clear activity for that buffer in other clients too.
NOTE: Activity state is not yet remembered between core restarts,
      since there are still some database issues.

Client/core protocol updated, distclean mandatory.

25 files changed:
Quassel.kdevelop.filelist
src/client/buffer.cpp
src/client/buffer.h
src/client/buffermodel.cpp
src/client/buffermodel.h
src/client/client.cpp
src/client/client.h
src/client/clientsyncer.cpp
src/client/networkmodel.cpp
src/client/networkmodel.h
src/common/buffersyncer.cpp [new file with mode: 0644]
src/common/buffersyncer.h [new file with mode: 0644]
src/common/common.pri
src/common/message.cpp
src/common/network.cpp
src/core/coresession.cpp
src/core/coresession.h
src/core/networkconnection.cpp
src/qtui/bufferwidget.cpp
src/qtui/bufferwidget.h
src/qtui/mainwin.cpp
src/qtui/settingspages/networkssettingspage.cpp
src/uisupport/bufferviewfilter.cpp
src/uisupport/uistyle.cpp
version.inc

index b74b808..9d3b4b2 100644 (file)
@@ -1,5 +1,4 @@
 # KDevelop Custom Project File List
-Makefile
 build
 build/buildconf.pri
 build/contrib
@@ -53,6 +52,8 @@ src/client/treemodel.h
 src/common
 src/common/bufferinfo.cpp
 src/common/bufferinfo.h
+src/common/buffersyncer.cpp
+src/common/buffersyncer.h
 src/common/common.pri
 src/common/global.cpp
 src/common/global.h
@@ -139,6 +140,8 @@ src/qtopia/ui/editcoreacctdlg.ui
 src/qtopia/ui/mainwidget.ui
 src/qtopia/ui/nicklistwidget.ui
 src/qtui
+src/qtui/aboutdlg.cpp
+src/qtui/aboutdlg.h
 src/qtui/bufferwidget.cpp
 src/qtui/bufferwidget.h
 src/qtui/chatitem.cpp
@@ -155,10 +158,16 @@ src/qtui/chatwidget.cpp
 src/qtui/chatwidget.h
 src/qtui/configwizard.cpp
 src/qtui/configwizard.h
+src/qtui/coreconfigwizard.cpp
+src/qtui/coreconfigwizard.h
 src/qtui/coreconnectdlg.cpp
 src/qtui/coreconnectdlg.h
 src/qtui/debugconsole.cpp
 src/qtui/debugconsole.h
+src/qtui/inputwidget.cpp
+src/qtui/inputwidget.h
+src/qtui/jumpkeyhandler.cpp
+src/qtui/jumpkeyhandler.h
 src/qtui/mainwin.cpp
 src/qtui/mainwin.h
 src/qtui/nicklistwidget.cpp
@@ -172,22 +181,29 @@ src/qtui/qtuistyle.cpp
 src/qtui/qtuistyle.h
 src/qtui/settingsdlg.cpp
 src/qtui/settingsdlg.h
+src/qtui/settingspagedlg.cpp
+src/qtui/settingspagedlg.h
 src/qtui/settingspages
 src/qtui/settingspages/colorsettingspage.cpp
 src/qtui/settingspages/colorsettingspage.h
+src/qtui/settingspages/colorsettingspage.ui
 src/qtui/settingspages/createidentitydlg.ui
 src/qtui/settingspages/fontssettingspage.cpp
 src/qtui/settingspages/fontssettingspage.h
 src/qtui/settingspages/fontssettingspage.ui
 src/qtui/settingspages/generalsettingspage.cpp
 src/qtui/settingspages/generalsettingspage.h
+src/qtui/settingspages/generalsettingspage.ui
 src/qtui/settingspages/identitiessettingspage.cpp
 src/qtui/settingspages/identitiessettingspage.h
 src/qtui/settingspages/identitiessettingspage.ui
+src/qtui/settingspages/networkeditdlg.ui
 src/qtui/settingspages/networkssettingspage.cpp
 src/qtui/settingspages/networkssettingspage.h
 src/qtui/settingspages/networkssettingspage.ui
+src/qtui/settingspages/nickeditdlg.ui
 src/qtui/settingspages/saveidentitiesdlg.ui
+src/qtui/settingspages/servereditdlg.ui
 src/qtui/settingspages/settingspages.pri
 src/qtui/topicwidget.cpp
 src/qtui/topicwidget.h
@@ -201,7 +217,13 @@ src/qtui/ui/mainwin.ui
 src/qtui/ui/nicklistwidget.ui
 src/qtui/ui/settingsdlg.ui
 src/qtui/ui/topicwidget.ui
+src/qtui/verticaldock.cpp
+src/qtui/verticaldock.h
 src/uisupport
+src/uisupport/action.cpp
+src/uisupport/action.h
+src/uisupport/actioncollection.cpp
+src/uisupport/actioncollection.h
 src/uisupport/bufferview.cpp
 src/uisupport/bufferview.h
 src/uisupport/bufferviewfilter.cpp
@@ -212,6 +234,8 @@ src/uisupport/inputline.cpp
 src/uisupport/inputline.h
 src/uisupport/nickview.cpp
 src/uisupport/nickview.h
+src/uisupport/nickviewfilter.cpp
+src/uisupport/nickviewfilter.h
 src/uisupport/settingspage.cpp
 src/uisupport/settingspage.h
 src/uisupport/tabcompleter.cpp
index a316ae1..54bd81a 100644 (file)
 
 #include "buffer.h"
 
+#include "buffersyncer.h"
 #include "client.h"
+#include "networkmodel.h"
+#include "quasselui.h"
 #include "util.h"
 
 
 Buffer::Buffer(BufferInfo bufferid, QObject *parent)
   : QObject(parent),
-    _bufferInfo(bufferid)
+    _bufferInfo(bufferid),
+    _isVisible(false),
+    _activityLevel(NoActivity)
 {
+
 }
 
 BufferInfo Buffer::bufferInfo() const {
@@ -41,12 +47,14 @@ QList<AbstractUiMsg *> Buffer::contents() const {
 }
 
 void Buffer::appendMsg(const Message &msg) {
+  updateActivityLevel(msg);
   AbstractUiMsg *m = Client::layoutMsg(msg);
   layoutedMsgs.append(m);
   emit msgAppended(m);
 }
 
 void Buffer::prependMsg(const Message &msg) {
+  updateActivityLevel(msg);
   layoutQueue.append(msg);
 }
 
@@ -59,3 +67,33 @@ bool Buffer::layoutMsg() {
   return layoutQueue.count();
 }
 
+void Buffer::setVisible(bool visible) {
+  _isVisible = visible;
+  setActivityLevel(NoActivity);
+  if(!layoutedMsgs.count()) return;
+  setLastSeen(layoutedMsgs.last()->timestamp());
+}
+
+void Buffer::setLastSeen(const QDateTime &seen) {
+  if(seen.isValid() && seen > lastSeen()) { //qDebug() << "setting:" << bufferInfo().bufferName() << seen;
+    _lastSeen = seen;
+    Client::bufferSyncer()->requestSetLastSeen(bufferInfo().bufferId(), seen);
+    setActivityLevel(NoActivity);
+  }
+}
+
+void Buffer::setActivityLevel(ActivityLevel level) {
+  _activityLevel = level;
+  if(bufferInfo().bufferId() > 0) Client::networkModel()->setBufferActivity(bufferInfo(), level);
+}
+
+void Buffer::updateActivityLevel(const Message &msg) {
+  if(isVisible()) return;
+  if(lastSeen().isValid() && lastSeen() >= msg.timestamp()) return;
+
+  ActivityLevel level = activityLevel() | OtherActivity;
+  if(msg.type() == Message::Plain || msg.type() == Message::Notice) level |= NewMessage;
+  if(msg.flags() & Message::Highlight) level |= Highlight;
+
+  if(level != activityLevel()) setActivityLevel(level);
+}
index 9bf4b78..def01bd 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef _BUFFER_H_
 #define _BUFFER_H_
 
+#include <QDateTime>
+
 class AbstractUiMsg;
 class IrcChannel;
 class NickModel;
@@ -30,19 +32,29 @@ struct BufferState;
 #include "message.h"
 #include "bufferinfo.h"
 
-//!\brief Encapsulates the contents of a single channel, query or server status context.
-/** A Buffer maintains a list of existing nicks and their status.
+/// Encapsulates the contents of a single channel, query or server status context.
+/**
  */
 class Buffer : public QObject {
   Q_OBJECT
 
 public:
+  enum Activity {
+    NoActivity = 0x00,
+    OtherActivity = 0x01,
+    NewMessage = 0x02,
+    Highlight = 0x40
+  };
+  Q_DECLARE_FLAGS(ActivityLevel, Activity)
+
   Buffer(BufferInfo, QObject *parent = 0);
 
   BufferInfo bufferInfo() const;
-
   QList<AbstractUiMsg *> contents() const;
-  
+  inline bool isVisible() const { return _isVisible; }
+  inline QDateTime lastSeen() const { return _lastSeen; }
+  inline ActivityLevel activityLevel() const { return _activityLevel; }
+
 signals:
   void msgAppended(AbstractUiMsg *);
   void msgPrepended(AbstractUiMsg *);
@@ -52,13 +64,22 @@ public slots:
   void appendMsg(const Message &);
   void prependMsg(const Message &);
   bool layoutMsg();
+  void setVisible(bool visible);
+  void setLastSeen(const QDateTime &);
+  void setActivityLevel(ActivityLevel level);
 
 private:
   BufferInfo _bufferInfo;
+  bool _isVisible;
+  QDateTime _lastSeen;
+  ActivityLevel _activityLevel;
 
   QList<Message> layoutQueue;
   QList<AbstractUiMsg *> layoutedMsgs;
 
+  void updateActivityLevel(const Message &msg);
 };
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(Buffer::ActivityLevel)
+
 #endif
index 4b78ea9..e0f80ed 100644 (file)
@@ -35,8 +35,6 @@ BufferModel::BufferModel(NetworkModel *parent)
   // initialize the Property Mapper
   _propertyMapper.setModel(this);
   _selectionModelSynchronizer.addRegularSelectionModel(_propertyMapper.selectionModel());
-  connect(_propertyMapper.selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
-         this, SLOT(currentChanged(QModelIndex, QModelIndex)));
 }
 
 BufferModel::~BufferModel() {
@@ -72,10 +70,3 @@ void BufferModel::mapProperty(int column, int role, QObject *target, const QByte
 QModelIndex BufferModel::currentIndex() {
   return propertyMapper()->selectionModel()->currentIndex();
 }
-
-void BufferModel::currentChanged(const QModelIndex &current, const QModelIndex &previous) {
-  Q_UNUSED(current);
-  setData(current, QDateTime::currentDateTime(), NetworkModel::LastSeenRole);
-  setData(previous, QDateTime::currentDateTime(), NetworkModel::LastSeenRole);
-  setData(previous, qVariantFromValue((int)BufferItem::NoActivity), NetworkModel::BufferActivityRole);
-}
index 80f1ec0..2d6f4b4 100644 (file)
@@ -51,9 +51,6 @@ public:
 
   QModelIndex currentIndex();
 
-private slots:
-  void currentChanged(const QModelIndex &current, const QModelIndex &previous);
-  
 private:
   SelectionModelSynchronizer _selectionModelSynchronizer;
   ModelPropertyMapper _propertyMapper;
index 4d716ed..a2473b1 100644 (file)
@@ -21,6 +21,7 @@
 #include "client.h"
 
 #include "bufferinfo.h"
+#include "buffersyncer.h"
 #include "global.h"
 #include "identity.h"
 #include "ircchannel.h"
@@ -61,6 +62,7 @@ Client::Client(QObject *parent)
     mainUi(0),
     _networkModel(0),
     _bufferModel(0),
+    _bufferSyncer(0),
     _connectedToCore(false),
     _syncedToCore(false)
 {
@@ -164,23 +166,6 @@ Buffer *Client::buffer(BufferInfo bufferInfo) {
   return buff;
 }
 
-Buffer *Client::monitorBuffer() {
-  return instance()->_monitorBuffer;
-}
-
-
-NetworkModel *Client::networkModel() {
-  return instance()->_networkModel;
-}
-
-BufferModel *Client::bufferModel() {
-  return instance()->_bufferModel;
-}
-
-SignalProxy *Client::signalProxy() {
-  return instance()->_signalProxy;
-}
-
 bool Client::isConnected() {
   return instance()->_connectedToCore;
 }
@@ -295,6 +280,12 @@ void Client::setConnectedToCore(QIODevice *sock, AccountId id) {
 }
 
 void Client::setSyncedToCore() {
+    // create buffersyncer
+  Q_ASSERT(!_bufferSyncer);
+  _bufferSyncer = new BufferSyncer(this);
+  connect(bufferSyncer(), SIGNAL(lastSeenSet(BufferId, const QDateTime &)), this, SLOT(updateLastSeen(BufferId, const QDateTime &)));
+  signalProxy()->synchronize(bufferSyncer());
+
   _syncedToCore = true;
   emit connected();
   emit coreConnectionStateChanged(true);
@@ -312,8 +303,19 @@ void Client::disconnectFromCore() {
   emit coreConnectionStateChanged(false);
 
   // Clear internal data. Hopefully nothing relies on it at this point.
+  _bufferSyncer->deleteLater();
+  _bufferSyncer = 0;
   _networkModel->clear();
 
+  QHash<BufferId, Buffer *>::iterator bufferIter =  _buffers.begin();
+  while(bufferIter != _buffers.end()) {
+    Buffer *buffer = bufferIter.value();
+    disconnect(buffer, SIGNAL(destroyed()), this, 0);
+    bufferIter = _buffers.erase(bufferIter);
+    buffer->deleteLater();
+  }
+  Q_ASSERT(_buffers.isEmpty());
+
   QHash<NetworkId, Network*>::iterator netIter = _networks.begin();
   while(netIter != _networks.end()) {
     Network *net = netIter.value();
@@ -324,15 +326,6 @@ void Client::disconnectFromCore() {
   }
   Q_ASSERT(_networks.isEmpty());
 
-  QHash<BufferId, Buffer *>::iterator bufferIter =  _buffers.begin();
-  while(bufferIter != _buffers.end()) {
-    Buffer *buffer = bufferIter.value();
-    disconnect(buffer, SIGNAL(destroyed()), this, 0);
-    bufferIter = _buffers.erase(bufferIter);
-    buffer->deleteLater();
-  }
-  Q_ASSERT(_buffers.isEmpty());
-
   QHash<IdentityId, Identity*>::iterator idIter = _identities.begin();
   while(idIter != _identities.end()) {
     Identity *id = idIter.value();
@@ -394,11 +387,11 @@ void Client::recvMessage(const Message &message) {
   } else {
     b = buffer(msg.bufferInfo());
   }
-  
+
   checkForHighlight(msg);
   b->appendMsg(msg);
-  networkModel()->updateBufferActivity(msg);
-  
+  //bufferModel()->updateBufferActivity(msg);
+
   if(msg.type() == Message::Plain || msg.type() == Message::Notice || msg.type() == Message::Action) {
     const Network *net = network(msg.bufferInfo().networkId());
     QString networkName = net != 0
@@ -408,7 +401,6 @@ void Client::recvMessage(const Message &message) {
     Message mmsg = Message(msg.timestamp(), msg.bufferInfo(), msg.type(), msg.text(), sender, msg.flags());
     monitorBuffer()->appendMsg(mmsg);
   }
-
 }
 
 void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) {
@@ -421,7 +413,7 @@ void Client::recvBacklogData(BufferInfo id, QVariantList msgs, bool /*done*/) {
     Message msg = v.value<Message>();
     checkForHighlight(msg);
     b->prependMsg(msg);
-    networkModel()->updateBufferActivity(msg);
+    //networkModel()->updateBufferActivity(msg);
     if(!layoutQueue.contains(b)) layoutQueue.append(b);
   }
   if(layoutQueue.count() && !layoutTimer->isActive()) layoutTimer->start();
@@ -442,7 +434,7 @@ AbstractUiMsg *Client::layoutMsg(const Message &msg) {
   return instance()->mainUi->layoutMsg(msg);
 }
 
-void Client::checkForHighlight(Message &msg) const {
+void Client::checkForHighlight(Message &msg) {
   const Network *net = network(msg.bufferInfo().networkId());
   if(net && !net->myNick().isEmpty()) {
     QRegExp nickRegExp("^(.*\\W)?" + QRegExp::escape(net->myNick()) + "(\\W.*)?$");
@@ -450,3 +442,19 @@ void Client::checkForHighlight(Message &msg) const {
       msg.setFlags(msg.flags() | Message::Highlight);
   }
 }
+
+void Client::updateLastSeen(BufferId id, const QDateTime &lastSeen) {
+  Buffer *b = buffer(id);
+  if(!b) {
+    qWarning() << "Client::updateLastSeen(): Unknown buffer" << id;
+    return;
+  }
+  b->setLastSeen(lastSeen);
+}
+
+void Client::setBufferLastSeen(BufferId id, const QDateTime &lastSeen) {
+  if(!bufferSyncer()) return;
+  bufferSyncer()->requestSetLastSeen(id, lastSeen);
+}
+
+
index c1463e5..feb9f16 100644 (file)
@@ -27,6 +27,7 @@
 #include <QPointer>
 
 #include "buffer.h" // needed for activity lvl
+
 class BufferInfo;
 class Message;
 
@@ -38,6 +39,7 @@ class AbstractUi;
 class AbstractUiMsg;
 class NetworkModel;
 class BufferModel;
+class BufferSyncer;
 class IrcUser;
 class IrcChannel;
 class SignalProxy;
@@ -58,7 +60,7 @@ public:
   static QList<Buffer *> buffers();
   static Buffer *buffer(BufferId bufferUid);
   static Buffer *buffer(BufferInfo);
-  static Buffer *monitorBuffer();
+  static inline Buffer *monitorBuffer() { return instance()->_monitorBuffer; }
 
   static QList<NetworkId> networkIds();
   static const Network * network(NetworkId);
@@ -88,9 +90,10 @@ public:
   static void updateNetwork(const NetworkInfo &info);
   static void removeNetwork(NetworkId id);
 
-  static NetworkModel *networkModel();
-  static BufferModel *bufferModel();
-  static SignalProxy *signalProxy();
+  static inline NetworkModel *networkModel() { return instance()->_networkModel; }
+  static inline BufferModel *bufferModel() { return instance()->_bufferModel; }
+  static inline SignalProxy *signalProxy() { return instance()->_signalProxy; }
+  static inline BufferSyncer *bufferSyncer() { return instance()->_bufferSyncer; }
 
   static AccountId currentCoreAccount();
 
@@ -103,8 +106,9 @@ public:
 
   enum ClientMode { LocalCore, RemoteCore };
 
-  void checkForHighlight(Message &msg) const;
-  
+  static void checkForHighlight(Message &msg);
+  static void setBufferLastSeen(BufferId id, const QDateTime &seen); // this is synced to core and other clients
+
 signals:
   void sendInput(BufferInfo, QString message);
   void showBuffer(Buffer *);
@@ -163,6 +167,7 @@ private slots:
   void recvStatusMsg(QString network, QString message);
   void recvBacklogData(BufferInfo, QVariantList, bool);
   void updateBufferInfo(BufferInfo);
+  void updateLastSeen(BufferId id, const QDateTime &lastSeen);
 
   void layoutMsg();
 
@@ -188,10 +193,12 @@ private:
   static QPointer<Client> instanceptr;
 
   QPointer<QIODevice> socket;
-  QPointer<SignalProxy> _signalProxy;
-  QPointer<AbstractUi> mainUi;
-  QPointer<NetworkModel> _networkModel;
-  QPointer<BufferModel> _bufferModel;
+
+  SignalProxy * _signalProxy;
+  AbstractUi * mainUi;
+  NetworkModel * _networkModel;
+  BufferModel * _bufferModel;
+  BufferSyncer * _bufferSyncer;
 
   ClientMode clientMode;
 
index 29b4973..601bff0 100644 (file)
@@ -172,7 +172,7 @@ void ClientSyncer::clientInitAck(const QVariantMap &msg) {
   // Core has accepted our version info and sent its own. Let's see if we accept it as well...
   if(msg["CoreBuild"].toUInt() < Global::coreBuildNeeded) {
     emit connectionError(tr("<b>The Quassel Core you are trying to connect to is too old!</b><br>"
-        "Need at least a Core Version %1 (Build >= %2) to connect.").arg(Global::quasselVersion).arg(Global::quasselBuild));
+        "Need at least a Core Version %1 (Build >= %2) to connect.").arg(Global::quasselVersion).arg(Global::coreBuildNeeded));
     disconnectFromCore();
     return;
   }
index 0060447..be13afd 100644 (file)
 BufferItem::BufferItem(BufferInfo bufferInfo, AbstractTreeItem *parent)
   : PropertyMapItem(QStringList() << "bufferName" << "topic" << "nickCount", parent),
     _bufferInfo(bufferInfo),
-    _activity(NoActivity)
+    _activity(Buffer::NoActivity)
 {
   Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
   if(bufferType() == BufferInfo::QueryBuffer)
     flags |= Qt::ItemIsDropEnabled;
   setFlags(flags);
-
-  _lastSeen = BufferSettings(bufferInfo.bufferId()).lastSeen();
 }
 
 const BufferInfo &BufferItem::bufferInfo() const {
@@ -70,18 +68,14 @@ bool BufferItem::isActive() const {
     return qobject_cast<NetworkItem *>(parent())->isActive();
 }
 
-BufferItem::ActivityLevel BufferItem::activity() const {
-  return _activity;
-}
-
-bool BufferItem::setActivity(const ActivityLevel &level) {
+bool BufferItem::setActivityLevel(Buffer::ActivityLevel level) {
   _activity = level;
   emit dataChanged();
   return true;
 }
 
-void BufferItem::updateActivity(const ActivityLevel &level) {
-  ActivityLevel oldActivity = _activity;
+void BufferItem::updateActivityLevel(Buffer::ActivityLevel level) {
+  Buffer::ActivityLevel oldActivity = _activity;
   _activity |= level;
   if(oldActivity != _activity)
     emit dataChanged();
@@ -102,7 +96,7 @@ QVariant BufferItem::data(int column, int role) const {
   case NetworkModel::ItemActiveRole:
     return isActive();
   case NetworkModel::BufferActivityRole:
-    return qVariantFromValue((int)activity());
+    return (int)activityLevel();
   default:
     return PropertyMapItem::data(column, role);
   }
@@ -111,9 +105,7 @@ QVariant BufferItem::data(int column, int role) const {
 bool BufferItem::setData(int column, const QVariant &value, int role) {
   switch(role) {
   case NetworkModel::BufferActivityRole:
-    return setActivity((ActivityLevel)value.toInt());
-  case NetworkModel::LastSeenRole:
-    return setLastSeen();
+    return setActivityLevel((Buffer::ActivityLevel)value.toInt());
   default:
     return PropertyMapItem::setData(column, value, role);
   }
@@ -271,11 +263,14 @@ void BufferItem::userModeChanged(IrcUser *ircUser) {
   addUserToCategory(ircUser);
 }
 
+/*
 void BufferItem::setLastMsgInsert(QDateTime msgDate) {
   if(msgDate.isValid() && msgDate > _lastMsgInsert)
     _lastMsgInsert = msgDate;
 }
-
+*/
+/*
+// FIXME emit dataChanged()
 bool BufferItem::setLastSeen() {
   if(_lastSeen > _lastMsgInsert)
     return false;
@@ -288,7 +283,7 @@ bool BufferItem::setLastSeen() {
 QDateTime BufferItem::lastSeen() {
   return _lastSeen;
 }
-
+*/
 /*****************************************
 *  Network Items
 *****************************************/
@@ -743,6 +738,7 @@ void NetworkModel::bufferUpdated(BufferInfo bufferInfo) {
   emit dataChanged(itemindex, itemindex);
 }
 
+/*
 void NetworkModel::updateBufferActivity(const Message &msg) {
   BufferItem *buff = bufferItem(msg.bufferInfo());
   Q_ASSERT(buff);
@@ -761,6 +757,14 @@ void NetworkModel::updateBufferActivity(const Message &msg) {
 
   bufferItem(msg.bufferInfo())->updateActivity(level);
 }
+*/
+
+void NetworkModel::setBufferActivity(const BufferInfo &info, Buffer::ActivityLevel level) {
+  BufferItem *buff = bufferItem(info);
+  Q_ASSERT(buff);
+
+  buff->setActivityLevel(level);
+}
 
 const Network *NetworkModel::networkByIndex(const QModelIndex &index) const {
   QVariant netVariant = index.data(NetworkIdRole);
index 8c36233..961c1ca 100644 (file)
@@ -62,23 +62,15 @@ public:
   QString bufferName() const;
   QString topic() const;
   int nickCount() const;
-  
+
   bool isStatusBuffer() const;
   BufferInfo::Type bufferType() const;
 
   bool isActive() const;
-  
-  enum Activity {
-    NoActivity = 0x00,
-    OtherActivity = 0x01,
-    NewMessage = 0x02,
-    Highlight = 0x40
-  };
-  Q_DECLARE_FLAGS(ActivityLevel, Activity)
 
-  ActivityLevel activity() const;
-  bool setActivity(const ActivityLevel &level);
-  void updateActivity(const ActivityLevel &level);
+  inline Buffer::ActivityLevel activityLevel() const { return _activity; }
+  bool setActivityLevel(Buffer::ActivityLevel level);
+  void updateActivityLevel(Buffer::ActivityLevel level);
 
   void setLastMsgInsert(QDateTime msgDate);
   bool setLastSeen();
@@ -92,20 +84,18 @@ public slots:
   void addUserToCategory(IrcUser *ircUser);
   void removeUserFromCategory(IrcUser *ircUser);
   void userModeChanged(IrcUser *ircUser);
-                                        
+
 private slots:
   void ircChannelDestroyed();
   void ircUserDestroyed();
-  
+
 private:
   BufferInfo _bufferInfo;
-  ActivityLevel _activity;
-  QDateTime _lastMsgInsert;
-  QDateTime _lastSeen;
+  Buffer::ActivityLevel _activity;
 
   QPointer<IrcChannel> _ircChannel;
 };
-Q_DECLARE_OPERATORS_FOR_FLAGS(BufferItem::ActivityLevel)
+
 
 /*****************************************
  *  Network Items
@@ -215,8 +205,7 @@ public:
     BufferIdRole,
     NetworkIdRole,
     BufferInfoRole,
-    ItemTypeRole,
-    LastSeenRole
+    ItemTypeRole
   };
 
   enum itemTypes {
@@ -225,7 +214,7 @@ public:
     UserCategoryItemType,
     IrcUserItemType
   };
-    
+
   NetworkModel(QObject *parent = 0);
   static QList<QVariant> defaultHeader();
 
@@ -244,9 +233,11 @@ public:
 
   const Network *networkByIndex(const QModelIndex &index) const;
 
+  Buffer::ActivityLevel bufferActivity(const BufferInfo &buffer) const;
+
 public slots:
   void bufferUpdated(BufferInfo bufferInfo);
-  void updateBufferActivity(const Message &msg);
+  void setBufferActivity(const BufferInfo &buffer, Buffer::ActivityLevel activity);
   void networkRemoved(const NetworkId &networkId);
   
 private:
diff --git a/src/common/buffersyncer.cpp b/src/common/buffersyncer.cpp
new file mode 100644 (file)
index 0000000..cf16d8d
--- /dev/null
@@ -0,0 +1,62 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "buffersyncer.h"
+
+BufferSyncer::BufferSyncer(QObject *parent) : SyncableObject(parent) {
+
+
+}
+
+
+QDateTime BufferSyncer::lastSeen(BufferId buffer) const {
+  if(_lastSeen.contains(buffer)) return _lastSeen[buffer];
+  return QDateTime();
+}
+
+bool BufferSyncer::setLastSeen(BufferId buffer, const QDateTime &time) {
+  if(_lastSeen[buffer] < time) {
+    _lastSeen[buffer] = time;
+    emit lastSeenSet(buffer, time);
+    return true;
+  }
+  return false;
+}
+
+QVariantList BufferSyncer::initLastSeen() const {
+  QVariantList list;
+  foreach(BufferId id, _lastSeen.keys()) {
+    list << QVariant::fromValue<BufferId>(id) << _lastSeen[id];
+  }
+  return list;
+}
+
+void BufferSyncer::initSetLastSeen(const QVariantList &list) {
+  _lastSeen.clear();
+  Q_ASSERT(list.count() % 2 == 0);
+  for(int i = 0; i < list.count(); i += 2) {
+    setLastSeen(list[i].value<BufferId>(), list[i+1].toDateTime());
+  }
+}
+
+void BufferSyncer::requestSetLastSeen(BufferId buffer, const QDateTime &time) {
+  if(setLastSeen(buffer, time)) emit setLastSeenRequested(buffer, time);
+}
+
diff --git a/src/common/buffersyncer.h b/src/common/buffersyncer.h
new file mode 100644 (file)
index 0000000..785c2be
--- /dev/null
@@ -0,0 +1,54 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef BUFFERSYNCER_H_
+#define BUFFERSYNCER_H_
+
+#include <QDateTime>
+
+#include "syncableobject.h"
+#include "types.h"
+
+class BufferSyncer : public SyncableObject {
+  Q_OBJECT
+
+  public:
+    explicit BufferSyncer(QObject *parent);
+
+    QDateTime lastSeen(BufferId buffer) const;
+
+  public slots:
+    QVariantList initLastSeen() const;
+    void initSetLastSeen(const QVariantList &);
+
+    void requestSetLastSeen(BufferId buffer, const QDateTime &time);
+
+  signals:
+    void lastSeenSet(BufferId buffer, const QDateTime &time);
+    void setLastSeenRequested(BufferId buffer, const QDateTime &time);
+
+  private slots:
+    bool setLastSeen(BufferId buffer, const QDateTime &time);
+
+  private:
+    QMap<BufferId, QDateTime> _lastSeen;
+};
+
+#endif
index 0555aee..98e9a3e 100644 (file)
@@ -1,6 +1,6 @@
-DEPMOD = 
+DEPMOD =
 QT_MOD = network
-SRCS += bufferinfo.cpp global.cpp identity.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp syncableobject.cpp \
+SRCS += bufferinfo.cpp buffersyncer.cpp global.cpp identity.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp syncableobject.cpp \
         util.cpp network.cpp ircuser.cpp ircchannel.cpp
-HDRS += bufferinfo.h global.h identity.h logger.h message.h settings.h signalproxy.h syncableobject.h \
+HDRS += bufferinfo.h buffersyncer.h global.h identity.h logger.h message.h settings.h signalproxy.h syncableobject.h \
         util.h network.h ircuser.h ircchannel.h types.h
index 4a6ba91..91e1f49 100644 (file)
@@ -112,9 +112,9 @@ void Message::format() {
     case Message::Error:
       s = tr("%De*"); t = tr("%De%1").arg(txt); break;
     case Message::Join:
-      s = tr("%Dj-->"); t = tr("%Dj%DN%DU%1%DU%DN %DH(%2@%3)%DH has joined %DC%DU%4%DU%DC").arg(nick, user, host, bufferName); break;
+      s = tr("%Dj-->"); t = tr("%Dj%DN%1%DN %DH(%2@%3)%DH has joined %DC%4%DC").arg(nick, user, host, bufferName); break;
     case Message::Part:
-      s = tr("%Dp<--"); t = tr("%Dp%DN%DU%1%DU%DN %DH(%2@%3)%DH has left %DC%DU%4%DU%DC").arg(nick, user, host, bufferName);
+      s = tr("%Dp<--"); t = tr("%Dp%DN%1%DN %DH(%2@%3)%DH has left %DC%4%DC").arg(nick, user, host, bufferName);
       if(!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt);
       break;
     case Message::Quit:
@@ -126,23 +126,23 @@ void Message::format() {
     QString victim = txt.section(" ", 0, 0);
         //if(victim == ui.ownNick->currentText()) victim = tr("you");
     QString kickmsg = txt.section(" ", 1);
-    t = tr("%Dk%DN%DU%1%DU%DN has kicked %DN%DU%2%DU%DN from %DC%DU%3%DU%DC").arg(nick).arg(victim).arg(bufferName);
+    t = tr("%Dk%DN%1%DN has kicked %DN%2%DN from %DC%3%DC").arg(nick).arg(victim).arg(bufferName);
     if(!kickmsg.isEmpty()) t = QString("%1 (%2)").arg(t).arg(kickmsg);
     }
     break;
     case Message::Nick:
       s = tr("%Dr<->");
       if(nick == text()) t = tr("%DrYou are now known as %DN%1%DN").arg(txt);
-      else t = tr("%Dr%DN%1%DN is now known as %DN%DU%2%DU%DN").arg(nick, txt);
+      else t = tr("%Dr%DN%1%DN is now known as %DN%2%DN").arg(nick, txt);
       break;
     case Message::Mode:
       s = tr("%Dm***");
       if(nick.isEmpty()) t = tr("%DmUser mode: %DM%1%DM").arg(text());
-      else t = tr("%DmMode %DM%1%DM by %DN%DU%2%DU%DN").arg(txt, nick);
+      else t = tr("%DmMode %DM%1%DM by %DN%2%DN").arg(txt, nick);
       break;
     case Message::Action:
       s = tr("%Da-*-");
-      t = tr("%Da%DN%DU%1%DU%DN %2").arg(nick).arg(txt);
+      t = tr("%Da%DN%1%DN %2").arg(nick).arg(txt);
       break;
     default:
       s = tr("%De%1").arg(sender());
index 3162bd4..b565a78 100644 (file)
@@ -725,7 +725,7 @@ void Network::requestConnect() const {
   if(proxy()->proxyMode() == SignalProxy::Client) emit connectRequested(); // on the client this triggers calling this slot on the core
   else {
     if(connectionState() != Disconnected) {
-      qWarning() << "Requesting connect while not being disconnected!";
+      qWarning() << "Requesting connect while already being connected!";
       return;
     }
     emit connectRequested(networkId());  // and this is for CoreSession :)
index d39498a..22ed212 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include <QtScript>
+
 #include "core.h"
 #include "coresession.h"
 #include "networkconnection.h"
 
 #include "signalproxy.h"
+#include "buffersyncer.h"
 #include "storage.h"
 
 #include "network.h"
 #include "util.h"
 #include "coreusersettings.h"
 
-#include <QtScript>
-
 CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObject(parent),
     _user(uid),
     _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
+    _bufferSyncer(new BufferSyncer(this)),
     scriptEngine(new QScriptEngine(this))
 {
 
@@ -67,6 +69,12 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObje
   loadSettings();
   initScriptEngine();
 
+  // init BufferSyncer
+  //QHash<BufferId, QDateTime> lastSeenHash = Core::bufferLastSeenDates(user());
+  //foreach(BufferId id, lastSeenHash.keys()) _bufferSyncer->requestSetLastSeen(id, lastSeenHash[id]);
+  // FIXME connect(_bufferSyncer, SIGNAL(lastSeenSet(BufferId, const QDateTime &)), this, SLOT(storeBufferLastSeen(BufferId, const QDateTime &)));
+  p->synchronize(_bufferSyncer);
+
   // Restore session state
   if(restoreState) restoreSessionState();
 
@@ -268,8 +276,8 @@ void CoreSession::networkDisconnected(NetworkId networkid) {
   // FIXME
   // connection should only go away on explicit /part, and handle reconnections etcpp internally otherwise
 
-  Q_ASSERT(_connections.contains(networkid));
-  _connections.take(networkid)->deleteLater();
+  //Q_ASSERT(_connections.contains(networkid));
+  if(_connections.contains(networkid)) _connections.take(networkid)->deleteLater();
 }
 
 // FIXME switch to BufferId
@@ -333,6 +341,10 @@ QVariant CoreSession::sessionState() {
   return v;
 }
 
+void CoreSession::storeBufferLastSeen(BufferId buffer, const QDateTime &lastSeen) {
+  Core::setBufferLastSeen(user(), buffer, lastSeen);
+}
+
 void CoreSession::sendBacklog(BufferInfo id, QVariant v1, QVariant v2) {
   QList<QVariant> log;
   QList<Message> msglist;
@@ -436,7 +448,7 @@ void CoreSession::updateNetwork(const NetworkInfo &info) {
     qWarning() << "Update request for unknown network received!";
     return;
   }
-  _networks[info.networkId]->setNetworkInfo(info);
+  _networks[info.networkId]->setNetworkInfo(info); qDebug() << "unlim" << info.unlimitedReconnectRetries << _networks[info.networkId]->unlimitedReconnectRetries();
   Core::updateNetwork(user(), info);
 }
 
index 51c14a7..640ea99 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "message.h"
 
+class BufferSyncer;
 class Identity;
 class NetworkConnection;
 class Network;
@@ -146,6 +147,8 @@ private slots:
    */
   void updateBufferInfo(UserId user, const BufferInfo &bufferInfo);
 
+  void storeBufferLastSeen(BufferId buffer, const QDateTime &lastSeen);
+
   void scriptRequest(QString script);
 
 private:
@@ -160,6 +163,8 @@ private:
   QHash<NetworkId, Network *> _networksToRemove;
   QHash<IdentityId, Identity *> _identities;
 
+  BufferSyncer *_bufferSyncer;
+
   QScriptEngine *scriptEngine;
 
 };
index 381e99d..6ac715c 100644 (file)
@@ -204,7 +204,10 @@ QVariant NetworkConnection::state() const {
 }
 
 void NetworkConnection::disconnectFromIrc() {
-  socket.disconnectFromHost();
+  if(socket.state() < QAbstractSocket::ConnectedState) {
+    setConnectionState(Network::Disconnected);
+    socketDisconnected();
+  } else socket.disconnectFromHost();
 }
 
 void NetworkConnection::socketHasData() {
index 99a2f30..8831a28 100644 (file)
@@ -31,7 +31,8 @@
 BufferWidget::BufferWidget(QWidget *parent)
   : QWidget(parent),
     _bufferModel(0),
-    _selectionModel(0)
+    _selectionModel(0),
+    _currentBuffer(0)
 {
   ui.setupUi(this);
 }
@@ -95,6 +96,7 @@ void BufferWidget::removeBuffer(BufferId bufferId) {
   if(!_chatWidgets.contains(bufferId))
     return;
 
+  if(Client::buffer(bufferId)) Client::buffer(bufferId)->setVisible(false);
   ChatWidget *chatWidget = _chatWidgets.take(bufferId);
   ui.stackedWidget->removeWidget(chatWidget);
   chatWidget->deleteLater();
@@ -107,20 +109,21 @@ void BufferWidget::currentChanged(const QModelIndex &current, const QModelIndex
   variant = current.data(NetworkModel::BufferIdRole);
   if(!variant.isValid())
     return;
-  
-  setCurrentBuffer(qVariantValue<BufferId>(variant));
+  setCurrentBuffer(variant.value<BufferId>());
 }
 
 void BufferWidget::setCurrentBuffer(BufferId bufferId) {
-  ChatWidget *chatWidget;
+  ChatWidget *chatWidget = 0;
+  Buffer *buf = Client::buffer(bufferId);
+  if(!buf) {
+    qWarning() << "BufferWidget::setBuffer(BufferId): Can't show unknown Buffer:" << bufferId;
+    return;
+  }
+  Buffer *prevBuffer = Client::buffer(currentBuffer());
+  if(prevBuffer) prevBuffer->setVisible(false);
   if(_chatWidgets.contains(bufferId)) {
      chatWidget = _chatWidgets[bufferId];
   } else {
-    Buffer *buf = Client::buffer(bufferId);
-    if(!buf) {
-      qWarning() << "BufferWidget::setBuffer(BufferId): Can't show unknown Buffer:" << bufferId;
-      return;
-    }
     chatWidget = new ChatWidget(this);
     chatWidget->init(bufferId);
     QList<ChatLine *> lines;
@@ -135,7 +138,9 @@ void BufferWidget::setCurrentBuffer(BufferId bufferId) {
     ui.stackedWidget->addWidget(chatWidget);
     chatWidget->setFocusProxy(this);
   }
+  _currentBuffer = bufferId;
   ui.stackedWidget->setCurrentWidget(chatWidget);
+  buf->setVisible(true);
   setFocus();
 }
 
index b9235f9..e484a18 100644 (file)
@@ -49,6 +49,8 @@ public:
 
   inline QItemSelectionModel *selectionModel() const { return _selectionModel; }
   void setSelectionModel(QItemSelectionModel *selectionModel);
+
+  inline BufferId currentBuffer() const { return _currentBuffer; }
   
 protected slots:
 //   virtual void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
@@ -70,6 +72,8 @@ private:
 
   QPointer<BufferModel> _bufferModel;
   QPointer<QItemSelectionModel> _selectionModel;
+
+  BufferId _currentBuffer;
 };
 
 #endif
index 1b73804..5b43087 100644 (file)
@@ -267,7 +267,7 @@ void MainWin::setupSystray() {
   systray = new QSystemTrayIcon(this);
   systray->setIcon(QIcon(":/icons/quassel-icon.png"));
 
-  QString toolTip("left click to minimize the quassel client to tray");
+  QString toolTip("Left click to minimize the Quassel Client to tray");
   systray->setToolTip(toolTip);
 
   systrayMenu = new QMenu(this);
@@ -430,13 +430,13 @@ void MainWin::clientNetworkUpdated() {
       a->setText(net->networkName());
       if(net->connectionState() == Network::Initialized) {
         a->setIcon(QIcon(":/16x16/actions/network-connect"));
-        a->setEnabled(true);
+        //a->setEnabled(true);
       } else if(net->connectionState() == Network::Disconnected) {
         a->setIcon(QIcon(":/16x16/actions/network-disconnect"));
-        a->setEnabled(true);
+        //a->setEnabled(true);
       } else {
         a->setIcon(QIcon(":/16x16/actions/gear"));
-        a->setEnabled(false);
+        //a->setEnabled(false);
       }
       return;
     }
index 88980f6..65301f0 100644 (file)
@@ -282,7 +282,7 @@ void NetworksSettingsPage::clientIdentityRemoved(IdentityId id) {
   if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]);
   //ui.identityList->removeItem(ui.identityList->findData(id.toInt()));
   foreach(NetworkInfo info, networkInfos.values()) {
-    qDebug() << info.networkName << info.networkId << info.identity;
+    //qDebug() << info.networkName << info.networkId << info.identity;
     if(info.identity == id) {
       if(info.networkId == currentId) ui.identityList->setCurrentIndex(0);
       info.identity = 1; // set to default
@@ -327,9 +327,9 @@ void NetworksSettingsPage::clientNetworkRemoved(NetworkId id) {
   if(id == currentId) displayNetwork(0);
   NetworkInfo info = networkInfos.take(id);
   QList<QListWidgetItem *> items = ui.networkList->findItems(info.networkName, Qt::MatchExactly);
-  if(items.count()) {
-    Q_ASSERT(items[0]->data(Qt::UserRole).value<NetworkId>() == id);
-    delete ui.networkList->takeItem(ui.networkList->row(items[0]));
+  foreach(QListWidgetItem *item, items) {
+    if(item->data(Qt::UserRole).value<NetworkId>() == id)
+      delete ui.networkList->takeItem(ui.networkList->row(item));
   }
   setWidgetStates();
   widgetHasChanged();
index 22b5141..bae2522 100644 (file)
@@ -173,13 +173,13 @@ QVariant BufferViewFilter::foreground(const QModelIndex &index) const {
   if(!index.data(NetworkModel::ItemActiveRole).toBool())
     return inactiveActivity.value<QColor>();
 
-  BufferItem::ActivityLevel activity = (BufferItem::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt();
+  Buffer::ActivityLevel activity = (Buffer::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt();
 
-  if(activity & BufferItem::Highlight)
+  if(activity & Buffer::Highlight)
     return highlightActivity.value<QColor>();
-  if(activity & BufferItem::NewMessage)
+  if(activity & Buffer::NewMessage)
     return newMessageActivity.value<QColor>();
-  if(activity & BufferItem::OtherActivity)
+  if(activity & Buffer::OtherActivity)
     return otherActivity.value<QColor>();
   
   return noActivity.value<QColor>();
index ec7364e..8c62b37 100644 (file)
@@ -25,7 +25,8 @@ UiStyle::UiStyle(const QString &settingsKey) : _settingsKey(settingsKey) {
   // Default format
   QTextCharFormat def;
   def.setForeground(QBrush("#000000"));
-  def.setFont(QFont("Courier", 10));
+  //def.setFont(QFont("Courier", 10));
+  def.font().setStyleHint(QFont::TypeWriter);
   _defaultFormats = QVector<QTextCharFormat>(NumFormatTypes, def);
   _customFormats = QVector<QTextCharFormat>(NumFormatTypes, QTextFormat().toCharFormat());
 
index 7d1679a..bbc453f 100644 (file)
@@ -4,15 +4,15 @@
 { using namespace Global;
 
   quasselVersion = "0.2.0-pre";
-  quasselDate = "2008-02-14";
-  quasselBuild = 523;
+  quasselDate = "2008-02-18";
+  quasselBuild = 526;
 
   //! Minimum client build number the core needs
-  clientBuildNeeded = 519;
+  clientBuildNeeded = 526;
   clientVersionNeeded = quasselVersion;
 
   //! Minimum core build number the client needs
-  coreBuildNeeded = 519;
+  coreBuildNeeded = 526;
   coreVersionNeeded = quasselVersion;
 
 }