QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk
CONFIG += x86 ppc
}
+
+sputdev {
+ DEFINES *= SPUTDEV
+}
#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;
_bufferSyncer(0),
_backlogManager(new ClientBacklogManager(this)),
_bufferViewManager(0),
+ _messageModel(0),
_connectedToCore(false),
_syncedToCore(false)
{
_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 &)));
}
}
+#ifndef SPUTDEV
void Client::recvMessage(const Message &message) {
Message msg = message;
Buffer *b;
// 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();
b = buffer(msg.bufferInfo());
b->appendMsg(msg);
}
-
//bufferModel()->updateBufferActivity(msg);
if(msg.type() == Message::Plain || msg.type() == Message::Notice || msg.type() == Message::Action) {
? 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_) {
layoutTimer->start();
}
}
+#endif /* SPUTDEV */
void Client::layoutMsg() {
if(layoutQueue.isEmpty()) {
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;
}
}
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;
}
class BufferInfo;
class Message;
+class MessageModel;
class Identity;
class Network;
-
class AbstractUi;
class AbstractUiMsg;
class NetworkModel;
class QTimer;
-
class Client : public QObject {
Q_OBJECT
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; }
ClientBacklogManager *_backlogManager;
BufferViewManager *_bufferViewManager;
+ MessageModel *_messageModel;
+
ClientMode clientMode;
bool _connectedToCore, _syncedToCore;
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
+}
+
--- /dev/null
+/***************************************************************************
+ * 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();
+ }
+}
+
--- /dev/null
+/***************************************************************************
+ * 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
#include <QObject>
#include "message.h"
+class MessageModel;
+
class AbstractUiMsg {
public:
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:
qRegisterMetaTypeStreamOperators<UserId>("UserId");
qRegisterMetaTypeStreamOperators<AccountId>("AccountId");
qRegisterMetaTypeStreamOperators<MsgId>("MsgId");
-
}
// Static variables
// 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;
#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");
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"));
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:
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;
}
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;
}
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();
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
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
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; }
_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 &)));
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);
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 ¶ms, 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 ¶m, const QByteArray &prefix = QByteArray());
void putCmd(const QString &cmd, const QList<QByteArray> ¶ms, const QByteArray &prefix = QByteArray());
//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 &)),
// 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));
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);
? CtcpReply
: CtcpQuery;
- quint8 flags = (messageType == Message::Notice && !network()->isChannelName(target))
+ Message::Flags flags = (messageType == Message::Notice && !network()->isChannelName(target))
? Message::Redirected
: Message::None;
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);
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()) {
(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;
}
(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;
}
(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;
}
}
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;
}
void UserInputHandler::handleOper(const BufferInfo &bufferInfo, const QString &msg) {
+ Q_UNUSED(bufferInfo)
emit putRawLine(serverEncode(QString("OPER %1").arg(msg)));
}
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();
return _styledSender;
}
-UiStyle::StyledText ChatLine::styledText() const {
- return _styledText;
+UiStyle::StyledText ChatLine::styledContents() const {
+ return _styledContents;
}
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;
if(!document()->isEmpty()) insertPlainText("\n");
insertStyledText(line->styledSender());
insertPlainText(" ");
- insertStyledText(line->styledText());
+ insertStyledText(line->styledContents());
setTextCursor(cursor);
}
bool flg = document()->isEmpty();
insertStyledText(line->styledSender());
insertPlainText(" ");
- insertStyledText(line->styledText());
+ insertStyledText(line->styledContents());
if(!flg) insertPlainText("\n");
setTextCursor(cursor);
}
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));
}
}
Global::runMode = Global::ClientOnly;
Global::defaultPort = 4242;
+ Global::DEBUG = true;
Network::setDefaultCodecForServer("ISO-8859-1");
Network::setDefaultCodecForEncoding("UTF-8");
***************************************************************************/
#include "bufferwidget.h"
-#include "chatline-old.h"
+#include "chatview.h"
#include "chatwidget.h"
#include "settings.h"
#include "client.h"
}
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);
--- /dev/null
+/***************************************************************************
+ * 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);
+}
+*/
+
+
+
--- /dev/null
+/***************************************************************************
+ * 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
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();
}
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;
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);
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;
}
}
}
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 {
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();
}
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;
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);
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);
}
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);
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++;
qreal hght;
Message msg;
qreal tsWidth, senderWidth, textWidth;
- UiStyle::StyledText styledTimeStamp, styledSender, styledText;
+ UiStyle::StyledText styledTimeStamp, styledSender, styledContents;
struct FormatRange {
int start;
--- /dev/null
+/***************************************************************************
+ * 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);
+
+}
--- /dev/null
+/***************************************************************************
+ * 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
+
--- /dev/null
+/***************************************************************************
+ * 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;
+}
--- /dev/null
+/***************************************************************************
+ * 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
--- /dev/null
+/***************************************************************************
+ * 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);
+ */
+}
--- /dev/null
+/***************************************************************************
+ * 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
--- /dev/null
+/***************************************************************************
+ * 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);
+}
+
--- /dev/null
+/***************************************************************************
+ * 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
#include "bufferviewconfig.h"
#include "bufferviewfilter.h"
#include "bufferviewmanager.h"
-#include "chatline-old.h"
#include "client.h"
#include "clientbacklogmanager.h"
#include "coreconnectdlg.h"
}
void MainWin::setupChatMonitor() {
+#ifndef SPUTDEV
VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this);
dock->setObjectName("ChatMonitorDock");
addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
ui.menuViews->addAction(dock->toggleViewAction());
+#endif /* SPUTDEV */
}
void MainWin::setupInputWidget() {
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)));
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);
void init();
void addBufferView(BufferViewConfig *config = 0);
- AbstractUiMsg *layoutMsg(const Message &);
void displayTrayIconMessage(const QString &title, const QString &message);
virtual bool event(QEvent *event);
#include "qtui.h"
+#ifdef SPUTDEV
+# include "chatlinemodel.h"
+#else
+# include "chatline-old.h"
+#endif
#include "mainwin.h"
-#include "chatline-old.h"
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() {
#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
QtUi();
~QtUi();
//void init();
+ MessageModel *createMessageModel(QObject *parent = 0);
AbstractUiMsg *layoutMsg(const Message &);
static QtUiStyle *style();
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
#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
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" >
<rect>
<x>0</x>
<y>0</y>
- <width>244</width>
- <height>332</height>
+ <width>301</width>
+ <height>326</height>
</rect>
</property>
<attribute name="title" >
<rect>
<x>0</x>
<y>0</y>
- <width>244</width>
- <height>332</height>
+ <width>301</width>
+ <height>326</height>
</rect>
</property>
<attribute name="title" >
<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" >
</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>
<rect>
<x>0</x>
<y>0</y>
- <width>244</width>
- <height>332</height>
+ <width>301</width>
+ <height>326</height>
</rect>
</property>
<attribute name="title" >
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) {
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());
}
height = QFontMetrics(qApp->font()).height();
setFixedHeight(height);
-
+#endif
// show topic in tooltip
setToolTip(tr("%1\n\nClick to edit!").arg(QAbstractButton::text()));
}
virtual void paintEvent(QPaintEvent *event);
private:
- UiStyle::StyledText styledText;
+#ifndef SPUTDEV
+ UiStyle::StyledText styledContents;
+#endif
QSize _sizeHint;
};
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
}
}
}
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())
--- /dev/null
+/***************************************************************************
+ * 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;
+}
--- /dev/null
+/***************************************************************************
+ * 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
#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()) {
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
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 {
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
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;
}
#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 {
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;
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
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) {
{ using namespace Global;
- quasselVersion = "0.2.0-beta2-pre";
+ quasselVersion = "0.3.0-pre";
quasselDate = "2008-05-09";
quasselBuild = 827;