...
 
Commits (9)
......@@ -29,8 +29,69 @@
*/
#include "Message.h"
#include <QDomElement>
#include <QMimeType>
static bool operator==(const QXmppStanza::Error &left, const QXmppStanza::Error &right) {
return left.code() == right.code()
&& left.text() == right.text()
&& left.condition() == right.condition()
&& left.type() == right.type();
}
static bool operator==(const QXmppElement &left, const QXmppElement &right) {
return left.sourceDomElement() == right.sourceDomElement()
&& left.attributeNames() == right.attributeNames()
&& left.tagName() == right.tagName()
&& left.value() == right.value();
}
static bool operator==(const QXmppExtendedAddress &left, const QXmppExtendedAddress &right) {
return left.description() == right.description()
&& left.jid() == right.jid()
&& left.type() == right.type()
&& left.isDelivered() == right.isDelivered();
}
static bool operator==(const QXmppStanza &left, const QXmppStanza &right) {
return left.to() == right.to()
&& left.from() == right.from()
&& left.id() == right.id()
&& left.lang() == right.lang()
&& left.error() == right.error()
&& left.extensions() == right.extensions()
&& left.extendedAddresses() == right.extendedAddresses()
&& left.isXmppStanza() == right.isXmppStanza();
}
static bool operator==(const QXmppMessage &left, const QXmppMessage &right) {
return operator==(static_cast<const QXmppStanza &>(left), static_cast<const QXmppStanza &>(right))
&& left.body() == right.body()
&& left.isAttentionRequested() == right.isAttentionRequested()
&& left.isReceiptRequested() == right.isReceiptRequested()
&& left.mucInvitationJid() == right.mucInvitationJid()
&& left.mucInvitationPassword() == right.mucInvitationPassword()
&& left.mucInvitationReason() == right.mucInvitationReason()
&& left.receiptId() == right.receiptId()
&& left.stamp() == right.stamp()
&& left.state() == right.state()
&& left.subject() == right.subject()
&& left.thread() == right.thread()
&& left.type() == right.type()
&& left.xhtml() == right.xhtml()
&& left.isMarkable() == right.isMarkable()
&& left.markedId() == right.markedId()
&& left.markedThread() == right.markedThread()
&& left.marker() == right.marker()
&& left.isPrivate() == right.isPrivate()
&& left.isXmppStanza() == right.isXmppStanza()
#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 0, 0)
&& left.outOfBandUrl() == right.outOfBandUrl()
#endif
&& left.replaceId() == right.replaceId();
}
MessageType Message::mediaTypeFromMimeType(const QMimeType &type)
{
if (type.inherits("image/jpeg") || type.inherits("image/png") ||
......@@ -51,23 +112,21 @@ MessageType Message::mediaTypeFromMimeType(const QMimeType &type)
bool Message::operator==(const Message &m) const
{
return m.id() == id() &&
m.body() == body() &&
m.from() == from() &&
m.to() == to() &&
m.type() == type() &&
m.stamp() == stamp() &&
#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 0, 0)
m.outOfBandUrl() == outOfBandUrl() &&
return ::operator==(static_cast<const QXmppMessage &>(m), static_cast<const QXmppMessage &>(*this))
&& m.mediaType() == mediaType()
&& m.sentByMe() == sentByMe()
&& m.isEdited() == isEdited()
&& m.isSent() == isSent()
&& m.isDelivered() == isDelivered()
#if (QXMPP_VERSION) < QT_VERSION_CHECK(1, 0, 0)
&& m.outOfBandUrl() == outOfBandUrl()
#endif
m.isSent() == isSent() &&
m.isDelivered() == isDelivered() &&
m.mediaType() == mediaType() &&
m.mediaContentType() == mediaContentType() &&
m.mediaLocation() == mediaLocation() &&
m.isEdited() == isEdited() &&
m.spoilerHint() == spoilerHint() &&
m.isSpoiler() == isSpoiler();
&& m.mediaLocation() == mediaLocation()
&& m.mediaContentType() == mediaContentType()
&& m.mediaLastModified() == mediaLastModified()
&& m.mediaSize() == mediaSize()
&& m.isSpoiler() == isSpoiler()
&& m.spoilerHint() == spoilerHint();
}
bool Message::operator!=(const Message &m) const
......
......@@ -131,7 +131,7 @@ private:
/**
* Size of the file in bytes.
*/
qint64 m_mediaSize;
qint64 m_mediaSize = 0;
/**
* Timestamp of the last modification date of the file locally on disk.
......
......@@ -108,8 +108,13 @@ QSqlRecord MessageDb::createUpdateRecord(const Message &oldMsg, const Message &n
"timestamp",
newMsg.stamp().toString(Qt::ISODate)
));
if (oldMsg.id() != newMsg.id())
rec.append(Utils::createSqlField("id", newMsg.id()));
if (oldMsg.id() != newMsg.id()) {
// TODO: remove as soon as 'NOT NULL' was removed from id column
if (newMsg.id().isEmpty())
rec.append(Utils::createSqlField("id", QStringLiteral(" ")));
else
rec.append(Utils::createSqlField("id", newMsg.id()));
}
if (oldMsg.body() != newMsg.body())
rec.append(Utils::createSqlField("message", newMsg.body()));
if (oldMsg.isSent() != newMsg.isSent())
......@@ -190,6 +195,7 @@ void MessageDb::addMessage(const Message &msg)
record.setValue("edited", msg.isEdited());
record.setValue("isSpoiler", msg.isSpoiler());
record.setValue("spoilerHint", msg.spoilerHint());
record.setValue("mediaUrl", msg.outOfBandUrl());
record.setValue("mediaContentType", msg.mediaContentType());
record.setValue("mediaLocation", msg.mediaLocation());
record.setValue("mediaSize", msg.mediaSize());
......
......@@ -82,13 +82,13 @@ QSqlRecord RosterDb::createUpdateRecord(const RosterItem &oldItem, const RosterI
rec.append(Utils::createSqlField("lastMessage", newItem.lastMessage()));
if (oldItem.lastExchanged() != newItem.lastExchanged())
rec.append(Utils::createSqlField(
"lastExchanged",
oldItem.lastExchanged().toString(Qt::ISODateWithMs)
"lastExchanged",
newItem.lastExchanged().toString(Qt::ISODateWithMs)
));
if (oldItem.unreadMessages() != newItem.unreadMessages())
rec.append(Utils::createSqlField(
"unreadMessages",
newItem.unreadMessages()
"unreadMessages",
newItem.unreadMessages()
));
return rec;
}
......@@ -247,7 +247,7 @@ void RosterDb::fetchItems()
{
QSqlQuery query(QSqlDatabase::database(DB_CONNECTION));
query.setForwardOnly(true);
Utils::execQuery(query, "SELECT * FROM Roster ORDER BY lastExchanged");
Utils::execQuery(query, "SELECT * FROM Roster");
QVector<RosterItem> items;
parseItemsFromQuery(query, items);
......
......@@ -119,10 +119,8 @@ void RosterManager::populateRoster()
vCardManager->fetchVCard(jid);
}
if (!items.isEmpty()) {
// replace current contacts with new ones from server
emit model->replaceItemsRequested(items);
}
// replace current contacts with new ones from server
emit model->replaceItemsRequested(items);
}
void RosterManager::addContact(const QString &jid, const QString &name, const QString &msg)
......
......@@ -127,6 +127,13 @@ void RosterModel::handleItemsFetched(const QVector<RosterItem> &items)
{
beginResetModel();
m_items = items;
std::sort(
m_items.begin(),
m_items.end(),
[] (const RosterItem &a, const RosterItem &b) {
return a.lastExchanged() > b.lastExchanged();
}
);
endResetModel();
}
......
......@@ -282,6 +282,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
qmlRegisterUncreatableType<QAbstractItemModel>("EmojiModel", 0, 1, "QAbstractItemModel", "Used by proxy models");
qmlRegisterUncreatableType<Emoji>("EmojiModel", 0, 1, "Emoji", "Used by emoji models");
qmlRegisterUncreatableType<TransferJob>(APPLICATION_ID, 1, 0, "TransferJob", "TransferJob type usable");
qmlRegisterUncreatableMetaObject(Enums::staticMetaObject, APPLICATION_ID,
1, 0, "Enums", "Can't create object; only enums defined!");
......
......@@ -351,6 +351,7 @@ Kirigami.ScrollablePage {
messageField.state = "compose"
spoilerHintField.text = ""
isWritingSpoiler = false
messageToCorrect = ''
// reenable the button
sendButton.enabled = true
......
......@@ -50,11 +50,12 @@ RowLayout {
property bool edited
property bool isLoading: kaidan.transferCache.hasUpload(msgId)
property string name
property var upload: {
if (mediaType !== Enums.MessageText &&
kaidan.transferCache.hasUpload(msgId)) {
kaidan.transferCache.jobByMessageId(model.id)
property TransferJob upload: {
if (mediaType !== Enums.MessageType.MessageText && isLoading) {
return kaidan.transferCache.jobByMessageId(model.id)
}
return null
}
property bool isSpoiler
property string spoilerHint
......@@ -66,11 +67,11 @@ RowLayout {
// own messages are on the right, others on the left
layoutDirection: sentByMe ? Qt.RightToLeft : Qt.LeftToRight
spacing: 8
width: parent.width
width: ListView.view.width
// placeholder
Item {
Layout.preferredWidth: 5
Layout.preferredWidth: root.layoutDirection === Qt.LeftToRight ? 5 : 10
}
RoundImage {
......@@ -132,7 +133,13 @@ RowLayout {
id: contextMenu
Controls.MenuItem {
text: qsTr("Copy Message")
onTriggered: isShowingSpoiler ? kaidan.utils.copyToClipboard(messageBody) : kaidan.copyToClipboard(spoilerHint)
enabled: bodyLabel.visible
onTriggered: {
if (!isSpoiler || isShowingSpoiler)
kaidan.utils.copyToClipboard(messageBody);
else
kaidan.utils.copyToClipboard(spoilerHint);
}
}
Controls.MenuItem {
......@@ -140,6 +147,12 @@ RowLayout {
enabled: kaidan.messageModel.canCorrectMessage(msgId)
onTriggered: root.messageEditRequested(msgId, messageBody)
}
Controls.MenuItem {
text: qsTr("Copy download URL")
enabled: mediaGetUrl
onTriggered: kaidan.utils.copyToClipboard(mediaGetUrl)
}
}
}
......@@ -163,7 +176,7 @@ RowLayout {
Controls.Label {
id: dateLabeltest
text: spoilerHint == "" ? qsTr("Spoiler") : spoilerHint
color: sentByMe ? Kirigami.Theme.buttonTextColor
color: sentByMe ? Kirigami.Theme.textColor
: Kirigami.Theme.complementaryTextColor
font.pixelSize: Kirigami.Units.gridUnit * 0.8
}
......@@ -177,7 +190,7 @@ RowLayout {
height: 28
width: 28
source: isShowingSpoiler ? "password-show-off" : "password-show-on"
color: sentByMe ? Kirigami.Theme.buttonTextColor : Kirigami.Theme.complementaryTextColor
color: sentByMe ? Kirigami.Theme.textColor : Kirigami.Theme.complementaryTextColor
}
}
Kirigami.Separator {
......@@ -185,7 +198,7 @@ RowLayout {
Layout.fillWidth: true
color: {
var bgColor = sentByMe ? Kirigami.Theme.backgroundColor : Kirigami.Theme.highlightColor
var textColor = sentByMe ? Kirigami.Theme.textColor : Kirigami.Theme.buttonTextColor
var textColor = sentByMe ? Kirigami.Theme.textColor : Kirigami.Theme.highlightedTextColor
return Qt.tint(textColor, Qt.rgba(bgColor.r, bgColor.g, bgColor.b, 0.7))
}
}
......@@ -226,13 +239,13 @@ RowLayout {
// message body
Controls.Label {
id: messageLabel
visible: messageBody !== ""
id: bodyLabel
visible: messageBody !== "" && messageBody !== mediaGetUrl
text: kaidan.utils.formatMessage(messageBody)
textFormat: Text.StyledText
wrapMode: Text.Wrap
color: sentByMe ? Kirigami.Theme.buttonTextColor
: Kirigami.Theme.complementaryTextColor
color: sentByMe ? Kirigami.Theme.textColor
: Kirigami.Theme.complementaryTextColor
onLinkActivated: Qt.openUrlExternally(link)
Layout.maximumWidth: mediaType === Enums.MessageImage && media.width !== 0
......@@ -244,7 +257,7 @@ RowLayout {
Layout.fillWidth: true
color: {
var bgColor = sentByMe ? Kirigami.Theme.backgroundColor : Kirigami.Theme.highlightColor
var textColor = sentByMe ? Kirigami.Theme.textColor : Kirigami.Theme.buttonTextColor
var textColor = sentByMe ? Kirigami.Theme.textColor : Kirigami.Theme.highlightedTextColor
return Qt.tint(textColor, Qt.rgba(bgColor.r, bgColor.g, bgColor.b, 0.7))
}
}
......@@ -254,7 +267,7 @@ RowLayout {
// progress bar for upload/download status
Controls.ProgressBar {
visible: isLoading
value: isLoading ? upload.progress : 0
value: upload ? upload.progress : 0
}
Controls.Label {
......