From: Manuel Nickschas Date: Mon, 27 Oct 2008 19:45:38 +0000 (+0100) Subject: Pimp my ChatView! X-Git-Tag: 0.3.1~114 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=6e277a228833579b9295d45ca7bd6c6f51aa1152 Pimp my ChatView! Sender items now fade out with a little gradient rather than being cut off hard if they don't fit. Also, ChatScene::setSenderCutoffMode(Cutoff[Left|Right]) allows setting how/where oversized senders are to be cutoff. Default is now the 0.2 behavior, as requested by users. We still lack a config UI for this. --- diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp index 21829c2f..585c958e 100644 --- a/src/qtui/chatitem.cpp +++ b/src/qtui/chatitem.cpp @@ -101,25 +101,9 @@ ChatItemPrivate *ChatItem::privateData() const { void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work - //if(_selectionMode == FullSelection) { - //painter->save(); - //painter->fillRect(boundingRect(), QApplication::palette().brush(QPalette::Highlight)); - //painter->restore(); - //} QVector formats = additionalFormats(); - if(_selectionMode != NoSelection) { - QTextLayout::FormatRange selectFmt; - selectFmt.format.setForeground(QApplication::palette().brush(QPalette::HighlightedText)); - selectFmt.format.setBackground(QApplication::palette().brush(QPalette::Highlight)); - if(_selectionMode == PartialSelection) { - selectFmt.start = qMin(_selectionStart, _selectionEnd); - selectFmt.length = qAbs(_selectionStart - _selectionEnd); - } else { // FullSelection - selectFmt.start = 0; - selectFmt.length = data(MessageModel::DisplayRole).toString().length(); - } - formats.append(selectFmt); - } + QTextLayout::FormatRange selectFmt = selectionFormat(); + if(selectFmt.format.isValid()) formats.append(selectFmt); layout()->draw(painter, QPointF(0,0), formats, boundingRect()); // Debuging Stuff @@ -180,6 +164,25 @@ void ChatItem::continueSelecting(const QPointF &pos) { update(); } +QTextLayout::FormatRange ChatItem::selectionFormat() const { + QTextLayout::FormatRange selectFmt; + if(_selectionMode != NoSelection) { + selectFmt.format.setForeground(QApplication::palette().brush(QPalette::HighlightedText)); + selectFmt.format.setBackground(QApplication::palette().brush(QPalette::Highlight)); + if(_selectionMode == PartialSelection) { + selectFmt.start = qMin(_selectionStart, _selectionEnd); + selectFmt.length = qAbs(_selectionStart - _selectionEnd); + } else { // FullSelection + selectFmt.start = 0; + selectFmt.length = data(MessageModel::DisplayRole).toString().length(); + } + } else { + selectFmt.start = -1; + selectFmt.length = 0; + } + return selectFmt; +} + QList ChatItem::findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive) { QList resultList; const QAbstractItemModel *model_ = model(); @@ -257,6 +260,51 @@ void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { // SenderChatItem // ************************************************************ +void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_UNUSED(option); Q_UNUSED(widget); + + //painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work + qreal layoutWidth = layout()->minimumWidth(); + qreal offset = 0; + if(chatScene()->senderCutoffMode() == ChatScene::CutoffLeft) + offset = qMin(width() - layoutWidth, (qreal)0); + else + offset = qMax(layoutWidth - width(), (qreal)0); + + QTextLayout::FormatRange selectFmt = selectionFormat(); + + if(layoutWidth > width()) { + // Draw a nice gradient for longer items + // Qt's text drawing with a gradient brush sucks, so we use an alpha-channeled pixmap instead + QPixmap pixmap(QSize(layout()->boundingRect().width(), layout()->boundingRect().height())); + pixmap.fill(QApplication::palette().brush(QPalette::Base).color()); + QPainter pixPainter(&pixmap); + layout()->draw(&pixPainter, QPointF(qMax(offset, (qreal)0), 0), QVector() << selectFmt); + pixPainter.end(); + + // Create alpha channel mask + QPixmap mask(pixmap.size()); + QPainter maskPainter(&mask); + QLinearGradient gradient; + if(offset < 0) { + gradient.setStart(0, 0); + gradient.setFinalStop(12, 0); + gradient.setColorAt(0, Qt::black); + gradient.setColorAt(1, Qt::white); + } else { + gradient.setStart(width()-10, 0); + gradient.setFinalStop(width(), 0); + gradient.setColorAt(0, Qt::white); + gradient.setColorAt(1, Qt::black); + } + maskPainter.fillRect(boundingRect(), gradient); + pixmap.setAlphaChannel(mask); + painter->drawPixmap(0, 0, pixmap); + } else { + layout()->draw(painter, QPointF(0,0), QVector() << selectFmt, boundingRect()); + } +} + // ************************************************************ // ContentsChatItem // ************************************************************ diff --git a/src/qtui/chatitem.h b/src/qtui/chatitem.h index 3ed2cee3..1f61fff6 100644 --- a/src/qtui/chatitem.h +++ b/src/qtui/chatitem.h @@ -69,7 +69,9 @@ protected: inline QTextLayout *layout() const; + virtual QTextLayout::FormatRange selectionFormat() const; virtual inline QVector additionalFormats() const { return QVector(); } + qint16 posToCursor(const QPointF &pos); inline bool hasPrivateData() const { return (bool)_data; } @@ -137,7 +139,8 @@ public: virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::SenderColumn; } protected: - virtual inline ChatItemPrivate *newPrivateData() { return new ChatItemPrivate(createLayout(QTextOption::WrapAnywhere, Qt::AlignRight)); } + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + virtual inline ChatItemPrivate *newPrivateData() { return new ChatItemPrivate(createLayout(QTextOption::ManualWrap, Qt::AlignRight)); } }; // ************************************************************ @@ -207,7 +210,8 @@ struct ContentsChatItemPrivate : ChatItemPrivate { ContentsChatItem::Clickable currentClickable; bool hasDragged; - ContentsChatItemPrivate(QTextLayout *l, const QList &c, ContentsChatItem *parent) : ChatItemPrivate(l), contentsItem(parent), clickables(c), hasDragged(false) {} + ContentsChatItemPrivate(QTextLayout *l, const QList &c, ContentsChatItem *parent) + : ChatItemPrivate(l), contentsItem(parent), clickables(c), hasDragged(false) {} }; //inlines regarding ContentsChatItemPrivate diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index 811eec3e..b4cb7869 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -47,6 +47,7 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w _sceneRect(0, 0, width, 0), _firstLineRow(-1), _viewportHeight(0), + _cutoffMode(CutoffLeft), _selectingItem(0), _selectionStart(-1), _isSelecting(false) diff --git a/src/qtui/chatscene.h b/src/qtui/chatscene.h index 753b8873..8f56d625 100644 --- a/src/qtui/chatscene.h +++ b/src/qtui/chatscene.h @@ -39,6 +39,11 @@ class ChatScene : public QGraphicsScene { Q_OBJECT public: + enum CutoffMode { + CutoffLeft, + CutoffRight + }; + ChatScene(QAbstractItemModel *model, const QString &idString, qreal width, QObject *parent); virtual ~ChatScene(); @@ -54,6 +59,9 @@ public: inline ColumnHandleItem *firstColumnHandle() const { return _firstColHandle; } inline ColumnHandleItem *secondColumnHandle() const { return _secondColHandle; } + inline CutoffMode senderCutoffMode() const { return _cutoffMode; } + inline void setSenderCutoffMode(CutoffMode mode) { _cutoffMode = mode; } + public slots: void updateForViewport(qreal width, qreal height); void setWidth(qreal width); @@ -109,6 +117,7 @@ private: ColumnHandleItem *_firstColHandle, *_secondColHandle; qreal _firstColHandlePos, _secondColHandlePos; + CutoffMode _cutoffMode; ChatItem *_selectingItem; int _selectionStartCol, _selectionMinCol;