+void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+ if(event->buttons() == Qt::LeftButton)
+ event->accept();
+ else
+ event->ignore();
+}
+
+void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+ if(_selectionMode != NoSelection && event->button() == Qt::LeftButton) {
+ chatScene()->selectionToClipboard(QClipboard::Selection);
+ event->accept();
+ } else
+ event->ignore();
+}
+
+void ChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) {
+ Q_UNUSED(pos);
+
+ GraphicalUi::contextMenuActionProvider()->addActions(menu, chatScene()->filter(), data(MessageModel::BufferIdRole).value<BufferId>());
+}
+
+// ************************************************************
+// SenderChatItem
+// ************************************************************
+
+void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+ Q_UNUSED(option); Q_UNUSED(widget);
+ paintBackground(painter);
+
+ QTextLayout layout;
+ initLayout(&layout);
+ 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);
+
+ 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(layout.boundingRect().toRect().size());
+ pixmap.fill(Qt::transparent);
+ QPainter pixPainter(&pixmap);
+ layout.draw(&pixPainter, QPointF(qMax(offset, (qreal)0), 0), additionalFormats());
+ 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), additionalFormats(), boundingRect());
+ }
+}
+
+// ************************************************************
+// ContentsChatItem
+// ************************************************************
+
+ContentsChatItem::ActionProxy ContentsChatItem::_actionProxy;
+
+ContentsChatItem::ContentsChatItem(const qreal &width, const QPointF &pos, QGraphicsItem *parent)
+ : ChatItem(0, 0, pos, parent),
+ _data(0)
+{
+ setGeometryByWidth(width);
+}
+
+QFontMetricsF *ContentsChatItem::fontMetrics() const {
+ return QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value<UiStyle::FormatList>().at(0).second, 0);
+}
+
+ContentsChatItem::~ContentsChatItem() {
+ delete _data;
+}
+
+ContentsChatItemPrivate *ContentsChatItem::privateData() const {
+ if(!_data) {
+ ContentsChatItem *that = const_cast<ContentsChatItem *>(this);
+ that->_data = new ContentsChatItemPrivate(ClickableList::fromString(data(ChatLineModel::DisplayRole).toString()), that);
+ }
+ return _data;
+}
+
+qreal ContentsChatItem::setGeometryByWidth(qreal w) {
+ // We use this for reloading layout info as well, so we can't bail out if the width doesn't change
+
+ // compute height
+ int lines = 1;
+ WrapColumnFinder finder(this);
+ while(finder.nextWrapColumn(w) > 0)
+ lines++;
+ qreal h = lines * fontMetrics()->lineSpacing();
+ delete _data;
+ _data = 0;
+
+ if(w != width() || h != height()) {
+ prepareGeometryChange();
+ setGeometry(w, h);
+ }
+ return h;
+}
+
+void ContentsChatItem::doLayout(QTextLayout *layout) const {
+ // QString t = data(Qt::DisplayRole).toString(); bool d = t.contains("protien");
+ ChatLineModel::WrapList wrapList = data(ChatLineModel::WrapListRole).value<ChatLineModel::WrapList>();
+ if(!wrapList.count()) return; // empty chatitem