From: Manuel Nickschas Date: Wed, 24 Oct 2007 00:39:10 +0000 (+0000) Subject: I CAN HAZ A STYLE ENGINES!? X-Git-Tag: 0.1.0~102 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=85cc2479ab9bd85b33f4d8494b1eeeb46a6a1049 I CAN HAZ A STYLE ENGINES!? 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. --- diff --git a/Quassel.kdevelop.filelist b/Quassel.kdevelop.filelist index d79678a4..6bd8bccc 100644 --- a/Quassel.kdevelop.filelist +++ b/Quassel.kdevelop.filelist @@ -68,18 +68,18 @@ src/common/util.cpp 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/qxtboundfunctionbase.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/qxtnullable.h src/contrib/qxt/qxtnull.cpp src/contrib/qxt/qxtnull.h +src/contrib/qxt/qxtnullable.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 @@ -114,11 +114,11 @@ src/qtopia/coreconnectdlg.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/qtopia.pri 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/qtui/bufferview.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 @@ -150,6 +150,8 @@ src/qtui/mainwin.h 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 @@ -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/uisupport +src/uisupport/uistyle.cpp +src/uisupport/uistyle.h diff --git a/build/modules/module.pri b/build/modules/module.pri index 1b680641..8054d404 100644 --- a/build/modules/module.pri +++ b/build/modules/module.pri @@ -15,7 +15,6 @@ MODNAME = $$basename(MODULE) MODPATH_PREFIX = $$dirname(MODULE) !isEmpty(MODPATH_PREFIX) { MODPATH_PREFIX ~= s,[^/]+,.. - #sprintf($$MODPATH_PREFIX%1 SRCPATH = $$MODPATH_PREFIX/$$SRCPATH } diff --git a/build/modules/uisupport.pro b/build/modules/uisupport.pro new file mode 100644 index 00000000..a996a1fa --- /dev/null +++ b/build/modules/uisupport.pro @@ -0,0 +1,2 @@ +MODULE = uisupport +include(module.pri) diff --git a/build/targets/monolithic.pri b/build/targets/monolithic.pri index 131a01bf..b848f9f9 100644 --- a/build/targets/monolithic.pri +++ b/build/targets/monolithic.pri @@ -1,7 +1,7 @@ # 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 diff --git a/build/targets/qtclient.pri b/build/targets/qtclient.pri index 529caf03..bbca57b3 100644 --- a/build/targets/qtclient.pri +++ b/build/targets/qtclient.pri @@ -1,7 +1,7 @@ # Modules for quasselclient TARGET = quasselclient -MODULES = qtui client common contrib/qxt +MODULES = qtui uisupport client common contrib/qxt DEFINES = BUILD_QTUI QT += network diff --git a/dev-notes/qxt-check b/dev-notes/qxt-check new file mode 100644 index 00000000..3ed293a5 --- /dev/null +++ b/dev-notes/qxt-check @@ -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 diff --git a/qtopia-build/quasseltopia.pro b/qtopia-build/quasseltopia.pro index 3110cc76..72edf5e3 100644 --- a/qtopia-build/quasseltopia.pro +++ b/qtopia-build/quasseltopia.pro @@ -5,7 +5,7 @@ CONFIG+=debug qtopia_main no_quicklaunch no_singleexec no_sxe_test 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 @@ -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/uisupport/uisupport.pri) # Fix variable names SOURCES = $$SRCS diff --git a/src/client/mappedselectionmodel.h b/src/client/mappedselectionmodel.h index 226f81ed..35f36180 100644 --- a/src/client/mappedselectionmodel.h +++ b/src/client/mappedselectionmodel.h @@ -24,7 +24,7 @@ #include #include #include -#include ; +#include class QAbstractProxyModel; diff --git a/src/qtui/chatline.cpp b/src/qtui/chatline.cpp index 335e15b7..f3b4a357 100644 --- a/src/qtui/chatline.cpp +++ b/src/qtui/chatline.cpp @@ -19,6 +19,7 @@ ***************************************************************************/ #include "chatline.h" +#include "qtui.h" //!\brief Construct a ChatLine object from a message. /** @@ -41,14 +42,29 @@ ChatLine::~ChatLine() { 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(); } -QList 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::calcFormatRanges(const UiStyle::StyledString &fs, QTextLayout::FormatRange additional) { QList 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 formats = fs.formats; formats.append(additional); int cur = -1; @@ -77,6 +93,7 @@ QList ChatLine::calcFormatRanges(const Style::StyledStrin range.height = metrics.lineSpacing(); ranges.append(range); } + */ 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) { - 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--) { @@ -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++) { - 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; @@ -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)); - 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) { } /* @@ -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()); } - 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()); } - 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; diff --git a/src/qtui/chatline.h b/src/qtui/chatline.h index 2707a171..be84f24e 100644 --- a/src/qtui/chatline.h +++ b/src/qtui/chatline.h @@ -24,7 +24,7 @@ #include #include "util.h" -#include "style.h" +#include "uistyle.h" #include "quasselui.h" //FIXME: chatline doku @@ -70,7 +70,7 @@ class ChatLine : public QObject, public AbstractUiMsg { qreal hght; Message msg; qreal tsWidth, senderWidth, textWidth; - Style::StyledString styledTimeStamp, styledSender, styledText; + UiStyle::StyledString styledTimeStamp, styledSender, styledText; struct FormatRange { int start; @@ -103,7 +103,7 @@ class ChatLine : public QObject, public AbstractUiMsg { int selectionStart, selectionEnd; void formatMsg(Message); void precomputeLine(); - QList calcFormatRanges(const Style::StyledString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange()); + QList calcFormatRanges(const UiStyle::StyledString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange()); }; #endif diff --git a/src/qtui/qtui.cpp b/src/qtui/qtui.cpp index 157aafe1..adcbe4cb 100644 --- a/src/qtui/qtui.cpp +++ b/src/qtui/qtui.cpp @@ -22,14 +22,19 @@ #include "mainwin.h" +QtUiStyle *QtUi::_style; + 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() { + delete _style; delete mainWin; } @@ -37,6 +42,10 @@ void QtUi::init() { mainWin->init(); } +QtUiStyle *QtUi::style() { + return _style; +} + AbstractUiMsg *QtUi::layoutMsg(const Message &msg) { return mainWin->layoutMsg(msg); } diff --git a/src/qtui/qtui.h b/src/qtui/qtui.h index dca9658a..19abd6f1 100644 --- a/src/qtui/qtui.h +++ b/src/qtui/qtui.h @@ -21,7 +21,9 @@ #ifndef _QTUI_H_ #define _QTUI_H_ +#include "qtuistyle.h" #include "quasselui.h" + class MainWin; //! This class encapsulates Quassel's Qt-based GUI. @@ -37,12 +39,15 @@ class QtUi : public AbstractUi { void init(); AbstractUiMsg *layoutMsg(const Message &); + static QtUiStyle *style(); + protected slots: void connectedToCore(); void disconnectedFromCore(); private: MainWin *mainWin; + static QtUiStyle *_style; }; #endif diff --git a/src/qtui/qtui.pri b/src/qtui/qtui.pri index 852bb311..49fa7125 100644 --- a/src/qtui/qtui.pri +++ b/src/qtui/qtui.pri @@ -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 \ - 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 \ - 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 \ diff --git a/src/qtui/qtuistyle.cpp b/src/qtui/qtuistyle.cpp new file mode 100644 index 00000000..a1eea532 --- /dev/null +++ b/src/qtui/qtuistyle.cpp @@ -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 index 00000000..ed48f426 --- /dev/null +++ b/src/qtui/qtuistyle.h @@ -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 index 00000000..3fc53bd7 --- /dev/null +++ b/src/uisupport/uistyle.cpp @@ -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(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 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 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 index 00000000..0ddc1b81 --- /dev/null +++ b/src/uisupport/uistyle.h @@ -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 +#include +#include + +#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 formats; + QList 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); + + QVector _formats; + QHash _formatCodes; + +}; + +#endif diff --git a/src/uisupport/uisupport.pri b/src/uisupport/uisupport.pri new file mode 100644 index 00000000..45fe465e --- /dev/null +++ b/src/uisupport/uisupport.pri @@ -0,0 +1,11 @@ +DEPMOD = common +QT_MOD = core gui + +SRCS += uistyle.cpp +HDRS += uistyle.h + +FORMNAMES = + +for(ui, FORMNAMES) { + FRMS += ui/$${ui} +}