diff --git a/i18n/de.ts b/i18n/de.ts
index b2a70868..44e4fdf9 100644
--- a/i18n/de.ts
+++ b/i18n/de.ts
@@ -39,7 +39,7 @@
GlobalDrawer
- Kontakt Hinzufügen
+ Kontakt Hinzufügen
@@ -49,6 +49,10 @@
Über
+
+
+
+
LoginPage
@@ -101,7 +105,7 @@
RosterAddContactSheet
- Kontakt Hinzufügen
+ Kontakt Hinzufügen
@@ -123,6 +127,10 @@
Hinzufügen
+
+
+
+
RosterPage
@@ -131,6 +139,25 @@
Kontakte
+
+ RosterRemoveContactSheet
+
+
+
+
+
+
+
+
+
+
+ Abbrechen
+
+
+
+
+
+
main
diff --git a/i18n/fr.ts b/i18n/fr.ts
index a8d4ce74..a0e2f136 100644
--- a/i18n/fr.ts
+++ b/i18n/fr.ts
@@ -38,15 +38,15 @@
GlobalDrawer
-
+
-
+
-
+
@@ -95,10 +95,6 @@
RosterAddContactSheet
-
-
-
-
@@ -119,6 +115,10 @@
+
+
+
+
RosterPage
@@ -127,4 +127,23 @@
+
+ RosterRemoveContactSheet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/i18n/ja.ts b/i18n/ja.ts
index 43f87f58..350ffd23 100644
--- a/i18n/ja.ts
+++ b/i18n/ja.ts
@@ -38,15 +38,15 @@
GlobalDrawer
-
+
-
+
-
+
@@ -99,10 +99,6 @@
RosterAddContactSheet
-
-
-
-
@@ -123,6 +119,10 @@
+
+
+
+
RosterPage
@@ -131,4 +131,23 @@
+
+ RosterRemoveContactSheet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/i18n/ru.ts b/i18n/ru.ts
index 1c61660d..9256f5fc 100644
--- a/i18n/ru.ts
+++ b/i18n/ru.ts
@@ -37,10 +37,6 @@
GlobalDrawer
-
-
-
-
Выйти
@@ -49,6 +45,10 @@
О программе
+
+
+
+
LoginPage
@@ -99,10 +99,6 @@
RosterAddContactSheet
-
-
-
-
@@ -123,6 +119,10 @@
+
+
+
+
RosterPage
@@ -131,6 +131,25 @@
Контакты
+
+ RosterRemoveContactSheet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
main
diff --git a/src/Kaidan.cpp b/src/Kaidan.cpp
index 8b6cd504..b16e3da8 100644
--- a/src/Kaidan.cpp
+++ b/src/Kaidan.cpp
@@ -31,12 +31,15 @@
// Boost
#include
// Swiften
-#include
+#include
+#include
#include
+#include
// Kaidan
#include "RosterController.h"
#include "PresenceController.h"
#include "MessageController.h"
+#include "MessageModel.h"
#include "VCardController.h"
#include "ServiceDiscoveryManager.h"
@@ -69,7 +72,7 @@ Kaidan::Kaidan(Swift::NetworkFactories* networkFactories, QObject *parent) : QOb
// create/update the full jid
updateFullJid();
- // load controlers
+ // load controllers
messageController = new MessageController(&jid);
rosterController = new RosterController();
presenceController = new PresenceController();
@@ -130,7 +133,7 @@ void Kaidan::mainConnect()
Swift::ClientOptions options;
options.useStreamCompression = false;
-
+
// .. and connect!
client->connect(options);
}
diff --git a/src/Kaidan.h b/src/Kaidan.h
index c06be24d..35d2aa5b 100644
--- a/src/Kaidan.h
+++ b/src/Kaidan.h
@@ -28,7 +28,8 @@
#include
#include
// Swiften
-#include
+#include
+#include
// Kaidan
#include "RosterController.h"
#include "MessageController.h"
diff --git a/src/MessageController.cpp b/src/MessageController.cpp
index 55bda960..71a4420f 100644
--- a/src/MessageController.cpp
+++ b/src/MessageController.cpp
@@ -32,7 +32,11 @@
#include
#include
// Swiften
-#include
+#include
+#include
+#include
+#include
+#include
// Kaidan
#include "MessageModel.h"
#include "Notifications.h"
@@ -67,6 +71,7 @@ MessageModel* MessageController::getMessageModel()
void MessageController::setRecipient(QString recipient_)
{
+ // update the recipient
if (recipient == recipient_)
return;
@@ -77,6 +82,9 @@ void MessageController::setRecipient(QString recipient_)
// we're offline or we haven't connected already.
messageModel->applyRecipientFilter(recipient, *ownJid);
emit messageModelChanged();
+
+ // reset the unread message counter for this contact
+ rosterController->resetUnreadMessagesForJid(recipient_);
}
QString MessageController::getRecipient()
@@ -84,11 +92,6 @@ QString MessageController::getRecipient()
return recipient;
}
-void MessageController::setMessageAsRead(const QString msgId)
-{
- messageModel->setMessageAsRead(msgId);
-}
-
void MessageController::handleMessageReceived(Swift::Message::ref message_)
{
boost::optional bodyOpt = message_->getBody();
@@ -100,7 +103,7 @@ void MessageController::handleMessageReceived(Swift::Message::ref message_)
//
// author is only the 'bare' JID: e.g. 'albert@einstein.ch'
- const QString author = QString(message_->getFrom().toBare().toString().c_str());
+ const QString author = QString::fromStdString(message_->getFrom().toBare().toString());
const QString author_resource = QString(message_->getFrom().getResource().c_str());
const QString recipient_resource = QString::fromStdString(client->getJID().getResource());
QString timestamp = QDateTime::currentDateTime().toString(Qt::ISODate); // fallback timestamp
@@ -162,11 +165,20 @@ void MessageController::handleMessageReceived(Swift::Message::ref message_)
}
//
- // Update lastExchanged in roster controller
+ // Update last exchanged, unread message count in roster controller
//
- rosterController->updateLastExchangedOfJid(QString::fromStdString(
- message_->getFrom().toBare().toString()));
+ if (bodyOpt)
+ {
+ const QString msgAuthor = QString::fromStdString(message_->getFrom().toBare().toString());
+
+ rosterController->updateLastExchangedOfJid(msgAuthor);
+
+ if (msgAuthor != this->recipient)
+ {
+ rosterController->newUnreadMessageForJid(msgAuthor);
+ }
+ }
}
void MessageController::sendMessage(const QString recipient_, const QString message_)
diff --git a/src/MessageController.h b/src/MessageController.h
index 529cc1d8..9970b87e 100644
--- a/src/MessageController.h
+++ b/src/MessageController.h
@@ -24,7 +24,8 @@
#include
#include
// Swiften
-#include
+#include
+#include
// Kaidan
#include "MessageModel.h"
#include "RosterController.h"
@@ -47,7 +48,6 @@ class MessageController : public QObject
QString getRecipient();
Q_INVOKABLE void sendMessage(const QString recipient_, const QString message_);
- Q_INVOKABLE void setMessageAsRead(const QString msgId);
signals:
void messageModelChanged();
diff --git a/src/MessageModel.cpp b/src/MessageModel.cpp
index d2347436..b592d820 100644
--- a/src/MessageModel.cpp
+++ b/src/MessageModel.cpp
@@ -47,20 +47,17 @@ static void createTable()
"'timestamp' TEXT NOT NULL,"
"'message' TEXT NOT NULL,"
"'id' TEXT NOT NULL,"
- "'isSent' BOOL,"
- "'isDelivered' BOOL,"
- "'isRead' BOOL,"
- "'meta' TEXT," // placeholder field for later additons
- "FOREIGN KEY('author') REFERENCES Contacts ('jid'),"
- "FOREIGN KEY('recipient') REFERENCES Contacts ('jid')"
+ "'isSent' BOOL," // is sent to server
+ "'isDelivered' BOOL," // message has arrived at other client
+ "FOREIGN KEY('author') REFERENCES Roster ('jid'),"
+ "FOREIGN KEY('recipient') REFERENCES Roster ('jid')"
")"))
{
qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
}
}
-MessageModel::MessageModel(QObject *parent) :
- QSqlTableModel(parent)
+MessageModel::MessageModel(QObject *parent) : QSqlTableModel(parent)
{
createTable();
setTable(conversationsTableName);
@@ -92,19 +89,12 @@ QVariant MessageModel::data(const QModelIndex &index, int role) const
QHash MessageModel::roleNames() const
{
- QHash names;
- names[Qt::UserRole] = "author";
- names[Qt::UserRole + 1] = "author_resource";
- names[Qt::UserRole + 2] = "recipient";
- names[Qt::UserRole + 3] = "recipient_resource";
- names[Qt::UserRole + 4] = "timestamp";
- names[Qt::UserRole + 5] = "message";
- names[Qt::UserRole + 6] = "id";
- names[Qt::UserRole + 7] = "isSent"; // sent to server
- names[Qt::UserRole + 8] = "isDelivered"; // message has arrived on a client
- names[Qt::UserRole + 9] = "isRead"; // message has been read from the recipient
- names[Qt::UserRole + 10] = "meta";
- return names;
+ QHash roles;
+ // record() returns an empty QSqlRecord
+ for (int i = 0; i < this->record().count(); i++) {
+ roles.insert(Qt::UserRole + i, record().fieldName(i).toUtf8());
+ }
+ return roles;
}
void MessageModel::setMessageAsSent(const QString msgId)
@@ -121,13 +111,6 @@ void MessageModel::setMessageAsDelivered(const QString msgId)
submitAll();
}
-void MessageModel::setMessageAsRead(const QString msgId)
-{
- QSqlQuery newQuery;
- newQuery.exec(QString("UPDATE 'Messages' SET 'isRead' = 1 WHERE id = '%1'").arg(msgId));
- submitAll();
-}
-
void MessageModel::addMessage(const QString* author, const QString* author_resource,
const QString* recipient, const QString* recipient_resource,
const QString* timestamp, const QString* message, const QString* msgId,
@@ -137,19 +120,20 @@ void MessageModel::addMessage(const QString* author, const QString* author_resou
// add the new message
//
- QSqlRecord newRecord = record();
- newRecord.setValue("author", *author);
- newRecord.setValue("author_resource", *author_resource);
- newRecord.setValue("recipient", *recipient);
- newRecord.setValue("recipient_resource", *recipient_resource);
- newRecord.setValue("timestamp", *timestamp);
- newRecord.setValue("message", *message);
- newRecord.setValue("id", *msgId);
- newRecord.setValue("isSent", sentByMe ? false : true);
- newRecord.setValue("isDelivered", sentByMe ? false : true);
- newRecord.setValue("isRead", sentByMe ? true : false);
-
- if (!insertRecord(rowCount(), newRecord)) {
+ QSqlRecord record = this->record();
+ record.setValue("author", *author);
+ record.setValue("author_resource", *author_resource);
+ record.setValue("recipient", *recipient);
+ record.setValue("recipient_resource", *recipient_resource);
+ record.setValue("timestamp", *timestamp);
+ record.setValue("message", *message);
+ record.setValue("id", *msgId);
+ record.setValue("isSent", sentByMe ? false : true);
+ record.setValue("isDelivered", sentByMe ? false : true);
+ record.setValue("isRead", sentByMe ? false : true);
+ record.setValue("isReadByMe", sentByMe ? true : false);
+
+ if (!insertRecord(rowCount(), record)) {
qWarning() << "Failed to add message to DB:" << lastError().text();
return;
}
diff --git a/src/MessageModel.h b/src/MessageModel.h
index fb014d9d..96585c32 100644
--- a/src/MessageModel.h
+++ b/src/MessageModel.h
@@ -39,7 +39,6 @@ class MessageModel : public QSqlTableModel
const QString* msgId, bool sentByMe);
void setMessageAsSent(const QString msgId);
void setMessageAsDelivered(const QString msgId);
- void setMessageAsRead(const QString msgId);
signals:
void recipientChanged();
diff --git a/src/PresenceController.cpp b/src/PresenceController.cpp
index faa017c3..8ff003f2 100644
--- a/src/PresenceController.cpp
+++ b/src/PresenceController.cpp
@@ -19,7 +19,8 @@
#include "PresenceController.h"
#include
-#include
+#include
+#include
#include
PresenceController::PresenceController(QObject* parent) : QObject(parent)
diff --git a/src/PresenceController.h b/src/PresenceController.h
index 9b7c276b..b23238bd 100644
--- a/src/PresenceController.h
+++ b/src/PresenceController.h
@@ -21,7 +21,8 @@
#define PRESENCECONTROLLER_H
#include
-#include
+#include
+#include
class PresenceController : public QObject
{
diff --git a/src/RosterController.cpp b/src/RosterController.cpp
index 626c0ccb..ef266384 100644
--- a/src/RosterController.cpp
+++ b/src/RosterController.cpp
@@ -20,7 +20,8 @@
// RosterController
#include "RosterController.h"
-// C++
+// Std
+#include
#include
// Qt 5
#include
@@ -32,7 +33,13 @@
// Kaidan
#include "RosterModel.h"
// Swiften
-#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
// Boost
#include
@@ -237,3 +244,19 @@ void RosterController::updateLastExchangedOfJid(const QString jid_)
// send signal for updating the GUI
emit rosterModelChanged();
}
+
+void RosterController::newUnreadMessageForJid(const QString jid_)
+{
+ // get the current unread message count
+ int msgCount = rosterModel->getUnreadMessageCountOfJid(&jid_);
+ // increase it by one
+ msgCount++;
+ // set the new increased count
+ rosterModel->setUnreadMessageCountOfJid(&jid_, msgCount);
+}
+
+void RosterController::resetUnreadMessagesForJid(const QString jid_)
+{
+ rosterModel->setUnreadMessageCountOfJid(&jid_, 0);
+ emit rosterModelChanged();
+}
diff --git a/src/RosterController.h b/src/RosterController.h
index 84663911..1384f442 100644
--- a/src/RosterController.h
+++ b/src/RosterController.h
@@ -26,7 +26,8 @@
#include
#include
// Swiften
-#include
+#include
+#include
// Kaidan
#include "RosterModel.h"
@@ -43,6 +44,8 @@ class RosterController : public QObject
void requestRosterFromClient();
RosterModel* getRosterModel();
void updateLastExchangedOfJid(const QString jid_);
+ void newUnreadMessageForJid(const QString jid_);
+ void resetUnreadMessagesForJid(const QString jid_);
Q_INVOKABLE void addContact(const QString jid_, const QString name_);
Q_INVOKABLE void removeContact(const QString);
@@ -57,7 +60,7 @@ class RosterController : public QObject
void handleJidUpdated(const Swift::JID &jid_, const std::string &name_, const std::vector&);
void handleRosterCleared();
Swift::Client* client;
- Swift::IQRouter *iqRouter;
+ Swift::IQRouter* iqRouter;
Swift::XMPPRoster* xmppRoster;
RosterModel* rosterModel;
};
diff --git a/src/RosterModel.cpp b/src/RosterModel.cpp
index 303f0879..891344aa 100644
--- a/src/RosterModel.cpp
+++ b/src/RosterModel.cpp
@@ -40,12 +40,12 @@ static void createTable()
"'jid' TEXT NOT NULL,"
"'name' TEXT NOT NULL,"
"'lastExchanged' TEXT NOT NULL,"
- "'unreadMessages' INTEGER," // < UNUSED v
- "'lastMessage' TEXT,"
+ "'unreadMessages' INTEGER,"
+ "'lastMessage' TEXT," // < UNUSED v
"'lastOnline' TEXT,"
"'activity' TEXT,"
"'status' TEXT,"
- "'mood' TEXT" // < UNUSED ^
+ "'mood' TEXT" // < UNUSED ^
")"))
{
qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
@@ -138,7 +138,7 @@ QStringList RosterModel::getJidList()
QStringList retVar;
QSqlQuery query;
- query.exec("SELECT * FROM 'Roster'");
+ query.exec("SELECT jid FROM Roster");
int jidCol = query.record().indexOf("jid");
@@ -164,3 +164,35 @@ void RosterModel::setLastExchangedOfJid(const QString jid_, const QString date_)
newQuery.exec(QString("UPDATE 'Roster' SET lastExchanged = '%1' WHERE jid = '%2'").arg(date_, jid_));
submitAll();
}
+
+int RosterModel::getUnreadMessageCountOfJid(const QString* jid_)
+{
+ QSqlQuery query;
+
+ query.prepare(QString("SELECT unreadMessages FROM Roster WHERE jid = '%1'").arg(*jid_));
+ if (!query.exec())
+ {
+ qDebug("Failed to query database: %s", qPrintable(query.lastError().text()));
+ return 0;
+ }
+
+ query.next();
+ return query.value("unreadMessages").toInt();
+}
+
+void RosterModel::setUnreadMessageCountOfJid(const QString* jid_, const int count_)
+{
+ QSqlQuery query;
+ query.prepare(QString("UPDATE Roster SET unreadMessages = %1 WHERE jid = '%2'")
+ .arg(QString::number(count_), *jid_));
+
+ if (!query.exec()) {
+ qDebug("Failed to query database: %s", qPrintable(query.lastError().text()));
+ qDebug() << query.lastQuery();
+ }
+ if (!select()) {
+ qDebug() << "Error on select in RosterModel::setUnreadMessageCountOfJid";
+ }
+
+ submit();
+}
diff --git a/src/RosterModel.h b/src/RosterModel.h
index 031a259b..83096cad 100644
--- a/src/RosterModel.h
+++ b/src/RosterModel.h
@@ -24,8 +24,6 @@
#include
#include
#include
-// Swiften
-#include
class RosterModel : public QSqlTableModel
{
@@ -43,9 +41,8 @@ class RosterModel : public QSqlTableModel
QStringList getJidList();
void removeListOfJids(QStringList*);
void setLastExchangedOfJid(const QString, const QString);
-
-private:
- Swift::Client* client;
+ int getUnreadMessageCountOfJid(const QString* jid_);
+ void setUnreadMessageCountOfJid(const QString* jid_, const int unreadMessageCount);
};
#endif // ROSTERMODEL_H
diff --git a/src/ServiceDiscoveryManager.cpp b/src/ServiceDiscoveryManager.cpp
index a36a787b..c188a2ff 100644
--- a/src/ServiceDiscoveryManager.cpp
+++ b/src/ServiceDiscoveryManager.cpp
@@ -26,7 +26,9 @@
// Boost
#include
// Swiften
-#include
+#include
+#include
+#include
ServiceDiscoveryManager::ServiceDiscoveryManager()
{
diff --git a/src/ServiceDiscoveryManager.h b/src/ServiceDiscoveryManager.h
index ce0b2d52..a88eac67 100644
--- a/src/ServiceDiscoveryManager.h
+++ b/src/ServiceDiscoveryManager.h
@@ -25,7 +25,9 @@
#define SERVICEDISCOVERYMANAGER_H
// Swiften
-#include
+#include
+#include
+#include
class ServiceDiscoveryManager
{
diff --git a/src/VCard.cpp b/src/VCard.cpp
index f7a60060..b9747804 100644
--- a/src/VCard.cpp
+++ b/src/VCard.cpp
@@ -19,12 +19,14 @@
// VCard
#include "VCard.h"
+// Std
+#include
// Qt 5
#include
// Boost
#include
// Swiften
-#include
+#include
VCard::VCard(QObject *parent) : QObject(parent)
{
diff --git a/src/VCard.h b/src/VCard.h
index 4924ebb7..e312a1e2 100644
--- a/src/VCard.h
+++ b/src/VCard.h
@@ -26,7 +26,7 @@
// Boost
#include
// Swiften
-#include
+#include
class VCard : public QObject
{
diff --git a/src/VCardController.cpp b/src/VCardController.cpp
index e9eb37f3..84f774f9 100644
--- a/src/VCardController.cpp
+++ b/src/VCardController.cpp
@@ -24,7 +24,8 @@
// Qt 5
#include
// Swiften
-#include
+#include
+#include
// Boost
#include
// Kaidan
diff --git a/src/VCardController.h b/src/VCardController.h
index 015a6f16..29633006 100644
--- a/src/VCardController.h
+++ b/src/VCardController.h
@@ -23,7 +23,9 @@
// Qt
#include
// Swiften
-#include
+#include
+#include
+#include
// Kaidan
#include "VCard.h"
diff --git a/src/main.cpp b/src/main.cpp
index 7180d0e3..f4209c60 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -35,6 +35,7 @@
#include
// Swiften
#include
+#include
// Kaidan
#include "Kaidan.h"
#include "VCard.h"
diff --git a/src/qml/AboutPage.qml b/src/qml/AboutPage.qml
index 97e10203..253e6498 100644
--- a/src/qml/AboutPage.qml
+++ b/src/qml/AboutPage.qml
@@ -63,9 +63,13 @@ Kirigami.Page {
}
Controls.Button {
- anchors.horizontalCenter: parent.horizontalCenter
+ id: closeButton
text: qsTr("Close")
- onClicked: pageStack.pop()
+ anchors.horizontalCenter: parent.horizontalCenter
+ onClicked: {
+ closeButton.enabled = false;
+ pageStack.pop();
+ }
}
}
}
diff --git a/src/qml/ChatPage.qml b/src/qml/ChatPage.qml
index e89fa039..0ad7fa09 100644
--- a/src/qml/ChatPage.qml
+++ b/src/qml/ChatPage.qml
@@ -110,13 +110,6 @@ Kirigami.Page {
}
}
}
-
- Component.onCompleted: {
- // mark unread messages as read
- if (!model.isRead) {
- kaidan.messageController.setMessageAsRead(model.id);
- }
- }
}
}
diff --git a/src/qml/RosterPage.qml b/src/qml/RosterPage.qml
index 57281f4f..dface14a 100644
--- a/src/qml/RosterPage.qml
+++ b/src/qml/RosterPage.qml
@@ -46,13 +46,20 @@ Kirigami.ScrollablePage {
text: model.name ? model.name : model.jid
}
- onClicked: {
- kaidan.messageController.recipient = model.jid;
+ // TODO: Add unread message counter: model.unreadMessages
+ onClicked: {
+ // first push the chat page
pageStack.push(chatPage, {
"chatName": (model.name ? model.name : model.jid),
"recipientJid": model.jid
});
+
+ // then set the message filter for this jid
+ // this will update the unread message count,
+ // which will update the roster and will reset the
+ // model variable
+ kaidan.messageController.recipient = model.jid;
}
actions: [