Tweak ChatItem/ChatLine layouting
[quassel.git] / src / qtui / chatscene.cpp
index 8954815..b159dc9 100644 (file)
 #include <QGraphicsSceneMouseEvent>
 #include <QMenu>
 #include <QPersistentModelIndex>
-#include <QWebView>
+
+#ifdef HAVE_WEBKIT
+#  include <QWebView>
+#endif
 
 #include "chatitem.h"
 #include "chatline.h"
@@ -34,6 +37,7 @@
 #include "client.h"
 #include "clientbacklogmanager.h"
 #include "columnhandleitem.h"
+#include "contextmenuactionprovider.h"
 #include "iconloader.h"
 #include "messagefilter.h"
 #include "qtui.h"
@@ -92,6 +96,7 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w
           this, SLOT(rowsInserted(const QModelIndex &, int, int)));
   connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
           this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
+  connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(dataChanged(QModelIndex, QModelIndex)));
 
   if(model->rowCount() > 0)
     rowsInserted(QModelIndex(), 0, model->rowCount() - 1);
@@ -376,6 +381,10 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e
   updateSceneRect();
 }
 
+void ChatScene::dataChanged(const QModelIndex &tl, const QModelIndex &br) {
+  layout(tl.row(), br.row(), _sceneRect.width());
+}
+
 void ChatScene::updateForViewport(qreal width, qreal height) {
   _viewportHeight = height;
   setWidth(width);
@@ -384,21 +393,37 @@ void ChatScene::updateForViewport(qreal width, qreal height) {
 void ChatScene::setWidth(qreal width) {
   if(width == _sceneRect.width())
     return;
+  layout(0, _lines.count()-1, width);
+}
 
+void ChatScene::layout(int start, int end, qreal width) {
   // clock_t startT = clock();
 
   // disabling the index while doing this complex updates is about
   // 2 to 10 times faster!
   //setItemIndexMethod(QGraphicsScene::NoIndex);
 
-  QList<ChatLine *>::iterator lineIter = _lines.end();
-  QList<ChatLine *>::iterator lineIterBegin = _lines.begin();
-  qreal linePos = _sceneRect.y() + _sceneRect.height();
-  qreal contentsWidth = width - secondColumnHandle()->sceneRight();
-  while(lineIter != lineIterBegin) {
-    lineIter--;
-    (*lineIter)->setGeometryByWidth(width, contentsWidth, linePos);
+  if(end >= 0) {
+    int row = end;
+    qreal linePos = _lines.at(row)->scenePos().y() + _lines.at(row)->height();
+    qreal contentsWidth = width - secondColumnHandle()->sceneRight();
+    while(row >= start) {
+      _lines.at(row--)->setGeometryByWidth(width, contentsWidth, linePos);
+    }
+
+    if(row >= 0) {
+      // remaining items don't need geometry changes, but maybe repositioning?
+      ChatLine *line = _lines.at(row);
+      qreal offset = linePos - (line->scenePos().y() + line->height());
+      if(offset != 0) {
+        while(row >= 0) {
+          line = _lines.at(row--);
+          line->setPos(0, line->scenePos().y() + offset);
+        }
+      }
+    }
   }
+
   //setItemIndexMethod(QGraphicsScene::BspTreeIndex);
 
   updateSceneRect(width);
@@ -586,7 +611,7 @@ void ChatScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
     item->addActionsToMenu(&menu, item->mapFromScene(pos));
   else
     // no item -> default scene actions
-    Client::mainUi()->actionProvider()->addActions(&menu, filter(), BufferId());
+    GraphicalUi::contextMenuActionProvider()->addActions(&menu, filter(), BufferId());
 
   menu.exec(event->screenPos());
 
@@ -707,7 +732,12 @@ void ChatScene::selectionToClipboard(QClipboard::Mode mode) {
   stringToClipboard(selection(), mode);
 }
 
-void ChatScene::stringToClipboard(const QString &str, QClipboard::Mode mode) {
+void ChatScene::stringToClipboard(const QString &str_, QClipboard::Mode mode) {
+  QString str = str_;
+  // remove trailing linefeeds
+  if(str.endsWith('\n'))
+    str.chop(1);
+
   switch(mode) {
     case QClipboard::Clipboard:
       QApplication::clipboard()->setText(str);