Fix chat message formatting and word wrapping

By switching from a QLabel to a QTextBrowser widget more formatting
options and word wrapping that breaks words is possible.  It comes with
an issue I have been unable to resolve

 * Selecting text and going down with the cursor will cause it to
   scroll.  It's possible to increase padding to remove this behavior,
   but it doesn't look great.
This commit is contained in:
Ryan Huffman 2014-04-12 00:20:43 -07:00
parent 16a2367b29
commit 13cf0c80e6
3 changed files with 102 additions and 10 deletions

View file

@ -0,0 +1,44 @@
//
// ChatMessageArea.cpp
// interface/src/ui
//
// Created by Ryan Huffman on 4/11/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "ChatMessageArea.h"
#include <QAbstractTextDocumentLayout>
#include <QWheelEvent>
ChatMessageArea::ChatMessageArea() : QTextBrowser() {
connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged,
this, &ChatMessageArea::updateLayout);
};
void ChatMessageArea::setHtml(const QString& html) {
// Create format with updated line height
QTextBlockFormat format;
format.setLineHeight(CHAT_MESSAGE_LINE_HEIGHT, QTextBlockFormat::ProportionalHeight);
// Possibly a bug in QT, the format won't take effect if `insertHtml` is used first. Inserting a space and deleting
// it after ensures the format is applied.
QTextCursor cursor = textCursor();
cursor.setBlockFormat(format);
cursor.insertText(" ");
cursor.insertHtml(html);
cursor.setPosition(0);
cursor.deleteChar();
};
void ChatMessageArea::updateLayout() {
setFixedHeight(document()->size().height());
updateGeometry();
}
void ChatMessageArea::wheelEvent(QWheelEvent* event) {
// Capture wheel events to stop Ctrl-WheelUp/Down zooming
event->ignore();
};

View file

@ -0,0 +1,33 @@
//
// ChatMessageArea.h
// interface/src/ui
//
// Created by Ryan Huffman on 4/11/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_ChatMessageArea_h
#define hifi_ChatMessageArea_h
#include <QTextBrowser>
const int CHAT_MESSAGE_LINE_HEIGHT = 130;
class ChatMessageArea : public QTextBrowser {
Q_OBJECT
public:
ChatMessageArea();
virtual void setHtml(const QString& html);
public slots:
void updateLayout();
protected:
virtual void wheelEvent(QWheelEvent* event);
};
#endif // hifi_ChatMessageArea_h

View file

@ -22,6 +22,7 @@
#include "qtimespan.h"
#include "ui_chatWindow.h"
#include "XmppClient.h"
#include "ChatMessageArea.h"
#include "ChatWindow.h"
@ -241,25 +242,39 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
userLabel->setStyleSheet("padding: 2px; font-weight: bold");
userLabel->setAlignment(Qt::AlignTop | Qt::AlignRight);
QLabel* messageLabel = new QLabel(message.body().replace(regexLinks, "<a href=\"\\1\">\\1</a>"));
messageLabel->setWordWrap(true);
messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
messageLabel->setOpenExternalLinks(true);
messageLabel->setStyleSheet("padding-bottom: 2px; padding-left: 2px; padding-top: 2px; padding-right: 20px");
messageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
ChatMessageArea* messageArea = new ChatMessageArea();
if (getParticipantName(message.from()) == AccountManager::getInstance().getUsername()) {
messageArea->setOpenLinks(true);
messageArea->setOpenExternalLinks(true);
messageArea->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
messageArea->setTextInteractionFlags(Qt::TextBrowserInteraction);
messageArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
messageArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
messageArea->setReadOnly(true);
messageArea->setStyleSheet("padding-bottom: 2px;"
"padding-left: 2px;"
"padding-top: 2px;"
"padding-right: 20px;"
"background-color: rgba(0, 0, 0, 0%);"
"border: 0;");
bool fromSelf = getParticipantName(message.from()) == AccountManager::getInstance().getUsername();
if (fromSelf) {
userLabel->setStyleSheet(userLabel->styleSheet() + "; background-color: #e1e8ea");
messageLabel->setStyleSheet(messageLabel->styleSheet() + "; background-color: #e1e8ea");
messageArea->setStyleSheet(messageArea->styleSheet() + "; background-color: #e1e8ea");
}
messageArea->setHtml(message.body().replace(regexLinks, "<a href=\"\\1\">\\1</a>"));
bool atBottom = isAtBottom();
ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0);
ui->messagesGridLayout->addWidget(messageLabel, ui->messagesGridLayout->rowCount() - 1, 1);
ui->messagesGridLayout->addWidget(messageArea, ui->messagesGridLayout->rowCount() - 1, 1);
ui->messagesGridLayout->parentWidget()->updateGeometry();
Application::processEvents();
if (atBottom) {
if (atBottom || fromSelf) {
scrollToBottom();
}