Moving branches/0.3 to trunk
authorManuel Nickschas <sputnick@quassel-irc.org>
Fri, 9 May 2008 15:48:46 +0000 (15:48 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Fri, 9 May 2008 15:48:46 +0000 (15:48 +0000)
54 files changed:
build/buildconf.pri
src/client/client.cpp
src/client/client.h
src/client/client.pri
src/client/messagemodel.cpp [new file with mode: 0644]
src/client/messagemodel.h [new file with mode: 0644]
src/client/quasselui.h
src/common/global.cpp
src/common/main.cpp
src/common/message.cpp
src/common/message.h
src/common/types.h
src/core/basichandler.cpp
src/core/basichandler.h
src/core/coresession.cpp
src/core/coresession.h
src/core/ctcphandler.cpp
src/core/networkconnection.h
src/core/sqlitestorage.cpp
src/core/userinputhandler.cpp
src/qtopia/chatline.cpp
src/qtopia/chatline.h
src/qtopia/chatwidget.cpp
src/qtopia/qtopiamainwin.cpp
src/qtui/bufferwidget.cpp
src/qtui/chatitem.cpp [new file with mode: 0644]
src/qtui/chatitem.h [new file with mode: 0644]
src/qtui/chatline-old.cpp
src/qtui/chatline-old.h
src/qtui/chatlinemodel.cpp [new file with mode: 0644]
src/qtui/chatlinemodel.h [new file with mode: 0644]
src/qtui/chatlinemodelitem.cpp [new file with mode: 0644]
src/qtui/chatlinemodelitem.h [new file with mode: 0644]
src/qtui/chatscene.cpp [new file with mode: 0644]
src/qtui/chatscene.h [new file with mode: 0644]
src/qtui/chatview.cpp [new file with mode: 0644]
src/qtui/chatview.h [new file with mode: 0644]
src/qtui/mainwin.cpp
src/qtui/mainwin.h
src/qtui/qtui.cpp
src/qtui/qtui.h
src/qtui/qtui.pri
src/qtui/qtuistyle.cpp
src/qtui/settingspages/networkssettingspage.ui
src/qtui/topicbutton.cpp
src/qtui/topicbutton.h
src/uisupport/bufferview.cpp
src/uisupport/bufferviewfilter.cpp
src/uisupport/old-uistyle.cpp [new file with mode: 0644]
src/uisupport/old-uistyle.h [new file with mode: 0644]
src/uisupport/uistyle.cpp
src/uisupport/uistyle.h
src/uisupport/uisupport.pri
version.inc

index b85f153..a5aa555 100644 (file)
@@ -23,3 +23,7 @@ mac:Tiger {
  QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk
  CONFIG += x86 ppc
 }
+
+sputdev {
+  DEFINES *= SPUTDEV
+}
index 536f2f7..6a7faa9 100644 (file)
 #include "client.h"
 
 #include "bufferinfo.h"
+#include "buffermodel.h"
+#include "buffersettings.h"
 #include "buffersyncer.h"
-#include "clientbacklogmanager.h"
 #include "bufferviewmanager.h"
+#include "clientbacklogmanager.h"
 #include "global.h"
 #include "identity.h"
 #include "ircchannel.h"
 #include "ircuser.h"
 #include "message.h"
+#ifdef SPUTDEV
+# include "messagemodel.h"
+#endif
 #include "network.h"
 #include "networkmodel.h"
-#include "buffermodel.h"
 #include "quasselui.h"
 #include "signalproxy.h"
 #include "util.h"
-#include "buffersettings.h"
 
 QPointer<Client> Client::instanceptr = 0;
 AccountId Client::_currentCoreAccount = 0;
@@ -68,6 +71,7 @@ Client::Client(QObject *parent)
     _bufferSyncer(0),
     _backlogManager(new ClientBacklogManager(this)),
     _bufferViewManager(0),
+    _messageModel(0),
     _connectedToCore(false),
     _syncedToCore(false)
 {
@@ -90,7 +94,9 @@ void Client::init() {
          _networkModel, SLOT(networkRemoved(NetworkId)));
 
   _bufferModel = new BufferModel(_networkModel);
-
+#ifdef SPUTDEV
+  _messageModel = mainUi->createMessageModel(this);
+#endif
   SignalProxy *p = signalProxy();
 
   p->attachSlot(SIGNAL(displayMsg(const Message &)), this, SLOT(recvMessage(const Message &)));
@@ -429,6 +435,7 @@ void Client::networkDestroyed() {
   }
 }
 
+#ifndef SPUTDEV
 void Client::recvMessage(const Message &message) {
   Message msg = message;
   Buffer *b;
@@ -437,6 +444,8 @@ void Client::recvMessage(const Message &message) {
 
   // FIXME clean up code! (dup)
 
+  // TODO: make redirected messages show up in the correct buffer!
+
   if(msg.flags() & Message::Redirected) {
     BufferSettings bufferSettings;
     bool inStatus = bufferSettings.value("UserMessagesInStatusBuffer", QVariant(true)).toBool();
@@ -480,7 +489,6 @@ void Client::recvMessage(const Message &message) {
     b = buffer(msg.bufferInfo());
     b->appendMsg(msg);
   }
-  
   //bufferModel()->updateBufferActivity(msg);
 
   if(msg.type() == Message::Plain || msg.type() == Message::Notice || msg.type() == Message::Action) {
@@ -489,17 +497,34 @@ void Client::recvMessage(const Message &message) {
       ? net->networkName() + ":"
       : QString();
     QString sender = networkName + msg.bufferInfo().bufferName() + ":" + msg.sender();
-    Message mmsg = Message(msg.timestamp(), msg.bufferInfo(), msg.type(), msg.text(), sender, msg.flags());
+    Message mmsg = Message(msg.timestamp(), msg.bufferInfo(), msg.type(), msg.contents(), sender, msg.flags());
     monitorBuffer()->appendMsg(mmsg);
   }
-
   emit messageReceived(msg);
 }
+#else
+
+void Client::recvMessage(const Message &msg) {
+  //checkForHighlight(msg);
+  _messageModel->insertMessage(msg);
+}
+
+#endif /* SPUTDEV */
 
 void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) {
   //recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg)));
 }
 
+#ifdef SPUTDEV
+void Client::receiveBacklog(BufferId bufferId, const QVariantList &msgs) {
+  //checkForHighlight(msg);
+  foreach(QVariant v, msgs) {
+    _messageModel->insertMessage(v.value<Message>());
+  }
+}
+
+#else
+
 void Client::receiveBacklog(BufferId bufferId, const QVariantList &msgs) {
   Buffer *buffer_ = buffer(bufferId);
   if(!buffer_) {
@@ -527,6 +552,7 @@ void Client::receiveBacklog(BufferId bufferId, const QVariantList &msgs) {
     layoutTimer->start();
   }
 }
+#endif /* SPUTDEV */
 
 void Client::layoutMsg() {
   if(layoutQueue.isEmpty()) {
@@ -562,7 +588,7 @@ void Client::checkForHighlight(Message &msg) {
       QRegExp nickRegExp("^(.*\\W)?" + QRegExp::escape(nickname) + "(\\W.*)?$");
       if((msg.type() & (Message::Plain | Message::Notice | Message::Action))
           && !(msg.flags() & Message::Self)
-          && nickRegExp.exactMatch(msg.text())) {
+          && nickRegExp.exactMatch(msg.contents())) {
         msg.setFlags(msg.flags() | Message::Highlight);
         return;
       }
@@ -582,7 +608,7 @@ void Client::checkForHighlight(Message &msg) {
       }
       if((msg.type() & (Message::Plain | Message::Notice | Message::Action))
           && !(msg.flags() & Message::Self)
-          && userRegExp.exactMatch(msg.text())) {
+          && userRegExp.exactMatch(msg.contents())) {
         msg.setFlags(msg.flags() | Message::Highlight);
         return;
       }
index bd31c32..4e7eb0e 100644 (file)
 
 class BufferInfo;
 class Message;
+class MessageModel;
 
 class Identity;
 class Network;
 
-
 class AbstractUi;
 class AbstractUiMsg;
 class NetworkModel;
@@ -49,7 +49,6 @@ struct NetworkInfo;
 
 class QTimer;
 
-
 class Client : public QObject {
   Q_OBJECT
 
@@ -94,6 +93,7 @@ public:
 
   static inline NetworkModel *networkModel() { return instance()->_networkModel; }
   static inline BufferModel *bufferModel() { return instance()->_bufferModel; }
+  static inline MessageModel *messageModel() { return instance()->_messageModel; }
   static inline SignalProxy *signalProxy() { return instance()->_signalProxy; }
 
   static inline ClientBacklogManager *backlogManager() { return instance()->_backlogManager; }
@@ -216,6 +216,8 @@ private:
   ClientBacklogManager *_backlogManager;
   BufferViewManager *_bufferViewManager;
 
+  MessageModel *_messageModel;
+
   ClientMode clientMode;
 
   bool _connectedToCore, _syncedToCore;
index d16cec3..0945919 100644 (file)
@@ -1,7 +1,13 @@
 DEPMOD = common
 QT_MOD = core network gui
 
-SRCS += buffer.cpp buffersettings.cpp clientbacklogmanager.cpp treemodel.cpp networkmodel.cpp buffermodel.cpp client.cpp clientsettings.cpp clientsyncer.cpp \
-        mappedselectionmodel.cpp selectionmodelsynchronizer.cpp
-HDRS += buffer.h buffersettings.h clientbacklogmanager.h treemodel.h networkmodel.h buffermodel.h client.h clientsettings.h clientsyncer.h quasselui.h \
-        mappedselectionmodel.h selectionmodelsynchronizer.h
+SRCS += buffer.cpp buffersettings.cpp clientbacklogmanager.cpp treemodel.cpp networkmodel.cpp buffermodel.cpp \
+        client.cpp clientsettings.cpp clientsyncer.cpp mappedselectionmodel.cpp selectionmodelsynchronizer.cpp
+HDRS += buffer.h buffersettings.h clientbacklogmanager.h treemodel.h networkmodel.h buffermodel.h \
+        client.h clientsettings.h clientsyncer.h quasselui.h mappedselectionmodel.h selectionmodelsynchronizer.h
+
+sputdev {
+  SRCS += messagemodel.cpp
+  HDRS += messagemodel.h
+}
+
diff --git a/src/client/messagemodel.cpp b/src/client/messagemodel.cpp
new file mode 100644 (file)
index 0000000..17e9049
--- /dev/null
@@ -0,0 +1,108 @@
+/***************************************************************************
+ *   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 "messagemodel.h"
+
+#include "message.h"
+
+MessageModel::MessageModel(QObject *parent) : QAbstractItemModel(parent) {
+  
+  
+  
+}
+
+MessageModel::~MessageModel() {
+  
+  
+}
+
+QVariant MessageModel::data(const QModelIndex &index, int role) const {
+  int row = index.row();
+  if(row < 0 || row >= _messageList.count()) return QVariant();
+  return _messageList[row]->data(index.column(), role);
+}
+
+bool MessageModel::setData(const QModelIndex &index, const QVariant &value, int role) {
+  int row = index.row();
+  if(row < 0 || row >= _messageList.count()) return false;
+  if(_messageList[row]->setData(index.column(), value, role)) {
+    emit dataChanged(index, index);
+    return true;
+  }
+  return false;
+}
+
+void MessageModel::insertMessage(const Message &msg) {
+  MsgId id = msg.msgId();
+  int idx = indexForId(id);
+  MessageModelItem *item = createMessageModelItem(msg);
+  beginInsertRows(QModelIndex(), idx, idx);
+  _messageList.insert(idx, item);
+  endInsertRows();
+}
+
+void MessageModel::insertMessages(const QList<Message> &msglist) {
+  if(msglist.isEmpty()) return;
+  // FIXME make this more efficient by grouping msgs
+  foreach(Message msg, msglist) insertMessage(msg);
+
+}
+
+// returns index of msg with given Id or of the next message after that (i.e., the index where we'd insert this msg)
+int MessageModel::indexForId(MsgId id) {
+  if(_messageList.isEmpty() || id <= _messageList[0]->data(0, MsgIdRole).value<MsgId>()) return 0;
+  if(id > _messageList.last()->data(0, MsgIdRole).value<MsgId>()) return _messageList.count();
+  // binary search
+  int start = 0; int end = _messageList.count()-1;
+  while(1) {
+    if(end - start == 1) return end;
+    int pivot = (end + start) / 2;
+    if(id <= _messageList[pivot]->data(0, MsgIdRole).value<MsgId>()) end = pivot;
+    else start = pivot;
+  }
+}
+
+/**********************************************************************************/
+
+MessageModelItem::MessageModelItem(const Message &msg) {
+  _timestamp = msg.timestamp();
+  _msgId = msg.msgId();
+  _bufferId = msg.bufferInfo().bufferId();
+  _type = msg.type();
+  _flags = msg.flags();
+
+}
+
+MessageModelItem::~MessageModelItem() {
+
+}
+
+QVariant MessageModelItem::data(int column, int role) const {
+  if(column < MessageModel::TimestampColumn || column > MessageModel::TextColumn) return QVariant();
+  switch(role) {
+    case MessageModel::MsgIdRole: return QVariant::fromValue<MsgId>(_msgId);
+    case MessageModel::BufferIdRole: return QVariant::fromValue<BufferId>(_bufferId);
+    case MessageModel::TypeRole: return _type;
+    case MessageModel::FlagsRole: return (int)_flags;
+    case MessageModel::TimestampRole: return _timestamp;
+    default: return QVariant();
+  }
+}
+
diff --git a/src/client/messagemodel.h b/src/client/messagemodel.h
new file mode 100644 (file)
index 0000000..d37100c
--- /dev/null
@@ -0,0 +1,101 @@
+/***************************************************************************
+ *   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 MESSAGEMODEL_H_
+#define MESSAGEMODEL_H_
+
+#include <QAbstractItemModel>
+#include <QDateTime>
+
+#include "message.h"
+#include "types.h"
+
+class MessageModelItem;
+class MsgId;
+
+class MessageModel : public QAbstractItemModel {
+  Q_OBJECT
+
+  public:
+    enum MessageRole {
+      MsgIdRole = Qt::UserRole,
+      BufferIdRole,
+      TypeRole,
+      FlagsRole,
+      TimestampRole,
+      DisplayRole,
+      FormatRole,
+      UserRole
+    };
+
+    enum ColumnType {
+      TimestampColumn, SenderColumn, TextColumn, UserColumnType
+    };
+
+    MessageModel(QObject *parent);
+    virtual ~MessageModel();
+
+    inline QModelIndex index(int row, int column, const QModelIndex &/*parent*/ = QModelIndex()) const { return createIndex(row, column); }
+    inline QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
+    inline int rowCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return _messageList.count(); }
+    inline int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 3; }
+
+    virtual QVariant data(const QModelIndex &index, int role) const;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
+
+    //virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+
+    void insertMessage(const Message &);
+    void insertMessages(const QList<Message> &);
+
+  protected:
+    virtual MessageModelItem *createMessageModelItem(const Message &) = 0;
+
+  private:
+    QList<MessageModelItem *> _messageList;
+
+    int indexForId(MsgId);
+
+};
+
+class MessageModelItem {
+
+  public:
+
+    //! Creates a MessageModelItem from a Message object.
+    /** This baseclass implementation takes care of all Message data *except* the stylable strings.
+     *  Subclasses need to provide Qt::DisplayRole at least, which should describe the plaintext
+     *  strings without formattings (e.g. for searching purposes).
+     */
+    MessageModelItem(const Message &);
+    virtual ~MessageModelItem();
+
+    virtual QVariant data(int column, int role) const;
+    virtual bool setData(int column, const QVariant &value, int role) = 0;
+
+  private:
+    QDateTime _timestamp;
+    MsgId _msgId;
+    BufferId _bufferId;
+    Message::Type _type;
+    Message::Flags _flags;
+};
+
+#endif
index 747d8b8..bcb512b 100644 (file)
@@ -24,6 +24,8 @@
 #include <QObject>
 #include "message.h"
 
+class MessageModel;
+
 class AbstractUiMsg {
 
   public:
@@ -42,6 +44,7 @@ class AbstractUi : public QObject {
 
   public:
     virtual void init() {};  // called after the client is initialized
+    virtual MessageModel *createMessageModel(QObject *parent = 0) = 0;
     virtual AbstractUiMsg *layoutMsg(const Message &) = 0;
 
   protected slots:
index 9f0e224..59afde1 100644 (file)
@@ -96,7 +96,6 @@ void Global::registerMetaTypes() {
   qRegisterMetaTypeStreamOperators<UserId>("UserId");
   qRegisterMetaTypeStreamOperators<AccountId>("AccountId");
   qRegisterMetaTypeStreamOperators<MsgId>("MsgId");
-
 }
 
 // Static variables
index 5fb3029..3c36a28 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv) {
 
   // Check if a non-standard core port is requested
   QStringList args = QCoreApplication::arguments();  // TODO Build a CLI parser
-  Global::DEBUG = args.contains("--debug"); // This enables (maybe) various debug features.
+  Global::DEBUG = args.contains("--debug"); // This enables various debug features.
 
   Global::defaultPort = 4242;
   int idx;
index 8c0ebb3..2ce40f8 100644 (file)
 
 #include <QDataStream>
 
-Message::Message(BufferInfo bufferInfo, Type type, QString text, QString sender, quint8 flags)
+Message::Message(const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender, Flags flags)
   : _timestamp(QDateTime::currentDateTime().toUTC()),
     _bufferInfo(bufferInfo),
-    _text(text),
+    _contents(contents),
     _sender(sender),
     _type(type),
     _flags(flags)
 {
 }
 
-Message::Message(QDateTime ts,BufferInfo bufferInfo, Type type, QString text, QString sender, quint8 flags)
+Message::Message(const QDateTime &ts, const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender, Flags flags)
   : _timestamp(ts),
     _bufferInfo(bufferInfo),
-    _text(text),
+    _contents(contents),
     _sender(sender),
     _type(type),
     _flags(flags)
 {
 }
 
-void Message::setFlags(quint8 flags) {
+void Message::setFlags(Flags flags) {
   _flags = flags;
 }
 
+#ifndef SPUTDEV
 QString Message::mircToInternal(QString mirc) {
   mirc.replace('%', "%%");      // escape % just to be sure
   mirc.replace('\x02', "%B");
@@ -98,7 +99,7 @@ void Message::format() {
   QString user = userFromMask(sender());
   QString host = hostFromMask(sender());
   QString nick = nickFromMask(sender());
-  QString txt = mircToInternal(text());
+  QString txt = mircToInternal(contents());
   QString bufferName = bufferInfo().bufferName();
 
   _formattedTimestamp = tr("%DT[%1]").arg(timestamp().toLocalTime().toString("hh:mm:ss"));
@@ -134,12 +135,12 @@ void Message::format() {
     break;
     case Message::Nick:
       s = tr("%Dr<->");
-      if(nick == text()) t = tr("%DrYou are now known as %DN%1%DN").arg(txt);
+      if(nick == contents()) t = tr("%DrYou are now known as %DN%1%DN").arg(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());
+      if(nick.isEmpty()) t = tr("%DmUser mode: %DM%1%DM").arg(contents());
       else t = tr("%DmMode %DM%1%DM by %DN%2%DN").arg(txt, nick);
       break;
     case Message::Action:
@@ -168,18 +169,11 @@ QString Message::formattedText() {
   format();
   return _formattedText;
 }
-
-/*
-QString Message::formattedToHtml(const QString &f) {
-
-
-  return f;
-}
-*/
+#endif /* SPUTDEV */
 
 QDataStream &operator<<(QDataStream &out, const Message &msg) {
   out << msg.msgId() << (quint32)msg.timestamp().toTime_t() << (quint32)msg.type() << (quint8)msg.flags()
-      << msg.bufferInfo() << msg.sender().toUtf8() << msg.text().toUtf8();
+      << msg.bufferInfo() << msg.sender().toUtf8() << msg.contents().toUtf8();
   return out;
 }
 
@@ -191,11 +185,11 @@ QDataStream &operator>>(QDataStream &in, Message &msg) {
   BufferInfo buf;
   in >> msg._msgId >> ts >> t >> f >> buf >> s >> m;
   msg._type = (Message::Type)t;
-  msg._flags = (quint8)f;
+  msg._flags = (Message::Flags)f;
   msg._bufferInfo = buf;
   msg._timestamp = QDateTime::fromTime_t(ts);
   msg._sender = QString::fromUtf8(s);
-  msg._text = QString::fromUtf8(m);
+  msg._contents = QString::fromUtf8(m);
   return in;
 }
 
index 08c70c6..797e28b 100644 (file)
@@ -48,31 +48,32 @@ public:
     Error  = 0x1000
   };
 
-  enum Flags {
+  enum Flag {
     None = 0,
     Self = 1,
     Highlight = 2,
     Redirected = 4
   };
-  Q_DECLARE_FLAGS(MessageFlags, Flags)
+  Q_DECLARE_FLAGS(Flags, Flag)
   
 
-  Message(BufferInfo bufferInfo = BufferInfo(), Type type = Plain, QString text = "", QString sender = "", quint8 flags = None);
-
-  Message(QDateTime ts, BufferInfo buffer = BufferInfo(), Type type = Plain, QString text = "", QString sender = "", quint8 flags = None);
+  Message(const BufferInfo &bufferInfo = BufferInfo(), Type type = Plain, const QString &contents = "", const QString &sender = "", Flags flags = None);
+  Message(const QDateTime &ts, const BufferInfo &buffer = BufferInfo(), Type type = Plain,
+          const QString &contents = "", const QString &sender = "", Flags flags = None);
 
   inline MsgId msgId() const { return _msgId; }
   inline void setMsgId(MsgId id) { _msgId = id; }
 
   inline BufferInfo bufferInfo() const { return _bufferInfo; }
-  inline QString text() const { return _text; }
+  inline QString contents() const { return _contents; }
   inline QString sender() const { return _sender; }
   inline Type type() const { return _type; }
-  inline quint8 flags() const { return _flags; }
+  inline Flags flags() const { return _flags; }
   inline QDateTime timestamp() const { return _timestamp; }
 
-  void setFlags(quint8 flags);
+  void setFlags(Flags flags);
   
+#ifndef SPUTDEV
   QString formattedTimestamp();
   QString formattedSender();
   QString formattedText();
@@ -83,15 +84,16 @@ public:
   static QString mircToInternal(QString);
 
   void format();
+#endif
 
 private:
   QDateTime _timestamp;
   MsgId _msgId;
   BufferInfo _bufferInfo;
-  QString _text;
+  QString _contents;
   QString _sender;
   Type _type;
-  quint8 _flags;
+  Flags _flags;
 
   QString _formattedTimestamp, _formattedSender, _formattedText; // cache
 
@@ -103,6 +105,6 @@ QDataStream &operator<<(QDataStream &out, const Message &msg);
 QDataStream &operator>>(QDataStream &in, Message &msg);
 
 Q_DECLARE_METATYPE(Message);
-Q_DECLARE_OPERATORS_FOR_FLAGS(Message::MessageFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Message::Flags)
 
 #endif
index 381c5d6..0154247 100644 (file)
@@ -37,6 +37,7 @@ class SignedId {
     inline bool operator==(const SignedId &other) const { return id == other.id; }
     inline bool operator!=(const SignedId &other) const { return id != other.id; }
     inline bool operator<(const SignedId &other) const { return id < other.id; }
+    inline bool operator<=(const SignedId &other) const { return id <= other.id; }
     inline bool operator>(const SignedId &other) const { return id > other.id; }
     inline bool operator>=(const SignedId &other) const { return id >= other.id; }
     inline bool operator==(int i) const { return id == i; }
index 02483d2..a00966d 100644 (file)
@@ -30,8 +30,8 @@ BasicHandler::BasicHandler(NetworkConnection *parent)
     _networkConnection(parent),
     initDone(false)
 {
-  connect(this, SIGNAL(displayMsg(Message::Type, BufferInfo::Type, QString, QString, QString, quint8)),
-         networkConnection(), SIGNAL(displayMsg(Message::Type, BufferInfo::Type, QString, QString, QString, quint8)));
+  connect(this, SIGNAL(displayMsg(Message::Type, BufferInfo::Type, QString, QString, QString, Message::Flags)),
+         networkConnection(), SIGNAL(displayMsg(Message::Type, BufferInfo::Type, QString, QString, QString, Message::Flags)));
 
   connect(this, SIGNAL(putCmd(QString, const QVariantList &, const QByteArray &)),
          networkConnection(), SLOT(putCmd(QString, const QVariantList &, const QByteArray &)));
@@ -189,7 +189,7 @@ void BasicHandler::putCmd(const QString &cmd, const QList<QByteArray> &params, c
   emit putCmd(cmd, list, prefix);
 }
 
-void BasicHandler::displayMsg(Message::Type msgType, QString target, QString text, QString sender, quint8 flags) {
+void BasicHandler::displayMsg(Message::Type msgType, QString target, QString text, QString sender, Message::Flags flags) {
   IrcChannel *channel = network()->ircChannel(target);
   if(!channel && (target.startsWith('$') || target.startsWith('#')))
     target = nickFromMask(sender);
index 757af6e..f641a30 100644 (file)
@@ -55,12 +55,12 @@ public:
   QList<QByteArray> userEncode(const QString &userNick, const QStringList &stringlist);
 
 signals:
-  void displayMsg(Message::Type, BufferInfo::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+  void displayMsg(Message::Type, BufferInfo::Type, QString target, QString text, QString sender = "", Message::Flags flags = Message::None);
   void putCmd(const QString &cmd, const QVariantList &params, const QByteArray &prefix);
   void putRawLine(const QByteArray &msg);
 
 protected:
-  void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+  void displayMsg(Message::Type, QString target, QString text, QString sender = "", Message::Flags flags = Message::None);
   void putCmd(const QString &cmd, const QByteArray &param, const QByteArray &prefix = QByteArray());
   void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
 
index b576854..68f3127 100644 (file)
@@ -192,8 +192,8 @@ void CoreSession::attachNetworkConnection(NetworkConnection *conn) {
   //signalProxy()->attachSignal(conn, SIGNAL(connected(NetworkId)), SIGNAL(networkConnected(NetworkId)));
   //signalProxy()->attachSignal(conn, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId)));
 
-  connect(conn, SIGNAL(displayMsg(Message::Type, BufferInfo::Type, QString, QString, QString, quint8)),
-         this, SLOT(recvMessageFromServer(Message::Type, BufferInfo::Type, QString, QString, QString, quint8)));
+  connect(conn, SIGNAL(displayMsg(Message::Type, BufferInfo::Type, QString, QString, QString, Message::Flags)),
+         this, SLOT(recvMessageFromServer(Message::Type, BufferInfo::Type, QString, QString, QString, Message::Flags)));
   connect(conn, SIGNAL(displayStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString)));
 
   connect(conn, SIGNAL(nickChanged(const NetworkId &, const QString &, const QString &)),
@@ -282,10 +282,11 @@ void CoreSession::msgFromClient(BufferInfo bufinfo, QString msg) {
 
 // ALL messages coming pass through these functions before going to the GUI.
 // So this is the perfect place for storing the backlog and log stuff.
-void CoreSession::recvMessageFromServer(Message::Type type, BufferInfo::Type bufferType, QString target, QString text, QString sender, quint8 flags) {
+void CoreSession::recvMessageFromServer(Message::Type type, BufferInfo::Type bufferType,
+                                        QString target, QString text, QString sender, Message::Flags flags) {
   NetworkConnection *netCon = qobject_cast<NetworkConnection*>(this->sender());
   Q_ASSERT(netCon);
-  
+
   BufferInfo bufferInfo = Core::bufferInfo(user(), netCon->networkId(), bufferType, target);
   Message msg(bufferInfo, type, text, sender, flags);
   msg.setMsgId(Core::storeMessage(msg));
index 482fa76..1403c74 100644 (file)
@@ -153,7 +153,7 @@ private slots:
   void removeClient(QIODevice *dev);
 
   void recvStatusMsgFromServer(QString msg);
-  void recvMessageFromServer(Message::Type, BufferInfo::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+  void recvMessageFromServer(Message::Type, BufferInfo::Type, QString target, QString text, QString sender = "", Message::Flags flags = Message::None);
   void networkConnected(NetworkId networkid);
   void networkDisconnected(NetworkId networkid);
 
index 95fe173..ba48964 100644 (file)
@@ -94,7 +94,7 @@ void CtcpHandler::parse(Message::Type messageType, const QString &prefix, const
     ? CtcpReply
     : CtcpQuery;
   
-  quint8 flags = (messageType == Message::Notice && !network()->isChannelName(target))
+  Message::Flags flags = (messageType == Message::Notice && !network()->isChannelName(target))
     ? Message::Redirected
     : Message::None;
 
index 1002cd6..9b4126d 100644 (file)
@@ -109,7 +109,7 @@ signals:
   void recvRawServerMsg(QString);
   void displayStatusMsg(QString);
   //void displayMsg(Message msg);
-  void displayMsg(Message::Type, BufferInfo::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+  void displayMsg(Message::Type, BufferInfo::Type, QString target, QString text, QString sender = "", Message::Flags flags = Message::None);
   void connected(NetworkId networkId);   ///< Emitted after receipt of 001 to indicate that we can now send data to the IRC server
   void disconnected(NetworkId networkId);
   void connectionStateChanged(Network::ConnectionState);
index 8cd4d5b..5dab67e 100644 (file)
@@ -629,9 +629,9 @@ MsgId SqliteStorage::logMessage(Message msg) {
   logMessageQuery->bindValue(":time", msg.timestamp().toTime_t());
   logMessageQuery->bindValue(":bufferid", msg.bufferInfo().bufferId().toInt());
   logMessageQuery->bindValue(":type", msg.type());
-  logMessageQuery->bindValue(":flags", msg.flags());
+  logMessageQuery->bindValue(":flags", (int)msg.flags());
   logMessageQuery->bindValue(":sender", msg.sender());
-  logMessageQuery->bindValue(":message", msg.text());
+  logMessageQuery->bindValue(":message", msg.contents());
   logMessageQuery->exec();
   
   if(logMessageQuery->lastError().isValid()) {
@@ -688,7 +688,7 @@ QList<Message> SqliteStorage::requestMsgs(UserId user, BufferId bufferId, int la
                 (Message::Type)msgQuery->value(2).toUInt(),
                 msgQuery->value(5).toString(),
                 msgQuery->value(4).toString(),
-                msgQuery->value(3).toUInt());
+                (Message::Flags)msgQuery->value(3).toUInt());
     msg.setMsgId(msgQuery->value(0).toInt());
     messagelist << msg;
   }
@@ -726,7 +726,7 @@ QList<Message> SqliteStorage::requestMsgs(UserId user, BufferId bufferId, QDateT
                 (Message::Type)msgQuery->value(2).toUInt(),
                 msgQuery->value(5).toString(),
                 msgQuery->value(4).toString(),
-                msgQuery->value(3).toUInt());
+                (Message::Flags)msgQuery->value(3).toUInt());
     msg.setMsgId(msgQuery->value(0).toInt());
     messagelist << msg;
   }
@@ -756,7 +756,7 @@ QList<Message> SqliteStorage::requestMsgRange(UserId user, BufferId bufferId, in
                 (Message::Type)rangeQuery->value(2).toUInt(),
                 rangeQuery->value(5).toString(),
                 rangeQuery->value(4).toString(),
-                rangeQuery->value(3).toUInt());
+                (Message::Flags)rangeQuery->value(3).toUInt());
     msg.setMsgId(rangeQuery->value(0).toInt());
     messagelist << msg;
   }
index 0ef5aba..9c7e03b 100644 (file)
@@ -168,6 +168,7 @@ void UserInputHandler::handleKick(const BufferInfo &bufferInfo, const QString &m
 }
 
 void UserInputHandler::handleKill(const BufferInfo &bufferInfo, const QString &msg) {
+  Q_UNUSED(bufferInfo)
   QString nick = msg.section(' ', 0, 0, QString::SectionSkipEmpty);
   QString pass = msg.section(' ', 1, -1, QString::SectionSkipEmpty);
   QList<QByteArray> params;
@@ -222,6 +223,7 @@ void UserInputHandler::handleOp(const BufferInfo &bufferInfo, const QString &msg
 }
 
 void UserInputHandler::handleOper(const BufferInfo &bufferInfo, const QString &msg) {
+  Q_UNUSED(bufferInfo)
   emit putRawLine(serverEncode(QString("OPER %1").arg(msg)));
 }
 
index a380314..0a709c0 100644 (file)
@@ -26,7 +26,7 @@
 
 ChatLine::ChatLine(Message msg) {
   _styledSender = QtopiaUi::style()->styleString(msg.formattedSender());
-  _styledText = QtopiaUi::style()->styleString(msg.formattedText());
+  _styledContents = QtopiaUi::style()->styleString(msg.formattedText());
   _timestamp = msg.timestamp();
   _msgId = msg.msgId();
   _bufferInfo = msg.bufferInfo();
@@ -58,8 +58,8 @@ UiStyle::StyledText ChatLine::styledSender() const {
   return _styledSender;
 }
 
-UiStyle::StyledText ChatLine::styledText() const {
-  return _styledText;
+UiStyle::StyledText ChatLine::styledContents() const {
+  return _styledContents;
 }
 
 
index 0d3f5e8..bdaf7d4 100644 (file)
@@ -35,11 +35,11 @@ class ChatLine : public AbstractUiMsg {
     QDateTime timestamp() const;
 
     UiStyle::StyledText styledSender() const;
-    UiStyle::StyledText styledText() const;
+    UiStyle::StyledText styledContents() const;
 
   private:
     QString _sender, _text, _htmlSender, _htmlText, _htmlTimestamp;
-    UiStyle::StyledText _styledSender, _styledText;
+    UiStyle::StyledText _styledSender, _styledContents;
     MsgId _msgId;
     BufferInfo _bufferInfo;
     QDateTime _timestamp;
index 9f8eabb..b6950c6 100644 (file)
@@ -53,7 +53,7 @@ void ChatWidget::appendChatLine(ChatLine *line) {
   if(!document()->isEmpty()) insertPlainText("\n");
   insertStyledText(line->styledSender());
   insertPlainText(" ");
-  insertStyledText(line->styledText());
+  insertStyledText(line->styledContents());
   setTextCursor(cursor);
 }
 
@@ -69,7 +69,7 @@ void ChatWidget::prependChatLine(ChatLine *line) {
   bool flg = document()->isEmpty();
   insertStyledText(line->styledSender());
   insertPlainText(" ");
-  insertStyledText(line->styledText());
+  insertStyledText(line->styledContents());
   if(!flg) insertPlainText("\n");
   setTextCursor(cursor);
 }
@@ -84,14 +84,14 @@ void ChatWidget::insertChatLine(ChatLine *line) {
   if(!document()->isEmpty()) insertPlainText("\n");
   insertStyledText(line->styledSender());
   insertPlainText(" ");
-  insertStyledText(line->styledText());
+  insertStyledText(line->styledContents());
 }
 
 void ChatWidget::insertStyledText(const QtopiaUiStyle::StyledText &stext) {
   QTextCursor cursor = textCursor();
-  foreach(QTextLayout::FormatRange format, stext.formats) {
+  foreach(QTextLayout::FormatRange format, stext.formatList) {
     cursor.setCharFormat(format.format);
     setTextCursor(cursor);
-    insertPlainText(stext.text.mid(format.start, format.length));
+    insertPlainText(stext.plainText.mid(format.start, format.length));
   }
 }
index 69b054a..b927e72 100644 (file)
@@ -47,6 +47,7 @@ QtopiaMainWin::QtopiaMainWin(QWidget *parent, Qt::WFlags flags) : QMainWindow(pa
 
   Global::runMode = Global::ClientOnly;
   Global::defaultPort = 4242;
+  Global::DEBUG = true;
 
   Network::setDefaultCodecForServer("ISO-8859-1");
   Network::setDefaultCodecForEncoding("UTF-8");
index d534b3d..bc10ca5 100644 (file)
@@ -19,7 +19,7 @@
  ***************************************************************************/
 
 #include "bufferwidget.h"
-#include "chatline-old.h"
+#include "chatview.h"
 #include "chatwidget.h"
 #include "settings.h"
 #include "client.h"
@@ -35,7 +35,12 @@ BufferWidget::~BufferWidget() {
 }
 
 AbstractChatView *BufferWidget::createChatView(BufferId id) {
-  QWidget *chatView = new ChatWidget(id, this);
+  QWidget *chatView;
+#ifdef SPUTDEV
+  chatView = new ChatView(Client::buffer(id), this);
+#else
+  chatView = new ChatWidget(id, this);
+#endif
   _chatViews[id] = chatView;
   ui.stackedWidget->addWidget(chatView);
   chatView->setFocusProxy(this);
diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp
new file mode 100644 (file)
index 0000000..a677e10
--- /dev/null
@@ -0,0 +1,142 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 <QFontMetrics>
+#include <QGraphicsSceneMouseEvent>
+#include <QTextCursor>
+#include <QTextDocument>
+
+#include <QtGui>
+
+#include "chatitem.h"
+
+ChatItem::ChatItem(const QPersistentModelIndex &index_, QGraphicsItem *parent) : QGraphicsItem(parent), _index(index_) {
+  //if(_wrapMode == WordWrap) {
+  //  setFlags(QGraphicsItem::ItemClipsToShape, true);
+  //}
+}
+
+ChatItem::~ChatItem() {
+
+}
+
+QVariant ChatItem::data(int role) const {
+  if(!_index.isValid()) {
+    qWarning() << "ChatItem::data(): Model index is invalid!";
+    return QVariant();
+  }
+  return _index.data(role);
+}
+
+QRectF ChatItem::boundingRect() const {
+  return QRectF(0, 0, 500,20);
+}
+
+void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+  Q_UNUSED(option); Q_UNUSED(widget);
+
+  painter->drawRect(boundingRect());
+  painter->drawText(boundingRect(), data(MessageModel::DisplayRole).toString());
+}
+
+
+/*
+void ChatItem::setWidth(int w) {
+  _width = w;
+  layout();
+}
+
+void ChatItem::setTextOption(const QTextOption &option) {
+  _textOption = option;
+  layout();
+}
+
+QTextOption ChatItem::textOption() const {
+  return _textOption;
+}
+
+QString ChatItem::text() const {
+  return _layout.text();
+}
+
+void ChatItem::setText(const UiStyle::StyledText &text) {
+  _layout.setText(text.text);
+  _layout.setAdditionalFormats(text.formatList);
+  layout();
+}
+
+void ChatItem::layout() {
+  if(!_layout.additionalFormats().count()) return; // no text set
+  if(_width <= 0) return;
+  prepareGeometryChange();
+  QFontMetrics metrics(_layout.additionalFormats()[0].format.font());
+  int leading = metrics.leading();
+  int height = 0;
+  _layout.setTextOption(textOption());
+  _layout.beginLayout();
+  while(1) {
+    QTextLine line = _layout.createLine();
+    if(!line.isValid()) break;
+    line.setLineWidth(_width);
+    if(textOption().wrapMode() != QTextOption::NoWrap && line.naturalTextWidth() > _width) {
+      // word did not fit, we need to wrap it in the middle
+      // this is a workaround for Qt failing to handle WrapAtWordBoundaryOrAnywhere correctly
+      QTextOption::WrapMode mode = textOption().wrapMode();
+      textOption().setWrapMode(QTextOption::WrapAnywhere);
+      _layout.setTextOption(textOption());
+      line.setLineWidth(_width);
+      textOption().setWrapMode(mode);
+      _layout.setTextOption(textOption());
+    }
+    height += leading;
+    line.setPosition(QPoint(0, height));
+    height += line.height();
+  }
+  _layout.endLayout();
+  update();
+}    QDateTime _timestamp;
+    MsgId _msgId;
+
+
+QRectF ChatItem::boundingRect() const {
+  return _layout.boundingRect();
+}
+
+void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+  Q_UNUSED(option); Q_UNUSED(widget);
+  _layout.draw(painter, QPointF(0, 0));
+
+}
+*/
+
+/*
+void ChatItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event ) {
+  qDebug() << (void*)this << "moving" << event->pos();
+  if(event->pos().y() < 0) {
+    QTextCursor cursor(document());
+    //cursor.insertText("foo");
+    //cursor.select(QTextCursor::Document);
+    event->ignore();
+  } else QGraphicsTextItem::mouseMoveEvent(event);
+}
+*/
+
+
+
diff --git a/src/qtui/chatitem.h b/src/qtui/chatitem.h
new file mode 100644 (file)
index 0000000..2b7ac8a
--- /dev/null
@@ -0,0 +1,66 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 _CHATITEM_H_
+#define _CHATITEM_H_
+
+#include <QGraphicsItem>
+#include <QPersistentModelIndex>
+#include <QTextLayout>
+#include <QTextOption>
+
+#include "messagemodel.h"
+#include "uistyle.h"
+
+class QGraphicsSceneMouseEvent;
+
+class ChatItem : public QGraphicsItem {
+
+  public:
+    ChatItem(const QPersistentModelIndex &index, QGraphicsItem *parent = 0);
+    virtual ~ChatItem();
+
+    virtual QRectF boundingRect() const;
+    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+    inline QPersistentModelIndex persistentIndex() const { return _index; }
+    inline const MessageModel *model() const { return _index.isValid() ? qobject_cast<const MessageModel *>(_index.model()) : 0; }
+    inline int row() const { return _index.isValid() ? _index.row() : 0; }
+    virtual QVariant data(int role) const;
+    //QString text() const;
+    //void setText(const UiStyle::StyledText &text);
+
+    //QTextOption textOption() const;
+    //void setTextOption(const QTextOption &option);
+
+    //void setWidth(int width);
+    //virtual void layout();
+
+  protected:
+    //void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
+
+  private:
+    //int _width;
+    //QTextLayout _layout;
+    //QTextOption _textOption;
+    QPersistentModelIndex _index;
+};
+
+#endif
index 497017d..3b0dae5 100644 (file)
@@ -51,7 +51,7 @@ void ChatLineOld::formatMsg(Message msg) {
   QTextOption tsOption, senderOption, textOption;
   styledTimeStamp = QtUi::style()->styleString(msg.formattedTimestamp());
   styledSender = QtUi::style()->styleString(msg.formattedSender());
-  styledText = QtUi::style()->styleString(msg.formattedText());
+  styledContents = QtUi::style()->styleString(msg.formattedText());
   precomputeLine();
 }
 
@@ -69,28 +69,28 @@ QList<ChatLineOld::FormatRange> ChatLineOld::calcFormatRanges(const UiStyle::Sty
   QList<FormatRange> ranges;
 
   if(additional.length > 0) {
-    for(int i = 0; i < fs.formats.count(); i++) {
-      int oldend = fs.formats[i].start + fs.formats[i].length - 1;
+    for(int i = 0; i < fs.formatList.count(); i++) {
+      int oldend = fs.formatList[i].start + fs.formatList[i].length - 1;
       int addend = additional.start + additional.length - 1;
       if(oldend < additional.start) continue;
-      fs.formats[i].length = additional.start - fs.formats[i].start;
-      QTextLayout::FormatRange addfmtrng = fs.formats[i];
+      fs.formatList[i].length = additional.start - fs.formatList[i].start;
+      QTextLayout::FormatRange addfmtrng = fs.formatList[i];
       addfmtrng.format.merge(additional.format);
       addfmtrng.start = additional.start;
       addfmtrng.length = qMin(oldend, addend) - additional.start + 1;
-      fs.formats.insert(++i, addfmtrng);
+      fs.formatList.insert(++i, addfmtrng);
       if(addend == oldend) break;
       if(addend < oldend) {
-        QTextLayout::FormatRange restfmtrng = fs.formats[i-1];
+        QTextLayout::FormatRange restfmtrng = fs.formatList[i-1];
         restfmtrng.start = addend + 1;
         restfmtrng.length = oldend - addend;
-        fs.formats.insert(++i, restfmtrng);
+        fs.formatList.insert(++i, restfmtrng);
         break;
       }
     }
   }
 
-  foreach(QTextLayout::FormatRange f, fs.formats) {
+  foreach(QTextLayout::FormatRange f, fs.formatList) {
     if(f.length <= 0) continue;
     FormatRange range;
     range.start = f.start;
@@ -112,7 +112,7 @@ void ChatLineOld::setSelection(SelectionMode mode, int start, int end) {
     case None:
       tsFormat = calcFormatRanges(styledTimeStamp);
       senderFormat = calcFormatRanges(styledSender);
-      textFormat = calcFormatRanges(styledText);
+      textFormat = calcFormatRanges(styledContents);
       break;
     case Partial:
       selectionStart = qMin(start, end); selectionEnd = qMax(start, end);
@@ -120,21 +120,21 @@ void ChatLineOld::setSelection(SelectionMode mode, int start, int end) {
       textSel.format.setBackground(pal.brush(QPalette::Highlight));
       textSel.start = selectionStart;
       textSel.length = selectionEnd - selectionStart;
-      textFormat = calcFormatRanges(styledText, textSel);
+      textFormat = calcFormatRanges(styledContents, textSel);
       break;
     case Full:
       tsSel.format.setForeground(pal.brush(QPalette::HighlightedText));
       tsSel.format.setBackground(pal.brush(QPalette::Highlight));
-      tsSel.start = 0; tsSel.length = styledTimeStamp.text.length();
+      tsSel.start = 0; tsSel.length = styledTimeStamp.plainText.length();
       tsFormat = calcFormatRanges(styledTimeStamp, tsSel);
       senderSel.format.setForeground(pal.brush(QPalette::HighlightedText));
       senderSel.format.setBackground(pal.brush(QPalette::Highlight));
-      senderSel.start = 0; senderSel.length = styledSender.text.length();
+      senderSel.start = 0; senderSel.length = styledSender.plainText.length();
       senderFormat = calcFormatRanges(styledSender, senderSel);
       textSel.format.setForeground(pal.brush(QPalette::HighlightedText));
       textSel.format.setBackground(pal.brush(QPalette::Highlight));
-      textSel.start = 0; textSel.length = styledText.text.length();
-      textFormat = calcFormatRanges(styledText, textSel);
+      textSel.start = 0; textSel.length = styledContents.plainText.length();
+      textFormat = calcFormatRanges(styledContents, textSel);
       break;
   }
 }
@@ -152,11 +152,11 @@ QDateTime ChatLineOld::timestamp() const {
 }
 
 QString ChatLineOld::sender() const {
-  return styledSender.text;
+  return styledSender.plainText;
 }
 
 QString ChatLineOld::text() const {
-  return styledText.text;
+  return styledContents.plainText;
 }
 
 bool ChatLineOld::isUrl(int c) const {
@@ -167,7 +167,7 @@ bool ChatLineOld::isUrl(int c) const {
 QUrl ChatLineOld::getUrl(int c) const {
   if(c < 0 || c >= charUrlIdx.count()) return QUrl();
   int i = charUrlIdx[c];
-  if(i >= 0) return styledText.urls[i].url;
+  if(i >= 0) return styledContents.urls[i].url;
   else return QUrl();
 }
 
@@ -197,18 +197,18 @@ int ChatLineOld::posToCursor(QPointF pos) {
 void ChatLineOld::precomputeLine() {
   tsFormat = calcFormatRanges(styledTimeStamp);
   senderFormat = calcFormatRanges(styledSender);
-  textFormat = calcFormatRanges(styledText);
+  textFormat = calcFormatRanges(styledContents);
 
   minHeight = 0;
   foreach(FormatRange fr, tsFormat) minHeight = qMax(minHeight, fr.height);
   foreach(FormatRange fr, senderFormat) minHeight = qMax(minHeight, fr.height);
 
   words.clear();
-  charPos.resize(styledText.text.length() + 1);
-  charHeights.resize(styledText.text.length());
-  charUrlIdx.fill(-1, styledText.text.length());
-  for(int i = 0; i < styledText.urls.count(); i++) {
-    QtUiStyle::UrlInfo url = styledText.urls[i];
+  charPos.resize(styledContents.plainText.length() + 1);
+  charHeights.resize(styledContents.plainText.length());
+  charUrlIdx.fill(-1, styledContents.plainText.length());
+  for(int i = 0; i < styledContents.urls.count(); i++) {
+    QtUiStyle::UrlInfo url = styledContents.urls[i];
     for(int j = url.start; j < url.end; j++) charUrlIdx[j] = i;
   }
   if(!textFormat.count()) return;
@@ -216,10 +216,10 @@ void ChatLineOld::precomputeLine() {
   QFontMetrics metrics(textFormat[0].format.font());
   Word wr;
   wr.start = -1; wr.trailing = -1;
-  for(int i = 0; i < styledText.text.length(); ) {
+  for(int i = 0; i < styledContents.plainText.length(); ) {
     charPos[i] = w; charHeights[i] = textFormat[idx].height;
-    w += metrics.charWidth(styledText.text, i);
-    if(!styledText.text[i].isSpace()) {
+    w += metrics.charWidth(styledContents.plainText, i);
+    if(!styledContents.plainText[i].isSpace()) {
       if(wr.trailing >= 0) {
         // new word after space
         words.append(wr);
@@ -237,13 +237,13 @@ void ChatLineOld::precomputeLine() {
         wr.trailing++;
       }
     }
-    if(++i < styledText.text.length() && ++cnt >= textFormat[idx].length) {
+    if(++i < styledContents.plainText.length() && ++cnt >= textFormat[idx].length) {
       cnt = 0; idx++;
       Q_ASSERT(idx < textFormat.count());
       metrics = QFontMetrics(textFormat[idx].format.font());
     }
   }
-  charPos[styledText.text.length()] = w;
+  charPos[styledContents.plainText.length()] = w;
   if(wr.start >= 0) words.append(wr);
 }
 
@@ -346,14 +346,14 @@ void ChatLineOld::draw(QPainter *p, const QPointF &pos) {
   foreach(FormatRange fr, tsFormat) {
     p->setFont(fr.format.font());
     p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background());
-    p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, styledTimeStamp.text.mid(fr.start, fr.length), &brect);
+    p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, styledTimeStamp.plainText.mid(fr.start, fr.length), &brect);
     rect.setLeft(brect.right());
   }
   rect = QRectF(pos + QPointF(tsWidth + QtUi::style()->sepTsSender(), 0), QSizeF(senderWidth, minHeight));
   for(int i = senderFormat.count() - 1; i >= 0; i--) {
     FormatRange fr = senderFormat[i];
     p->setFont(fr.format.font()); p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background());
-    p->drawText(rect, Qt::AlignRight|Qt::TextSingleLine, styledSender.text.mid(fr.start, fr.length), &brect);
+    p->drawText(rect, Qt::AlignRight|Qt::TextSingleLine, styledSender.plainText.mid(fr.start, fr.length), &brect);
     rect.setRight(brect.left());
   }
   QPointF tpos = pos + QPointF(tsWidth + QtUi::style()->sepTsSender() + senderWidth + QtUi::style()->sepSenderText(), 0);
@@ -371,7 +371,7 @@ void ChatLineOld::draw(QPainter *p, const QPointF &pos) {
       llend = lineLayouts[l].start + lineLayouts[l].length;
       start = qMax(fr.start, lineLayouts[l].start); end = qMin(frend, llend);
       rect.setLeft(tpos.x() + charPos[start] - offset);
-      p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, styledText.text.mid(start, end - start), &brect);
+      p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, styledContents.plainText.mid(start, end - start), &brect);
       if(llend <= end) {
         h += lineLayouts[l].height;
         l++;
index 5ce5fc3..b2b9445 100644 (file)
@@ -70,7 +70,7 @@ class ChatLineOld : public QObject, public AbstractUiMsg {
     qreal hght;
     Message msg;
     qreal tsWidth, senderWidth, textWidth;
-    UiStyle::StyledText styledTimeStamp, styledSender, styledText;
+    UiStyle::StyledText styledTimeStamp, styledSender, styledContents;
 
     struct FormatRange {
       int start;
diff --git a/src/qtui/chatlinemodel.cpp b/src/qtui/chatlinemodel.cpp
new file mode 100644 (file)
index 0000000..9ca1ff8
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *   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 "chatlinemodel.h"
+
+#include "chatlinemodelitem.h"
+
+ChatlineModel::ChatlineModel(QObject *parent) : MessageModel(parent) {
+
+
+}
+
+ChatlineModel::~ChatlineModel() {
+
+}
+
+
+MessageModelItem *ChatlineModel::createMessageModelItem(const Message &msg) {
+  return new ChatlineModelItem(msg);
+
+}
diff --git a/src/qtui/chatlinemodel.h b/src/qtui/chatlinemodel.h
new file mode 100644 (file)
index 0000000..11c9a07
--- /dev/null
@@ -0,0 +1,43 @@
+/***************************************************************************
+ *   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 CHATLINEMODEL_H_
+#define CHATLINEMODEL_H_
+
+#include "messagemodel.h"
+
+class ChatlineModel : public MessageModel {
+  Q_OBJECT
+
+  public:
+    enum ChatlineRole {
+      FormatRole = MessageModel::UserRole
+    };
+
+    ChatlineModel(QObject *parent = 0);
+    virtual ~ChatlineModel();
+
+  protected:
+    virtual MessageModelItem *createMessageModelItem(const Message &);
+
+};
+
+#endif
+
diff --git a/src/qtui/chatlinemodelitem.cpp b/src/qtui/chatlinemodelitem.cpp
new file mode 100644 (file)
index 0000000..009d535
--- /dev/null
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 "chatlinemodelitem.h"
+#include "chatlinemodel.h"
+#include "qtui.h"
+#include "uistyle.h"
+
+ChatlineModelItem::ChatlineModelItem(const Message &msg) : MessageModelItem(msg) {
+  QtUiStyle::StyledMessage m = QtUi::style()->styleMessage(msg);
+
+  _timestamp.plainText = m.timestamp.plainText;
+  _sender.plainText = m.sender.plainText;
+  _contents.plainText = m.contents.plainText;
+
+  _timestamp.formatList = m.timestamp.formatList;
+  _sender.formatList = m.sender.formatList;
+  _contents.formatList = m.contents.formatList;
+
+}
+
+
+QVariant ChatlineModelItem::data(int column, int role) const {
+  const ChatlinePart *part;
+
+  switch(column) {
+    case ChatlineModel::TimestampColumn: part = &_timestamp; break;
+    case ChatlineModel::SenderColumn:    part = &_sender; break;
+    case ChatlineModel::TextColumn:      part = &_contents; break;
+    default: return MessageModelItem::data(column, role);
+  }
+
+  switch(role) {
+    case ChatlineModel::DisplayRole: return part->plainText;
+    case ChatlineModel::FormatRole:  return QVariant::fromValue<UiStyle::FormatList>(part->formatList);
+  }
+
+  return MessageModelItem::data(column, role);
+}
+
+bool ChatlineModelItem::setData(int column, const QVariant &value, int role) {
+  return false;
+}
diff --git a/src/qtui/chatlinemodelitem.h b/src/qtui/chatlinemodelitem.h
new file mode 100644 (file)
index 0000000..4d5469e
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 CHATLINEMODELITEM_H_
+#define CHATLINEMODELITEM_H_
+
+#include "messagemodel.h"
+#include "uistyle.h"
+
+class ChatlineModelItem : public MessageModelItem {
+
+  public:
+    ChatlineModelItem(const Message &);
+    //virtual ~ChatlineModelItem() {};
+
+    virtual QVariant data(int column, int role) const;
+    virtual bool setData(int column, const QVariant &value, int role);
+
+  private:
+    struct ChatlinePart {
+      QString plainText;
+      UiStyle::FormatList formatList;
+
+    };
+
+    ChatlinePart _timestamp, _sender, _contents;
+};
+
+#endif
diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp
new file mode 100644 (file)
index 0000000..a78c2ba
--- /dev/null
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 <QGraphicsSceneMouseEvent>
+#include <QPersistentModelIndex>
+
+#include "buffer.h"
+#include "chatitem.h"
+#include "chatlinemodelitem.h"
+#include "chatscene.h"
+#include "quasselui.h"
+
+ChatScene::ChatScene(MessageModel *model, QObject *parent) : QGraphicsScene(parent), _model(model) {
+  connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int, int)));
+  for(int i = 0; i < model->rowCount(); i++) {
+    ChatItem *item = new ChatItem(QPersistentModelIndex(model->index(i, 2)));
+    addItem(item);
+    item->setPos(30, i*item->boundingRect().height());
+  }
+
+  
+}
+
+ChatScene::~ChatScene() {
+
+
+}
+
+
+void ChatScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent ) {
+  /*
+  qDebug() << "recv" << mouseEvent->scenePos();
+  ChatLine *line = static_cast<ChatLine*>(itemAt(mouseEvent->scenePos()));
+  ChatItem *item = static_cast<ChatItem*>(itemAt(mouseEvent->scenePos()));
+  qDebug() << (void*)line << (void*)item;
+  if(line) {
+    line->myMousePressEvent(mouseEvent);
+  } else  QGraphicsScene::mousePressEvent(mouseEvent);
+  */
+}
diff --git a/src/qtui/chatscene.h b/src/qtui/chatscene.h
new file mode 100644 (file)
index 0000000..1ce9304
--- /dev/null
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 _CHATSCENE_H_
+#define _CHATSCENE_H_
+
+#include <QGraphicsScene>
+
+#include "messagemodel.h"
+
+class AbstractUiMsg;
+class Buffer;
+class ChatItem;
+class ChatLine;
+class QGraphicsSceneMouseEvent;
+
+class ChatScene : public QGraphicsScene {
+  Q_OBJECT
+
+  public:
+    ChatScene(MessageModel *model, QObject *parent);
+    virtual ~ChatScene();
+
+    Buffer *buffer() const;
+    inline MessageModel *model() const { return _model; }
+
+  public slots:
+
+  protected slots:
+
+    void mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent );
+
+  private:
+    //Buffer *_buffer;
+    //QList<ChatLine*> _lines;
+    MessageModel *_model;
+    QList<ChatItem *> _items;
+
+};
+
+#endif
diff --git a/src/qtui/chatview.cpp b/src/qtui/chatview.cpp
new file mode 100644 (file)
index 0000000..f76cf2a
--- /dev/null
@@ -0,0 +1,88 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 <QGraphicsTextItem>
+
+#include "buffer.h"
+#include "chatlinemodelitem.h"
+#include "chatscene.h"
+#include "chatview.h"
+#include "client.h"
+#include "quasselui.h"
+
+ChatView::ChatView(Buffer *buf, QWidget *parent) : QGraphicsView(parent), AbstractChatView() {
+  _scene = new ChatScene(Client::messageModel(), this);
+  setScene(_scene);
+
+  //QGraphicsTextItem *item = scene()->addText(buf->bufferInfo().bufferName());
+
+}
+
+
+ChatView::~ChatView() {
+
+}
+
+
+ChatScene *ChatView::scene() const {
+  return _scene;
+}
+
+
+void ChatView::clear()
+{
+}
+
+void ChatView::prependMsg(AbstractUiMsg *msg) {
+  //ChatLine *line = dynamic_cast<ChatLine*>(msg);
+  //Q_ASSERT(line);
+  //prependChatLine(line);
+}
+
+void ChatView::prependChatLine(ChatLine *line) {
+  //qDebug() << "prepending";
+}
+
+void ChatView::prependChatLines(QList<ChatLine *> clist) {
+
+}
+
+void ChatView::appendMsg(AbstractUiMsg *msg) {
+  //ChatLine *line = dynamic_cast<ChatLine*>(msg);
+  //Q_ASSERT(line);
+  //appendChatLine(line);
+}
+
+void ChatView::appendChatLine(ChatLine *line) {
+  //qDebug() << "appending";
+}
+
+
+void ChatView::appendChatLines(QList<ChatLine *> list) {
+  //foreach(ChatLine *line, list) {
+    
+  //}
+}
+
+void ChatView::setContents(const QList<AbstractUiMsg *> &list) {
+  //qDebug() << "setting" << list.count();
+  //appendChatLines(list);
+}
+
diff --git a/src/qtui/chatview.h b/src/qtui/chatview.h
new file mode 100644 (file)
index 0000000..7ae7c8d
--- /dev/null
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 CHATVIEW_H_
+#define CHATVIEW_H_
+
+#include <QGraphicsView>
+
+#include "abstractbuffercontainer.h"
+
+class AbstractUiMsg;
+class Buffer;
+class ChatLine;
+class ChatScene;
+
+class ChatView : public QGraphicsView, public AbstractChatView {
+  Q_OBJECT
+
+  public:
+    ChatView(Buffer *, QWidget *parent = 0);
+    ~ChatView();
+
+    ChatScene *scene() const;
+
+  public slots:
+
+    void clear();
+
+    void prependMsg(AbstractUiMsg *);
+    void appendMsg(AbstractUiMsg *);
+
+    void prependChatLine(ChatLine *);
+    void appendChatLine(ChatLine *);
+    void prependChatLines(QList<ChatLine *>);
+    void appendChatLines(QList<ChatLine *>);
+
+    void setContents(const QList<AbstractUiMsg *> &);
+
+  private:
+    ChatScene *_scene;
+};
+
+#endif
index ebd83f6..64d4fd7 100644 (file)
@@ -25,7 +25,6 @@
 #include "bufferviewconfig.h"
 #include "bufferviewfilter.h"
 #include "bufferviewmanager.h"
-#include "chatline-old.h"
 #include "client.h"
 #include "clientbacklogmanager.h"
 #include "coreconnectdlg.h"
@@ -275,6 +274,7 @@ void MainWin::setupNickWidget() {
 }
 
 void MainWin::setupChatMonitor() {
+#ifndef SPUTDEV
   VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this);
   dock->setObjectName("ChatMonitorDock");
 
@@ -293,6 +293,7 @@ void MainWin::setupChatMonitor() {
 
   addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
   ui.menuViews->addAction(dock->toggleViewAction());
+#endif /* SPUTDEV */
 }
 
 void MainWin::setupInputWidget() {
@@ -483,10 +484,6 @@ void MainWin::setDisconnectedState() {
   sslLabel->setPixmap(QPixmap());
 }
 
-AbstractUiMsg *MainWin::layoutMsg(const Message &msg) {
-  return new ChatLineOld(msg);
-}
-
 void MainWin::showCoreConnectionDlg(bool autoConnect) {
   coreConnectDlg = new CoreConnectDlg(this, autoConnect);
   connect(coreConnectDlg, SIGNAL(finished(int)), this, SLOT(coreConnectionDlgFinished(int)));
@@ -570,12 +567,13 @@ void MainWin::receiveMessage(const Message &msg) {
 
     UiSettings uiSettings;
 
+#ifndef SPUTDEV
     if(uiSettings.value("DisplayPopupMessages", QVariant(true)).toBool()) {
       // FIXME don't invoke style engine for this!
-      QString text = QtUi::style()->styleString(Message::mircToInternal(msg.text())).text;
+      QString text = QtUi::style()->styleString(Message::mircToInternal(msg.contents())).plainText;
       displayTrayIconMessage(title, text);
     }
-
+#endif
     if(uiSettings.value("AnimateTrayIcon", QVariant(true)).toBool()) {
       QApplication::alert(this);
       setTrayIconActivity(true);
index 96e0c71..e2e703f 100644 (file)
@@ -52,7 +52,6 @@ class MainWin : public QMainWindow {
     void init();
     void addBufferView(BufferViewConfig *config = 0);
 
-    AbstractUiMsg *layoutMsg(const Message &);
     void displayTrayIconMessage(const QString &title, const QString &message);
 
     virtual bool event(QEvent *event);
index b353921..a65a479 100644 (file)
 
 #include "qtui.h"
 
+#ifdef SPUTDEV
+# include "chatlinemodel.h"
+#else
+# include "chatline-old.h"
+#endif
 #include "mainwin.h"
-#include "chatline-old.h"
 
 QtUiStyle *QtUi::_style;
 
@@ -48,8 +52,21 @@ QtUiStyle *QtUi::style() {
   return _style;
 }
 
+MessageModel *QtUi::createMessageModel(QObject *parent) {
+#ifndef SPUTDEV
+  Q_UNUSED(parent)
+  return 0;
+#else
+  return new ChatlineModel(parent);
+#endif
+}
+
 AbstractUiMsg *QtUi::layoutMsg(const Message &msg) {
+#ifndef SPUTDEV
   return new ChatLineOld(msg);
+#else
+  return 0;
+#endif
 }
 
 void QtUi::connectedToCore() {
index f6f1db5..bbe31f7 100644 (file)
@@ -25,6 +25,7 @@
 #include "quasselui.h"
 
 class MainWin;
+class MessageModel;
 
 //! This class encapsulates Quassel's Qt-based GUI.
 /** This is basically a wrapper around MainWin, which is necessary because we cannot derive MainWin
@@ -37,6 +38,7 @@ class QtUi : public AbstractUi {
     QtUi();
     ~QtUi();
     //void init();
+    MessageModel *createMessageModel(QObject *parent = 0);
     AbstractUiMsg *layoutMsg(const Message &);
 
     static QtUiStyle *style();
index ab2774f..5688c06 100644 (file)
@@ -11,6 +11,14 @@ HDRS += aboutdlg.h bufferwidget.h chatline-old.h chatwidget.h \
         coreconnectdlg.h mainwin.h nicklistwidget.h qtui.h qtuisettings.h qtuistyle.h settingsdlg.h settingspagedlg.h \
         titlesetter.h topicbutton.h topicwidget.h verticaldock.h jumpkeyhandler.h
 
+# new chatline model stuff
+sputdev {
+  SRCS += chatitem.cpp chatlinemodelitem.cpp chatlinemodel.cpp chatscene.cpp chatview.cpp
+  HDRS += chatitem.h chatlinemodelitem.h chatlinemodel.h chatscene.h chatview.h
+  SRCS -= chatline-old.cpp chatwidget.cpp
+  HDRS -= chatline-old.h chatwidget.h
+}
+
 FORMNAMES = aboutdlg.ui mainwin.ui coreaccounteditdlg.ui coreconnectdlg.ui bufferviewwidget.ui bufferwidget.ui nicklistwidget.ui settingsdlg.ui \
             settingspagedlg.ui topicwidget.ui debugconsole.ui inputwidget.ui \
             coreconfigwizardintropage.ui coreconfigwizardadminuserpage.ui coreconfigwizardstorageselectionpage.ui coreconfigwizardsyncpage.ui
index cb4436d..78255dc 100644 (file)
 
 #include "qtuistyle.h"
 
+#ifndef SPUTDEV
 QtUiStyle::QtUiStyle() : UiStyle("QtUiStyle") {
+#else
+QtUiStyle::QtUiStyle() : UiStyle("QtUiStyleNew") {
+#endif
   // We need to just set our internal formats; everything else is done by the base class...
 
   // Internal message formats
index a180f3e..aae2401 100644 (file)
 Unless you *really* know what you do, leave this as ISO-8859-1!</string>
         </property>
         <property name="currentIndex" >
-         <number>0</number>
+         <number>1</number>
         </property>
         <widget class="QWidget" name="serversTab" >
          <property name="enabled" >
@@ -171,8 +171,8 @@ Unless you *really* know what you do, leave this as ISO-8859-1!</string>
           <rect>
            <x>0</x>
            <y>0</y>
-           <width>244</width>
-           <height>332</height>
+           <width>301</width>
+           <height>326</height>
           </rect>
          </property>
          <attribute name="title" >
@@ -337,8 +337,8 @@ Unless you *really* know what you do, leave this as ISO-8859-1!</string>
           <rect>
            <x>0</x>
            <y>0</y>
-           <width>244</width>
-           <height>332</height>
+           <width>301</width>
+           <height>326</height>
           </rect>
          </property>
          <attribute name="title" >
@@ -377,6 +377,13 @@ Unless you *really* know what you do, leave this as ISO-8859-1!</string>
              <bool>true</bool>
             </property>
             <layout class="QGridLayout" name="gridLayout" >
+             <item row="0" column="0" >
+              <widget class="QLabel" name="label_2" >
+               <property name="text" >
+                <string>Service:</string>
+               </property>
+              </widget>
+             </item>
              <item row="0" column="1" >
               <widget class="QLineEdit" name="autoIdentifyService" >
                <property name="enabled" >
@@ -387,30 +394,23 @@ Unless you *really* know what you do, leave this as ISO-8859-1!</string>
                </property>
               </widget>
              </item>
-             <item row="1" column="1" >
-              <widget class="QLineEdit" name="autoIdentifyPassword" >
+             <item row="1" column="0" >
+              <widget class="QLabel" name="label_3" >
                <property name="enabled" >
                 <bool>true</bool>
                </property>
-               <property name="echoMode" >
-                <enum>QLineEdit::Password</enum>
-               </property>
-              </widget>
-             </item>
-             <item row="0" column="0" >
-              <widget class="QLabel" name="label_2" >
                <property name="text" >
-                <string>Service:</string>
+                <string>Password:</string>
                </property>
               </widget>
              </item>
-             <item row="1" column="0" >
-              <widget class="QLabel" name="label_3" >
+             <item row="1" column="1" >
+              <widget class="QLineEdit" name="autoIdentifyPassword" >
                <property name="enabled" >
                 <bool>true</bool>
                </property>
-               <property name="text" >
-                <string>Password:</string>
+               <property name="echoMode" >
+                <enum>QLineEdit::Password</enum>
                </property>
               </widget>
              </item>
@@ -428,8 +428,8 @@ Unless you *really* know what you do, leave this as ISO-8859-1!</string>
           <rect>
            <x>0</x>
            <y>0</y>
-           <width>244</width>
-           <height>332</height>
+           <width>301</width>
+           <height>326</height>
           </rect>
          </property>
          <attribute name="title" >
index 4c26bfc..f2f60af 100644 (file)
@@ -45,17 +45,20 @@ void TopicButton::paintEvent(QPaintEvent *event) {
   QPainter painter(this);
   painter.setBackgroundMode(Qt::OpaqueMode);
 
+  // FIXME re-enable topic painting
+#ifndef SPUTDEV
   QRect drawRect = rect();
   QRect brect;
   QString textPart;
-  foreach(QTextLayout::FormatRange fr, styledText.formats) {
-    textPart = styledText.text.mid(fr.start, fr.length);
+  foreach(QTextLayout::FormatRange fr, styledContents.formatList) {
+    textPart = styledContents.plainText.mid(fr.start, fr.length);
     painter.setFont(fr.format.font());
     painter.setPen(QPen(fr.format.foreground(), 0));
     painter.setBackground(fr.format.background());
     painter.drawText(drawRect, Qt::AlignLeft|Qt::TextSingleLine, textPart, &brect);
     drawRect.setLeft(brect.right());
   }
+#endif
 }
 
 void TopicButton::setAndStyleText(const QString &text) {
@@ -64,9 +67,10 @@ void TopicButton::setAndStyleText(const QString &text) {
 
   setText(text); // this triggers a repaint event
 
-  styledText = QtUi::style()->styleString(Message::mircToInternal(text));
+#ifndef SPUTDEV
+  styledContents = QtUi::style()->styleString(Message::mircToInternal(text));
   int height = 1;
-  foreach(QTextLayout::FormatRange fr, styledText.formats) {
+  foreach(QTextLayout::FormatRange fr, styledContents.formatList) {
     height = qMax(height, QFontMetrics(fr.format.font()).height());
   }
 
@@ -75,7 +79,7 @@ void TopicButton::setAndStyleText(const QString &text) {
     height = QFontMetrics(qApp->font()).height();
   
   setFixedHeight(height);
-  
+#endif  
   // show topic in tooltip
   setToolTip(tr("%1\n\nClick to edit!").arg(QAbstractButton::text()));
 }
index e0b2188..71e9cd8 100644 (file)
@@ -38,7 +38,9 @@ protected:
   virtual void paintEvent(QPaintEvent *event);
 
 private:
-  UiStyle::StyledText styledText;
+#ifndef SPUTDEV
+  UiStyle::StyledText styledContents;
+#endif
   QSize _sizeHint;
 };
 
index c0e85ad..8e90fc6 100644 (file)
@@ -263,7 +263,11 @@ void BufferView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bott
       continue;
 
     bool isActive = networkIdx.data(NetworkModel::ItemActiveRole).toBool();
+#ifdef SPUTDEV
+    if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, true);
+#else
     if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, isActive);
+#endif
   }
 }
 
index 59dd184..e02549c 100644 (file)
@@ -266,7 +266,7 @@ QVariant BufferViewFilter::foreground(const QModelIndex &index) const {
 }
 
 void BufferViewFilter::source_rowsInserted(const QModelIndex &parent, int start, int end) {
-  if(parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType)
+  if(parent.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType)
     return;
 
   if(!config() || !config()->addNewBuffersAutomatically())
diff --git a/src/uisupport/old-uistyle.cpp b/src/uisupport/old-uistyle.cpp
new file mode 100644 (file)
index 0000000..83024aa
--- /dev/null
@@ -0,0 +1,242 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 <QApplication>
+
+#include "uistyle.h"
+#include "uistylesettings.h"
+
+UiStyle::UiStyle(const QString &settingsKey) : _settingsKey(settingsKey) {
+  // Default format
+  QTextCharFormat def;
+  def.setForeground(QBrush("#000000"));
+  def.setFont(QFont("Monospace", QApplication::font().pointSize()));
+  def.font().setFixedPitch(true);
+  def.font().setStyleHint(QFont::TypeWriter);
+  _defaultFormats = QVector<QTextCharFormat>(NumFormatTypes, def);
+  _customFormats = QVector<QTextCharFormat>(NumFormatTypes, QTextFormat().toCharFormat());
+
+  // Load saved custom formats
+  UiStyleSettings s(_settingsKey);
+  foreach(FormatType type, s.availableFormats()) {
+    _customFormats[type] = s.customFormat(type);
+  }
+
+  // Initialize color codes according to mIRC "standard"
+  QStringList colors;
+  //colors << "white" << "black" << "navy" << "green" << "red" << "maroon" << "purple" << "orange";
+  //colors << "yellow" << "lime" << "teal" << "aqua" << "royalblue" << "fuchsia" << "grey" << "silver";
+  colors << "#ffffff" << "#000000" << "#000080" << "#008000" << "#ff0000" << "#800000" << "#800080" << "#ffa500";
+  colors << "#ffff00" << "#00ff00" << "#008080" << "#00ffff" << "#4169E1" << "#ff00ff" << "#808080" << "#c0c0c0";
+
+  // Now initialize the mapping between FormatCodes and FormatTypes...
+  _formatCodes["%O"] = None;
+  _formatCodes["%B"] = Bold;
+  _formatCodes["%S"] = Italic;
+  _formatCodes["%U"] = Underline;
+  _formatCodes["%R"] = Reverse;
+
+  _formatCodes["%D0"] = PlainMsg;
+  _formatCodes["%Dn"] = NoticeMsg;
+  _formatCodes["%Ds"] = ServerMsg;
+  _formatCodes["%De"] = ErrorMsg;
+  _formatCodes["%Dj"] = JoinMsg;
+  _formatCodes["%Dp"] = PartMsg;
+  _formatCodes["%Dq"] = QuitMsg;
+  _formatCodes["%Dk"] = KickMsg;
+  _formatCodes["%Dr"] = RenameMsg;
+  _formatCodes["%Dm"] = ModeMsg;
+  _formatCodes["%Da"] = ActionMsg;
+
+  _formatCodes["%DT"] = Timestamp;
+  _formatCodes["%DS"] = Sender;
+  _formatCodes["%DN"] = Nick;
+  _formatCodes["%DH"] = Hostmask;
+  _formatCodes["%DC"] = ChannelName;
+  _formatCodes["%DM"] = ModeFlags;
+  _formatCodes["%DU"] = Url;
+
+  // Set color formats
+  for(int i = 0; i < 16; i++) {
+    QString idx = QString("%1").arg(i, (int)2, (int)10, (QChar)'0');
+    _formatCodes[QString("%Dcf%1").arg(idx)] = (FormatType)(FgCol00 + i);
+    _formatCodes[QString("%Dcb%1").arg(idx)] = (FormatType)(BgCol00 + i);
+    QTextCharFormat fgf, bgf;
+    fgf.setForeground(QBrush(QColor(colors[i]))); setFormat((FormatType)(FgCol00 + i), fgf, Settings::Default);
+    bgf.setBackground(QBrush(QColor(colors[i]))); setFormat((FormatType)(BgCol00 + i), bgf, Settings::Default);
+    //FIXME fix the havoc caused by ColorSettingsPage
+    setFormat((FormatType)(FgCol00 + i), fgf, Settings::Custom);
+    setFormat((FormatType)(BgCol00 + i), bgf, Settings::Custom);
+  }
+
+  // Set a few more standard formats
+  QTextCharFormat bold; bold.setFontWeight(QFont::Bold);
+  setFormat(Bold, bold, Settings::Default);
+
+  QTextCharFormat italic; italic.setFontItalic(true);
+  setFormat(Italic, italic, Settings::Default);
+
+  QTextCharFormat underline; underline.setFontUnderline(true);
+  setFormat(Underline, underline, Settings::Default);
+
+  // All other formats should be defined in derived classes.
+}
+
+UiStyle::~ UiStyle() {
+  
+}
+
+void UiStyle::setFormat(FormatType ftype, QTextCharFormat fmt, Settings::Mode mode) {
+  if(mode == Settings::Default) {
+    _defaultFormats[ftype] = fmt;
+  } else {
+    UiStyleSettings s(_settingsKey);
+    if(fmt != _defaultFormats[ftype]) {
+      _customFormats[ftype] = fmt;
+      s.setCustomFormat(ftype, fmt);
+    } else {
+      _customFormats[ftype] = QTextFormat().toCharFormat();
+      s.removeCustomFormat(ftype);
+    }
+  }
+}
+
+QTextCharFormat UiStyle::format(FormatType ftype, Settings::Mode mode) const {
+  if(mode == Settings::Custom && _customFormats[ftype].isValid()) return _customFormats[ftype];
+  else return _defaultFormats[ftype];
+}
+
+UiStyle::FormatType UiStyle::formatType(const QString & code) const {
+  if(_formatCodes.contains(code)) return _formatCodes.value(code);
+  return Invalid;
+}
+
+QString UiStyle::formatCode(FormatType ftype) const {
+  return _formatCodes.key(ftype);
+}
+
+UiStyle::StyledText UiStyle::styleString(const QString &_s) {
+  QString s = _s;
+  StyledText result;
+  QList<FormatType> fmtList;
+  fmtList.append(None);
+  QTextLayout::FormatRange curFmtRng;
+  curFmtRng.format = format(None);
+  curFmtRng.start = 0;
+  result.formatList.append(curFmtRng);
+  int pos = 0; int length = 0;
+  int fgCol = -1, bgCol = -1;  // marks current mIRC color
+  for(;;) {
+    pos = s.indexOf('%', pos);
+    if(pos < 0) break;
+    if(s[pos+1] == '%') { // escaped %, just remove one and continue
+      s.remove(pos, 1);
+      pos++;
+      continue;
+    } else if(s[pos+1] == 'D' && s[pos+2] == 'c') { // color code
+      if(s[pos+3] == '-') { // color off
+        if(fgCol >= 0) {
+          fmtList.removeAll((FormatType)(FgCol00 + fgCol));
+          fgCol = -1;
+        }
+        if(bgCol >= 0) {
+          fmtList.removeAll((FormatType)(BgCol00 + bgCol));
+          bgCol = -1;
+        }
+        curFmtRng.format = mergedFormat(fmtList);
+        length = 4;
+      } else {
+        int color = 10 * s[pos+4].digitValue() + s[pos+5].digitValue();
+        //TODO: use 99 as transparent color (re mirc color "standard")
+        color &= 0x0f;
+        int *colptr; FormatType coltype;
+        if(s[pos+3] == 'f') { // foreground
+          colptr = &fgCol; coltype = FgCol00;
+        } else {              // background
+          Q_ASSERT(s[pos+3] == 'b');
+          colptr = &bgCol; coltype = BgCol00;
+        }
+        if(*colptr >= 0) {
+          // color already set, remove format code and add new one
+          Q_ASSERT(fmtList.contains((FormatType)(coltype + *colptr)));
+          fmtList.removeAll((FormatType)(coltype + *colptr));
+          fmtList.append((FormatType)(coltype + color));
+          curFmtRng.format = mergedFormat(fmtList);
+        } else {
+          fmtList.append((FormatType)(coltype + color));
+          curFmtRng.format.merge(format(fmtList.last()));
+        }
+        *colptr = color;
+        length = 6;
+      }
+    } else if(s[pos+1] == 'O') { // reset formatting
+      fmtList.clear(); fmtList.append(None);
+      curFmtRng.format = format(None);
+      fgCol = bgCol = -1;
+      length = 2;
+    } else if(s[pos+1] == 'R') { // reverse
+      // TODO: implement reverse formatting
+
+      length = 2;
+    } else { // all others are toggles
+      QString code = QString("%") + s[pos+1];
+      if(s[pos+1] == 'D') code += s[pos+2];
+      FormatType ftype = formatType(code);
+      if(ftype == Invalid) {
+        qWarning(qPrintable(QString("Invalid format code in string: %1").arg(s)));
+        continue;
+      }
+      //Q_ASSERT(ftype != Invalid);
+      length = code.length();
+      if(!fmtList.contains(ftype)) {
+        // toggle it on
+        fmtList.append(ftype);
+        curFmtRng.format.merge(format(ftype));
+      } else {
+        // toggle it off
+        fmtList.removeAll(ftype);
+        curFmtRng.format = mergedFormat(fmtList);
+      }
+    }
+    s.remove(pos, length); // remove format code from string
+    // now see if something changed and else insert the format
+    if(curFmtRng.format == result.formatList.last().format) continue;  // no change, so we just ignore
+    curFmtRng.start = pos;
+    if(pos == result.formatList.last().start) {
+      // same starting point -> we just overwrite the old format
+      result.formatList.last() = curFmtRng;
+    } else {
+      // fix length of last format
+      result.formatList.last().length = pos - result.formatList.last().start;
+      result.formatList.append(curFmtRng);
+    }
+  }
+  result.formatList.last().length = s.length() - result.formatList.last().start;
+  if(result.formatList.last().length == 0) result.formatList.removeLast();
+  result.plainText = s;
+  return result;
+}
+
+QTextCharFormat UiStyle::mergedFormat(QList<FormatType> formatList) {
+  QTextCharFormat fmt;
+  foreach(FormatType ftype, formatList) {
+    fmt.merge(format(ftype));
+  }
+  return fmt;
+}
diff --git a/src/uisupport/old-uistyle.h b/src/uisupport/old-uistyle.h
new file mode 100644 (file)
index 0000000..7b58c12
--- /dev/null
@@ -0,0 +1,83 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   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 _OLD_UISTYLE_H_
+#define _OLD_UISTYLE_H_
+
+#include <QTextCharFormat>
+#include <QTextLayout>
+#include <QUrl>
+
+#include "message.h"
+#include "settings.h"
+
+class UiStyle {
+
+  public:
+    UiStyle(const QString &settingsKey);
+    virtual ~UiStyle();
+
+    /** This enumerates the possible formats a text element may have. */
+    enum FormatType {
+      None, Bold, Italic, Underline, Reverse,                                        // Standard formats
+      PlainMsg, NoticeMsg, ServerMsg, ErrorMsg, JoinMsg, PartMsg, QuitMsg, KickMsg,  // Internal message formats
+      RenameMsg, ModeMsg, ActionMsg,                                                 // ...cnt'd
+      Timestamp, Sender, Nick, Hostmask, ChannelName, ModeFlags, Url,                // individual elements
+      FgCol00, FgCol01, FgCol02, FgCol03, FgCol04, FgCol05, FgCol06, FgCol07,        // Color codes
+      FgCol08, FgCol09, FgCol10, FgCol11, FgCol12, FgCol13, FgCol14, FgCol15,
+      BgCol00, BgCol01, BgCol02, BgCol03, BgCol04, BgCol05, BgCol06, BgCol07,
+      BgCol08, BgCol09, BgCol10, BgCol11, BgCol12, BgCol13, BgCol14, BgCol15,
+      NumFormatTypes, Invalid   // Do not add anything after this
+    };
+
+    struct UrlInfo {
+      int start, end;
+      QUrl url;
+    };
+
+    struct StyledText {
+      QString plainText;
+      QList<QTextLayout::FormatRange> formatList;
+      QList<UrlInfo> urls;
+    };
+
+    StyledText styleString(const QString &);
+
+    void setFormat(FormatType, QTextCharFormat, Settings::Mode mode/* = Settings::Custom*/);
+    QTextCharFormat format(FormatType, Settings::Mode mode = Settings::Custom) const;
+
+    FormatType formatType(const QString &code) const;
+    QString formatCode(FormatType) const;
+
+  protected:
+
+
+  private:
+    QTextCharFormat mergedFormat(QList<FormatType>);
+
+    QVector<QTextCharFormat> _defaultFormats;
+    QVector<QTextCharFormat> _customFormats;
+    QHash<QString, FormatType> _formatCodes;
+
+    QString _settingsKey;
+
+};
+
+#endif
index 94c9742..10b25e7 100644 (file)
 
 #include "uistyle.h"
 #include "uistylesettings.h"
+#include "util.h"
 
 UiStyle::UiStyle(const QString &settingsKey) : _settingsKey(settingsKey) {
-  // Default format
-  QTextCharFormat def;
-  def.setForeground(QBrush("#000000"));
-  def.setFont(QFont("Monospace", QApplication::font().pointSize()));
-  def.font().setFixedPitch(true);
-  def.font().setStyleHint(QFont::TypeWriter);
-  _defaultFormats = QVector<QTextCharFormat>(NumFormatTypes, def);
-  _customFormats = QVector<QTextCharFormat>(NumFormatTypes, QTextFormat().toCharFormat());
+  // register FormatList if that hasn't happened yet
+  // FIXME I don't think this actually avoids double registration... then again... does it hurt?
+  if(QVariant::nameToType("UiStyle::FormatList") == QVariant::Invalid) {
+    qRegisterMetaType<FormatList>("UiStyle::FormatList");
+    qRegisterMetaTypeStreamOperators<FormatList>("UiStyle::FormatList");
+    Q_ASSERT(QVariant::nameToType("UiStyle::FormatList") != QVariant::Invalid);
+  }
 
+  // Default format
+  _defaultPlainFormat.setForeground(QBrush("#000000"));
+  _defaultPlainFormat.setFont(QFont("Monospace", QApplication::font().pointSize()));
+  _defaultPlainFormat.font().setFixedPitch(true);
+  _defaultPlainFormat.font().setStyleHint(QFont::TypeWriter);
+  setFormat(None, _defaultPlainFormat, Settings::Default);
+  
   // Load saved custom formats
   UiStyleSettings s(_settingsKey);
   foreach(FormatType type, s.availableFormats()) {
@@ -80,9 +87,6 @@ UiStyle::UiStyle(const QString &settingsKey) : _settingsKey(settingsKey) {
     QTextCharFormat fgf, bgf;
     fgf.setForeground(QBrush(QColor(colors[i]))); setFormat((FormatType)(FgCol00 + i), fgf, Settings::Default);
     bgf.setBackground(QBrush(QColor(colors[i]))); setFormat((FormatType)(BgCol00 + i), bgf, Settings::Default);
-    //FIXME fix the havoc caused by ColorSettingsPage
-    setFormat((FormatType)(FgCol00 + i), fgf, Settings::Custom);
-    setFormat((FormatType)(BgCol00 + i), bgf, Settings::Custom);
   }
 
   // Set a few more standard formats
@@ -115,11 +119,35 @@ void UiStyle::setFormat(FormatType ftype, QTextCharFormat fmt, Settings::Mode mo
       s.removeCustomFormat(ftype);
     }
   }
+  // TODO: invalidate only affected cached formats... if that's possible with less overhead than just rebuilding them
+  _cachedFormats.clear();
 }
 
 QTextCharFormat UiStyle::format(FormatType ftype, Settings::Mode mode) const {
-  if(mode == Settings::Custom && _customFormats[ftype].isValid()) return _customFormats[ftype];
-  else return _defaultFormats[ftype];
+  if(mode == Settings::Custom && _customFormats.contains(ftype)) return _customFormats.value(ftype);
+  else return _defaultFormats.value(ftype, QTextCharFormat());
+}
+
+// NOTE: This function is intimately tied to the values in FormatType. Don't change this
+//       until you _really_ know what you do!
+QTextCharFormat UiStyle::mergedFormat(quint32 ftype) {
+  if(_cachedFormats.contains(ftype)) return _cachedFormats[ftype];
+  if(ftype == Invalid) return QTextCharFormat();
+  // Now we construct the merged format, starting with the default
+  QTextCharFormat fmt = format(None);
+  // First: general message format
+  fmt.merge(format((FormatType)(ftype & 0x0f)));
+  // now more specific ones
+  for(quint32 mask = 0x0010; mask <= 0x2000; mask <<= 1) {
+    if(ftype & mask) fmt.merge(format((FormatType)mask));
+  }
+  // color codes!
+  if(ftype & 0x00400000) fmt.merge(format((FormatType)(ftype & 0x0f400000))); // foreground
+  if(ftype & 0x00800000) fmt.merge(format((FormatType)(ftype & 0xf0800000))); // background
+  // URL
+  if(ftype & Url) fmt.merge(format(Url));
+  _cachedFormats[ftype] = fmt;
+  return fmt;
 }
 
 UiStyle::FormatType UiStyle::formatType(const QString & code) const {
@@ -131,64 +159,38 @@ QString UiStyle::formatCode(FormatType ftype) const {
   return _formatCodes.key(ftype);
 }
 
-UiStyle::StyledText UiStyle::styleString(const QString &_s) {
-  QString s = _s;
-  StyledText result;
-  QList<FormatType> fmtList;
-  fmtList.append(None);
-  QTextLayout::FormatRange curFmtRng;
-  curFmtRng.format = format(None);
-  curFmtRng.start = 0;
-  result.formats.append(curFmtRng);
+// This method expects a well-formatted string, there is no error checking!
+// Since we create those ourselves, we should be pretty safe that nobody does something crappy here.
+UiStyle::StyledString UiStyle::styleString(const QString &s_) {
+  QString s = s_;
+  StyledString result;
+  result.formatList.append(qMakePair(0, (quint32)None));
+  quint32 curfmt = (quint32)None;
   int pos = 0; int length = 0;
-  int fgCol = -1, bgCol = -1;  // marks current mIRC color
   for(;;) {
     pos = s.indexOf('%', pos);
     if(pos < 0) break;
-    if(s[pos+1] == '%') { // escaped %, just remove one and continue
+    if(s[pos+1] == '%') { // escaped %, we just remove one and continue
       s.remove(pos, 1);
       pos++;
       continue;
-    } else if(s[pos+1] == 'D' && s[pos+2] == 'c') { // color code
-      if(s[pos+3] == '-') { // color off
-        if(fgCol >= 0) {
-          fmtList.removeAll((FormatType)(FgCol00 + fgCol));
-          fgCol = -1;
-        }
-        if(bgCol >= 0) {
-          fmtList.removeAll((FormatType)(BgCol00 + bgCol));
-          bgCol = -1;
-        }
-        curFmtRng.format = mergedFormat(fmtList);
+    }
+    if(s[pos+1] == 'D' && s[pos+2] == 'c') { // color code
+      if(s[pos+3] == '-') {  // color off
+        curfmt &= 0x003fffff;
         length = 4;
       } else {
         int color = 10 * s[pos+4].digitValue() + s[pos+5].digitValue();
         //TODO: use 99 as transparent color (re mirc color "standard")
         color &= 0x0f;
-        int *colptr; FormatType coltype;
-        if(s[pos+3] == 'f') { // foreground
-          colptr = &fgCol; coltype = FgCol00;
-        } else {              // background
-          Q_ASSERT(s[pos+3] == 'b');
-          colptr = &bgCol; coltype = BgCol00;
-        }
-        if(*colptr >= 0) {
-          // color already set, remove format code and add new one
-          Q_ASSERT(fmtList.contains((FormatType)(coltype + *colptr)));
-          fmtList.removeAll((FormatType)(coltype + *colptr));
-          fmtList.append((FormatType)(coltype + color));
-          curFmtRng.format = mergedFormat(fmtList);
-        } else {
-          fmtList.append((FormatType)(coltype + color));
-          curFmtRng.format.merge(format(fmtList.last()));
-        }
-        *colptr = color;
+        if(pos+3 == 'f')
+          curfmt |= (color << 24) | 0x00400000;
+        else
+          curfmt |= (color << 28) | 0x00800000;
         length = 6;
       }
     } else if(s[pos+1] == 'O') { // reset formatting
-      fmtList.clear(); fmtList.append(None);
-      curFmtRng.format = format(None);
-      fgCol = bgCol = -1;
+      curfmt &= 0x0000000f; // we keep message type-specific formatting
       length = 2;
     } else if(s[pos+1] == 'R') { // reverse
       // TODO: implement reverse formatting
@@ -202,41 +204,143 @@ UiStyle::StyledText UiStyle::styleString(const QString &_s) {
         qWarning(qPrintable(QString("Invalid format code in string: %1").arg(s)));
         continue;
       }
-      //Q_ASSERT(ftype != Invalid);
+      curfmt ^= ftype;
       length = code.length();
-      if(!fmtList.contains(ftype)) {
-        // toggle it on
-        fmtList.append(ftype);
-        curFmtRng.format.merge(format(ftype));
-      } else {
-        // toggle it off
-        fmtList.removeAll(ftype);
-        curFmtRng.format = mergedFormat(fmtList);
-      }
     }
-    s.remove(pos, length); // remove format code from string
-    // now see if something changed and else insert the format
-    if(curFmtRng.format == result.formats.last().format) continue;  // no change, so we just ignore
-    curFmtRng.start = pos;
-    if(pos == result.formats.last().start) {
-      // same starting point -> we just overwrite the old format
-      result.formats.last() = curFmtRng;
+    s.remove(pos, length);
+    if(pos == result.formatList.last().first)
+      result.formatList.last().second = curfmt;
+    else
+      result.formatList.append(qMakePair(pos, curfmt));
+  }
+  result.plainText = s;
+  return result;
+}
+
+QString UiStyle::mircToInternal(const QString &mirc_) {
+  QString mirc = mirc_;
+  mirc.replace('%', "%%");      // escape % just to be sure
+  mirc.replace('\x02', "%B");
+  mirc.replace('\x0f', "%O");
+  mirc.replace('\x12', "%R");
+  mirc.replace('\x16', "%R");
+  mirc.replace('\x1d', "%S");
+  mirc.replace('\x1f', "%U");
+
+  // Now we bring the color codes (\x03) in a sane format that can be parsed more easily later.
+  // %Dcfxx is foreground, %Dcbxx is background color, where xx is a 2 digit dec number denoting the color code.
+  // %Dc- turns color off.
+  // Note: We use the "mirc standard" as described in <http://www.mirc.co.uk/help/color.txt>.
+  //       This means that we don't accept something like \x03,5 (even though others, like WeeChat, do).
+  int pos = 0;
+  for(;;) {
+    pos = mirc.indexOf('\x03', pos);
+    if(pos < 0) break; // no more mirc color codes
+    QString ins, num;
+    int l = mirc.length();
+    int i = pos + 1;
+    // check for fg color
+    if(i < l && mirc[i].isDigit()) {
+      num = mirc[i++];
+      if(i < l && mirc[i].isDigit()) num.append(mirc[i++]);
+      else num.prepend('0');
+      ins = QString("%Dcf%1").arg(num);
+
+      if(i+1 < l && mirc[i] == ',' && mirc[i+1].isDigit()) {
+        i++;
+        num = mirc[i++];
+        if(i < l && mirc[i].isDigit()) num.append(mirc[i++]);
+        else num.prepend('0');
+        ins += QString("%Dcb%1").arg(num);
+      }
     } else {
-      // fix length of last format
-      result.formats.last().length = pos - result.formats.last().start;
-      result.formats.append(curFmtRng);
+      ins = "%Dc-";
     }
+    mirc.replace(pos, i-pos, ins);
   }
-  result.formats.last().length = s.length() - result.formats.last().start;
-  if(result.formats.last().length == 0) result.formats.removeLast();
-  result.text = s;
+  return mirc;
+}
+
+UiStyle::StyledMessage UiStyle::styleMessage(const Message &msg) {
+  QString user = userFromMask(msg.sender());
+  QString host = hostFromMask(msg.sender());
+  QString nick = nickFromMask(msg.sender());
+  QString txt = mircToInternal(msg.contents());
+  QString bufferName = msg.bufferInfo().bufferName();
+
+  StyledMessage result;
+
+  result.timestamp = styleString(tr("%DT[%1]").arg(msg.timestamp().toLocalTime().toString("hh:mm:ss")));
+
+  QString s, t;
+  switch(msg.type()) {
+    case Message::Plain:
+      s = tr("%DS<%1>").arg(nick); t = tr("%D0%1").arg(txt); break;
+    case Message::Notice:
+      s = tr("%Dn[%1]").arg(nick); t = tr("%Dn%1").arg(txt); break;
+    case Message::Server:
+      s = tr("%Ds*"); t = tr("%Ds%1").arg(txt); break;
+    case Message::Error:
+      s = tr("%De*"); t = tr("%De%1").arg(txt); break;
+    case Message::Join:
+      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%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:
+      s = tr("%Dq<--"); t = tr("%Dq%DN%DU%1%DU%DN %DH(%2@%3)%DH has quit").arg(nick, user, host);
+      if(!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt);
+      break;
+    case Message::Kick:
+      { s = tr("%Dk<-*");
+        QString victim = txt.section(" ", 0, 0);
+        //if(victim == ui.ownNick->currentText()) victim = tr("you");
+        QString kickmsg = txt.section(" ", 1);
+        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 == msg.contents()) t = tr("%DrYou are now known as %DN%1%DN").arg(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(txt);
+      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%1%DN %2").arg(nick).arg(txt);
+      break;
+    default:
+      s = tr("%De%1").arg(msg.sender());
+      t = tr("%De[%1]").arg(txt);
+  }
+  result.sender = styleString(s);
+  result.contents = styleString(t);
   return result;
 }
 
-QTextCharFormat UiStyle::mergedFormat(QList<FormatType> formatList) {
-  QTextCharFormat fmt;
-  foreach(FormatType ftype, formatList) {
-    fmt.merge(format(ftype));
+QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList) {
+  out << formatList.count();
+  UiStyle::FormatList::const_iterator it = formatList.begin();
+  while(it != formatList.end()) {
+    out << (*it).first << (*it).second;
+    ++it;
   }
-  return fmt;
+  return out;
+}
+
+QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList) {
+  int cnt;
+  in >> cnt;
+  for(int i = 0; i < cnt; i++) {
+    int pos; quint32 ftype;
+    in >> pos >> ftype;
+    formatList.append(qMakePair(pos, ftype));
+  }
+  return in;
 }
index c722be8..426b398 100644 (file)
 #ifndef _UISTYLE_H_
 #define _UISTYLE_H_
 
+#ifndef SPUTDEV
+# include "old-uistyle.h"
+#else
+
+#include <QDataStream>
 #include <QTextCharFormat>
 #include <QTextLayout>
 #include <QUrl>
 #include "settings.h"
 
 class UiStyle {
+  Q_DECLARE_TR_FUNCTIONS (UiStyle);
 
   public:
     UiStyle(const QString &settingsKey);
     virtual ~UiStyle();
 
-    /** This enumerates the possible formats a text element may have. */
+    typedef QList<QPair<int, quint32> > FormatList;
+
+    //! This enumerates the possible formats a text element may have. */
+    /** These formats are ordered on increasing importance, in cases where a given property is specified
+     *  by multiple active formats.
+     *  \NOTE: Do not change/add values here without also adapting the relevant
+     *         methods in this class (in particular mergedFormat())!
+     *         Also, we _do_ rely on certain properties of these values in styleString() and friends!
+     */
     enum FormatType {
-      None, Bold, Italic, Underline, Reverse,                                        // Standard formats
-      PlainMsg, NoticeMsg, ServerMsg, ErrorMsg, JoinMsg, PartMsg, QuitMsg, KickMsg,  // Internal message formats
-      RenameMsg, ModeMsg, ActionMsg,                                                 // ...cnt'd
-      Timestamp, Sender, Nick, Hostmask, ChannelName, ModeFlags, Url,                // individual elements
-      FgCol00, FgCol01, FgCol02, FgCol03, FgCol04, FgCol05, FgCol06, FgCol07,        // Color codes
-      FgCol08, FgCol09, FgCol10, FgCol11, FgCol12, FgCol13, FgCol14, FgCol15,
-      BgCol00, BgCol01, BgCol02, BgCol03, BgCol04, BgCol05, BgCol06, BgCol07,
-      BgCol08, BgCol09, BgCol10, BgCol11, BgCol12, BgCol13, BgCol14, BgCol15,
-      NumFormatTypes, Invalid   // Do not add anything after this
+      None            = 0x00000000,
+      Invalid         = 0x11111111,
+      // Message Formats (mutually exclusive!)
+      PlainMsg        = 0x00000001,
+      NoticeMsg       = 0x00000002,
+      ServerMsg       = 0x00000003,
+      ErrorMsg        = 0x00000004,
+      JoinMsg         = 0x00000005,
+      PartMsg         = 0x00000006,
+      QuitMsg         = 0x00000007,
+      KickMsg         = 0x00000008,
+      RenameMsg       = 0x00000009,
+      ModeMsg         = 0x0000000a,
+      ActionMsg       = 0x0000000b,
+      // Standard Formats
+      Bold            = 0x00000010,
+      Italic          = 0x00000020,
+      Underline       = 0x00000040,
+      Reverse         = 0x00000080,
+      // Individual parts of a message
+      Timestamp       = 0x00000100,
+      Sender          = 0x00000200,
+      Nick            = 0x00000400,
+      Hostmask        = 0x00000800,
+      ChannelName     = 0x00001000,
+      ModeFlags       = 0x00002000,
+      // URL is special, we want that to take precedence over the rest...
+      Url             = 0x00100000,
+      // Colors
+      FgCol00         = 0x00400000,
+      FgCol01         = 0x01400000,
+      FgCol02         = 0x02400000,
+      FgCol03         = 0x03400000,
+      FgCol04         = 0x04400000,
+      FgCol05         = 0x05400000,
+      FgCol06         = 0x06400000,
+      FgCol07         = 0x07400000,
+      FgCol08         = 0x08400000,
+      FgCol09         = 0x09400000,
+      FgCol10         = 0x0a400000,
+      FgCol11         = 0x0b400000,
+      FgCol12         = 0x0c400000,
+      FgCol13         = 0x0d400000,
+      FgCol14         = 0x0e400000,
+      FgCol15         = 0x0f400000,
+
+      BgCol00         = 0x00800000,
+      BgCol01         = 0x10800000,
+      BgCol02         = 0x20800000,
+      BgCol03         = 0x30800000,
+      BgCol04         = 0x40800000,
+      BgCol05         = 0x50800000,
+      BgCol06         = 0x60800000,
+      BgCol07         = 0x70800000,
+      BgCol08         = 0x80800000,
+      BgCol09         = 0x90800000,
+      BgCol10         = 0xa0800000,
+      BgCol11         = 0xb0800000,
+      BgCol12         = 0xc0800000,
+      BgCol13         = 0xd0800000,
+      BgCol14         = 0xe0800000,
+      BgCol15         = 0xf0800000
+
     };
 
     struct UrlInfo {
@@ -52,16 +120,23 @@ class UiStyle {
       QUrl url;
     };
 
-    struct StyledText {
-      QString text;
-      QList<QTextLayout::FormatRange> formats;
-      QList<UrlInfo> urls;
+    struct StyledString {
+      QString plainText;
+      FormatList formatList;  // starting pos, ftypes
+    };
+
+    struct StyledMessage {
+      StyledString timestamp;
+      StyledString sender;
+      StyledString contents;
     };
 
-    StyledText styleString(const QString &);
+    StyledString styleString(const QString &);
+    StyledMessage styleMessage(const Message &);
 
     void setFormat(FormatType, QTextCharFormat, Settings::Mode mode/* = Settings::Custom*/);
     QTextCharFormat format(FormatType, Settings::Mode mode = Settings::Custom) const;
+    QTextCharFormat mergedFormat(quint32 formatType);
 
     FormatType formatType(const QString &code) const;
     QString formatCode(FormatType) const;
@@ -70,14 +145,21 @@ class UiStyle {
 
 
   private:
-    QTextCharFormat mergedFormat(QList<FormatType>);
+    QString mircToInternal(const QString &);
 
-    QVector<QTextCharFormat> _defaultFormats;
-    QVector<QTextCharFormat> _customFormats;
+    QTextCharFormat _defaultPlainFormat;
+    QHash<FormatType, QTextCharFormat> _defaultFormats;
+    QHash<FormatType, QTextCharFormat> _customFormats;
+    QHash<quint32, QTextCharFormat> _cachedFormats;
     QHash<QString, FormatType> _formatCodes;
 
     QString _settingsKey;
-
 };
 
+QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList);
+QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList);
+
+Q_DECLARE_METATYPE(UiStyle::FormatList);
+
+#endif // SPUTDEV
 #endif
index 1f5de7f..d23c408 100644 (file)
@@ -6,6 +6,13 @@ SRCS += abstractbuffercontainer.cpp abstractitemview.cpp bufferview.cpp buffervi
 HDRS += abstractbuffercontainer.h abstractitemview.h bufferview.h bufferviewfilter.h clearablelineedit.h colorbutton.h \
         nickviewfilter.h inputline.h nickview.h settingspage.h tabcompleter.h uisettings.h uistyle.h uistylesettings.h
 
+!sputdev {
+  SRCS += old-uistyle.cpp
+  SRCS -= uistyle.cpp
+  HDRS += old-uistyle.h
+  HDRS -= uistyle.h
+}
+
 FORMNAMES = 
 
 for(ui, FORMNAMES) {
index 44d28eb..8a4fbd8 100644 (file)
@@ -3,7 +3,7 @@
 
 { using namespace Global;
 
-  quasselVersion = "0.2.0-beta2-pre";
+  quasselVersion = "0.3.0-pre";
   quasselDate = "2008-05-09";
   quasselBuild = 827;