+void ContentsChatItem::endHoverMode() {
+ if(layoutData()->currentClickable.isValid()) {
+ setCursor(Qt::ArrowCursor);
+ layoutData()->currentClickable = Clickable();
+ update();
+ }
+}
+
+void ContentsChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+ layoutData()->hasDragged = false;
+ ChatItem::mousePressEvent(event);
+}
+
+void ContentsChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+ if(!event->buttons() && !layoutData()->hasDragged) {
+ // got a click
+ Clickable click = layoutData()->currentClickable;
+ if(click.isValid()) {
+ QString str = data(ChatLineModel::DisplayRole).toString().mid(click.start, click.length);
+ switch(click.type) {
+ case Clickable::Url:
+ QDesktopServices::openUrl(str);
+ break;
+ case Clickable::Channel:
+ // TODO join or whatever...
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ ChatItem::mouseReleaseEvent(event);
+}
+
+void ContentsChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+ // mouse move events always mean we're not hovering anymore...
+ endHoverMode();
+ // also, check if we have dragged the mouse
+ if(!layoutData()->hasDragged && event->buttons() & Qt::LeftButton
+ && (event->buttonDownScreenPos(Qt::LeftButton) - event->screenPos()).manhattanLength() >= QApplication::startDragDistance())
+ layoutData()->hasDragged = true;
+ ChatItem::mouseMoveEvent(event);
+}
+
+void ContentsChatItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
+ endHoverMode();
+ event->accept();
+}
+
+void ContentsChatItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
+ bool onClickable = false;
+ qint16 idx = posToCursor(event->pos());
+ for(int i = 0; i < layoutData()->clickables.count(); i++) {
+ Clickable click = layoutData()->clickables.at(i);
+ if(idx >= click.start && idx < click.start + click.length) {
+ if(click.type == Clickable::Url)
+ onClickable = true;
+ else if(click.type == Clickable::Channel) {
+ // TODO: don't make clickable if it's our own name
+ //onClickable = true; //FIXME disabled for now
+ }
+ if(onClickable) {
+ setCursor(Qt::PointingHandCursor);
+ layoutData()->currentClickable = click;
+ update();
+ break;
+ }
+ }
+ }
+ if(!onClickable) endHoverMode();
+ event->accept();
+}
+
+/*************************************************************************************************/
+
+ContentsChatItem::WrapColumnFinder::WrapColumnFinder(ChatItem *_item)
+ : item(_item),
+ layout(0),
+ wrapList(item->data(ChatLineModel::WrapListRole).value<ChatLineModel::WrapList>()),
+ wordidx(0),
+ lastwrapcol(0),
+ lastwrappos(0),
+ w(0)
+{
+}
+
+ContentsChatItem::WrapColumnFinder::~WrapColumnFinder() {
+ delete layout;
+}
+
+qint16 ContentsChatItem::WrapColumnFinder::nextWrapColumn() {
+ while(wordidx < wrapList.count()) {
+ w += wrapList.at(wordidx).width;
+ if(w >= item->width()) {
+ if(lastwrapcol >= wrapList.at(wordidx).start) {
+ // first word, and it doesn't fit
+ if(!line.isValid()) {
+ layout = item->createLayout(QTextOption::NoWrap);
+ layout->beginLayout();
+ line = layout->createLine();
+ line.setLineWidth(item->width());
+ layout->endLayout();
+ }
+ int idx = line.xToCursor(lastwrappos + item->width(), QTextLine::CursorOnCharacter);
+ qreal x = line.cursorToX(idx, QTextLine::Trailing);
+ w = w - wrapList.at(wordidx).width - (x - lastwrappos);
+ lastwrappos = x;
+ lastwrapcol = idx;
+ return idx;
+ }
+ // not the first word, so just wrap before this
+ lastwrapcol = wrapList.at(wordidx).start;
+ lastwrappos = lastwrappos + w - wrapList.at(wordidx).width;
+ w = 0;
+ return lastwrapcol;
+ }
+ w += wrapList.at(wordidx).trailing;
+ wordidx++;
+ }
+ return -1;
+}