1
1
/***************************************************************************
2
* Copyright (C) 2005-09 by the Quassel Project *
2
* Copyright (C) 2005-2010 by the Quassel Project *
3
3
* devel@quassel-irc.org *
5
5
* This program is free software; you can redistribute it and/or modify *
39
40
#include "qtuistyle.h"
41
ChatItem::ChatItem(const qreal &width, const qreal &height, const QPointF &pos, QGraphicsItem *parent)
42
: QGraphicsItem(parent),
43
_boundingRect(0, 0, width, height),
44
_selectionMode(NoSelection),
42
ChatItem::ChatItem(const QRectF &boundingRect, ChatLine *parent)
44
_boundingRect(boundingRect),
45
_selectionMode(NoSelection),
47
setAcceptHoverEvents(true);
52
51
QVariant ChatItem::data(int role) const {
58
57
return model()->data(index, role);
61
qint16 ChatItem::posToCursor(const QPointF &pos) const {
60
qint16 ChatItem::posToCursor(const QPointF &posInLine) const {
61
QPointF pos = mapFromLine(posInLine);
62
62
if(pos.y() > height()) return data(MessageModel::DisplayRole).toString().length();
63
63
if(pos.y() < 0) return 0;
105
105
void ChatItem::paintBackground(QPainter *painter) {
106
painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work
108
106
QVariant bgBrush;
109
107
if(_selectionMode == FullSelection)
110
108
bgBrush = data(ChatLineModel::SelectedBackgroundRole);
118
116
// This is a deliberate trade-off. (-> selectFmt creation, data() call)
119
117
void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
120
118
Q_UNUSED(option); Q_UNUSED(widget);
120
painter->setClipRect(boundingRect());
121
121
paintBackground(painter);
123
123
QTextLayout layout;
124
124
initLayout(&layout);
125
layout.draw(painter, QPointF(0,0), additionalFormats(), boundingRect());
125
layout.draw(painter, pos(), additionalFormats(), boundingRect());
127
127
// layout()->draw(painter, QPointF(0,0), formats, boundingRect());
153
153
// 3) draw bounding rect
154
154
// painter->drawRect(_boundingRect.adjusted(0, 0, -1, -1));
157
159
void ChatItem::overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const {
229
231
_selectionMode = mode;
230
232
_selectionStart = start;
231
233
_selectionEnd = end;
234
chatLine()->update();
235
237
void ChatItem::setFullSelection() {
236
238
if(_selectionMode != FullSelection) {
237
239
_selectionMode = FullSelection;
240
chatLine()->update();
242
244
void ChatItem::clearSelection() {
243
245
if(_selectionMode != NoSelection) {
244
246
_selectionMode = NoSelection;
247
chatLine()->update();
249
251
void ChatItem::continueSelecting(const QPointF &pos) {
250
252
_selectionMode = PartialSelection;
251
253
_selectionEnd = posToCursor(pos);
254
chatLine()->update();
255
257
bool ChatItem::isPosOverSelection(const QPointF &pos) const {
296
298
chatScene()->setSelectingItem(this);
297
299
_selectionStart = _selectionEnd = posToCursor(pos);
298
300
_selectionMode = NoSelection; // will be set to PartialSelection by mouseMoveEvent
301
chatLine()->update();
303
305
void ChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
304
306
if(event->buttons() == Qt::LeftButton) {
305
if(contains(event->pos())) {
307
if(boundingRect().contains(event->pos())) {
306
308
qint16 end = posToCursor(event->pos());
307
309
if(end != _selectionEnd) {
308
310
_selectionEnd = end;
309
311
_selectionMode = (_selectionStart != _selectionEnd ? PartialSelection : NoSelection);
312
chatLine()->update();
313
315
setFullSelection();
347
349
void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
348
350
Q_UNUSED(option); Q_UNUSED(widget);
352
painter->setClipRect(boundingRect());
349
353
paintBackground(painter);
351
355
QTextLayout layout;
381
385
gradient.setColorAt(0, Qt::white);
382
386
gradient.setColorAt(1, Qt::black);
384
maskPainter.fillRect(boundingRect(), gradient);
388
maskPainter.fillRect(0, 0, pixmap.width(), pixmap.height(), gradient);
385
389
pixmap.setAlphaChannel(mask);
386
painter->drawPixmap(0, 0, pixmap);
390
painter->drawPixmap(pos(), pixmap);
388
layout.draw(painter, QPointF(0,0), additionalFormats(), boundingRect());
392
layout.draw(painter, pos(), additionalFormats(), boundingRect());
397
void SenderChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) {
398
if(clickMode == ChatScene::DoubleClick) {
399
BufferInfo curBufInfo = Client::networkModel()->bufferInfo(data(MessageModel::BufferIdRole).value<BufferId>());
400
QString nick = data(MessageModel::EditRole).toString();
401
// check if the nick is a valid ircUser
402
if(!nick.isEmpty() && Client::network(curBufInfo.networkId())->ircUser(nick))
403
Client::bufferModel()->switchToOrStartQuery(curBufInfo.networkId(), nick);
406
ChatItem::handleClick(pos, clickMode);
392
409
// ************************************************************
396
413
ContentsChatItem::ActionProxy ContentsChatItem::_actionProxy;
398
ContentsChatItem::ContentsChatItem(const qreal &width, const QPointF &pos, QGraphicsItem *parent)
399
: ChatItem(0, 0, pos, parent),
415
ContentsChatItem::ContentsChatItem(const QPointF &pos, const qreal &width, ChatLine *parent)
416
: ChatItem(QRectF(pos, QSizeF(width, 0)), parent),
402
420
setGeometryByWidth(width);
508
525
void ContentsChatItem::endHoverMode() {
509
526
if(privateData()) {
510
527
if(privateData()->currentClickable.isValid()) {
511
setCursor(Qt::ArrowCursor);
528
chatLine()->setCursor(Qt::ArrowCursor);
512
529
privateData()->currentClickable = Clickable();
514
531
clearWebPreview();
532
chatLine()->update();
635
652
qreal height = line.height();
636
653
qreal y = height * line.lineNumber();
638
QPointF topLeft = scenePos() + QPointF(x, y);
655
QPointF topLeft = mapToScene(pos()) + QPointF(x, y);
639
656
QRectF urlRect = QRectF(topLeft.x(), topLeft.y(), width, height);
641
658
QString urlstr = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length());