encrypted messages now are displayed in the feed

This commit is contained in:
Blue 2023-11-06 20:57:08 -03:00
parent 637eb702a8
commit 0a530bfa93
Signed by: blue
GPG Key ID: 9B203B252A63EE38
34 changed files with 439 additions and 245 deletions

View File

@ -38,9 +38,9 @@ option(WITH_OMEMO "Build OMEMO support module" ON)
# Dependencies # Dependencies
## Qt ## Qt
if (NOT DEFINED QT_VERSION_MAJOR) if (NOT DEFINED QT_VERSION_MAJOR)
find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core) find_package(QT NAMES Qt6 Qt5 CONFIG REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core)
else () else ()
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core) find_package(Qt${QT_VERSION_MAJOR} CONFIG REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core)
endif() endif()
find_package(Boost COMPONENTS) find_package(Boost COMPONENTS)

View File

@ -117,9 +117,8 @@ bool Core::MessageHandler::handleChatMessage(const QXmppMessage& msg, bool outgo
qDebug() << "appending message" << sMsg.getId() << "to an out of roster contact"; qDebug() << "appending message" << sMsg.getId() << "to an out of roster contact";
} }
if (sMsg.getOutgoing()) { if (sMsg.getOutgoing()) {
if (sMsg.getForwarded()) { if (sMsg.getForwarded())
sMsg.setState(Shared::Message::State::sent); sMsg.setState(Shared::Message::State::sent);
}
} else { } else {
sMsg.setState(Shared::Message::State::delivered); sMsg.setState(Shared::Message::State::delivered);
} }
@ -208,6 +207,12 @@ void Core::MessageHandler::initializeMessage(Shared::Message& target, const QXmp
target.setTo(source.to()); target.setTo(source.to());
target.setBody(source.body()); target.setBody(source.body());
target.setForwarded(forwarded); target.setForwarded(forwarded);
#ifdef WITH_OMEMO
#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0)
if (source.encryptionMethod() == QXmpp::EncryptionMethod::Omemo2)
target.setEncryption(Shared::EncryptionProtocol::omemo2);
#endif
#endif
if (guessing) if (guessing)
outgoing = target.getFromJid() == acc->getBareJid(); outgoing = target.getFromJid() == acc->getBareJid();

View File

@ -27,8 +27,7 @@
#include <Omemo/QXmppOmemoStorage.h> #include <Omemo/QXmppOmemoStorage.h>
#endif #endif
int main(int argc, char *argv[]) int main(int argc, char *argv[]) {
{
qRegisterMetaType<Shared::Message>("Shared::Message"); qRegisterMetaType<Shared::Message>("Shared::Message");
qRegisterMetaType<Shared::MessageInfo>("Shared::MessageInfo"); qRegisterMetaType<Shared::MessageInfo>("Shared::MessageInfo");
qRegisterMetaType<Shared::VCard>("Shared::VCard"); qRegisterMetaType<Shared::VCard>("Shared::VCard");

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 11,3 C 8.784,3 7,4.784 7,7 l 0,4 -2,0 c 0,2.666667 0,5.333333 0,8 4,0 8,0 12,0 l 0,-8 c -0.666667,0 -1.333333,0 -2,0 L 15,7 C 15,4.784 13.216,3 11,3 m 0,1 c 1.662,0 3,1.561 3,3.5 L 14,11 8,11 8,7.5 C 8,5.561 9.338,4 11,4"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 558 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8,2 C 8,2 6.5,3.9931391 2,4.4931641 2,4.4931641 2,11.493575 8,14 14,11.493575 14,4.4931641 14,4.4931641 9.5,3.9931391 8,2 8,2 Z m 0,1.0327148 c 1.1902463,1.008525 2.90787,1.6813196 5.134277,2.0200196 C 13.013333,6.1366343 12.897371,6.9523225 12.617188,7.7407227 12.02837,9.3975477 11.341831,10.405496 10.726074,11.130371 9.7719035,12.253646 8.905394,12.708244 8,13.160644 7.094606,12.708244 6.2280961,12.253646 5.2739258,11.130371 4.658169,10.405496 3.97163,9.3975477 3.3828125,7.7407227 3.102629,6.9523225 2.9866669,6.1366343 2.8657227,5.0527344 5.0921299,4.7140344 6.8097538,4.0412398 8,3.0327148 Z M 8,3.9321289 C 6.6923817,4.8398539 5.2233869,5.2995548 3.7490234,5.6123046 4.4471579,9.5738045 5.9510862,11.267813 8,12.328613 10.048914,11.267813 11.552843,9.5738045 12.250977,5.6123046 10.776613,5.2995547 9.3076183,4.8398539 8,3.9321289 Z"
class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="m11 3c-2.216 0-4 1.784-4 4v1h1v-.5c0-1.939 1.338-3.5 3-3.5 1.662 0 3 1.561 3 3.5v3.5h-5-1-1-1-1v1 7h1 10 1v-8h-1-1v-4c0-2.216-1.784-4-4-4m-5 9h10v6h-10v-6"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 491 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8,2 C 6.3431375,2 5,3.3431372 5,5 l 0,3 -2,0 0,6 10,0 0,-6 -2,0 0,-3 C 11,3.3431372 9.6568625,2 8,2 Z m 0,1 c 1.1045695,0 2,0.8954305 2,2 L 10,8 6,8 6,5 C 6,3.8954305 6.8954305,3 8,3 Z"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 522 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8,2 C 8,2 6.5,3.9931391 2,4.4931641 2,4.4931641 2,11.493575 8,14 14,11.493575 14,4.4931641 14,4.4931641 9.5,3.9931391 8,2 8,2 Z m 0,1.0327148 c 1.1902463,1.008525 2.90787,1.6813196 5.134277,2.0200196 C 13.013333,6.1366343 12.897371,6.9523225 12.617188,7.7407227 12.02837,9.3975477 11.341831,10.405496 10.726074,11.130371 9.7719035,12.253646 8.905394,12.708244 8,13.160644 7.094606,12.708244 6.2280961,12.253646 5.2739258,11.130371 4.658169,10.405496 3.97163,9.3975477 3.3828125,7.7407227 3.102629,6.9523225 2.9866669,6.1366343 2.8657227,5.0527344 5.0921299,4.7140344 6.8097538,4.0412398 8,3.0327148 Z M 8,3.9321289 C 6.6923817,4.8398539 5.2233869,5.2995548 3.7490234,5.6123046 4.4471579,9.5738045 5.9510862,11.267813 8,12.328613 10.048914,11.267813 11.552843,9.5738045 12.250977,5.6123046 10.776613,5.2995547 9.3076183,4.8398539 8,3.9321289 Z"
class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8 2 C 6.3431375 2 5 3.3431371 5 5 L 5 6 L 6 6 L 6 5 C 6 3.8954305 6.8954305 3 8 3 C 9.1045695 3 10 3.8954305 10 5 L 10 8 L 7 8 L 6 8 L 5 8 L 3 8 L 3 14 L 13 14 L 13 8 L 11 8 L 11 5 C 11 3.3431371 9.6568625 2 8 2 z M 4 9 L 12 9 L 12 13 L 4 13 L 4 9 z "
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 588 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 11,3 C 8.784,3 7,4.784 7,7 l 0,4 -2,0 c 0,2.666667 0,5.333333 0,8 4,0 8,0 12,0 l 0,-8 c -0.666667,0 -1.333333,0 -2,0 L 15,7 C 15,4.784 13.216,3 11,3 m 0,1 c 1.662,0 3,1.561 3,3.5 L 14,11 8,11 8,7.5 C 8,5.561 9.338,4 11,4"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 558 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8,2 C 8,2 6.5,3.9931391 2,4.4931641 2,4.4931641 2,11.493575 8,14 14,11.493575 14,4.4931641 14,4.4931641 9.5,3.9931391 8,2 8,2 Z m 0,1.0327148 c 1.1902463,1.008525 2.90787,1.6813196 5.134277,2.0200196 C 13.013333,6.1366343 12.897371,6.9523225 12.617188,7.7407227 12.02837,9.3975477 11.341831,10.405496 10.726074,11.130371 9.7719035,12.253646 8.905394,12.708244 8,13.160644 7.094606,12.708244 6.2280961,12.253646 5.2739258,11.130371 4.658169,10.405496 3.97163,9.3975477 3.3828125,7.7407227 3.102629,6.9523225 2.9866669,6.1366343 2.8657227,5.0527344 5.0921299,4.7140344 6.8097538,4.0412398 8,3.0327148 Z M 8,3.9321289 C 6.6923817,4.8398539 5.2233869,5.2995548 3.7490234,5.6123046 4.4471579,9.5738045 5.9510862,11.267813 8,12.328613 10.048914,11.267813 11.552843,9.5738045 12.250977,5.6123046 10.776613,5.2995547 9.3076183,4.8398539 8,3.9321289 Z"
class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="m11 3c-2.216 0-4 1.784-4 4v1h1v-.5c0-1.939 1.338-3.5 3-3.5 1.662 0 3 1.561 3 3.5v3.5h-5-1-1-1-1v1 7h1 10 1v-8h-1-1v-4c0-2.216-1.784-4-4-4m-5 9h10v6h-10v-6"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 491 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8,2 C 6.3431375,2 5,3.3431372 5,5 l 0,3 -2,0 0,6 10,0 0,-6 -2,0 0,-3 C 11,3.3431372 9.6568625,2 8,2 Z m 0,1 c 1.1045695,0 2,0.8954305 2,2 L 10,8 6,8 6,5 C 6,3.8954305 6.8954305,3 8,3 Z"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 522 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8,2 C 8,2 6.5,3.9931391 2,4.4931641 2,4.4931641 2,11.493575 8,14 14,11.493575 14,4.4931641 14,4.4931641 9.5,3.9931391 8,2 8,2 Z m 0,1.0327148 c 1.1902463,1.008525 2.90787,1.6813196 5.134277,2.0200196 C 13.013333,6.1366343 12.897371,6.9523225 12.617188,7.7407227 12.02837,9.3975477 11.341831,10.405496 10.726074,11.130371 9.7719035,12.253646 8.905394,12.708244 8,13.160644 7.094606,12.708244 6.2280961,12.253646 5.2739258,11.130371 4.658169,10.405496 3.97163,9.3975477 3.3828125,7.7407227 3.102629,6.9523225 2.9866669,6.1366343 2.8657227,5.0527344 5.0921299,4.7140344 6.8097538,4.0412398 8,3.0327148 Z M 8,3.9321289 C 6.6923817,4.8398539 5.2233869,5.2995548 3.7490234,5.6123046 4.4471579,9.5738045 5.9510862,11.267813 8,12.328613 10.048914,11.267813 11.552843,9.5738045 12.250977,5.6123046 10.776613,5.2995547 9.3076183,4.8398539 8,3.9321289 Z"
class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 8 2 C 6.3431375 2 5 3.3431371 5 5 L 5 6 L 6 6 L 6 5 C 6 3.8954305 6.8954305 3 8 3 C 9.1045695 3 10 3.8954305 10 5 L 10 8 L 7 8 L 6 8 L 5 8 L 3 8 L 3 14 L 13 14 L 13 8 L 11 8 L 11 5 C 11 3.3431371 9.6568625 2 8 2 z M 4 9 L 12 9 L 12 13 L 4 13 L 4 9 z "
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 588 B

View File

@ -42,6 +42,9 @@
<file>images/fallback/dark/big/add.svg</file> <file>images/fallback/dark/big/add.svg</file>
<file>images/fallback/dark/big/folder.svg</file> <file>images/fallback/dark/big/folder.svg</file>
<file>images/fallback/dark/big/document-preview.svg</file> <file>images/fallback/dark/big/document-preview.svg</file>
<file>images/fallback/dark/big/shield.svg</file>
<file>images/fallback/dark/big/lock.svg</file>
<file>images/fallback/dark/big/unlock.svg</file>
<file>images/fallback/dark/small/absent.svg</file> <file>images/fallback/dark/small/absent.svg</file>
@ -84,6 +87,9 @@
<file>images/fallback/dark/small/add.svg</file> <file>images/fallback/dark/small/add.svg</file>
<file>images/fallback/dark/small/folder.svg</file> <file>images/fallback/dark/small/folder.svg</file>
<file>images/fallback/dark/small/document-preview.svg</file> <file>images/fallback/dark/small/document-preview.svg</file>
<file>images/fallback/dark/small/shield.svg</file>
<file>images/fallback/dark/small/lock.svg</file>
<file>images/fallback/dark/small/unlock.svg</file>
<file>images/fallback/light/big/absent.svg</file> <file>images/fallback/light/big/absent.svg</file>
@ -126,6 +132,9 @@
<file>images/fallback/light/big/add.svg</file> <file>images/fallback/light/big/add.svg</file>
<file>images/fallback/light/big/folder.svg</file> <file>images/fallback/light/big/folder.svg</file>
<file>images/fallback/light/big/document-preview.svg</file> <file>images/fallback/light/big/document-preview.svg</file>
<file>images/fallback/light/big/shield.svg</file>
<file>images/fallback/light/big/lock.svg</file>
<file>images/fallback/light/big/unlock.svg</file>
<file>images/fallback/light/small/absent.svg</file> <file>images/fallback/light/small/absent.svg</file>
@ -168,5 +177,8 @@
<file>images/fallback/light/small/add.svg</file> <file>images/fallback/light/small/add.svg</file>
<file>images/fallback/light/small/folder.svg</file> <file>images/fallback/light/small/folder.svg</file>
<file>images/fallback/light/small/document-preview.svg</file> <file>images/fallback/light/small/document-preview.svg</file>
<file>images/fallback/light/small/shield.svg</file>
<file>images/fallback/light/small/lock.svg</file>
<file>images/fallback/light/small/unlock.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef SHARED_ENUMS_H #pragma once
#define SHARED_ENUMS_H
#include <deque> #include <deque>
@ -170,4 +169,3 @@ static const EncryptionProtocol EncryptionProtocolHighest = EncryptionProtocol::
static const EncryptionProtocol EncryptionProtocolLowest = EncryptionProtocol::omemo2; static const EncryptionProtocol EncryptionProtocolLowest = EncryptionProtocol::omemo2;
} }
#endif // SHARED_ENUMS_H

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef EXCEPTION_H #pragma once
#define EXCEPTION_H
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
@ -36,5 +35,3 @@ namespace Utils
const char* what() const noexcept( true ); const char* what() const noexcept( true );
}; };
} }
#endif // EXCEPTION_H

View File

@ -62,70 +62,78 @@ Shared::Global::ColorSchemeName Shared::Global::colorSchemeName = 0;
Shared::Global::CreatePalette Shared::Global::createPalette = 0; Shared::Global::CreatePalette Shared::Global::createPalette = 0;
#endif #endif
Shared::Global::Global(): Shared::Global::Global():
availability({ availability({
tr("Online", "Availability"), QCoreApplication::translate("Global", "Online", "Availability"),
tr("Away", "Availability"), QCoreApplication::translate("Global", "Away", "Availability"),
tr("Absent", "Availability"), QCoreApplication::translate("Global", "Absent", "Availability"),
tr("Busy", "Availability"), QCoreApplication::translate("Global", "Busy", "Availability"),
tr("Chatty", "Availability"), QCoreApplication::translate("Global", "Chatty", "Availability"),
tr("Invisible", "Availability"), QCoreApplication::translate("Global", "Invisible", "Availability"),
tr("Offline", "Availability") QCoreApplication::translate("Global", "Offline", "Availability")
}), }),
connectionState({ connectionState({
tr("Disconnected", "ConnectionState"), QCoreApplication::translate("Global", "Disconnected", "ConnectionState"),
tr("Scheduled", "ConnectionState"), QCoreApplication::translate("Global", "Scheduled", "ConnectionState"),
tr("Connecting", "ConnectionState"), QCoreApplication::translate("Global", "Connecting", "ConnectionState"),
tr("Connected", "ConnectionState"), QCoreApplication::translate("Global", "Connected", "ConnectionState"),
tr("Error", "ConnectionState") QCoreApplication::translate("Global", "Error", "ConnectionState")
}), }),
subscriptionState({ subscriptionState({
tr("None", "SubscriptionState"), QCoreApplication::translate("Global", "None", "SubscriptionState"),
tr("From", "SubscriptionState"), QCoreApplication::translate("Global", "From", "SubscriptionState"),
tr("To", "SubscriptionState"), QCoreApplication::translate("Global", "To", "SubscriptionState"),
tr("Both", "SubscriptionState"), QCoreApplication::translate("Global", "Both", "SubscriptionState"),
tr("Unknown", "SubscriptionState") QCoreApplication::translate("Global", "Unknown", "SubscriptionState")
}), }),
affiliation({ affiliation({
tr("Unspecified", "Affiliation"), QCoreApplication::translate("Global", "Unspecified", "Affiliation"),
tr("Outcast", "Affiliation"), QCoreApplication::translate("Global", "Outcast", "Affiliation"),
tr("Nobody", "Affiliation"), QCoreApplication::translate("Global", "Nobody", "Affiliation"),
tr("Member", "Affiliation"), QCoreApplication::translate("Global", "Member", "Affiliation"),
tr("Admin", "Affiliation"), QCoreApplication::translate("Global", "Admin", "Affiliation"),
tr("Owner", "Affiliation") QCoreApplication::translate("Global", "Owner", "Affiliation")
}), }),
role({ role({
tr("Unspecified", "Role"), QCoreApplication::translate("Global", "Unspecified", "Role"),
tr("Nobody", "Role"), QCoreApplication::translate("Global", "Nobody", "Role"),
tr("Visitor", "Role"), QCoreApplication::translate("Global", "Visitor", "Role"),
tr("Participant", "Role"), QCoreApplication::translate("Global", "Participant", "Role"),
tr("Moderator", "Role") QCoreApplication::translate("Global", "Moderator", "Role")
}), }),
messageState({ messageState({
tr("Pending", "MessageState"), QCoreApplication::translate("Global", "Pending", "MessageState"),
tr("Sent", "MessageState"), QCoreApplication::translate("Global", "Sent", "MessageState"),
tr("Delivered", "MessageState"), QCoreApplication::translate("Global", "Delivered", "MessageState"),
tr("Error", "MessageState") QCoreApplication::translate("Global", "Error", "MessageState")
}), }),
accountPassword({ accountPassword({
tr("Plain", "AccountPassword"), QCoreApplication::translate("Global", "Plain", "AccountPassword"),
tr("Jammed", "AccountPassword"), QCoreApplication::translate("Global", "Jammed", "AccountPassword"),
tr("Always Ask", "AccountPassword"), QCoreApplication::translate("Global", "Always Ask", "AccountPassword"),
tr("KWallet", "AccountPassword") QCoreApplication::translate("Global", "KWallet", "AccountPassword")
}), }),
trustLevel({ trustLevel({
tr("Undecided", "TrustLevel"), QCoreApplication::translate("Global", "Undecided", "TrustLevel"),
tr("Automatically distrusted", "TrustLevel"), QCoreApplication::translate("Global", "Automatically distrusted", "TrustLevel"),
tr("Manually distrusted", "TrustLevel"), QCoreApplication::translate("Global", "Manually distrusted", "TrustLevel"),
tr("Automatically trusted", "TrustLevel"), QCoreApplication::translate("Global", "Automatically trusted", "TrustLevel"),
tr("Manually trusted", "TrustLevel"), QCoreApplication::translate("Global", "Manually trusted", "TrustLevel"),
tr("Authenticated", "TrustLevel") QCoreApplication::translate("Global", "Authenticated", "TrustLevel")
}),
encryptionProtocols({
QCoreApplication::translate("Global", "None", "EncryptionProtocol"),
QCoreApplication::translate("Global", "OMEMO 0", "EncryptionProtocol"),
QCoreApplication::translate("Global", "OMEMO 1", "EncryptionProtocol"),
QCoreApplication::translate("Global", "OMEMO 2", "EncryptionProtocol")
}), }),
accountPasswordDescription({ accountPasswordDescription({
tr("Your password is going to be stored in config file in plain text", "AccountPasswordDescription"), QCoreApplication::translate("Global", "Your password is going to be stored in config file in plain text", "AccountPasswordDescription"),
tr("Your password is going to be stored in config file but jammed with constant encryption key you can find in program source code. It might look like encryption but it's not", "AccountPasswordDescription"), QCoreApplication::translate("Global", "Your password is going to be stored in config file but jammed with constant encryption key you can find in program source code. It might look like encryption but it's not", "AccountPasswordDescription"),
tr("Squawk is going to query you for the password on every start of the program", "AccountPasswordDescription"), QCoreApplication::translate("Global", "Squawk is going to query you for the password on every start of the program", "AccountPasswordDescription"),
tr("Your password is going to be stored in KDE wallet storage (KWallet). You're going to be queried for permissions", "AccountPasswordDescription") QCoreApplication::translate("Global", "Your password is going to be stored in KDE wallet storage (KWallet). You're going to be queried for permissions", "AccountPasswordDescription")
}), }),
defaultSystemStyle(QApplication::style()->objectName()), defaultSystemStyle(QApplication::style()->objectName()),
defaultSystemPalette(QApplication::palette()), defaultSystemPalette(QApplication::palette()),
@ -262,6 +270,10 @@ QString Shared::Global::getName(Shared::TrustLevel tl) {
return instance->trustLevel[static_cast<int>(tl)]; return instance->trustLevel[static_cast<int>(tl)];
} }
QString Shared::Global::getName(EncryptionProtocol ep) {
return instance->encryptionProtocols[static_cast<int>(ep)];
}
void Shared::Global::setSupported(const QString& pluginName, bool support) { void Shared::Global::setSupported(const QString& pluginName, bool support) {
std::map<QString, bool>::iterator itr = instance->pluginSupport.find(pluginName); std::map<QString, bool>::iterator itr = instance->pluginSupport.find(pluginName);
if (itr != instance->pluginSupport.end()) { if (itr != instance->pluginSupport.end()) {

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef SHARED_GLOBAL_H #pragma once
#define SHARED_GLOBAL_H
#include "enums.h" #include "enums.h"
#include "message.h" #include "message.h"
@ -48,7 +47,6 @@
namespace Shared { namespace Shared {
class Global { class Global {
Q_DECLARE_TR_FUNCTIONS(Global)
public: public:
struct FileInfo { struct FileInfo {
enum class Preview { enum class Preview {
@ -75,6 +73,7 @@ namespace Shared {
static QString getName(Message::State rl); static QString getName(Message::State rl);
static QString getName(AccountPassword ap); static QString getName(AccountPassword ap);
static QString getName(TrustLevel tl); static QString getName(TrustLevel tl);
static QString getName(EncryptionProtocol ep);
static QString getDescription(AccountPassword ap); static QString getDescription(AccountPassword ap);
@ -86,6 +85,7 @@ namespace Shared {
const std::deque<QString> messageState; const std::deque<QString> messageState;
const std::deque<QString> accountPassword; const std::deque<QString> accountPassword;
const std::deque<QString> trustLevel; const std::deque<QString> trustLevel;
const std::deque<QString> encryptionProtocols;
const std::deque<QString> accountPasswordDescription; const std::deque<QString> accountPasswordDescription;
@ -161,5 +161,3 @@ namespace Shared {
#endif #endif
}; };
} }
#endif // SHARED_GLOBAL_H

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef SHARED_ICONS_H #pragma once
#define SHARED_ICONS_H
#include <QIcon> #include <QIcon>
@ -175,8 +174,9 @@ static const std::map<QString, std::pair<QString, QString>> icons = {
{"unfavorite", {"draw-star", "unfavorite"}}, {"unfavorite", {"draw-star", "unfavorite"}},
{"list-add", {"list-add", "add"}}, {"list-add", {"list-add", "add"}},
{"folder", {"folder", "folder"}}, {"folder", {"folder", "folder"}},
{"document-preview", {"document-preview", "document-preview"}} {"document-preview", {"document-preview", "document-preview"}},
{"secure", {"security-high", "shield"}},
{"lock", {"lock", "lock"}},
{"unlock", {"unlock", "unlock"}}
}; };
} }
#endif // SHARED_ICONS_H

View File

@ -37,7 +37,8 @@ Shared::Message::Message(Shared::Message::Type p_type):
originalMessage(), originalMessage(),
lastModified(), lastModified(),
stanzaId(), stanzaId(),
attachPath() attachPath(),
encryption(EncryptionProtocol::none)
{} {}
Shared::Message::Message(): Shared::Message::Message():
@ -58,7 +59,8 @@ Shared::Message::Message():
originalMessage(), originalMessage(),
lastModified(), lastModified(),
stanzaId(), stanzaId(),
attachPath() attachPath(),
encryption(EncryptionProtocol::none)
{} {}
QString Shared::Message::getBody() const { QString Shared::Message::getBody() const {
@ -234,9 +236,8 @@ void Shared::Message::setType(Shared::Message::Type t) {
void Shared::Message::setState(Shared::Message::State p_state) { void Shared::Message::setState(Shared::Message::State p_state) {
state = p_state; state = p_state;
if (state != State::error) { if (state != State::error)
errorText = ""; errorText = "";
}
} }
bool Shared::Message::serverStored() const { bool Shared::Message::serverStored() const {

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef SHAPER_MESSAGE_H #pragma once
#define SHAPER_MESSAGE_H
#include <QString> #include <QString>
#include <QDateTime> #include <QDateTime>
@ -154,5 +153,3 @@ private:
}; };
} }
#endif // SHAPER_MESSAGE_H

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PATHCHECK_H #pragma once
#define PATHCHECK_H
#include <QString> #include <QString>
#include <QStandardPaths> #include <QStandardPaths>
@ -40,5 +39,3 @@ QString squawkifyPath(QString path);
bool isSubdirectoryOfSettings(const QString& path); bool isSubdirectoryOfSettings(const QString& path);
} }
#endif // PATHCHECK_H

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef SHARED_UTILS_H #pragma once
#define SHARED_UTILS_H
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
@ -76,5 +75,3 @@ enum class Hover {
anchor anchor
}; };
} }
#endif // SHARED_UTILS_H

View File

@ -24,12 +24,11 @@
#include "shared/icons.h" #include "shared/icons.h"
#include "shared/global.h" #include "shared/global.h"
namespace Ui namespace Ui {
{
class Chat; class Chat;
} }
class Chat : public Conversation
{ class Chat : public Conversation {
Q_OBJECT Q_OBJECT
public: public:
Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent = 0); Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent = 0);

View File

@ -120,6 +120,7 @@ Conversation::~Conversation() {
delete contextMenu; delete contextMenu;
element->feed->decrementObservers(); element->feed->decrementObservers();
delete m_ui;
} }
void Conversation::onAccountChanged(Models::Item* item, int row, int col) { void Conversation::onAccountChanged(Models::Item* item, int row, int col) {

View File

@ -20,6 +20,7 @@
#define CONVERSATION_H #define CONVERSATION_H
#include <QWidget> #include <QWidget>
#include <QObject>
#include <QScopedPointer> #include <QScopedPointer>
#include <QMap> #include <QMap>
#include <QMimeData> #include <QMimeData>
@ -134,7 +135,7 @@ protected:
Models::Element* element; Models::Element* element;
QString palJid; QString palJid;
QString activePalResource; QString activePalResource;
QScopedPointer<Ui::Conversation> m_ui; Ui::Conversation* m_ui;
KeyEnterReceiver ker; KeyEnterReceiver ker;
QString thread; QString thread;
QLabel* statusIcon; QLabel* statusIcon;

View File

@ -14,5 +14,4 @@ set(HEADER_FILES
target_sources(squawk PRIVATE target_sources(squawk PRIVATE
${SOURCE_FILES} ${SOURCE_FILES}
${HEADER_FILES}
) )

View File

@ -47,22 +47,23 @@ MessageDelegate::MessageDelegate(QObject* parent):
dateFont(Shared::Global::getInstance()->smallFont), dateFont(Shared::Global::getInstance()->smallFont),
nickMetrics(Shared::Global::getInstance()->headerFontMetrics), nickMetrics(Shared::Global::getInstance()->headerFontMetrics),
dateMetrics(Shared::Global::getInstance()->smallFontMetrics), dateMetrics(Shared::Global::getInstance()->smallFontMetrics),
bodyRenderer(new QTextDocument()), bodyRenderer(),
buttonHeight(0), buttonHeight(0),
buttonWidth(0), buttonWidth(0),
barHeight(0), barHeight(0),
buttons(new std::map<QString, FeedButton*>()), buttons(),
bars(new std::map<QString, QProgressBar*>()), bars(),
statusIcons(new std::map<QString, QLabel*>()), statusIcons(),
pencilIcons(new std::map<QString, QLabel*>()), pencilIcons(),
previews(new std::map<QString, Preview*>()), encryptionIcons(),
idsToKeep(new std::set<QString>()), previews(),
idsToKeep(),
clearingWidgets(false), clearingWidgets(false),
currentId(""), currentId(""),
selection(0, 0) selection(0, 0)
{ {
bodyRenderer->setDocumentMargin(0); bodyRenderer.setDocumentMargin(0);
bodyRenderer->setDefaultFont(bodyFont); bodyRenderer.setDefaultFont(bodyFont);
QPushButton btn(QCoreApplication::translate("MessageLine", "Download")); QPushButton btn(QCoreApplication::translate("MessageLine", "Download"));
buttonHeight = btn.sizeHint().height(); buttonHeight = btn.sizeHint().height();
@ -73,28 +74,23 @@ MessageDelegate::MessageDelegate(QObject* parent):
} }
MessageDelegate::~MessageDelegate() { MessageDelegate::~MessageDelegate() {
for (const std::pair<const QString, FeedButton*>& pair: *buttons) for (const std::pair<const QString, FeedButton*>& pair: buttons)
delete pair.second; delete pair.second;
for (const std::pair<const QString, QProgressBar*>& pair: *bars) for (const std::pair<const QString, QProgressBar*>& pair: bars)
delete pair.second; delete pair.second;
for (const std::pair<const QString, QLabel*>& pair: *statusIcons) for (const std::pair<const QString, QLabel*>& pair: statusIcons)
delete pair.second; delete pair.second;
for (const std::pair<const QString, QLabel*>& pair: *pencilIcons) for (const std::pair<const QString, QLabel*>& pair: pencilIcons)
delete pair.second; delete pair.second;
for (const std::pair<const QString, Preview*>& pair: *previews) for (const std::pair<const QString, QLabel*>& pair: encryptionIcons)
delete pair.second; delete pair.second;
delete statusIcons; for (const std::pair<const QString, Preview*>& pair: previews)
delete pencilIcons; delete pair.second;
delete idsToKeep;
delete buttons;
delete bars;
delete previews;
delete bodyRenderer;
} }
void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
@ -168,6 +164,7 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
painter->setPen(q); painter->setPen(q);
painter->drawText(opt.rect, opt.displayAlignment, dateString, &rect); painter->drawText(opt.rect, opt.displayAlignment, dateString, &rect);
int currentY = opt.rect.y(); int currentY = opt.rect.y();
int statusOffset = statusIconSize;
if (data.sentByMe) { if (data.sentByMe) {
QLabel* statusIcon = getStatusIcon(data); QLabel* statusIcon = getStatusIcon(data);
@ -176,30 +173,43 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
statusIcon->show(); statusIcon->show();
opt.rect.adjust(0, statusIconSize + textMargin, 0, 0); opt.rect.adjust(0, statusIconSize + textMargin, 0, 0);
statusOffset = statusIconSize + margin;
} }
if (data.correction.corrected) { if (data.correction.corrected) {
QLabel* pencilIcon = getPencilIcon(data); QLabel* pencilIcon = getPencilIcon(data);
pencilIcon->setParent(vp); pencilIcon->setParent(vp);
if (data.sentByMe) if (data.sentByMe)
pencilIcon->move(opt.rect.left() + statusIconSize + margin, currentY); pencilIcon->move(opt.rect.left() + statusOffset, currentY);
else else
pencilIcon->move(opt.rect.right() - statusIconSize - margin, currentY); pencilIcon->move(opt.rect.right() - statusOffset, currentY);
pencilIcon->show(); pencilIcon->show();
statusOffset += statusIconSize + margin;
} else { } else {
std::map<QString, QLabel*>::const_iterator itr = pencilIcons->find(data.id); std::map<QString, QLabel*>::const_iterator itr = pencilIcons.find(data.id);
if (itr != pencilIcons->end()) { if (itr != pencilIcons.end()) {
delete itr->second; delete itr->second;
pencilIcons->erase(itr); pencilIcons.erase(itr);
} }
} }
if (data.encryption != Shared::EncryptionProtocol::none) {
QLabel* shieldIcon = getEncryptionIcon(data);
shieldIcon->setParent(vp);
if (data.sentByMe)
shieldIcon->move(opt.rect.left() + statusOffset, currentY);
else
shieldIcon->move(opt.rect.right() - statusOffset, currentY);
shieldIcon->show();
statusOffset += statusIconSize + margin;
}
painter->restore(); painter->restore();
if (clearingWidgets) if (clearingWidgets)
idsToKeep->insert(data.id); idsToKeep.insert(data.id);
} }
void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const { void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const {
@ -281,11 +291,11 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
Models::FeedItem data = qvariant_cast<Models::FeedItem>(vi); Models::FeedItem data = qvariant_cast<Models::FeedItem>(vi);
QSize messageSize(0, 0); QSize messageSize(0, 0);
if (data.text.size() > 0) { if (data.text.size() > 0) {
bodyRenderer->setPlainText(data.text); bodyRenderer.setPlainText(data.text);
bodyRenderer->setTextWidth(messageRect.size().width()); bodyRenderer.setTextWidth(messageRect.size().width());
QSizeF size = bodyRenderer->size(); QSizeF size = bodyRenderer.size();
size.setWidth(bodyRenderer->idealWidth()); size.setWidth(bodyRenderer.idealWidth());
messageSize = QSize(std::ceil(size.width()), std::ceil(size.height())); messageSize = QSize(std::ceil(size.width()), std::ceil(size.height()));
messageSize.rheight() += textMargin; messageSize.rheight() += textMargin;
} }
@ -338,9 +348,12 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
messageSize.rheight() += dateSize.height() > statusIconSize ? dateSize.height() : statusIconSize; messageSize.rheight() += dateSize.height() > statusIconSize ? dateSize.height() : statusIconSize;
int statusWidth = dateSize.width() + statusIconSize + margin; int statusWidth = dateSize.width() + statusIconSize + margin;
if (data.correction.corrected) { if (data.correction.corrected)
statusWidth += statusIconSize + margin; statusWidth += statusIconSize + margin;
}
if (data.encryption != Shared::EncryptionProtocol::none)
statusWidth += statusIconSize + margin;
messageSize.setWidth(std::max(statusWidth, messageSize.width())); messageSize.setWidth(std::max(statusWidth, messageSize.width()));
messageSize.rwidth() += 2 * bubbleMargin; messageSize.rwidth() += 2 * bubbleMargin;
@ -399,10 +412,10 @@ QString MessageDelegate::getAnchor(const QPoint& point, const QModelIndex& index
if (localHint.contains(point)) { if (localHint.contains(point)) {
QPoint translated = point - localHint.topLeft(); QPoint translated = point - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text)); bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width()); bodyRenderer.setTextWidth(localHint.size().width());
return bodyRenderer->documentLayout()->anchorAt(translated); return bodyRenderer.documentLayout()->anchorAt(translated);
} }
} }
@ -424,13 +437,13 @@ QString MessageDelegate::leftDoubleClick(const QPoint& point, const QModelIndex&
if (localHint.contains(point)) { if (localHint.contains(point)) {
QPoint translated = point - localHint.topLeft(); QPoint translated = point - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text)); bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width()); bodyRenderer.setTextWidth(localHint.size().width());
QAbstractTextDocumentLayout* lay = bodyRenderer->documentLayout(); QAbstractTextDocumentLayout* lay = bodyRenderer.documentLayout();
int position = lay->hitTest(translated, Qt::HitTestAccuracy::FuzzyHit); int position = lay->hitTest(translated, Qt::HitTestAccuracy::FuzzyHit);
QTextCursor cursor(bodyRenderer); QTextCursor cursor(&bodyRenderer);
cursor.setPosition(position, QTextCursor::MoveAnchor); cursor.setPosition(position, QTextCursor::MoveAnchor);
cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor); cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
@ -456,10 +469,10 @@ Shared::Hover MessageDelegate::hoverType(const QPoint& point, const QModelIndex&
if (localHint.contains(point)) { if (localHint.contains(point)) {
QPoint translated = point - localHint.topLeft(); QPoint translated = point - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text)); bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width()); bodyRenderer.setTextWidth(localHint.size().width());
QAbstractTextDocumentLayout* lay = bodyRenderer->documentLayout(); QAbstractTextDocumentLayout* lay = bodyRenderer.documentLayout();
QString anchor = lay->anchorAt(translated); QString anchor = lay->anchorAt(translated);
if (anchor.size() > 0) { if (anchor.size() > 0) {
@ -489,15 +502,15 @@ QString MessageDelegate::mouseDrag(const QPoint& start, const QPoint& end, const
last.setY(std::max(last.y(), 0)); last.setY(std::max(last.y(), 0));
last.setY(std::min(last.y(), localHint.height())); last.setY(std::min(last.y(), localHint.height()));
bodyRenderer->setHtml(Shared::processMessageBody(data.text)); bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width()); bodyRenderer.setTextWidth(localHint.size().width());
selection.first = bodyRenderer->documentLayout()->hitTest(first, Qt::HitTestAccuracy::FuzzyHit); selection.first = bodyRenderer.documentLayout()->hitTest(first, Qt::HitTestAccuracy::FuzzyHit);
selection.second = bodyRenderer->documentLayout()->hitTest(last, Qt::HitTestAccuracy::FuzzyHit); selection.second = bodyRenderer.documentLayout()->hitTest(last, Qt::HitTestAccuracy::FuzzyHit);
currentId = data.id; currentId = data.id;
if (selection.first != selection.second) { if (selection.first != selection.second) {
QTextCursor cursor(bodyRenderer); QTextCursor cursor(&bodyRenderer);
cursor.setPosition(selection.first, QTextCursor::MoveAnchor); cursor.setPosition(selection.first, QTextCursor::MoveAnchor);
cursor.setPosition(selection.second, QTextCursor::KeepAnchor); cursor.setPosition(selection.second, QTextCursor::KeepAnchor);
return cursor.selectedText(); return cursor.selectedText();
@ -562,17 +575,17 @@ int MessageDelegate::paintBar(QProgressBar* bar, QPainter* painter, bool sentByM
int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const { int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const {
Preview* preview = 0; Preview* preview = 0;
std::map<QString, Preview*>::iterator itr = previews->find(data.id); std::map<QString, Preview*>::iterator itr = previews.find(data.id);
QSize size = option.rect.size(); QSize size = option.rect.size();
QString path = Shared::resolvePath(data.attach.localPath); QString path = Shared::resolvePath(data.attach.localPath);
if (itr != previews->end()) { if (itr != previews.end()) {
preview = itr->second; preview = itr->second;
preview->actualize(path, size, option.rect.topLeft()); preview->actualize(path, size, option.rect.topLeft());
} else { } else {
QWidget* vp = static_cast<QWidget*>(painter->device()); QWidget* vp = static_cast<QWidget*>(painter->device());
preview = new Preview(path, size, option.rect.topLeft(), vp); preview = new Preview(path, size, option.rect.topLeft(), vp);
previews->insert(std::make_pair(data.id, preview)); previews.insert(std::make_pair(data.id, preview));
} }
if (!preview->isFileReachable()) //this is the situation when the file preview couldn't be painted because the file was moved if (!preview->isFileReachable()) //this is the situation when the file preview couldn't be painted because the file was moved
@ -585,15 +598,15 @@ int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painte
} }
QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const { QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const {
std::map<QString, FeedButton*>::const_iterator itr = buttons->find(data.id); std::map<QString, FeedButton*>::const_iterator itr = buttons.find(data.id);
FeedButton* result = 0; FeedButton* result = 0;
if (itr != buttons->end()) { if (itr != buttons.end()) {
result = itr->second; result = itr->second;
} else { } else {
std::map<QString, QProgressBar*>::const_iterator barItr = bars->find(data.id); std::map<QString, QProgressBar*>::const_iterator barItr = bars.find(data.id);
if (barItr != bars->end()) { if (barItr != bars.end()) {
delete barItr->second; delete barItr->second;
bars->erase(barItr); bars.erase(barItr);
} }
} }
@ -601,7 +614,7 @@ QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const {
result = new FeedButton(); result = new FeedButton();
result->messageId = data.id; result->messageId = data.id;
result->setText(QCoreApplication::translate("MessageLine", "Download")); result->setText(QCoreApplication::translate("MessageLine", "Download"));
buttons->insert(std::make_pair(data.id, result)); buttons.insert(std::make_pair(data.id, result));
connect(result, &QPushButton::clicked, this, &MessageDelegate::onButtonPushed); connect(result, &QPushButton::clicked, this, &MessageDelegate::onButtonPushed);
} }
@ -609,22 +622,22 @@ QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const {
} }
QProgressBar * MessageDelegate::getBar(const Models::FeedItem& data) const { QProgressBar * MessageDelegate::getBar(const Models::FeedItem& data) const {
std::map<QString, QProgressBar*>::const_iterator barItr = bars->find(data.id); std::map<QString, QProgressBar*>::const_iterator barItr = bars.find(data.id);
QProgressBar* result = 0; QProgressBar* result = 0;
if (barItr != bars->end()) { if (barItr != bars.end()) {
result = barItr->second; result = barItr->second;
} else { } else {
std::map<QString, FeedButton*>::const_iterator itr = buttons->find(data.id); std::map<QString, FeedButton*>::const_iterator itr = buttons.find(data.id);
if (itr != buttons->end()) { if (itr != buttons.end()) {
delete itr->second; delete itr->second;
buttons->erase(itr); buttons.erase(itr);
} }
} }
if (result == 0) { if (result == 0) {
result = new QProgressBar(); result = new QProgressBar();
result->setRange(0, 100); result->setRange(0, 100);
bars->insert(std::make_pair(data.id, result)); bars.insert(std::make_pair(data.id, result));
} }
result->setValue(data.attach.progress * 100); result->setValue(data.attach.progress * 100);
@ -633,14 +646,14 @@ QProgressBar * MessageDelegate::getBar(const Models::FeedItem& data) const {
} }
QLabel * MessageDelegate::getStatusIcon(const Models::FeedItem& data) const { QLabel * MessageDelegate::getStatusIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = statusIcons->find(data.id); std::map<QString, QLabel*>::const_iterator itr = statusIcons.find(data.id);
QLabel* result = 0; QLabel* result = 0;
if (itr != statusIcons->end()) { if (itr != statusIcons.end()) {
result = itr->second; result = itr->second;
} else { } else {
result = new QLabel(); result = new QLabel();
statusIcons->insert(std::make_pair(data.id, result)); statusIcons.insert(std::make_pair(data.id, result));
} }
QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast<uint8_t>(data.state)])); QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast<uint8_t>(data.state)]));
@ -657,17 +670,17 @@ QLabel * MessageDelegate::getStatusIcon(const Models::FeedItem& data) const {
return result; return result;
} }
QLabel * MessageDelegate::getPencilIcon(const Models::FeedItem& data) const { QLabel* MessageDelegate::getPencilIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = pencilIcons->find(data.id); std::map<QString, QLabel*>::const_iterator itr = pencilIcons.find(data.id);
QLabel* result = 0; QLabel* result = 0;
if (itr != pencilIcons->end()) { if (itr != pencilIcons.end()) {
result = itr->second; result = itr->second;
} else { } else {
result = new QLabel(); result = new QLabel();
QIcon icon = Shared::icon("edit-rename"); QIcon icon = Shared::icon("edit-rename");
result->setPixmap(icon.pixmap(statusIconSize)); result->setPixmap(icon.pixmap(statusIconSize));
pencilIcons->insert(std::make_pair(data.id, result)); pencilIcons.insert(std::make_pair(data.id, result));
} }
result->setToolTip("Last time edited: " + data.correction.lastCorrection.toLocalTime().toString() result->setToolTip("Last time edited: " + data.correction.lastCorrection.toLocalTime().toString()
@ -676,30 +689,46 @@ QLabel * MessageDelegate::getPencilIcon(const Models::FeedItem& data) const {
return result; return result;
} }
QLabel* MessageDelegate::getEncryptionIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = encryptionIcons.find(data.id);
QLabel* result = 0;
if (itr != encryptionIcons.end()) {
result = itr->second;
} else {
result = new QLabel();
QIcon icon = Shared::icon("secure");
result->setPixmap(icon.pixmap(statusIconSize));
encryptionIcons.insert(std::make_pair(data.id, result));
result->setToolTip("Encrypted: " + Shared::Global::getName(data.encryption));
}
return result;
}
template <typename T> template <typename T>
void removeElements(std::map<QString, T*>* elements, std::set<QString>* idsToKeep) { void removeElements(std::map<QString, T*>& elements, std::set<QString>& idsToKeep) {
std::set<QString> toRemove; std::set<QString> toRemove;
for (const std::pair<const QString, T*>& pair: *elements) { for (const std::pair<const QString, T*>& pair: elements) {
if (idsToKeep->find(pair.first) == idsToKeep->end()) { if (idsToKeep.find(pair.first) == idsToKeep.end()) {
delete pair.second; delete pair.second;
toRemove.insert(pair.first); toRemove.insert(pair.first);
} }
} }
for (const QString& key : toRemove) { for (const QString& key : toRemove)
elements->erase(key); elements.erase(key);
}
} }
int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const
{ {
if (data.text.size() > 0) { if (data.text.size() > 0) {
bodyRenderer->setHtml(Shared::processMessageBody(data.text)); bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(option.rect.size().width()); bodyRenderer.setTextWidth(option.rect.size().width());
painter->save(); painter->save();
painter->translate(option.rect.topLeft()); painter->translate(option.rect.topLeft());
if (data.id == currentId) { if (data.id == currentId) {
QTextCursor cursor(bodyRenderer); QTextCursor cursor(&bodyRenderer);
cursor.setPosition(selection.first, QTextCursor::MoveAnchor); cursor.setPosition(selection.first, QTextCursor::MoveAnchor);
cursor.setPosition(selection.second, QTextCursor::KeepAnchor); cursor.setPosition(selection.second, QTextCursor::KeepAnchor);
QTextCharFormat format = cursor.charFormat(); QTextCharFormat format = cursor.charFormat();
@ -708,10 +737,10 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
cursor.setCharFormat(format); cursor.setCharFormat(format);
} }
bodyRenderer->drawContents(painter); bodyRenderer.drawContents(painter);
painter->restore(); painter->restore();
QSize bodySize(std::ceil(bodyRenderer->idealWidth()), std::ceil(bodyRenderer->size().height())); QSize bodySize(std::ceil(bodyRenderer.idealWidth()), std::ceil(bodyRenderer.size().height()));
option.rect.adjust(0, bodySize.height() + textMargin, 0, 0); option.rect.adjust(0, bodySize.height() + textMargin, 0, 0);
return bodySize.width(); return bodySize.width();
@ -720,7 +749,7 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
} }
void MessageDelegate::beginClearWidgets() { void MessageDelegate::beginClearWidgets() {
idsToKeep->clear(); idsToKeep.clear();
clearingWidgets = true; clearingWidgets = true;
} }
@ -730,9 +759,10 @@ void MessageDelegate::endClearWidgets() {
removeElements(bars, idsToKeep); removeElements(bars, idsToKeep);
removeElements(statusIcons, idsToKeep); removeElements(statusIcons, idsToKeep);
removeElements(pencilIcons, idsToKeep); removeElements(pencilIcons, idsToKeep);
removeElements(encryptionIcons, idsToKeep);
removeElements(previews, idsToKeep); removeElements(previews, idsToKeep);
idsToKeep->clear(); idsToKeep.clear();
clearingWidgets = false; clearingWidgets = false;
} }
} }
@ -743,15 +773,15 @@ void MessageDelegate::onButtonPushed() const {
} }
void MessageDelegate::clearHelperWidget(const Models::FeedItem& data) const { void MessageDelegate::clearHelperWidget(const Models::FeedItem& data) const {
std::map<QString, FeedButton*>::const_iterator itr = buttons->find(data.id); std::map<QString, FeedButton*>::const_iterator itr = buttons.find(data.id);
if (itr != buttons->end()) { if (itr != buttons.end()) {
delete itr->second; delete itr->second;
buttons->erase(itr); buttons.erase(itr);
} else { } else {
std::map<QString, QProgressBar*>::const_iterator barItr = bars->find(data.id); std::map<QString, QProgressBar*>::const_iterator barItr = bars.find(data.id);
if (barItr != bars->end()) { if (barItr != bars.end()) {
delete barItr->second; delete barItr->second;
bars->erase(barItr); bars.erase(barItr);
} }
} }
} }

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MESSAGEDELEGATE_H #pragma once
#define MESSAGEDELEGATE_H
#include <map> #include <map>
#include <set> #include <set>
@ -44,8 +43,7 @@ namespace Models {
struct FeedItem; struct FeedItem;
}; };
class MessageDelegate : public QStyledItemDelegate class MessageDelegate : public QStyledItemDelegate {
{
Q_OBJECT Q_OBJECT
public: public:
MessageDelegate(QObject *parent = nullptr); MessageDelegate(QObject *parent = nullptr);
@ -85,6 +83,7 @@ protected:
QProgressBar* getBar(const Models::FeedItem& data) const; QProgressBar* getBar(const Models::FeedItem& data) const;
QLabel* getStatusIcon(const Models::FeedItem& data) const; QLabel* getStatusIcon(const Models::FeedItem& data) const;
QLabel* getPencilIcon(const Models::FeedItem& data) const; QLabel* getPencilIcon(const Models::FeedItem& data) const;
QLabel* getEncryptionIcon(const Models::FeedItem& data) const;
void clearHelperWidget(const Models::FeedItem& data) const; void clearHelperWidget(const Models::FeedItem& data) const;
bool needToDrawAvatar(const QModelIndex& index, const Models::FeedItem& data, const QStyleOptionViewItem& option) const; bool needToDrawAvatar(const QModelIndex& index, const Models::FeedItem& data, const QStyleOptionViewItem& option) const;
@ -107,21 +106,20 @@ private:
const QFont& dateFont; const QFont& dateFont;
const QFontMetrics& nickMetrics; const QFontMetrics& nickMetrics;
const QFontMetrics& dateMetrics; const QFontMetrics& dateMetrics;
QTextDocument* bodyRenderer; mutable QTextDocument bodyRenderer;
int buttonHeight; int buttonHeight;
int buttonWidth; int buttonWidth;
int barHeight; int barHeight;
std::map<QString, FeedButton*>* buttons; mutable std::map<QString, FeedButton*> buttons;
std::map<QString, QProgressBar*>* bars; mutable std::map<QString, QProgressBar*> bars;
std::map<QString, QLabel*>* statusIcons; mutable std::map<QString, QLabel*> statusIcons;
std::map<QString, QLabel*>* pencilIcons; mutable std::map<QString, QLabel*> pencilIcons;
std::map<QString, Preview*>* previews; mutable std::map<QString, QLabel*> encryptionIcons;
std::set<QString>* idsToKeep; mutable std::map<QString, Preview*> previews;
mutable std::set<QString> idsToKeep;
bool clearingWidgets; bool clearingWidgets;
QString currentId; QString currentId;
std::pair<int, int> selection; std::pair<int, int> selection;
}; };
#endif // MESSAGEDELEGATE_H

View File

@ -29,6 +29,7 @@ const QHash<int, QByteArray> Models::MessageFeed::roles = {
{Sender, "sender"}, {Sender, "sender"},
{Date, "date"}, {Date, "date"},
{DeliveryState, "deliveryState"}, {DeliveryState, "deliveryState"},
{Encryption, "encryption"},
{Correction, "correction"}, {Correction, "correction"},
{SentByMe,"sentByMe"}, {SentByMe,"sentByMe"},
{Avatar, "avatar"}, {Avatar, "avatar"},
@ -51,20 +52,16 @@ Models::MessageFeed::MessageFeed(const Element* ri, QObject* parent):
failedUploads(), failedUploads(),
unreadMessages(new std::set<QString>()), unreadMessages(new std::set<QString>()),
observersAmount(0) observersAmount(0)
{ {}
}
Models::MessageFeed::~MessageFeed() Models::MessageFeed::~MessageFeed() {
{
delete unreadMessages; delete unreadMessages;
for (Shared::Message* message : storage) { for (Shared::Message* message : storage)
delete message; delete message;
}
} }
void Models::MessageFeed::addMessage(const Shared::Message& msg) void Models::MessageFeed::addMessage(const Shared::Message& msg) {
{
QString id = msg.getId(); QString id = msg.getId();
StorageById::const_iterator itr = indexById.find(id); StorageById::const_iterator itr = indexById.find(id);
if (itr != indexById.end()) { if (itr != indexById.end()) {
@ -75,11 +72,11 @@ void Models::MessageFeed::addMessage(const Shared::Message& msg)
Shared::Message* copy = new Shared::Message(msg); Shared::Message* copy = new Shared::Message(msg);
StorageByTime::const_iterator tItr = indexByTime.upper_bound(msg.getTime()); StorageByTime::const_iterator tItr = indexByTime.upper_bound(msg.getTime());
int position; int position;
if (tItr == indexByTime.end()) { if (tItr == indexByTime.end())
position = storage.size(); position = storage.size();
} else { else
position = indexByTime.rank(tItr); position = indexByTime.rank(tItr);
}
beginInsertRows(QModelIndex(), position, position); beginInsertRows(QModelIndex(), position, position);
storage.insert(copy); storage.insert(copy);
endInsertRows(); endInsertRows();
@ -93,8 +90,7 @@ void Models::MessageFeed::addMessage(const Shared::Message& msg)
} }
} }
void Models::MessageFeed::changeMessage(const QString& id, const QMap<QString, QVariant>& data) void Models::MessageFeed::changeMessage(const QString& id, const QMap<QString, QVariant>& data) {
{
StorageById::iterator itr = indexById.find(id); StorageById::iterator itr = indexById.find(id);
if (itr == indexById.end()) { if (itr == indexById.end()) {
qDebug() << "received a command to change a message, but the message couldn't be found, skipping"; qDebug() << "received a command to change a message, but the message couldn't be found, skipping";
@ -159,9 +155,8 @@ void Models::MessageFeed::changeMessage(const QString& id, const QMap<QString, Q
} }
QVector<int> cr; QVector<int> cr;
for (MessageRoles role : changeRoles) { for (MessageRoles role : changeRoles)
cr.push_back(role); cr.push_back(role);
}
emit dataChanged(index, index, cr); emit dataChanged(index, index, cr);
@ -173,14 +168,15 @@ void Models::MessageFeed::changeMessage(const QString& id, const QMap<QString, Q
} }
} }
std::set<Models::MessageFeed::MessageRoles> Models::MessageFeed::detectChanges(const Shared::Message& msg, const QMap<QString, QVariant>& data) const std::set<Models::MessageFeed::MessageRoles> Models::MessageFeed::detectChanges(
{ const Shared::Message& msg,
const QMap<QString, QVariant>& data
) const {
std::set<MessageRoles> roles; std::set<MessageRoles> roles;
Shared::Message::State state = msg.getState(); Shared::Message::State state = msg.getState();
QMap<QString, QVariant>::const_iterator itr = data.find("state"); QMap<QString, QVariant>::const_iterator itr = data.find("state");
if (itr != data.end() && static_cast<Shared::Message::State>(itr.value().toUInt()) != state) { if (itr != data.end() && static_cast<Shared::Message::State>(itr.value().toUInt()) != state)
roles.insert(MessageRoles::DeliveryState); roles.insert(MessageRoles::DeliveryState);
}
itr = data.find("outOfBandUrl"); itr = data.find("outOfBandUrl");
bool att = false; bool att = false;
@ -255,10 +251,9 @@ QVariant Models::MessageFeed::data(const QModelIndex& index, int role) const {
case Qt::DisplayRole: case Qt::DisplayRole:
case Text: { case Text: {
QString body = msg->getBody(); QString body = msg->getBody();
if (body != msg->getOutOfBandUrl()) { if (body != msg->getOutOfBandUrl())
answer = body; answer = body;
} }
}
break; break;
case Sender: case Sender:
if (sentByMe(*msg)) { if (sentByMe(*msg)) {
@ -276,6 +271,9 @@ QVariant Models::MessageFeed::data(const QModelIndex& index, int role) const {
case DeliveryState: case DeliveryState:
answer = static_cast<unsigned int>(msg->getState()); answer = static_cast<unsigned int>(msg->getState());
break; break;
case Encryption:
answer = QVariant::fromValue(msg->getEncryption());
break;
case Correction: case Correction:
answer.setValue(fillCorrection(*msg));; answer.setValue(fillCorrection(*msg));;
break; break;
@ -318,13 +316,13 @@ QVariant Models::MessageFeed::data(const QModelIndex& index, int role) const {
item.sentByMe = sentByMe(*msg); item.sentByMe = sentByMe(*msg);
item.date = msg->getTime(); item.date = msg->getTime();
item.state = msg->getState(); item.state = msg->getState();
item.encryption = msg->getEncryption();
item.error = msg->getErrorText(); item.error = msg->getErrorText();
item.correction = fillCorrection(*msg); item.correction = fillCorrection(*msg);
QString body = msg->getBody(); QString body = msg->getBody();
if (body != msg->getOutOfBandUrl()) { if (body != msg->getOutOfBandUrl())
item.text = body; item.text = body;
}
item.avatar.clear(); item.avatar.clear();
if (item.sentByMe) { if (item.sentByMe) {
@ -419,13 +417,11 @@ QModelIndex Models::MessageFeed::index(int row, int column, const QModelIndex& p
return QModelIndex(); return QModelIndex();
StorageByTime::iterator itr = indexByTime.nth(row); StorageByTime::iterator itr = indexByTime.nth(row);
if (itr != indexByTime.end()) { if (itr == indexByTime.end())
Shared::Message* msg = *itr;
return createIndex(row, column, msg);
} else {
return QModelIndex(); return QModelIndex();
}
Shared::Message* msg = *itr;
return createIndex(row, column, msg);
} }
QHash<int, QByteArray> Models::MessageFeed::roleNames() const {return roles;} QHash<int, QByteArray> Models::MessageFeed::roleNames() const {return roles;}

View File

@ -16,12 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MESSAGEFEED_H #pragma once
#define MESSAGEFEED_H
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QDateTime> #include <QDateTime>
#include <QString> #include <QString>
#include <QHash>
#include <set> #include <set>
@ -100,6 +100,7 @@ public:
Sender, Sender,
Date, Date,
DeliveryState, DeliveryState,
Encryption,
Correction, Correction,
SentByMe, SentByMe,
Avatar, Avatar,
@ -216,6 +217,7 @@ struct FeedItem {
Edition correction; Edition correction;
QDateTime date; QDateTime date;
Shared::Message::State state; Shared::Message::State state;
Shared::EncryptionProtocol encryption;
Attachment attach; Attachment attach;
}; };
}; };
@ -224,4 +226,4 @@ Q_DECLARE_METATYPE(Models::Attachment);
Q_DECLARE_METATYPE(Models::Edition); Q_DECLARE_METATYPE(Models::Edition);
Q_DECLARE_METATYPE(Models::FeedItem); Q_DECLARE_METATYPE(Models::FeedItem);
#endif // MESSAGEFEED_H #pragma once

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PREVIEW_H #pragma once
#define PREVIEW_H
#include <QWidget> #include <QWidget>
#include <QString> #include <QString>
@ -75,5 +74,3 @@ private:
bool fileReachable; bool fileReachable;
bool actualPreview; bool actualPreview;
}; };
#endif // PREVIEW_H