Implement the ChatLine element in C++
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 13 Aug 2011 00:44:54 +0000 (02:44 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 13 Aug 2011 00:44:54 +0000 (02:44 +0200)
Now that I get my brain wrapped around QML a bit, let's take things
more seriously. Turns out, while Text elements seem to be efficient enough,
TextEdit elements (needed for selection and mousehandling) are not, so resizing
is sluggish.

Thus, instead of using any of the stock elements, we're now implementing this ourselves
in C++, and will probably do much the same as we did for the QGV-based ChatView (minus
some of the hackery, if we're lucky). This means layouting and drawing the text ourselves.
On the upside, we can just keep using the old styleengine for now...

Here's hoping that things will turn out to be more efficient anyway, because ListView seems
to be creating and discarding its items as needed; so there shouldn't be a scene with thousands
of items involved to manage...

src/qmlui/CMakeLists.txt
src/qmlui/qml/ChatLine.qml [deleted file]
src/qmlui/qml/ChatView.qml
src/qmlui/qml/qml.qrc
src/qmlui/qmlchatline.cpp [new file with mode: 0644]
src/qmlui/qmlchatline.h [new file with mode: 0644]
src/qmlui/qmlmessagemodel.cpp
src/qmlui/qmlmessagemodel.h
src/qmlui/qmlmessagemodelitem.cpp
src/qmlui/qmlmessagemodelitem.h

index ab6808c..59998a8 100644 (file)
@@ -6,12 +6,14 @@ include(${QT_USE_FILE})
 
 
 set(SOURCES
+    qmlchatline.cpp
     qmlchatview.cpp
     qmlmessagemodel.cpp
     qmlmessagemodelitem.cpp
 )
 
 set(MOC_HDRS
+    qmlchatline.h
     qmlchatview.h
     qmlmessagemodel.h
 )
diff --git a/src/qmlui/qml/ChatLine.qml b/src/qmlui/qml/ChatLine.qml
deleted file mode 100644 (file)
index 1cf3ae8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-import QtQuick 1.1
-
-Item {
-  Row {
-    id: chatLine
-    Text { text: timestamp; wrapMode: Text.NoWrap; width: 100 }
-    Text { text: sender; wrapMode: Text.NoWrap; width: 100 }
-    Text { text: contents; wrapMode: Text.Wrap; width: chatView.width-200}
-  }
-  height: chatLine.height
-}
index 5781fc7..aa72fb4 100644 (file)
@@ -1,6 +1,8 @@
-import QtQuick 1.0
+import QtQuick 1.1
 // import Qt.components 1.0
 
+import eu.quassel.qmlui 1.0
+
 Rectangle {
   id: container
 
@@ -8,14 +10,40 @@ Rectangle {
     id: chatView
     anchors.fill: parent
     model: msgModel
+
     delegate: Component {
-      ChatLine { }
+      ChatLine {
+        chatLineData: chatLineDataRole
+      }
     }
 
+    //interactive: false
+    boundsBehavior: Flickable.StopAtBounds
+
+    property int timestampWidth: 50
+    property int senderWidth: 80
+    property int contentsWidth: width - timestampWidth - senderWidth - 30;
+
     Connections {
       target: msgModel
       onRowsInserted: chatView.positionViewAtEnd();
     }
+/*
+    MouseArea {
+      id: mouseArea
+      anchors.fill: parent
+      acceptedButtons: Qt.LeftButton
+
+      onClicked: {
+        console.log("clicked")
+        parent.senderWidth = parent.senderWidth + 10
+      }
+      onPositionChanged: {
+        console.log("changed" + mouseX + mouseY)
+      }
+
+    }
+*/
 
     Rectangle {
       id: scrollbar
index 9da2458..d58f0f6 100644 (file)
@@ -1,7 +1,6 @@
 <!DOCTYPE RCC>
 <RCC version="1.0">
   <qresource prefix="/qml" >
-    <file>ChatLine.qml</file>
     <file>ChatView.qml</file>
   </qresource>
 </RCC>
diff --git a/src/qmlui/qmlchatline.cpp b/src/qmlui/qmlchatline.cpp
new file mode 100644 (file)
index 0000000..874437c
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *   Copyright (C) 2005-2011 by the Quassel Project                        *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#include <QPainter>
+
+#include "qmlchatline.h"
+
+void QmlChatLine::registerTypes() {
+  qRegisterMetaType<Data>("QmlChatLine::Data");
+  qRegisterMetaTypeStreamOperators<Data>("QmlChatLine::Data");
+  qmlRegisterType<QmlChatLine>("eu.quassel.qmlui", 1, 0, "ChatLine");
+}
+
+QDataStream &operator<<(QDataStream &out, const QmlChatLine::Data &data) {
+  out << data.timestamp.text << data.timestamp.formats
+      << data.sender.text << data.sender.formats
+      << data.contents.text << data.contents.formats;
+  return out;
+}
+
+QDataStream &operator>>(QDataStream &in, QmlChatLine::Data &data) {
+  in >> data.timestamp.text >> data.timestamp.formats
+     >> data.sender.text >> data.sender.formats
+     >> data.contents.text >> data.contents.formats;
+  return in;
+}
+
+QmlChatLine::QmlChatLine(QDeclarativeItem *parent) : QDeclarativeItem(parent) {
+  setFlag(ItemHasNoContents, false);
+  setImplicitHeight(20);
+  setImplicitWidth(100);
+}
+
+QmlChatLine::~QmlChatLine() {
+
+}
+
+void QmlChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+  painter->drawText(0, 0, data().contents.text);
+
+}
+
+
diff --git a/src/qmlui/qmlchatline.h b/src/qmlui/qmlchatline.h
new file mode 100644 (file)
index 0000000..12ce82e
--- /dev/null
@@ -0,0 +1,68 @@
+/***************************************************************************
+ *   Copyright (C) 2005-2011 by the Quassel Project                        *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef QMLCHATLINE_H_
+#define QMLCHATLINE_H_
+
+#include <QDeclarativeItem>
+
+#include "uistyle.h"
+
+class QmlChatLine : public QDeclarativeItem {
+  Q_OBJECT
+
+  Q_PROPERTY(QVariant chatLineData READ chatLineData WRITE setChatLineData)
+
+  //Q_PROPERTY(QVariant )
+
+public:
+  //! Contains all data needed to render a QmlChatLine
+  struct Data {
+    struct ChatLineColumnData {
+      QString text;
+      UiStyle::FormatList formats;
+    };
+
+    ChatLineColumnData timestamp;
+    ChatLineColumnData sender;
+    ChatLineColumnData contents;
+  };
+
+  QmlChatLine(QDeclarativeItem *parent = 0);
+  virtual ~QmlChatLine();
+
+  inline Data data() const { return _data; }
+  inline QVariant chatLineData() const { return QVariant::fromValue<Data>(_data); }
+  inline void setChatLineData(const QVariant &data) { _data = data.value<Data>(); }
+
+  virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+  static void registerTypes();
+
+private:
+  Data _data;
+};
+
+QDataStream &operator<<(QDataStream &out, const QmlChatLine::Data &data);
+QDataStream &operator>>(QDataStream &in, QmlChatLine::Data &data);
+
+Q_DECLARE_METATYPE(QmlChatLine::Data)
+
+#endif
index 45ebc31..fc7ecc3 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include <QtDeclarative>
+
 #include "qmlmessagemodel.h"
+#include "qmlchatline.h"
 
 QmlMessageModel::QmlMessageModel(QObject *parent)
   : MessageModel(parent)
 {
+  QmlChatLine::registerTypes();
+
   QHash<int, QByteArray> roles;
-  roles[TimestampRole] = "timestamp";
-  roles[SenderRole] = "sender";
-  roles[ContentsRole] = "contents";
+  roles[ChatLineDataRole] = "chatLineDataRole";
   setRoleNames(roles);
-
 }
 
 void QmlMessageModel::insertMessages__(int pos, const QList<Message> &messages) {
index 052db04..92ce1e7 100644 (file)
@@ -31,9 +31,7 @@ class QmlMessageModel : public MessageModel {
 
 public:
   enum QmlMessageModelRole {
-    TimestampRole = MessageModel::UserRole,
-    SenderRole,
-    ContentsRole,
+    ChatLineDataRole = MessageModel::UserRole,
     UserRole
   };
 
index 864790a..561c9b7 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include "qmlchatline.h"
 #include "qmlmessagemodel.h"
 #include "qmlmessagemodelitem.h"
+#include "uistyle.h"
 
 QmlMessageModelItem::QmlMessageModelItem(const Message &msg)
   : MessageModelItem(),
@@ -29,28 +31,19 @@ QmlMessageModelItem::QmlMessageModelItem(const Message &msg)
     _styledMsg.setFlags(msg.flags() |= Message::ServerMsg);
 }
 
-bool QmlMessageModelItem::setData(int column, const QVariant &value, int role) {
-  switch(role) {
-    case MessageModel::FlagsRole:
-      _styledMsg.setFlags((Message::Flags)value.toUInt());
-      return true;
-    default:
-      return MessageModelItem::setData(column, value, role);
-  }
-}
-
 QVariant QmlMessageModelItem::data(int column, int role) const {
   QVariant variant;
   switch(role) {
-  case QmlMessageModel::TimestampRole:
-    variant = _styledMsg.timestamp();
-    break;
-  case QmlMessageModel::SenderRole:
-    variant = _styledMsg.sender();
-    break;
-  case QmlMessageModel::ContentsRole:
-    variant = _styledMsg.contents();
-    break;
+  case QmlMessageModel::ChatLineDataRole: {
+    QmlChatLine::Data data;
+    data.timestamp.text = _styledMsg.decoratedTimestamp();
+    data.timestamp.formats = UiStyle::FormatList() << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp);
+    data.sender.text = _styledMsg.decoratedSender();
+    data.sender.formats = UiStyle::FormatList() << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender);
+    data.contents.text = _styledMsg.plainContents();
+    data.contents.formats = _styledMsg.contentsFormatList();
+    return QVariant::fromValue<QmlChatLine::Data>(data);
+  }
   default:
     break;
   }
@@ -58,28 +51,3 @@ QVariant QmlMessageModelItem::data(int column, int role) const {
     return MessageModelItem::data(column, role);
   return variant;
 }
-
-QVariant QmlMessageModelItem::timestampData(int role) const {
-  switch(role) {
-  case MessageModel::DisplayRole:
-    return _styledMsg.timestamp();
-  }
-  return QVariant();
-}
-
-QVariant QmlMessageModelItem::senderData(int role) const {
-  switch(role) {
-  case MessageModel::DisplayRole:
-    return _styledMsg.sender();
-  }
-  return QVariant();
-}
-
-QVariant QmlMessageModelItem::contentsData(int role) const {
-  switch(role) {
-  case MessageModel::DisplayRole:
-    return _styledMsg.contents();
-  }
-  return QVariant();
-}
-
index 47d46cf..7138df3 100644 (file)
 #define QMLMESSAGEMODELITEM_H_
 
 #include "messagemodel.h"
+#include "uistyle.h"
 
 class QmlMessageModelItem : public MessageModelItem {
 public:
   QmlMessageModelItem(const Message &msg);
 
   virtual QVariant data(int column, int role) const;
-  virtual bool setData(int column, const QVariant &value, int role);
 
   virtual inline const Message &message() const { return _styledMsg; }
   virtual inline const QDateTime &timestamp() const { return _styledMsg.timestamp(); }
@@ -39,11 +39,7 @@ public:
   virtual inline Message::Flags msgFlags() const { return _styledMsg.flags(); }
 
 private:
-  QVariant timestampData(int role) const;
-  QVariant senderData(int role) const;
-  QVariant contentsData(int role) const;
-
-  Message _styledMsg;
+  UiStyle::StyledMessage _styledMsg;
 };
 
 #endif