Show remaining character count in SMS app
## Summary This adds character counter below the “Send” button in SMS conversation. It uses format XXX/Y where XXX is number of characters that can be added without splitting the SMS into multiple messages (see article Concatenated SMS on Wikipedia). Y is number of messages in in current concatenated SMS. The counter is not visible when insertion of 10 7-bit or 16-bit (depends on SMS encoding) does not create concatenated SMS. SMS encoding is automatically guessed. 8-bit encodings are not supported. If the message contains characters that are not supported by GSM 7-bit encoding, counter automatically switches to UCS-2. ## Test Plan Try entering some text that is longer than 150 characters in [GSM 03.38 encoding][1] or 60 characters in UCS-2. Number of remaining characters should be visible below the “Send” button. The character counter should show `0` at exactly 160 or 70 characters. Inserting one character should switch the counter to [Concatenated SMS][2] mode when number of messages is shown. It should show exactly same number as SMS app in Android. ## Screenshots These images are in APNG. ![grab.apng](/uploads/21ae23f2fa75c7aca487e61ddce94644/grab.apng) ![grab-cz.apng](/uploads/785e670a8598c5a65a4209f17e75f578/grab-cz.apng) [1]: https://en.wikipedia.org/w/index.php?oldid=932080074#GSM_7-bit_default_alphabet_and_extension_table_of_3GPP_TS_23.038_/_GSM_03.38 [2]: https://en.wikipedia.org/w/index.php?oldid=943185255#Message_size
This commit is contained in:
parent
f211d7e401
commit
365791dc59
9 changed files with 443 additions and 34 deletions
|
@ -4,6 +4,7 @@ find_package(KF5People)
|
||||||
|
|
||||||
add_library(kdeconnectsmshelper
|
add_library(kdeconnectsmshelper
|
||||||
smshelper.cpp
|
smshelper.cpp
|
||||||
|
gsmasciimap.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(kdeconnectsmshelper PROPERTIES
|
set_target_properties(kdeconnectsmshelper PROPERTIES
|
||||||
|
|
|
@ -192,3 +192,21 @@ void ConversationModel::handleConversationLoaded(qint64 threadID, quint64 numMes
|
||||||
// so we should not be showing a loading indicator
|
// so we should not be showing a loading indicator
|
||||||
Q_EMIT loadingFinished();
|
Q_EMIT loadingFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ConversationModel::getCharCountInfo(const QString& message) const
|
||||||
|
{
|
||||||
|
SmsCharCount count = SmsHelper::getCharCount(message);
|
||||||
|
|
||||||
|
if (count.messages > 1) {
|
||||||
|
// Show remaining char count and message count
|
||||||
|
return QString::number(count.remaining) + QLatin1Char('/') + QString::number(count.messages);
|
||||||
|
}
|
||||||
|
if (count.messages == 1 && count.remaining < 10) {
|
||||||
|
// Show only remaining char count
|
||||||
|
return QString::number(count.remaining);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Do not show anything
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -78,6 +78,8 @@ public:
|
||||||
* TODO: Move to smshelper (or maybe make part of kirigami-addons chat library?)
|
* TODO: Move to smshelper (or maybe make part of kirigami-addons chat library?)
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void copyToClipboard(const QString& message) const;
|
Q_INVOKABLE void copyToClipboard(const QString& message) const;
|
||||||
|
|
||||||
|
Q_INVOKABLE QString getCharCountInfo(const QString& message) const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void loadingFinished();
|
void loadingFinished();
|
||||||
|
|
154
smsapp/gsmasciimap.cpp
Normal file
154
smsapp/gsmasciimap.cpp
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2020 Jiří Wolker <woljiri@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License or (at your option) version 3 or any later version
|
||||||
|
* accepted by the membership of KDE e.V. (or its successor approved
|
||||||
|
* by the membership of KDE e.V.), which shall act as a proxy
|
||||||
|
* defined in Section 14 of version 3 of the license.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map used to determine that ASCII character is in GSM 03.38 7-bit alphabet.
|
||||||
|
*
|
||||||
|
* Only allowed control characters are CR and LF but GSM alphabet has more of them.
|
||||||
|
*/
|
||||||
|
bool gsm_ascii_map[] = {
|
||||||
|
false, // 0x0, some control char
|
||||||
|
false, // 0x1, some control char
|
||||||
|
false, // 0x2, some control char
|
||||||
|
false, // 0x3, some control char
|
||||||
|
false, // 0x4, some control char
|
||||||
|
false, // 0x5, some control char
|
||||||
|
false, // 0x6, some control char
|
||||||
|
false, // 0x7, some control char
|
||||||
|
false, // 0x8, some control char
|
||||||
|
false, // 0x9, some control char
|
||||||
|
true, // 0xA, LF
|
||||||
|
false, // 0xB, some control char
|
||||||
|
false, // 0xC, some control char
|
||||||
|
true, // 0xD, CR
|
||||||
|
false, // 0xE, some control char
|
||||||
|
false, // 0xF, some control char
|
||||||
|
false, // 0x10, some control char
|
||||||
|
false, // 0x11, some control char
|
||||||
|
false, // 0x12, some control char
|
||||||
|
false, // 0x13, some control char
|
||||||
|
false, // 0x14, some control char
|
||||||
|
false, // 0x15, some control char
|
||||||
|
false, // 0x16, some control char
|
||||||
|
false, // 0x17, some control char
|
||||||
|
false, // 0x18, some control char
|
||||||
|
false, // 0x19, some control char
|
||||||
|
false, // 0x1A, some control char
|
||||||
|
false, // 0x1B, some control char
|
||||||
|
false, // 0x1C, some control char
|
||||||
|
false, // 0x1D, some control char
|
||||||
|
false, // 0x1E, some control char
|
||||||
|
false, // 0x1F, some control char
|
||||||
|
true, // 20, space
|
||||||
|
true, // 21, !
|
||||||
|
true, // 22, "
|
||||||
|
true, // 23, #
|
||||||
|
true, // 24, $
|
||||||
|
true, // 25, %
|
||||||
|
true, // 26, &
|
||||||
|
true, // 27, '
|
||||||
|
true, // 28, (
|
||||||
|
true, // 29, )
|
||||||
|
true, // 2A, *
|
||||||
|
true, // 2B, +
|
||||||
|
true, // 2C, ,
|
||||||
|
true, // 2D, -
|
||||||
|
true, // 2E, .
|
||||||
|
true, // 2F, /
|
||||||
|
true, // 30, 0
|
||||||
|
true, // 31, 1
|
||||||
|
true, // 32, 2
|
||||||
|
true, // 33, 3
|
||||||
|
true, // 34, 4
|
||||||
|
true, // 35, 5
|
||||||
|
true, // 36, 6
|
||||||
|
true, // 37, 7
|
||||||
|
true, // 38, 8
|
||||||
|
true, // 39, 9
|
||||||
|
true, // 3A, :
|
||||||
|
true, // 3B, ;
|
||||||
|
true, // 3C, <
|
||||||
|
true, // 3D, =
|
||||||
|
true, // 3E, >
|
||||||
|
true, // 3F, ?
|
||||||
|
true, // 40, @
|
||||||
|
true, // 41, A
|
||||||
|
true, // 42, B
|
||||||
|
true, // 43, C
|
||||||
|
true, // 44, D
|
||||||
|
true, // 45, E
|
||||||
|
true, // 46, F
|
||||||
|
true, // 47, G
|
||||||
|
true, // 48, H
|
||||||
|
true, // 49, I
|
||||||
|
true, // 4A, J
|
||||||
|
true, // 4B, K
|
||||||
|
true, // 4C, L
|
||||||
|
true, // 4D, M
|
||||||
|
true, // 4E, N
|
||||||
|
true, // 4F, O
|
||||||
|
true, // 50, P
|
||||||
|
true, // 51, Q
|
||||||
|
true, // 52, R
|
||||||
|
true, // 53, S
|
||||||
|
true, // 54, T
|
||||||
|
true, // 55, U
|
||||||
|
true, // 56, V
|
||||||
|
true, // 57, W
|
||||||
|
true, // 58, X
|
||||||
|
true, // 59, Y
|
||||||
|
true, // 5A, Z
|
||||||
|
false, // 5B, [
|
||||||
|
false, // 5C, backslash
|
||||||
|
false, // 5D, ]
|
||||||
|
false, // 5E, ^
|
||||||
|
true, // 5F, _
|
||||||
|
false, // 60, `
|
||||||
|
true, // 61, a
|
||||||
|
true, // 62, b
|
||||||
|
true, // 63, c
|
||||||
|
true, // 64, d
|
||||||
|
true, // 65, e
|
||||||
|
true, // 66, f
|
||||||
|
true, // 67, g
|
||||||
|
true, // 68, h
|
||||||
|
true, // 69, i
|
||||||
|
true, // 6A, j
|
||||||
|
true, // 6B, k
|
||||||
|
true, // 6C, l
|
||||||
|
true, // 6D, m
|
||||||
|
true, // 6E, n
|
||||||
|
true, // 6F, o
|
||||||
|
true, // 70, p
|
||||||
|
true, // 71, q
|
||||||
|
true, // 72, r
|
||||||
|
true, // 73, s
|
||||||
|
true, // 74, t
|
||||||
|
true, // 75, u
|
||||||
|
true, // 76, v
|
||||||
|
true, // 77, w
|
||||||
|
true, // 78, x
|
||||||
|
true, // 79, y
|
||||||
|
true, // 7A, z
|
||||||
|
false, // 7B, {
|
||||||
|
false, // 7C, |
|
||||||
|
false, // 7D, }
|
||||||
|
false, // 7E, ~
|
||||||
|
};
|
27
smsapp/gsmasciimap.h
Normal file
27
smsapp/gsmasciimap.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2020 Jiří Wolker <woljiri@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License or (at your option) version 3 or any later version
|
||||||
|
* accepted by the membership of KDE e.V. (or its successor approved
|
||||||
|
* by the membership of KDE e.V.), which shall act as a proxy
|
||||||
|
* defined in Section 14 of version 3 of the license.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GSMASCIIMAP_H
|
||||||
|
#define GSMASCIIMAP_H
|
||||||
|
|
||||||
|
extern bool gsm_ascii_map[128];
|
||||||
|
|
||||||
|
#endif // GSMASCIIMAP_H
|
||||||
|
|
|
@ -219,41 +219,50 @@ Kirigami.ScrollablePage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
ToolButton {
|
||||||
|
id: sendButton
|
||||||
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
||||||
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
||||||
|
padding: 0
|
||||||
|
Kirigami.Icon {
|
||||||
|
source: "document-send"
|
||||||
|
enabled: sendButton.enabled
|
||||||
|
isMask: true
|
||||||
|
smooth: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Kirigami.Units.gridUnit * 1.5
|
||||||
|
height: width
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
// don't send empty messages
|
||||||
|
if (!messageField.text.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ToolButton {
|
// disable the button to prevent sending
|
||||||
id: sendButton
|
// the same message several times
|
||||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
sendButton.enabled = false
|
||||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
||||||
padding: 0
|
// send the message
|
||||||
Kirigami.Icon {
|
if (page.conversationId == page.invalidId) {
|
||||||
source: "document-send"
|
conversationModel.sendMessageWithoutConversation(messageField.text, page.otherParty)
|
||||||
enabled: sendButton.enabled
|
} else {
|
||||||
isMask: true
|
conversationModel.sendReplyToConversation(messageField.text)
|
||||||
smooth: true
|
}
|
||||||
anchors.centerIn: parent
|
messageField.text = ""
|
||||||
width: Kirigami.Units.gridUnit * 1.5
|
|
||||||
height: width
|
// re-enable the button
|
||||||
|
sendButton.enabled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onClicked: {
|
|
||||||
// don't send empty messages
|
|
||||||
if (!messageField.text.length) {
|
Label {
|
||||||
return
|
id: "charCount"
|
||||||
}
|
text: conversationModel.getCharCountInfo(messageField.text)
|
||||||
|
visible: text.length > 0
|
||||||
// disable the button to prevent sending
|
|
||||||
// the same message several times
|
|
||||||
sendButton.enabled = false
|
|
||||||
|
|
||||||
// send the message
|
|
||||||
if (page.conversationId == page.invalidId) {
|
|
||||||
conversationModel.sendMessageWithoutConversation(messageField.text, page.otherParty)
|
|
||||||
} else {
|
|
||||||
conversationModel.sendReplyToConversation(messageField.text)
|
|
||||||
}
|
|
||||||
messageField.text = ""
|
|
||||||
|
|
||||||
// re-enable the button
|
|
||||||
sendButton.enabled = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
50
smsapp/smscharcount.h
Normal file
50
smsapp/smscharcount.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2020 Jiří Wolker <woljiri@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License or (at your option) version 3 or any later version
|
||||||
|
* accepted by the membership of KDE e.V. (or its successor approved
|
||||||
|
* by the membership of KDE e.V.), which shall act as a proxy
|
||||||
|
* defined in Section 14 of version 3 of the license.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CHARCOUNT_H
|
||||||
|
#define CHARCOUNT_H
|
||||||
|
|
||||||
|
class SmsCharCount {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Number of octets in current message.
|
||||||
|
*/
|
||||||
|
qint32 octets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bits per character (7, 8 or 16).
|
||||||
|
*/
|
||||||
|
qint32 bitsPerChar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of chars remaining in current SMS.
|
||||||
|
*/
|
||||||
|
qint32 remaining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count of SMSes in concatenated SMS.
|
||||||
|
*/
|
||||||
|
qint32 messages;
|
||||||
|
|
||||||
|
SmsCharCount(){};
|
||||||
|
~SmsCharCount(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHARCOUNT_H
|
|
@ -32,6 +32,7 @@
|
||||||
#include <KPeople/PersonsModel>
|
#include <KPeople/PersonsModel>
|
||||||
|
|
||||||
#include "interfaces/conversationmessage.h"
|
#include "interfaces/conversationmessage.h"
|
||||||
|
#include "smsapp/gsmasciimap.h"
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(KDECONNECT_SMS_SMSHELPER, "kdeconnect.sms.smshelper")
|
Q_LOGGING_CATEGORY(KDECONNECT_SMS_SMSHELPER, "kdeconnect.sms.smshelper")
|
||||||
|
|
||||||
|
@ -274,3 +275,139 @@ QIcon SmsHelper::getIconForAddresses(const QList<ConversationAddress>& addresses
|
||||||
// around randomly (based on how the data came to us from Android)
|
// around randomly (based on how the data came to us from Android)
|
||||||
return combineIcons(icons);
|
return combineIcons(icons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SmsCharCount SmsHelper::getCharCount(const QString& message)
|
||||||
|
{
|
||||||
|
const int remainingWhenEmpty = 160;
|
||||||
|
const int septetsInSingleSms = 160;
|
||||||
|
const int septetsInSingleConcatSms = 153;
|
||||||
|
const int charsInSingleUcs2Sms = 70;
|
||||||
|
const int charsInSingleConcatUcs2Sms = 67;
|
||||||
|
|
||||||
|
SmsCharCount count;
|
||||||
|
bool enc7bit = true; // 7-bit is used when true, UCS-2 if false
|
||||||
|
quint32 septets = 0; // GSM encoding character count (characters in extension are counted as 2 chars)
|
||||||
|
int length = message.length();
|
||||||
|
|
||||||
|
// Count characters and detect encoding
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
QChar ch = message[i];
|
||||||
|
|
||||||
|
if (isInGsmAlphabet(ch)) {
|
||||||
|
septets++;
|
||||||
|
}
|
||||||
|
else if (isInGsmAlphabetExtension(ch)) {
|
||||||
|
septets += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enc7bit = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
count.bitsPerChar = 7;
|
||||||
|
count.octets = 0;
|
||||||
|
count.remaining = remainingWhenEmpty;
|
||||||
|
count.messages = 1;
|
||||||
|
}
|
||||||
|
else if (enc7bit) {
|
||||||
|
count.bitsPerChar = 7;
|
||||||
|
count.octets = (septets * 7 + 6) / 8;
|
||||||
|
if (septets > septetsInSingleSms) {
|
||||||
|
count.messages = (septetsInSingleConcatSms - 1 + septets) / septetsInSingleConcatSms;
|
||||||
|
count.remaining = (septetsInSingleConcatSms * count.messages - septets) % septetsInSingleConcatSms;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
count.messages = 1;
|
||||||
|
count.remaining = (septetsInSingleSms - septets) % septetsInSingleSms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
count.bitsPerChar = 16;
|
||||||
|
count.octets = length * 2; // QString should be in UTF-16
|
||||||
|
if (length > charsInSingleUcs2Sms) {
|
||||||
|
count.messages = (charsInSingleConcatUcs2Sms - 1 + length) / charsInSingleConcatUcs2Sms;
|
||||||
|
count.remaining = (charsInSingleConcatUcs2Sms * count.messages - length) % charsInSingleConcatUcs2Sms;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
count.messages = 1;
|
||||||
|
count.remaining = (charsInSingleUcs2Sms - length) % charsInSingleUcs2Sms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmsHelper::isInGsmAlphabet(const QChar& ch)
|
||||||
|
{
|
||||||
|
wchar_t unicode = ch.unicode();
|
||||||
|
|
||||||
|
if ((unicode & ~0x7f) == 0) { // If the character is ASCII
|
||||||
|
// use map
|
||||||
|
return gsm_ascii_map[unicode];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (unicode) {
|
||||||
|
case 0xa1: // “¡”
|
||||||
|
case 0xa7: // “§”
|
||||||
|
case 0xbf: // “¿”
|
||||||
|
case 0xa4: // “¤”
|
||||||
|
case 0xa3: // “£”
|
||||||
|
case 0xa5: // “¥”
|
||||||
|
case 0xe0: // “à”
|
||||||
|
case 0xe5: // “å”
|
||||||
|
case 0xc5: // “Å”
|
||||||
|
case 0xe4: // “ä”
|
||||||
|
case 0xc4: // “Ä”
|
||||||
|
case 0xe6: // “æ”
|
||||||
|
case 0xc6: // “Æ”
|
||||||
|
case 0xc7: // “Ç”
|
||||||
|
case 0xe9: // “é”
|
||||||
|
case 0xc9: // “É”
|
||||||
|
case 0xe8: // “è”
|
||||||
|
case 0xec: // “ì”
|
||||||
|
case 0xf1: // “ñ”
|
||||||
|
case 0xd1: // “Ñ”
|
||||||
|
case 0xf2: // “ò”
|
||||||
|
case 0xf5: // “ö”
|
||||||
|
case 0xd6: // “Ö”
|
||||||
|
case 0xf8: // “ø”
|
||||||
|
case 0xd8: // “Ø”
|
||||||
|
case 0xdf: // “ß”
|
||||||
|
case 0xf9: // “ù”
|
||||||
|
case 0xfc: // “ü”
|
||||||
|
case 0xdc: // “Ü”
|
||||||
|
case 0x393: // “Γ”
|
||||||
|
case 0x394: // “Δ”
|
||||||
|
case 0x398: // “Θ”
|
||||||
|
case 0x39b: // “Λ”
|
||||||
|
case 0x39e: // “Ξ”
|
||||||
|
case 0x3a0: // “Π”
|
||||||
|
case 0x3a3: // “Σ”
|
||||||
|
case 0x3a6: // “Φ”
|
||||||
|
case 0x3a8: // “Ψ”
|
||||||
|
case 0x3a9: // “Ω”
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmsHelper::isInGsmAlphabetExtension(const QChar& ch)
|
||||||
|
{
|
||||||
|
wchar_t unicode = ch.unicode();
|
||||||
|
switch (unicode) {
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '|':
|
||||||
|
case '\\':
|
||||||
|
case '^':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '~':
|
||||||
|
case 0x20ac: // Euro sign
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "interfaces/conversationmessage.h"
|
#include "interfaces/conversationmessage.h"
|
||||||
|
|
||||||
#include "kdeconnectsms_export.h"
|
#include "kdeconnectsms_export.h"
|
||||||
|
#include "smsapp/smscharcount.h"
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_SMS_SMSHELPER)
|
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_SMS_SMSHELPER)
|
||||||
|
|
||||||
|
@ -106,7 +107,17 @@ public:
|
||||||
* Get the data for all persons currently stored on device
|
* Get the data for all persons currently stored on device
|
||||||
*/
|
*/
|
||||||
static QList<QSharedPointer<KPeople::PersonData>> getAllPersons();
|
static QList<QSharedPointer<KPeople::PersonData>> getAllPersons();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SMS character count status of SMS. It contains number of remaining characters
|
||||||
|
* in current SMS (automatically selects 7-bit, 8-bit or 16-bit mode), octet count and
|
||||||
|
* number of messages in concatenated SMS.
|
||||||
|
*/
|
||||||
|
static SmsCharCount getCharCount(const QString& message);
|
||||||
|
|
||||||
|
static bool isInGsmAlphabet(const QChar& ch);
|
||||||
|
static bool isInGsmAlphabetExtension(const QChar& ch);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SmsHelper(){};
|
SmsHelper(){};
|
||||||
~SmsHelper(){};
|
~SmsHelper(){};
|
||||||
|
|
Loading…
Reference in a new issue