Commit 70ae878f authored by Edric Milaret's avatar Edric Milaret

Rewrite instant messaging screen

- HyperLink activated - YAY
- No more bubble size problem
- Username and date are now in an italic footer
- Username and date display are now saved in user preferences
- Remove sender avatar from right message as it's kind of
unnecessary

* Need LRC patch connecting message engine stuff : 4059 *

Change-Id: Id1adb1e96d99eb02a2c1e85a066dbbdc3e87cdc0
Tuleap: #601
Tuleap: #290
parent 74474f5b
......@@ -20,6 +20,7 @@
#include "ui_callwidget.h"
#include <QClipboard>
#include <QDesktopServices>
#include <memory>
......@@ -53,6 +54,7 @@
#include "smartlistdelegate.h"
#include "imdelegate.h"
#include "pixbufmanipulator.h"
#include "settingskey.h"
#include "profilemodel.h"
#include "peerprofilecollection.h"
......@@ -233,17 +235,20 @@ CallWidget::setupOutOfCallIM()
QApplication::clipboard()->setText(text.value<QString>());
}
});
QSettings settings;
auto displayDate = new QAction(tr("Display date"), this);
displayDate->setCheckable(true);
displayDate->setChecked(settings.value(SettingsKey::imShowDate).toBool());
ui->listMessageView->addAction(displayDate);
auto displayAuthor = new QAction(tr("Display author"), this);
displayAuthor->setCheckable(true);
displayAuthor->setChecked(settings.value(SettingsKey::imShowAuthor).toBool());
ui->listMessageView->addAction(displayAuthor);
auto lamdba = [=](){
int opts = 0;
displayAuthor->isChecked() ? opts |= ImDelegate::DisplayOptions::AUTHOR : opts;
displayDate->isChecked() ? opts |= ImDelegate::DisplayOptions::DATE : opts;
imDelegate_->setDisplayOptions(static_cast<ImDelegate::DisplayOptions>(opts));
QSettings settings;
settings.setValue(SettingsKey::imShowAuthor, displayAuthor->isChecked());
settings.setValue(SettingsKey::imShowDate, displayDate->isChecked());
emit imDelegate_->sizeHintChanged(QModelIndex());
};
connect(displayAuthor, &QAction::triggered, lamdba);
connect(displayDate, &QAction::triggered, lamdba);
......@@ -690,6 +695,15 @@ CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
ui->contactMethodComboBox->addItem(cm->uri());
}
slidePage(ui->messagingPage, true);
disconnect(imClickedConnection_);
imClickedConnection_ = connect(ui->listMessageView, &QListView::clicked, [this](const QModelIndex& index) {
auto urlList = index.data(static_cast<int>(Media::TextRecording::Role::LinkList)).value<QList<QUrl>>();
if (urlList.size() == 1)
QDesktopServices::openUrl(urlList.at(0));
else if (urlList.size()) {
//TODO Handle multiple url in one message
}
});
}
void
......
......@@ -109,6 +109,7 @@ private:
QMetaObject::Connection imConnection_;
QMetaObject::Connection imVisibleConnection_;
QMetaObject::Connection callChangedConnection_;
QMetaObject::Connection imClickedConnection_;
QPropertyAnimation* pageAnim_;
QMenu* shareMenu_;
......
......@@ -19,36 +19,41 @@
#include "imdelegate.h"
#include <QApplication>
#include <QTextDocument>
#include <QSettings>
#include <QDateTime>
#include "media/text.h"
#include "media/textrecording.h"
#include "ringthemeutils.h"
#include "settingskey.h"
ImDelegate::ImDelegate(QObject *parent)
: QStyledItemDelegate(parent), showDate_(false), showAuthor_(false)
{}
void ImDelegate::setDisplayOptions(ImDelegate::DisplayOptions opt)
: QStyledItemDelegate(parent)
{
showAuthor_ = opt & DisplayOptions::AUTHOR;
showDate_ = opt & DisplayOptions::DATE;
emit sizeHintChanged(QModelIndex());
}
void
ImDelegate::formatMsg(const QModelIndex& index, QString& msg) const
{
if (showAuthor_) {
auto author = index.data(
QSettings settings;
QStringList meta;
if (settings.value(SettingsKey::imShowAuthor).toBool()) {
meta << index.data(
static_cast<int>(Media::TextRecording::Role::AuthorDisplayname)).toString();
msg = QString("(%1)\n%2").arg(author, msg);
}
if (showDate_) {
auto formattedDate = index.data(
static_cast<int>(Media::TextRecording::Role::FormattedDate)).toString();
msg = QString("%2\n%1").arg(formattedDate, msg);
if (settings.value(SettingsKey::imShowDate).toBool()) {
auto timeStamp = index.data(
static_cast<int>(Media::TextRecording::Role::Timestamp)).value<uint>();
auto date = QDateTime::fromTime_t(timeStamp);
auto now = QDateTime::currentDateTime();
if (now.date() == date.date())
meta << date.time().toString();
else
meta << date.toString();
}
msg = QString("%2<footer><i>%1</i></footer>").arg(meta.join(" - "), msg);
}
void
......@@ -64,7 +69,7 @@ ImDelegate::paint(QPainter* painter,
painter->setFont(fontMsg_);
if (index.isValid()) {
auto msg = index.data(Qt::DisplayRole).toString();
auto msg = index.data(static_cast<int>(Media::TextRecording::Role::FormattedHtml)).toString();
opt.text.clear();
QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
......@@ -76,53 +81,73 @@ ImDelegate::paint(QPainter* painter,
QRect textRect = getBoundingRect(dir, msg, opt);
QRect bubbleRect(textRect.left() - padding_,
textRect.top() - padding_,
textRect.width() + 2 * padding_,
textRect.height() + 2 * padding_ );
opt.decorationSize = iconSize_;
opt.decorationPosition = (dir == Qt::AlignRight ?
QStyleOptionViewItem::Right : QStyleOptionViewItem::Left);
opt.decorationAlignment = Qt::AlignTop | Qt::AlignHCenter;
if (dir == Qt::AlignLeft) {
opt.decorationSize = iconSize_;
opt.decorationPosition = (dir == Qt::AlignRight ?
QStyleOptionViewItem::Right : QStyleOptionViewItem::Left);
opt.decorationAlignment = Qt::AlignTop | Qt::AlignHCenter;
} else
opt.decorationSize = QSize();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
QPainterPath path;
path.addRoundedRect(bubbleRect, padding_, padding_);
path.addRoundedRect(textRect, padding_, padding_);
if (dir == Qt::AlignRight) {
painter->fillPath(path, RingTheme::blue_);
painter->setPen(Qt::white);
}
else {
painter->fillPath(path, Qt::white);
painter->setPen(Qt::black);
}
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, msg);
painter->save();
QTextDocument document;
document.setDefaultFont(fontMsg_);
if (dir == Qt::AlignRight)
document.setDefaultStyleSheet("body { color : white; } i { opacity: 100; font-size : 11px; text-align : right; }");
else
document.setDefaultStyleSheet("body { color : black; } i { opacity: 100; font-size : 11px; text-align : right; }");
document.setHtml(msg);
auto textOptions = QTextOption(Qt::AlignLeft);
textOptions.setWrapMode(QTextOption::WrapMode::WordWrap);
document.setDefaultTextOption(textOptions);
document.setTextWidth(textRect.width());
painter->translate(textRect.topLeft());
document.drawContents(painter);
painter->restore();
}
}
QRect ImDelegate::getBoundingRect(const Qt::AlignmentFlag& dir, const QString& msg, const QStyleOptionViewItem &option) const
QRect ImDelegate::getBoundingRect(const Qt::AlignmentFlag& dir,
const QString& msg,
const QStyleOptionViewItem &option) const
{
QFont textFont = option.font;
QFontMetrics textFontMetrics(textFont);
QRect textRect;
if (dir == Qt::AlignRight) {
textRect = textFontMetrics.boundingRect(option.rect.left() + 2 * padding_,
option.rect.top() + 2 * padding_,
option.rect.width() - iconSize_.width() - 4 * padding_,
0,
dir|Qt::AlignTop|Qt::TextWordWrap,
msg);
QTextDocument txtDoc;
txtDoc.setDefaultFont(fontMsg_);
txtDoc.setHtml(msg);
auto textOptions = QTextOption(Qt::AlignLeft);
textOptions.setWrapMode(QTextOption::WrapMode::WordWrap);
txtDoc.setDefaultTextOption(textOptions);
if (dir == Qt::AlignLeft) {
txtDoc.setTextWidth(option.rect.width() - iconSize_.width() - padding_);
textRect.setRect(option.rect.left() + iconSize_.width() + padding_,
option.rect.top() + padding_,
txtDoc.idealWidth(),
txtDoc.size().height());
} else {
textRect = textFontMetrics.boundingRect(option.rect.left() + iconSize_.width() + 2 * padding_,
option.rect.top() + 2 * padding_,
option.rect.width() - iconSize_.width() - 4 * padding_ ,
0,
dir|Qt::AlignTop|Qt::TextWordWrap,
msg);
txtDoc.setTextWidth(option.rect.width() - padding_);
textRect.setRect(option.rect.right() - padding_ - txtDoc.idealWidth(),
option.rect.top() + padding_,
txtDoc.idealWidth(),
txtDoc.size().height());
}
return textRect;
}
......@@ -134,7 +159,7 @@ ImDelegate::sizeHint(const QStyleOptionViewItem& option,
QStyleOptionViewItem opt = option;
opt.font = fontMsg_;
QString msg = index.data(Qt::DisplayRole).toString();
QString msg = index.data(static_cast<int>(Media::TextRecording::Role::FormattedHtml)).toString();
auto dir = index.data(
static_cast<int>(Media::TextRecording::Role::Direction))
......@@ -145,11 +170,13 @@ ImDelegate::sizeHint(const QStyleOptionViewItem& option,
QRect boundingRect = getBoundingRect(dir, msg, opt);
QSize size(option.rect.width(), boundingRect.height() + padding_);
QSize size(option.rect.width(), boundingRect.height());
/* Keep the minimum height needed. */
if(size.height() < iconSize_.height())
size.setHeight(iconSize_.height() + padding_);
size.setHeight(iconSize_.height());
size.setHeight(size.height() + 2 * padding_);
return size;
}
......
......@@ -31,14 +31,10 @@ public:
DATE
};
void setDisplayOptions(DisplayOptions opt);
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
private:
bool showDate_;
bool showAuthor_;
void formatMsg(const QModelIndex& index, QString& msg) const;
QRect getBoundingRect(const Qt::AlignmentFlag& dir, const QString& msg, const QStyleOptionViewItem &option) const;
......
......@@ -30,6 +30,7 @@
#include "imdelegate.h"
#include "globalsystemtray.h"
#include "settingskey.h"
InstantMessagingWidget::InstantMessagingWidget(QWidget *parent) :
QWidget(parent),
......@@ -47,17 +48,20 @@ InstantMessagingWidget::InstantMessagingWidget(QWidget *parent) :
connect(copyAction, &QAction::triggered, [=]() {
copyToClipboard();
});
QSettings settings;
auto displayDate = new QAction(tr("Display date"), this);
displayDate->setCheckable(true);
displayDate->setChecked(settings.value(SettingsKey::imShowDate).toBool());
ui->listMessageView->addAction(displayDate);
auto displayAuthor = new QAction(tr("Display author"), this);
displayAuthor->setCheckable(true);
displayAuthor->setChecked(settings.value(SettingsKey::imShowAuthor).toBool());
ui->listMessageView->addAction(displayAuthor);
auto lamdba = [=](){
int opts = 0;
displayAuthor->isChecked() ? opts |= ImDelegate::DisplayOptions::AUTHOR : opts;
displayDate->isChecked() ? opts |= ImDelegate::DisplayOptions::DATE : opts;
imDelegate_->setDisplayOptions(static_cast<ImDelegate::DisplayOptions>(opts));
QSettings settings;
settings.setValue(SettingsKey::imShowAuthor, displayAuthor->isChecked());
settings.setValue(SettingsKey::imShowDate, displayDate->isChecked());
emit imDelegate_->sizeHintChanged(QModelIndex());
};
connect(displayAuthor, &QAction::triggered, lamdba);
connect(displayDate, &QAction::triggered, lamdba);
......
......@@ -21,6 +21,7 @@
namespace RingTheme {
static const QColor blue_ {"#3AC0D2"};
static const QColor lightBlue_ {"#c1ebf0"};
static const QColor lightGrey_ {242, 242, 242};
static const QColor lightBlack_ {63, 63, 63};
static const QColor grey_ {192, 192, 192};
......
......@@ -24,6 +24,8 @@ constexpr static char closeOrMinimized[] = "closeOrMin";
constexpr static char autoAnswer[] = "autoAnswer";
constexpr static char savedSize[] = "savedSize";
constexpr static char savedPos[] = "savedPos";
constexpr static char imShowAuthor[] = "imShowAuthor";
constexpr static char imShowDate[] = "imShowDate";
}
#define accountAutoAnswer(A) (A+SettingsKey::autoAnswer)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment