* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <QApplication>
+#include <QClipboard>
#include <QFontMetrics>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
+#include <QPalette>
#include <QTextLayout>
#include "chatitem.h"
_fontMetrics = QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value<UiStyle::FormatList>().at(0).second);
_layout = 0;
_lines = 0;
+ _selectionStart = -1;
}
ChatItem::~ChatItem() {
_layout->draw(painter, QPointF(0,0), QVector<QTextLayout::FormatRange>(), boundingRect());
}
-/*
-void ChatItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event ) {
- qDebug() << (void*)this << "moving" << event->pos();
- if(event->pos().y() < 0) {
- QTextCursor cursor(document());
- //cursor.insertText("foo");
- //cursor.select(QTextCursor::Document);
+int ChatItem::posToCursor(const QPointF &pos) {
+ if(pos.y() > height()) return data(MessageModel::DisplayRole).toString().length();
+ if(pos.y() < 0) return 0;
+ if(!haveLayout()) updateLayout();
+ for(int l = _layout->lineCount() - 1; l >= 0; l--) {
+ QTextLine line = _layout->lineAt(l);
+ if(pos.y() >= line.y()) {
+ return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter);
+ }
+ }
+ return 0;
+}
+
+void ChatItem::clearSelection() {
+ if(_selectionStart >= 0) {
+ QList<QTextLayout::FormatRange> formats = _layout->additionalFormats();
+ formats.removeLast();
+ _layout->setAdditionalFormats(formats);
+ _selectionStart = -1;
+ updateLayout();
+ update();
+ }
+}
+
+void ChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+ int selectionEnd = posToCursor(event->pos());
+ QList<QTextLayout::FormatRange> formats = _layout->additionalFormats();
+ formats.last().start = qMin(_selectionStart, selectionEnd);
+ formats.last().length = qMax(_selectionStart, selectionEnd) - formats.last().start;
+ _layout->setAdditionalFormats(formats);
+ updateLayout();
+ update();
+}
+
+void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+ if(event->buttons() & Qt::LeftButton) {
+ if(!haveLayout()) updateLayout();
+ chatScene()->setSelectingItem(this);
+ _selectionStart = posToCursor(event->pos());
+ QList<QTextLayout::FormatRange> formats = _layout->additionalFormats();
+ QTextLayout::FormatRange selectFmt;
+ QPalette pal = QApplication::palette();
+ selectFmt.format.setForeground(pal.brush(QPalette::HighlightedText));
+ selectFmt.format.setBackground(pal.brush(QPalette::Highlight));
+ selectFmt.length = 0;
+ formats.append(selectFmt);
+ _layout->setAdditionalFormats(formats);
+ updateLayout();
+ update();
+ event->accept();
+ } else {
event->ignore();
- } else QGraphicsTextItem::mouseMoveEvent(event);
+ }
+}
+
+void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+ if(_selectionStart >= 0) {
+ int selectionEnd = posToCursor(event->pos());
+ QString selection
+ = data(MessageModel::DisplayRole).toString().mid(qMin(_selectionStart, selectionEnd), qAbs(_selectionStart - selectionEnd));
+ QApplication::clipboard()->setText(selection, QClipboard::Clipboard); // TODO configure where selections should go
+ event->accept();
+ } else {
+ event->ignore();
+ }
}
-*/
/*************************************************************************************************/
#define CHATITEM_H_
#include <QGraphicsItem>
+#include <QObject>
#include "chatline.h"
#include "chatlinemodel.h"
+#include "chatscene.h"
#include "uistyle.h"
class QTextLayout;
inline QPersistentModelIndex index() const { return _index; }
inline const MessageModel *model() const { return _index.isValid() ? qobject_cast<const MessageModel *>(_index.model()) : 0; }
inline int row() const { return _index.isValid() ? _index.row() : 0; }
+ inline ChatScene *chatScene() const { return qobject_cast<ChatScene *>(scene()); }
inline QFontMetricsF *fontMetrics() const { return _fontMetrics; }
inline virtual QRectF boundingRect() const { return _boundingRect; }
// returns height
int setWidth(int width);
+ // selection stuff, to be called by the scene
+ void clearSelection();
+ void setFullSelection();
+
protected:
- //void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private:
+ int posToCursor(const QPointF &pos);
int heightForWidth(int width);
QTextLayout *createLayout(QTextOption::WrapMode, Qt::Alignment = Qt::AlignLeft);
QTextLayout *_layout;
QList<quint16> _wrapPositions;
+ int _selectionStart;
class WrapColumnFinder;
};
_model(model)
{
_width = 0;
+ _selectingItem = 0;
connect(this, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(rectChanged(const QRectF &)));
connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int, int)));
// width() should be the same for both handles, so just use firstColHandle regardless
update(qMin(oldx, xpos) - firstColHandle->width()/2, 0, qMax(oldx, xpos) + firstColHandle->width()/2, height());
}
+
+void ChatScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+
+ QGraphicsScene::mouseMoveEvent(event);
+}
+
+void ChatScene::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+
+ QGraphicsScene::mousePressEvent(event);
+}
+
+void ChatScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+
+ QGraphicsScene::mouseReleaseEvent(event);
+}
+
+void ChatScene::setSelectingItem(ChatItem *item) {
+ if(_selectingItem) _selectingItem->clearSelection();
+ _selectingItem = item;
+}
public slots:
void setWidth(qreal);
- private slots:
- void rectChanged(const QRectF &);
- void handlePositionChanged(qreal xpos);
+ // these are used by the chatitems to notify the scene
+ void setSelectingItem(ChatItem *item);
+ ChatItem *selectingItem() const { return _selectingItem; }
signals:
void heightChanged(qreal height);
+ protected:
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
+
protected slots:
void rowsInserted(const QModelIndex &, int, int);
+ private slots:
+ void rectChanged(const QRectF &);
+ void handlePositionChanged(qreal xpos);
+
private:
QString _idString;
qreal _width, _height;
ColumnHandleItem *firstColHandle, *secondColHandle;
qreal firstColHandlePos, secondColHandlePos;
+
+ ChatItem *_selectingItem;
};
#endif