I CAN HAZ A STYLE ENGINES!?
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 24 Oct 2007 00:39:10 +0000 (00:39 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 24 Oct 2007 00:39:10 +0000 (00:39 +0000)
Say hello to the new module "uisupport", which shall contain code that is shared
across UI implementations (and may depend on QtGui). For now, this is our brand-new
shiny style engine that replaces the dirty hack that was style.cpp/h. UI styles now derive
from UiStyle and set the text formats as they wish through an easy API.
ChatLine has been switched to use QtUiStyle, but since ChatLine might be removed soon, I
did not bother to fully implement this, which in particular means that text selections are
no longer displayed.

18 files changed:
Quassel.kdevelop.filelist
build/modules/module.pri
build/modules/uisupport.pro [new file with mode: 0644]
build/targets/monolithic.pri
build/targets/qtclient.pri
dev-notes/qxt-check [new file with mode: 0644]
qtopia-build/quasseltopia.pro
src/client/mappedselectionmodel.h
src/qtui/chatline.cpp
src/qtui/chatline.h
src/qtui/qtui.cpp
src/qtui/qtui.h
src/qtui/qtui.pri
src/qtui/qtuistyle.cpp [new file with mode: 0644]
src/qtui/qtuistyle.h [new file with mode: 0644]
src/uisupport/uistyle.cpp [new file with mode: 0644]
src/uisupport/uistyle.h [new file with mode: 0644]
src/uisupport/uisupport.pri [new file with mode: 0644]

index d79678a..6bd8bcc 100644 (file)
@@ -68,18 +68,18 @@ src/common/util.cpp
 src/common/util.h
 src/contrib
 src/contrib/qxt
 src/common/util.h
 src/contrib
 src/contrib/qxt
+src/contrib/qxt/qxt.pri
+src/contrib/qxt/qxt.pro
 src/contrib/qxt/qxtboundcfunction.h
 src/contrib/qxt/qxtboundcfunction.h
-src/contrib/qxt/qxtboundfunctionbase.h
 src/contrib/qxt/qxtboundfunction.h
 src/contrib/qxt/qxtboundfunction.h
+src/contrib/qxt/qxtboundfunctionbase.h
 src/contrib/qxt/qxtglobal.h
 src/contrib/qxt/qxtmetaobject.cpp
 src/contrib/qxt/qxtmetaobject.h
 src/contrib/qxt/qxtglobal.h
 src/contrib/qxt/qxtmetaobject.cpp
 src/contrib/qxt/qxtmetaobject.h
-src/contrib/qxt/qxtnullable.h
 src/contrib/qxt/qxtnull.cpp
 src/contrib/qxt/qxtnull.h
 src/contrib/qxt/qxtnull.cpp
 src/contrib/qxt/qxtnull.h
+src/contrib/qxt/qxtnullable.h
 src/contrib/qxt/qxtpimpl.h
 src/contrib/qxt/qxtpimpl.h
-src/contrib/qxt/qxt.pri
-src/contrib/qxt/qxt.pro
 src/contrib/qxt/qxtrpcpeer.cpp
 src/contrib/qxt/qxtrpcpeer.h
 src/core
 src/contrib/qxt/qxtrpcpeer.cpp
 src/contrib/qxt/qxtrpcpeer.h
 src/core
@@ -114,11 +114,11 @@ src/qtopia/coreconnectdlg.h
 src/qtopia/main.cpp
 src/qtopia/mainwidget.cpp
 src/qtopia/mainwidget.h
 src/qtopia/main.cpp
 src/qtopia/mainwidget.cpp
 src/qtopia/mainwidget.h
+src/qtopia/qtopia.pri
 src/qtopia/qtopiagui.cpp
 src/qtopia/qtopiagui.h
 src/qtopia/qtopiamainwin.cpp
 src/qtopia/qtopiamainwin.h
 src/qtopia/qtopiagui.cpp
 src/qtopia/qtopiagui.h
 src/qtopia/qtopiamainwin.cpp
 src/qtopia/qtopiamainwin.h
-src/qtopia/qtopia.pri
 src/qtopia/topicbar.cpp
 src/qtopia/topicbar.h
 src/qtopia/ui
 src/qtopia/topicbar.cpp
 src/qtopia/topicbar.h
 src/qtopia/ui
@@ -128,9 +128,9 @@ src/qtopia/ui/editcoreacctdlg.ui
 src/qtopia/ui/mainwidget.ui
 src/qtui
 src/qtui/bufferview.cpp
 src/qtopia/ui/mainwidget.ui
 src/qtui
 src/qtui/bufferview.cpp
+src/qtui/bufferview.h
 src/qtui/bufferviewfilter.cpp
 src/qtui/bufferviewfilter.h
 src/qtui/bufferviewfilter.cpp
 src/qtui/bufferviewfilter.h
-src/qtui/bufferview.h
 src/qtui/bufferwidget.cpp
 src/qtui/bufferwidget.h
 src/qtui/channelwidgetinput.cpp
 src/qtui/bufferwidget.cpp
 src/qtui/bufferwidget.h
 src/qtui/channelwidgetinput.cpp
@@ -150,6 +150,8 @@ src/qtui/mainwin.h
 src/qtui/qtui.cpp
 src/qtui/qtui.h
 src/qtui/qtui.pri
 src/qtui/qtui.cpp
 src/qtui/qtui.h
 src/qtui/qtui.pri
+src/qtui/qtuistyle.cpp
+src/qtui/qtuistyle.h
 src/qtui/serverlist.cpp
 src/qtui/serverlist.h
 src/qtui/settingsdlg.cpp
 src/qtui/serverlist.cpp
 src/qtui/serverlist.h
 src/qtui/settingsdlg.cpp
@@ -182,3 +184,6 @@ src/qtui/ui/serverlistdlg.ui
 src/qtui/ui/settingsdlg.ui
 src/qtui/ui/topicwidget.ui
 src/qtui/ui/usermgmtpage.ui
 src/qtui/ui/settingsdlg.ui
 src/qtui/ui/topicwidget.ui
 src/qtui/ui/usermgmtpage.ui
+src/uisupport
+src/uisupport/uistyle.cpp
+src/uisupport/uistyle.h
index 1b68064..8054d40 100644 (file)
@@ -15,7 +15,6 @@ MODNAME = $$basename(MODULE)
 MODPATH_PREFIX = $$dirname(MODULE)
 !isEmpty(MODPATH_PREFIX) {
   MODPATH_PREFIX ~= s,[^/]+,..
 MODPATH_PREFIX = $$dirname(MODULE)
 !isEmpty(MODPATH_PREFIX) {
   MODPATH_PREFIX ~= s,[^/]+,..
-  #sprintf($$MODPATH_PREFIX%1
   SRCPATH = $$MODPATH_PREFIX/$$SRCPATH
 }
 
   SRCPATH = $$MODPATH_PREFIX/$$SRCPATH
 }
 
diff --git a/build/modules/uisupport.pro b/build/modules/uisupport.pro
new file mode 100644 (file)
index 0000000..a996a1f
--- /dev/null
@@ -0,0 +1,2 @@
+MODULE = uisupport
+include(module.pri)
index 131a01b..b848f9f 100644 (file)
@@ -1,7 +1,7 @@
 # Modules for monolithic client
 
 TARGET  = quassel
 # Modules for monolithic client
 
 TARGET  = quassel
-MODULES = core qtui client common contrib/qxt
+MODULES = core qtui uisupport client common contrib/qxt
 DEFINES = BUILD_MONO
 
 QT += network sql
 DEFINES = BUILD_MONO
 
 QT += network sql
index 529caf0..bbca57b 100644 (file)
@@ -1,7 +1,7 @@
 # Modules for quasselclient
 
 TARGET  = quasselclient
 # Modules for quasselclient
 
 TARGET  = quasselclient
-MODULES = qtui client common contrib/qxt
+MODULES = qtui uisupport client common contrib/qxt
 DEFINES = BUILD_QTUI
 
 QT += network
 DEFINES = BUILD_QTUI
 
 QT += network
diff --git a/dev-notes/qxt-check b/dev-notes/qxt-check
new file mode 100644 (file)
index 0000000..3ed293a
--- /dev/null
@@ -0,0 +1,4 @@
+CONFIG += QXT
+
+defined(QXTINSTALLDIR):message(you're Qt installation is extended)
+you can also check for  $$[QT_INSTALL_DATA]/mkspecs/features/qxt.prf
index 3110cc7..72edf5e 100644 (file)
@@ -5,7 +5,7 @@ CONFIG+=debug qtopia_main no_quicklaunch no_singleexec no_sxe_test
 QT = core gui network
 
 # Find files
 QT = core gui network
 
 # Find files
-INCLUDEPATH+=../src/qtopia ../src/client ../src/common ../src/contrib/qxt
+INCLUDEPATH+=../src/qtopia ../src/uisupport ../src/client ../src/common ../src/contrib/qxt
 
 
 # Include .pri from src dirs
 
 
 # Include .pri from src dirs
@@ -13,6 +13,7 @@ include(../src/contrib/qxt/qxt.pri)
 include(../src/common/common.pri)
 include(../src/qtopia/qtopia.pri)
 include(../src/client/client.pri)
 include(../src/common/common.pri)
 include(../src/qtopia/qtopia.pri)
 include(../src/client/client.pri)
+include(../src/uisupport/uisupport.pri)
 
 # Fix variable names
 SOURCES = $$SRCS
 
 # Fix variable names
 SOURCES = $$SRCS
index 226f81e..35f3618 100644 (file)
@@ -24,7 +24,7 @@
 #include <QObject>
 #include <QModelIndex>
 #include <QItemSelection>
 #include <QObject>
 #include <QModelIndex>
 #include <QItemSelection>
-#include <QItemSelectionModel>;
+#include <QItemSelectionModel>
 
 class QAbstractProxyModel;
 
 
 class QAbstractProxyModel;
 
index 335e15b..f3b4a35 100644 (file)
@@ -19,6 +19,7 @@
  ***************************************************************************/
 
 #include "chatline.h"
  ***************************************************************************/
 
 #include "chatline.h"
+#include "qtui.h"
 
 //!\brief Construct a ChatLine object from a message.
 /**
 
 //!\brief Construct a ChatLine object from a message.
 /**
@@ -41,14 +42,29 @@ ChatLine::~ChatLine() {
 
 void ChatLine::formatMsg(Message msg) {
   QTextOption tsOption, senderOption, textOption;
 
 void ChatLine::formatMsg(Message msg) {
   QTextOption tsOption, senderOption, textOption;
-  styledTimeStamp = Style::formattedToStyled(msg.formattedTimeStamp());
-  styledSender = Style::formattedToStyled(msg.formattedSender());
-  styledText = Style::formattedToStyled(msg.formattedText());
+  styledTimeStamp = QtUi::style()->styleString(msg.formattedTimeStamp());
+  styledSender = QtUi::style()->styleString(msg.formattedSender());
+  styledText = QtUi::style()->styleString(msg.formattedText());
   precomputeLine();
 }
 
   precomputeLine();
 }
 
-QList<ChatLine::FormatRange> ChatLine::calcFormatRanges(const Style::StyledString &fs, QTextLayout::FormatRange additional) {
+// This function is almost obsolete, since with the new style engine, we already get a list of formats...
+// We don't know yet if we keep this implementation of ChatLine, so I won't bother making this actually nice.
+// Also, the additional format is ignored for now, which means that you won't see a selection...
+// FIXME TODO
+QList<ChatLine::FormatRange> ChatLine::calcFormatRanges(const UiStyle::StyledString &fs, QTextLayout::FormatRange additional) {
   QList<FormatRange> ranges;
   QList<FormatRange> ranges;
+
+  foreach(QTextLayout::FormatRange f, fs.formats) {
+    FormatRange range;
+    range.start = f.start;
+    range.length = f.length;
+    range.format = f.format;
+    QFontMetrics metrics(range.format.font());
+    range.height = metrics.lineSpacing();
+    ranges.append(range);
+  }
+  /*
   QList<QTextLayout::FormatRange> formats = fs.formats;
   formats.append(additional);
   int cur = -1;
   QList<QTextLayout::FormatRange> formats = fs.formats;
   formats.append(additional);
   int cur = -1;
@@ -77,6 +93,7 @@ QList<ChatLine::FormatRange> ChatLine::calcFormatRanges(const Style::StyledStrin
     range.height = metrics.lineSpacing();
     ranges.append(range);
   }
     range.height = metrics.lineSpacing();
     ranges.append(range);
   }
+  */
   return ranges;
 }
 
   return ranges;
 }
 
@@ -156,8 +173,8 @@ QUrl ChatLine::getUrl(int c) const {
  * \return The cursor position, [or -3 for invalid,] or -2 for timestamp, or -1 for sender
  */
 int ChatLine::posToCursor(QPointF pos) {
  * \return The cursor position, [or -3 for invalid,] or -2 for timestamp, or -1 for sender
  */
 int ChatLine::posToCursor(QPointF pos) {
-  if(pos.x() < tsWidth + (int)Style::sepTsSender()/2) return -2;
-  qreal textStart = tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText();
+  if(pos.x() < tsWidth + (int)QtUi::style()->sepTsSender()/2) return -2;
+  qreal textStart = tsWidth + QtUi::style()->sepTsSender() + senderWidth + QtUi::style()->sepSenderText();
   if(pos.x() < textStart) return -1;
   int x = (int)(pos.x() - textStart);
   for(int l = lineLayouts.count() - 1; l >=0; l--) {
   if(pos.x() < textStart) return -1;
   int x = (int)(pos.x() - textStart);
   for(int l = lineLayouts.count() - 1; l >=0; l--) {
@@ -187,7 +204,7 @@ void ChatLine::precomputeLine() {
   charHeights.resize(styledText.text.length());
   charUrlIdx.fill(-1, styledText.text.length());
   for(int i = 0; i < styledText.urls.count(); i++) {
   charHeights.resize(styledText.text.length());
   charUrlIdx.fill(-1, styledText.text.length());
   for(int i = 0; i < styledText.urls.count(); i++) {
-    Style::UrlInfo url = styledText.urls[i];
+    QtUiStyle::UrlInfo url = styledText.urls[i];
     for(int j = url.start; j < url.end; j++) charUrlIdx[j] = i;
   }
   if(!textFormat.count()) return;
     for(int j = url.start; j < url.end; j++) charUrlIdx[j] = i;
   }
   if(!textFormat.count()) return;
@@ -298,7 +315,7 @@ void ChatLine::draw(QPainter *p, const QPointF &pos) {
   if(selectionMode == Full) {
     p->setPen(Qt::NoPen);
     p->setBrush(pal.brush(QPalette::Highlight));
   if(selectionMode == Full) {
     p->setPen(Qt::NoPen);
     p->setBrush(pal.brush(QPalette::Highlight));
-    p->drawRect(QRectF(pos, QSizeF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText() + textWidth, height())));
+    p->drawRect(QRectF(pos, QSizeF(tsWidth + QtUi::style()->sepTsSender() + senderWidth + QtUi::style()->sepSenderText() + textWidth, height())));
   } else if(selectionMode == Partial) {
 
   } /*
   } else if(selectionMode == Partial) {
 
   } /*
@@ -321,14 +338,14 @@ void ChatLine::draw(QPainter *p, const QPointF &pos) {
     p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, styledTimeStamp.text.mid(fr.start, fr.length), &brect);
     rect.setLeft(brect.right());
   }
     p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, styledTimeStamp.text.mid(fr.start, fr.length), &brect);
     rect.setLeft(brect.right());
   }
-  rect = QRectF(pos + QPointF(tsWidth + Style::sepTsSender(), 0), QSizeF(senderWidth, minHeight));
+  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);
     rect.setRight(brect.left());
   }
   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);
     rect.setRight(brect.left());
   }
-  QPointF tpos = pos + QPointF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(), 0);
+  QPointF tpos = pos + QPointF(tsWidth + QtUi::style()->sepTsSender() + senderWidth + QtUi::style()->sepSenderText(), 0);
   qreal h = 0; int l = 0;
   rect = QRectF(tpos + QPointF(0, h), QSizeF(textWidth, lineLayouts[l].height));
   int offset = 0;
   qreal h = 0; int l = 0;
   rect = QRectF(tpos + QPointF(0, h), QSizeF(textWidth, lineLayouts[l].height));
   int offset = 0;
index 2707a17..be84f24 100644 (file)
@@ -24,7 +24,7 @@
 #include <QtGui>
 
 #include "util.h"
 #include <QtGui>
 
 #include "util.h"
-#include "style.h"
+#include "uistyle.h"
 #include "quasselui.h"
 
 //FIXME: chatline doku
 #include "quasselui.h"
 
 //FIXME: chatline doku
@@ -70,7 +70,7 @@ class ChatLine : public QObject, public AbstractUiMsg {
     qreal hght;
     Message msg;
     qreal tsWidth, senderWidth, textWidth;
     qreal hght;
     Message msg;
     qreal tsWidth, senderWidth, textWidth;
-    Style::StyledString styledTimeStamp, styledSender, styledText;
+    UiStyle::StyledString styledTimeStamp, styledSender, styledText;
 
     struct FormatRange {
       int start;
 
     struct FormatRange {
       int start;
@@ -103,7 +103,7 @@ class ChatLine : public QObject, public AbstractUiMsg {
     int selectionStart, selectionEnd;
     void formatMsg(Message);
     void precomputeLine();
     int selectionStart, selectionEnd;
     void formatMsg(Message);
     void precomputeLine();
-    QList<FormatRange> calcFormatRanges(const Style::StyledString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange());
+    QList<FormatRange> calcFormatRanges(const UiStyle::StyledString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange());
 };
 
 #endif
 };
 
 #endif
index 157aafe..adcbe4c 100644 (file)
 
 #include "mainwin.h"
 
 
 #include "mainwin.h"
 
+QtUiStyle *QtUi::_style;
+
 QtUi::QtUi() : AbstractUi() {
   mainWin = new MainWin(this);
 QtUi::QtUi() : AbstractUi() {
   mainWin = new MainWin(this);
+  _style = new QtUiStyle;
+
   connect(mainWin, SIGNAL(connectToCore(const QVariantMap &)), this, SIGNAL(connectToCore(const QVariantMap &)));
   connect(mainWin, SIGNAL(disconnectFromCore()), this, SIGNAL(disconnectFromCore()));
 
 }
 
 QtUi::~QtUi() {
   connect(mainWin, SIGNAL(connectToCore(const QVariantMap &)), this, SIGNAL(connectToCore(const QVariantMap &)));
   connect(mainWin, SIGNAL(disconnectFromCore()), this, SIGNAL(disconnectFromCore()));
 
 }
 
 QtUi::~QtUi() {
+  delete _style;
   delete mainWin;
 }
 
   delete mainWin;
 }
 
@@ -37,6 +42,10 @@ void QtUi::init() {
   mainWin->init();
 }
 
   mainWin->init();
 }
 
+QtUiStyle *QtUi::style() {
+  return _style;
+}
+
 AbstractUiMsg *QtUi::layoutMsg(const Message &msg) {
   return mainWin->layoutMsg(msg);
 }
 AbstractUiMsg *QtUi::layoutMsg(const Message &msg) {
   return mainWin->layoutMsg(msg);
 }
index dca9658..19abd6f 100644 (file)
@@ -21,7 +21,9 @@
 #ifndef _QTUI_H_
 #define _QTUI_H_
 
 #ifndef _QTUI_H_
 #define _QTUI_H_
 
+#include "qtuistyle.h"
 #include "quasselui.h"
 #include "quasselui.h"
+
 class MainWin;
 
 //! This class encapsulates Quassel's Qt-based GUI.
 class MainWin;
 
 //! This class encapsulates Quassel's Qt-based GUI.
@@ -37,12 +39,15 @@ class QtUi : public AbstractUi {
     void init();
     AbstractUiMsg *layoutMsg(const Message &);
 
     void init();
     AbstractUiMsg *layoutMsg(const Message &);
 
+    static QtUiStyle *style();
+
   protected slots:
     void connectedToCore();
     void disconnectedFromCore();
 
   private:
     MainWin *mainWin;
   protected slots:
     void connectedToCore();
     void disconnectedFromCore();
 
   private:
     MainWin *mainWin;
+    static QtUiStyle *_style;
 };
 
 #endif
 };
 
 #endif
index 852bb31..49fa712 100644 (file)
@@ -1,12 +1,12 @@
-DEPMOD = common client contrib/qxt
+DEPMOD = uisupport common client contrib/qxt
 QT_MOD = core gui network
 
 SRCS += bufferview.cpp bufferviewfilter.cpp bufferwidget.cpp channelwidgetinput.cpp chatline.cpp \
        chatwidget.cpp coreconnectdlg.cpp \
 QT_MOD = core gui network
 
 SRCS += bufferview.cpp bufferviewfilter.cpp bufferwidget.cpp channelwidgetinput.cpp chatline.cpp \
        chatwidget.cpp coreconnectdlg.cpp \
-       guisettings.cpp identities.cpp mainwin.cpp qtui.cpp serverlist.cpp settingsdlg.cpp style.cpp tabcompleter.cpp topicwidget.cpp
+       guisettings.cpp identities.cpp mainwin.cpp qtui.cpp qtuistyle.cpp serverlist.cpp settingsdlg.cpp style.cpp tabcompleter.cpp topicwidget.cpp
 
 HDRS += bufferview.h bufferviewfilter.h bufferwidget.h channelwidgetinput.h chatline.h chatwidget.h coreconnectdlg.h \
 
 HDRS += bufferview.h bufferviewfilter.h bufferwidget.h channelwidgetinput.h chatline.h chatwidget.h coreconnectdlg.h \
-       guisettings.h identities.h mainwin.h qtui.h serverlist.h settingsdlg.h settingspage.h style.h tabcompleter.h topicwidget.h
+       guisettings.h identities.h mainwin.h qtui.h qtuistyle.h serverlist.h settingsdlg.h settingspage.h style.h tabcompleter.h topicwidget.h
 
 
 FORMNAMES = identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui mainwin.ui nickeditdlg.ui serverlistdlg.ui \
 
 
 FORMNAMES = identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui mainwin.ui nickeditdlg.ui serverlistdlg.ui \
diff --git a/src/qtui/qtuistyle.cpp b/src/qtui/qtuistyle.cpp
new file mode 100644 (file)
index 0000000..a1eea53
--- /dev/null
@@ -0,0 +1,108 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by The Quassel IRC Development Team             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "qtuistyle.h"
+
+QtUiStyle::QtUiStyle() : UiStyle() {
+  // We need to just set our internal formats; everything else is done by the base class...
+
+  // Internal message formats
+  QTextCharFormat plainMsg;
+  plainMsg.setForeground(QBrush("black"));
+  setFormat(PlainMsg, plainMsg);
+
+  QTextCharFormat notice;
+  notice.setForeground(QBrush("navy"));
+  setFormat(NoticeMsg, notice);
+
+  QTextCharFormat server;
+  server.setForeground(QBrush("navy"));
+  setFormat(ServerMsg, server);
+
+  QTextCharFormat error;
+  error.setForeground(QBrush("red"));
+  setFormat(ErrorMsg, error);
+
+  QTextCharFormat join;
+  join.setForeground(QBrush("green"));
+  setFormat(JoinMsg, join);
+
+  QTextCharFormat part;
+  part.setForeground(QBrush("indianred"));
+  setFormat(PartMsg, part);
+
+  QTextCharFormat quit;
+  quit.setForeground(QBrush("indianred"));
+  setFormat(QuitMsg, quit);
+
+  QTextCharFormat kick;
+  kick.setForeground(QBrush("indianred"));
+  setFormat(KickMsg, kick);
+
+  QTextCharFormat nren;
+  nren.setForeground(QBrush("magenta"));
+  setFormat(RenameMsg, nren);
+
+  QTextCharFormat mode;
+  mode.setForeground(QBrush("steelblue"));
+  setFormat(ModeMsg, mode);
+
+  QTextCharFormat action;
+  action.setFontItalic(true);
+  action.setForeground(QBrush("darkmagenta"));
+  setFormat(ActionMsg, action);
+
+  // Internal message element formats
+  QTextCharFormat ts;
+  ts.setForeground(QBrush("grey"));
+  setFormat(Timestamp, ts);
+
+  QTextCharFormat sender;
+  sender.setAnchor(true);
+  sender.setForeground(QBrush("navy"));
+  setFormat(Sender, sender);
+
+  QTextCharFormat nick;
+  nick.setAnchor(true);
+  nick.setFontWeight(QFont::Bold);
+  setFormat(Nick, nick);
+
+  QTextCharFormat hostmask;
+  hostmask.setFontItalic(true);
+  setFormat(Hostmask, hostmask);
+
+  QTextCharFormat channel;
+  channel.setAnchor(true);
+  channel.setFontWeight(QFont::Bold);
+  setFormat(ChannelName, channel);
+
+  QTextCharFormat flags;
+  flags.setFontWeight(QFont::Bold);
+  setFormat(ModeFlags, flags);
+
+  QTextCharFormat url;
+  url.setFontUnderline(true);
+  url.setAnchor(true);
+  setFormat(Url, url);
+
+
+}
+
+QtUiStyle::~QtUiStyle() {}
diff --git a/src/qtui/qtuistyle.h b/src/qtui/qtuistyle.h
new file mode 100644 (file)
index 0000000..ed48f42
--- /dev/null
@@ -0,0 +1,36 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by The Quassel IRC Development Team             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef _QTUISTYLE_H_
+#define _QTUISTYLE_H_
+
+#include "uistyle.h"
+
+class QtUiStyle : public UiStyle {
+
+  public:
+    QtUiStyle();
+    virtual ~QtUiStyle();
+
+    virtual int sepTsSender() { return 10; }
+    virtual int sepSenderText() { return 10; }
+};
+
+#endif
diff --git a/src/uisupport/uistyle.cpp b/src/uisupport/uistyle.cpp
new file mode 100644 (file)
index 0000000..3fc53bd
--- /dev/null
@@ -0,0 +1,209 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 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) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "uistyle.h"
+
+UiStyle::UiStyle() {
+  // Default format
+  QTextCharFormat def;
+  def.setForeground(QBrush("black"));
+  def.setFont(QFont("Verdana",9));
+
+  _formats = QVector<QTextCharFormat>(NumFormatTypes, def);
+
+  // 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";
+
+  // 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]))); _formats[FgCol00 + i] = fgf;
+    bgf.setBackground(QBrush(QColor(colors[i]))); _formats[BgCol00 + i] = bgf;
+  }
+
+  // Set a few more standard formats
+  QTextCharFormat bold; bold.setFontWeight(QFont::Bold);
+  setFormat(Bold, bold);
+
+  QTextCharFormat italic; italic.setFontItalic(true);
+  setFormat(Italic, italic);
+
+  QTextCharFormat underline; underline.setFontUnderline(true);
+  setFormat(Underline, underline);
+
+  // All other formats should be defined in derived classes.
+}
+
+UiStyle::~ UiStyle() {
+  
+}
+
+void UiStyle::setFormat(FormatType ftype, QTextCharFormat fmt) {
+  _formats[ftype] = fmt;
+}
+
+QTextCharFormat UiStyle::format(FormatType ftype) const {
+  return _formats[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::StyledString UiStyle::styleString(QString s) {
+  StyledString result;
+  QList<FormatType> fmtList;
+  fmtList.append(None);
+  QTextLayout::FormatRange curFmtRng;
+  curFmtRng.format = format(None);
+  result.formats.append(curFmtRng);
+  int pos = 0; int length;
+  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();
+        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 = 1;
+    } else if(s[pos+1] == 'R') { // reverse
+      // TODO: implement reverse formatting
+
+      length = 1;
+    } else { // all others are toggles
+      QString code = QString("%") + s[pos+1];
+      if(s[pos+1] == 'D') code += s[pos+2];
+      FormatType ftype = formatType(code);
+      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.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;
+    } else {
+      // fix length of last format
+      result.formats.last().length = pos - result.formats.last().start;
+      result.formats.append(curFmtRng);
+    }
+  }
+  result.formats.last().length = s.length() - result.formats.last().start;
+  if(result.formats.last().length == 0) result.formats.removeLast();
+  result.text = 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/uistyle.h b/src/uisupport/uistyle.h
new file mode 100644 (file)
index 0000000..0ddc1b8
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 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) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef _UISTYLE_H_
+#define _UISTYLE_H_
+
+#include <QTextCharFormat>
+#include <QTextLayout>
+#include <QUrl>
+
+#include "message.h"
+
+class UiStyle {
+
+  public:
+    UiStyle();
+    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 StyledString {
+      QString text;
+      QList<QTextLayout::FormatRange> formats;
+      QList<UrlInfo> urls;
+    };
+
+    StyledString styleString(QString);
+
+    void setFormat(FormatType, QTextCharFormat);
+    QTextCharFormat format(FormatType) const;
+
+    FormatType formatType(const QString &code) const;
+    QString formatCode(FormatType) const;
+
+  protected:
+
+
+  private:
+    QTextCharFormat mergedFormat(QList<FormatType>);
+
+    QVector<QTextCharFormat> _formats;
+    QHash<QString, FormatType> _formatCodes;
+
+};
+
+#endif
diff --git a/src/uisupport/uisupport.pri b/src/uisupport/uisupport.pri
new file mode 100644 (file)
index 0000000..45fe465
--- /dev/null
@@ -0,0 +1,11 @@
+DEPMOD = common
+QT_MOD = core gui
+
+SRCS += uistyle.cpp
+HDRS += uistyle.h
+
+FORMNAMES = 
+
+for(ui, FORMNAMES) {
+  FRMS += ui/$${ui}
+}