Merge pull request #2660 from huffman/19554

19554 Continue refining Chat
This commit is contained in:
Clément Brisset 2014-04-14 14:35:08 -07:00
commit f61d72fcf0
7 changed files with 255 additions and 28 deletions

View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="44px"
height="44px"
viewBox="0 0 44 44"
version="1.1"
id="svg3085"
inkscape:version="0.48.2 r9819"
sodipodi:docname="close_hover.svg">
<metadata
id="metadata3099">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Slice 1</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="814"
inkscape:window-height="783"
id="namedview3097"
showgrid="false"
inkscape:zoom="10.727273"
inkscape:cx="14.784087"
inkscape:cy="19.379049"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="Page-1" />
<title
id="title3087">Slice 1</title>
<description
id="description3089">Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs
id="defs3091" />
<g
id="Page-1"
sketch:type="MSPage"
stroke-width="1"
stroke="none"
fill-rule="evenodd"
fill="none">
<g
id="close"
sketch:type="MSLayerGroup"
fill="#CCCCCC">
<path
d="M0.286382588,32.6200761 L32.6200759,0.286382745 C33.0019275,-0.0954590326 33.6210173,-0.0954590326 34.0028688,0.286382745 L43.380667,9.66418097 C43.7625088,10.0460227 43.7625088,10.6651125 43.380667,11.0469543 L43.380667,11.0469543 L11.0469639,43.3806574 C10.6651221,43.7624992 10.0460226,43.7624992 9.66418081,43.3806574 L0.286382588,34.0028592 C-0.0954591894,33.6210076 -0.0954591894,33.0019179 0.286382588,32.6200761 L0.286382588,32.6200761 L0.286382588,32.6200761 Z"
id="path16"
sketch:type="MSShapeGroup"
style="fill:#e6e6e6" />
<path
d="M32.6200759,43.3806574 L0.286382588,11.0469543 C-0.0954591894,10.6651125 -0.0954591894,10.0460227 0.286382588,9.66418097 L9.66418081,0.286382745 C10.0460226,-0.0954590326 10.6651221,-0.0954590326 11.0469639,0.286382745 L43.380667,32.6200761 C43.7625088,33.0019179 43.7625088,33.6210076 43.380667,34.0028592 L34.0028688,43.3806574 C33.6210173,43.7624992 33.0019275,43.7624992 32.6200759,43.3806574 L32.6200759,43.3806574 Z"
id="path18"
sketch:type="MSShapeGroup"
style="fill:#e6e6e6" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -1063,18 +1063,12 @@ void Menu::showChat() {
mainWindow->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow());
}
if (!_chatWindow->toggleViewAction()->isChecked()) {
int width = _chatWindow->width();
int y = qMax((mainWindow->height() - _chatWindow->height()) / 2, 0);
_chatWindow->move(mainWindow->width(), y);
const QRect& windowGeometry = mainWindow->geometry();
_chatWindow->move(windowGeometry.topRight().x() - _chatWindow->width(),
windowGeometry.topRight().y() + (windowGeometry.height() / 2) - (_chatWindow->height() / 2));
_chatWindow->resize(0, _chatWindow->height());
_chatWindow->toggleViewAction()->trigger();
QPropertyAnimation* slideAnimation = new QPropertyAnimation(_chatWindow, "geometry", _chatWindow);
slideAnimation->setStartValue(_chatWindow->geometry());
slideAnimation->setEndValue(QRect(mainWindow->width() - width, _chatWindow->y(),
width, _chatWindow->height()));
slideAnimation->setDuration(250);
slideAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
}

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

@ -24,6 +24,7 @@
#include "qtimespan.h"
#include "ui_chatWindow.h"
#include "XmppClient.h"
#include "ChatMessageArea.h"
#include "ChatWindow.h"
@ -33,7 +34,9 @@ const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)");
ChatWindow::ChatWindow() :
ui(new Ui::ChatWindow),
numMessagesAfterLastTimeStamp(0)
numMessagesAfterLastTimeStamp(0),
_mousePressed(false),
_mouseStartPosition()
{
ui->setupUi(this);
@ -86,6 +89,25 @@ ChatWindow::~ChatWindow() {
delete ui;
}
void ChatWindow::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton && isFloating()) {
_mousePressed = true;
_mouseStartPosition = e->pos();
}
}
void ChatWindow::mouseMoveEvent(QMouseEvent *e) {
if (_mousePressed) {
move(mapToParent(e->pos() - _mouseStartPosition));
}
}
void ChatWindow::mouseReleaseEvent( QMouseEvent *e ) {
if ( e->button() == Qt::LeftButton ) {
_mousePressed = false;
}
}
void ChatWindow::keyPressEvent(QKeyEvent* event) {
QDockWidget::keyPressEvent(event);
if (event->key() == Qt::Key_Escape) {
@ -158,8 +180,18 @@ void ChatWindow::addTimeStamp() {
"padding: 4px;");
timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
timeLabel->setAlignment(Qt::AlignHCenter);
bool atBottom = isAtBottom();
ui->messagesGridLayout->addWidget(timeLabel, ui->messagesGridLayout->rowCount(), 0, 1, 2);
ui->messagesGridLayout->parentWidget()->updateGeometry();
Application::processEvents();
numMessagesAfterLastTimeStamp = 0;
if (atBottom) {
scrollToBottom();
}
}
}
@ -235,25 +267,41 @@ 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();
QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setSliderPosition(verticalScrollBar->maximum());
messageLabel->updateGeometry();
if (atBottom || fromSelf) {
scrollToBottom();
}
++numMessagesAfterLastTimeStamp;
if (message.stamp().isValid()) {
@ -265,6 +313,17 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
#endif
bool ChatWindow::isAtBottom() {
QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar();
return verticalScrollBar->sliderPosition() == verticalScrollBar->maximum();
}
// Scroll chat message area to bottom.
void ChatWindow::scrollToBottom() {
QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setSliderPosition(verticalScrollBar->maximum());
}
void ChatWindow::togglePinned() {
QMainWindow* mainWindow = Application::getInstance()->getWindow();
mainWindow->removeDockWidget(this);
@ -276,4 +335,4 @@ void ChatWindow::togglePinned() {
}
this->setFloating(!ui->togglePinnedButton->isChecked());
setTitleBarWidget(ui->togglePinnedButton->isChecked()?new QWidget():titleBar);
}
}

View file

@ -39,6 +39,10 @@ public:
virtual void keyPressEvent(QKeyEvent *event);
virtual void showEvent(QShowEvent* event);
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseMoveEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
protected:
bool eventFilter(QObject* sender, QEvent* event);
@ -48,11 +52,15 @@ private:
#endif
void startTimerForTimeStamps();
void addTimeStamp();
bool isAtBottom();
void scrollToBottom();
Ui::ChatWindow* ui;
QWidget* titleBar;
int numMessagesAfterLastTimeStamp;
QDateTime lastMessageStamp;
bool _mousePressed;
QPoint _mouseStartPosition;
private slots:
void connected();

View file

@ -135,13 +135,23 @@
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
background-color: rgba( 0, 0, 0, 0% );
border: none;
image: url(../resources/images/close.svg)
}
QPushButton:pressed {
background-color: rgba( 0, 0, 0, 0% );
border: none;
image: url(../resources/images/close_down.svg)
}</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../resources/images/close.svg</normaloff>../resources/images/close.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>