5 Commits

  1. 11
      CHANGELOG.md
  2. 11
      core/account.cpp
  3. 2
      core/account.h
  4. 20
      core/archive.cpp
  5. 1
      core/archive.h
  6. 13
      core/networkaccess.cpp
  7. 16
      core/rosteritem.cpp
  8. 52
      core/squawk.cpp
  9. 2
      packaging/squawk.desktop
  10. 795
      translations/squawk.pt_BR.ts
  11. 5
      ui/models/item.cpp
  12. 16
      ui/widgets/conversation.cpp
  13. 1
      ui/widgets/conversation.h

11
CHANGELOG.md

@ -1,5 +1,16 @@
# Changelog
## Squawk 0.2.0 (Unreleased)
### Bug fixes
- carbon copies switches on again after reconnection
- requesting the history of the current chat after reconnection
- global availability (in drop down list) gets restored after reconnection
- status icon in active chat changes when presence of the pen pal changes
### Improvements
- slightly reduced the traffic on the startup by not requesting history of all MUCs
## Squawk 0.1.5 (Jul 29, 2020)
### Bug fixes
- error with sending attached files to the conference

11
core/account.cpp

@ -183,7 +183,6 @@ void Core::Account::connect()
reconnectTimer->stop();
}
if (state == Shared::ConnectionState::disconnected) {
qDebug() << presence.availableStatusType();
client.connectToServer(config, presence);
} else {
qDebug("An attempt to connect an account which is already connected, skipping");
@ -219,6 +218,7 @@ void Core::Account::onClientStateChange(QXmppClient::State st)
Shared::ConnectionState os = state;
state = Shared::ConnectionState::connected;
if (os == Shared::ConnectionState::connecting) {
qDebug() << "running service discovery for account" << name;
dm->requestItems(getServer());
dm->requestInfo(getServer());
}
@ -238,9 +238,8 @@ void Core::Account::onClientStateChange(QXmppClient::State st)
}
break;
case QXmppClient::DisconnectedState: {
cancelHistoryRequests();
pendingVCardRequests.clear();
if (state != Shared::ConnectionState::disconnected) {
handleDisconnection();
state = Shared::ConnectionState::disconnected;
emit connectionStateChanged(state);
} else {
@ -887,15 +886,18 @@ void Core::Account::onDiscoveryItemsReceived(const QXmppDiscoveryIq& items)
void Core::Account::onDiscoveryInfoReceived(const QXmppDiscoveryIq& info)
{
qDebug() << "Discovery info received for account" << name;
if (info.from() == getServer()) {
if (info.features().contains("urn:xmpp:carbons:2")) {
qDebug() << "Enabling carbon copies for account" << name;
cm->setCarbonsEnabled(true);
}
}
}
void Core::Account::cancelHistoryRequests()
void Core::Account::handleDisconnection()
{
cm->setCarbonsEnabled(false);
rh->handleOffline();
archiveQueries.clear();
pendingVCardRequests.clear();
@ -903,6 +905,7 @@ void Core::Account::cancelHistoryRequests()
for (const QString& jid : pendingVCardRequests) {
emit receivedVCard(jid, vCard); //need to show it better in the future, like with an error
}
pendingVCardRequests.clear();
ownVCardRequestInProgress = false;
}

2
core/account.h

@ -185,7 +185,7 @@ private slots:
void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info);
private:
void cancelHistoryRequests();
void handleDisconnection();
void onReconnectTimer();
};

20
core/archive.cpp

@ -214,6 +214,26 @@ Shared::Message Core::Archive::getElement(const QString& id) const
}
}
bool Core::Archive::hasElement(const QString& id) const
{
if (!opened) {
throw Closed("hasElement", jid.toStdString());
}
MDB_txn *txn;
mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
bool has;
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size();
lmdbKey.mv_data = (char*)id.toStdString().c_str();
int rc = mdb_get(txn, main, &lmdbKey, &lmdbData);
has = rc == 0;
mdb_txn_abort(txn);
return has;
}
Shared::Message Core::Archive::getMessage(const std::string& id, MDB_txn* txn) const
{
MDB_val lmdbKey, lmdbData;

1
core/archive.h

@ -46,6 +46,7 @@ public:
bool addElement(const Shared::Message& message);
unsigned int addElements(const std::list<Shared::Message>& messages);
Shared::Message getElement(const QString& id) const;
bool hasElement(const QString& id) const;
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
Shared::Message oldest();
QString oldestId();

13
core/networkaccess.cpp

@ -334,7 +334,11 @@ void Core::NetworkAccess::startDownload(const QString& messageId, const QString&
QNetworkRequest req(url);
dwn->reply = manager->get(req);
connect(dwn->reply, &QNetworkReply::downloadProgress, this, &NetworkAccess::onDownloadProgress);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(dwn->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::errorOccurred), this, &NetworkAccess::onDownloadError);
#else
connect(dwn->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this, &NetworkAccess::onDownloadError);
#endif
connect(dwn->reply, &QNetworkReply::finished, this, &NetworkAccess::onDownloadFinished);
downloads.insert(std::make_pair(url, dwn));
emit downloadFileProgress(messageId, 0);
@ -414,7 +418,12 @@ void Core::NetworkAccess::startUpload(const QString& messageId, const QString& u
upl->reply = manager->put(req, file);
connect(upl->reply, &QNetworkReply::uploadProgress, this, &NetworkAccess::onUploadProgress);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::errorOccurred), this, &NetworkAccess::onUploadError);
#else
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this, &NetworkAccess::onUploadError);
#endif
connect(upl->reply, &QNetworkReply::finished, this, &NetworkAccess::onUploadFinished);
uploads.insert(std::make_pair(url, upl));
emit downloadFileProgress(messageId, 0);
@ -490,7 +499,11 @@ void Core::NetworkAccess::uploadFile(const QString& messageId, const QString& pa
upl->reply = manager->put(req, file);
connect(upl->reply, &QNetworkReply::uploadProgress, this, &NetworkAccess::onUploadProgress);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::errorOccurred), this, &NetworkAccess::onUploadError);
#else
connect(upl->reply, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this, &NetworkAccess::onUploadError);
#endif
connect(upl->reply, &QNetworkReply::finished, this, &NetworkAccess::onUploadFinished);
uploads.insert(std::make_pair(put.toString(), upl));
emit downloadFileProgress(messageId, 0);

16
core/rosteritem.cpp

@ -248,18 +248,22 @@ void Core::RosterItem::appendMessageToArchive(const Shared::Message& msg)
}
break;
case beginning:
appendCache.push_back(msg);
if (!syncronizing) {
requestHistory(-1, getId(msg));
if (!archive->hasElement(msg.getId())) {
appendCache.push_back(msg);
if (!syncronizing) {
requestHistory(-1, getId(msg));
}
}
break;
case end:
archive->addElement(msg);
break;
case chunk:
appendCache.push_back(msg);
if (!syncronizing) {
requestHistory(-1, getId(msg));
if (!archive->hasElement(msg.getId())) {
appendCache.push_back(msg);
if (!syncronizing) {
requestHistory(-1, getId(msg));
}
}
break;
case complete:

52
core/squawk.cpp

@ -223,30 +223,40 @@ void Core::Squawk::onAccountConnectionStateChanged(Shared::ConnectionState p_sta
Account* acc = static_cast<Account*>(sender());
emit changeAccount(acc->getName(), {{"state", QVariant::fromValue(p_state)}});
switch (p_state) {
case Shared::ConnectionState::disconnected: {
bool equals = true;
for (Accounts::const_iterator itr = accounts.begin(), end = accounts.end(); itr != end; itr++) {
if ((*itr)->getState() != Shared::ConnectionState::disconnected) {
equals = false;
}
}
if (equals && state != Shared::Availability::offline) {
state = Shared::Availability::offline;
emit stateChanged(state);
}
}
break;
case Shared::ConnectionState::connected:
#ifdef WITH_KWALLET
if (acc->getPasswordType() == Shared::AccountPassword::kwallet && kwallet.supportState() == PSE::KWallet::success) {
kwallet.requestWritePassword(acc->getName(), acc->getPassword(), true);
}
if (p_state == Shared::ConnectionState::connected) {
if (acc->getPasswordType() == Shared::AccountPassword::kwallet && kwallet.supportState() == PSE::KWallet::success) {
kwallet.requestWritePassword(acc->getName(), acc->getPassword(), true);
}
}
#endif
break;
default:
break;
Accounts::const_iterator itr = accounts.begin();
bool es = true;
bool ea = true;
Shared::ConnectionState cs = (*itr)->getState();
Shared::Availability av = (*itr)->getAvailability();
itr++;
for (Accounts::const_iterator end = accounts.end(); itr != end; itr++) {
Account* item = *itr;
if (item->getState() != cs) {
es = false;
}
if (item->getAvailability() != av) {
ea = false;
}
}
if (es) {
if (cs == Shared::ConnectionState::disconnected) {
state = Shared::Availability::offline;
emit stateChanged(state);
} else if (ea) {
state = av;
emit stateChanged(state);
}
}
}
void Core::Squawk::onAccountAddContact(const QString& jid, const QString& group, const QMap<QString, QVariant>& data)

2
packaging/squawk.desktop

@ -5,8 +5,10 @@ Version=1.0
Name=Squawk
GenericName=Instant Messenger
GenericName[ru]=Мгновенные сообщения
GenericName[pt_BR]=Mensageiro instantâneo
Comment=XMPP (Jabber) instant messenger client
Comment[ru]=XMPP (Jabber) клиент обмена мгновенными сообщениями
Comment[pt_BR]=Cliente de mensagem instantânea XMPP (Jabber)
Exec=squawk %u
Icon=squawk
StartupNotify=true

795
translations/squawk.pt_BR.ts

@ -0,0 +1,795 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pt_BR">
<context>
<name>Account</name>
<message>
<source>Account</source>
<translation>Conta</translation>
</message>
<message>
<source>Your account login</source>
<translation>Suas informações de login</translation>
</message>
<message>
<source>john_smith1987</source>
<translation>josé_silva1987</translation>
</message>
<message>
<source>Server</source>
<translation>Servidor</translation>
</message>
<message>
<source>A server address of your account. Like 404.city or macaw.me</source>
<translation>O endereço do servidor da sua conta, como o 404.city ou o macaw.me</translation>
</message>
<message>
<source>macaw.me</source>
<translation>macaw.me</translation>
</message>
<message>
<source>Login</source>
<translation>Usuário</translation>
</message>
<message>
<source>Password</source>
<translation>Senha</translation>
</message>
<message>
<source>Password of your account</source>
<translation>Senha da sua conta</translation>
</message>
<message>
<source>Name</source>
<translation>Nome</translation>
</message>
<message>
<source>Just a name how would you call this account, doesn&apos;t affect anything</source>
<translation>Apenas um nome para identificar esta conta. Não influencia em nada</translation>
</message>
<message>
<source>John</source>
<translation>José</translation>
</message>
<message>
<source>Resource</source>
<translation>Recurso</translation>
</message>
<message>
<source>A resource name like &quot;Home&quot; or &quot;Work&quot;</source>
<translation>Um nome de recurso como &quot;Casa&quot; ou &quot;Trabalho&quot;</translation>
</message>
<message>
<source>QXmpp</source>
<translation>QXmpp</translation>
</message>
<message>
<source>Password storage</source>
<translation>Armazenamento de senha</translation>
</message>
</context>
<context>
<name>Accounts</name>
<message>
<source>Accounts</source>
<translation>Contas</translation>
</message>
<message>
<source>Delete</source>
<translation>Apagar</translation>
</message>
<message>
<source>Add</source>
<translation>Adicionar</translation>
</message>
<message>
<source>Edit</source>
<translation>Editar</translation>
</message>
<message>
<source>Change password</source>
<translation>Alterar senha</translation>
</message>
<message>
<source>Connect</source>
<translation>Conectar</translation>
</message>
<message>
<source>Disconnect</source>
<translation>Desconectar</translation>
</message>
</context>
<context>
<name>Conversation</name>
<message>
<source>Type your message here...</source>
<translation>Digite sua mensagem aqui...</translation>
</message>
<message>
<source>Chose a file to send</source>
<translation>Escolha um arquivo para enviar</translation>
</message>
<message>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Liberation Sans&apos;; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Drop files here to attach them to your message</source>
<translation>Arraste seus arquivos aqui para anexá-los a sua mensagem</translation>
</message>
</context>
<context>
<name>Global</name>
<message>
<source>Online</source>
<comment>Availability</comment>
<translation>Conectado</translation>
</message>
<message>
<source>Away</source>
<comment>Availability</comment>
<translation>Distante</translation>
</message>
<message>
<source>Absent</source>
<comment>Availability</comment>
<translation>Ausente</translation>
</message>
<message>
<source>Busy</source>
<comment>Availability</comment>
<translation>Ocupado</translation>
</message>
<message>
<source>Chatty</source>
<comment>Availability</comment>
<translation>Tagarela</translation>
</message>
<message>
<source>Invisible</source>
<comment>Availability</comment>
<translation>Invisível</translation>
</message>
<message>
<source>Offline</source>
<comment>Availability</comment>
<translation>Desconectado</translation>
</message>
<message>
<source>Disconnected</source>
<comment>ConnectionState</comment>
<translation>Desconectado</translation>
</message>
<message>
<source>Connecting</source>
<comment>ConnectionState</comment>
<translation>Connectando</translation>
</message>
<message>
<source>Connected</source>
<comment>ConnectionState</comment>
<translation>Conectado</translation>
</message>
<message>
<source>Error</source>
<comment>ConnectionState</comment>
<translation>Erro</translation>
</message>
<message>
<source>None</source>
<comment>SubscriptionState</comment>
<translation>Nenhum</translation>
</message>
<message>
<source>From</source>
<comment>SubscriptionState</comment>
<translation>De</translation>
</message>
<message>
<source>To</source>
<comment>SubscriptionState</comment>
<translation>Para</translation>
</message>
<message>
<source>Both</source>
<comment>SubscriptionState</comment>
<translation>Ambos</translation>
</message>
<message>
<source>Unknown</source>
<comment>SubscriptionState</comment>
<translation>Desconhecido</translation>
</message>
<message>
<source>Unspecified</source>
<comment>Affiliation</comment>
<translation>Não especificado</translation>
</message>
<message>
<source>Outcast</source>
<comment>Affiliation</comment>
<translation>Rejeitado</translation>
</message>
<message>
<source>Nobody</source>
<comment>Affiliation</comment>
<translation>Ninguém</translation>
</message>
<message>
<source>Member</source>
<comment>Affiliation</comment>
<translation>Membro</translation>
</message>
<message>
<source>Admin</source>
<comment>Affiliation</comment>
<translation>Administrador</translation>
</message>
<message>
<source>Owner</source>
<comment>Affiliation</comment>
<translation>Dono</translation>
</message>
<message>
<source>Unspecified</source>
<comment>Role</comment>
<translation>Não especificado</translation>
</message>
<message>
<source>Nobody</source>
<comment>Role</comment>
<translation>Ninguém</translation>
</message>
<message>
<source>Visitor</source>
<comment>Role</comment>
<translation>Visitante</translation>
</message>
<message>
<source>Participant</source>
<comment>Role</comment>
<translation>Participante</translation>
</message>
<message>
<source>Moderator</source>
<comment>Role</comment>
<translation>Moderador</translation>
</message>
<message>
<source>Pending</source>
<comment>MessageState</comment>
<translation>Aguardando</translation>
</message>
<message>
<source>Sent</source>
<comment>MessageState</comment>
<translation>Enviada</translation>
</message>
<message>
<source>Delivered</source>
<comment>MessageState</comment>
<translation>Entregue</translation>
</message>
<message>
<source>Error</source>
<comment>MessageState</comment>
<translation>Erro</translation>
</message>
<message>
<source>Plain</source>
<comment>AccountPassword</comment>
<translation>Texto simples</translation>
</message>
<message>
<source>Jammed</source>
<comment>AccountPassword</comment>
<translation>Embaralhado</translation>
</message>
<message>
<source>Always Ask</source>
<comment>AccountPassword</comment>
<translation>Sempre perguntar</translation>
</message>
<message>
<source>KWallet</source>
<comment>AccountPassword</comment>
<translation>KWallet</translation>
</message>
<message>
<source>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&apos;s not</source>
<comment>AccountPasswordDescription</comment>
<translation>Sua senha será armazenada em um arquivo de configurações, porém embaralhada com uma chave criptográfica constante que você pode encontrar no código fonte do programa. Parece criptografado, mas não é</translation>
</message>
<message>
<source>Squawk is going to query you for the password on every start of the program</source>
<comment>AccountPasswordDescription</comment>
<translation>O Squark vai requisitar sua senha a cada vez que você abrir o programa</translation>
</message>
<message>
<source>Your password is going to be stored in config file in plain text</source>
<comment>AccountPasswordDescription</comment>
<translation>Sua senha será armazenada em um arquivo de configurações em texto simples</translation>
</message>
<message>
<source>Your password is going to be stored in KDE wallet storage (KWallet). You&apos;re going to be queried for permissions</source>
<comment>AccountPasswordDescription</comment>
<translation>Sua senha será armazenada no KDE wallet (KWallet). Sua autorização será requerida</translation>
</message>
</context>
<context>
<name>JoinConference</name>
<message>
<source>Join new conference</source>
<translatorcomment>Заголовок окна</translatorcomment>
<translation>Entrar em uma nova conferência</translation>
</message>
<message>
<source>JID</source>
<translation>JID</translation>
</message>
<message>
<source>Room JID</source>
<translation>Sala JID</translation>
</message>
<message>
<source>identifier@conference.server.org</source>
<translation>identifier@conference.server.org</translation>
</message>
<message>
<source>Account</source>
<translation>Conta</translation>
</message>
<message>
<source>Join on login</source>
<translation>Entrar ao se conectar</translation>
</message>
<message>
<source>If checked Squawk will try to join this conference on login</source>
<translation>Se marcado, o Squawk tentará entrar nesta conferência automaticamente durante o login</translation>
</message>
<message>
<source>Nick name</source>
<translation>Apelido</translation>
</message>
<message>
<source>Your nick name for that conference. If you leave this field empty your account name will be used as a nick name</source>
<translation>Seu apelido para essa conferência. Se você deixar este campo em branco, seu nome de usuário será usado como apelido</translation>
</message>
<message>
<source>John</source>
<translation>José</translation>
</message>
</context>
<context>
<name>Message</name>
<message>
<source>Open</source>
<translation>Abrir</translation>
</message>
</context>
<context>
<name>MessageLine</name>
<message>
<source>Downloading...</source>
<translation>Baixando...</translation>
</message>
<message>
<source>Download</source>
<translation>Baixar</translation>
</message>
<message>
<source>Error uploading file: %1
You can try again</source>
<translation>Error fazendo upload do arquivo: %1
Você pode tentar novamente</translation>
</message>
<message>
<source>Upload</source>
<translation>Upload</translation>
</message>
<message>
<source>Error downloading file: %1
You can try again</source>
<translation>Erro baixando arquivo: %1
Você pode tentar novamente</translation>
</message>
<message>
<source>Uploading...</source>
<translation>Fazendo upload...</translation>
</message>
<message>
<source>Push the button to download the file</source>
<translation>Pressione o botão para baixar o arquivo</translation>
</message>
</context>
<context>
<name>Models::Room</name>
<message>
<source>Subscribed</source>
<translation>Inscrito</translation>
</message>
<message>
<source>Temporarily unsubscribed</source>
<translation>Inscrição temporariamente cancelada</translation>
</message>
<message>
<source>Temporarily subscribed</source>
<translation>Temporariamente inscrito</translation>
</message>
<message>
<source>Unsubscribed</source>
<translation>Não inscrito</translation>
</message>
</context>
<context>
<name>Models::Roster</name>
<message>
<source>New messages</source>
<translation>Novas mensagens</translation>
</message>
<message>
<source>New messages: </source>
<translation>Novas mensagens: </translation>
</message>
<message>
<source>Jabber ID: </source>
<translation>ID Jabber: </translation>
</message>
<message>
<source>Availability: </source>
<translation>Disponibilidade: </translation>
</message>
<message>
<source>Status: </source>
<translation>Status: </translation>
</message>
<message>
<source>Subscription: </source>
<translation>Inscrição: </translation>
</message>
<message>
<source>Affiliation: </source>
<translatorcomment>Я правда не знаю, как это объяснить, не то что перевести</translatorcomment>
<translation>Afiliação: </translation>
</message>
<message>
<source>Role: </source>
<translation>Papel: </translation>
</message>
<message>
<source>Online contacts: </source>
<translation>Contatos online: </translation>
</message>
<message>
<source>Total contacts: </source>
<translation>Contatos totais: </translation>
</message>
<message>
<source>Members: </source>
<translation>Membros: </translation>
</message>
</context>
<context>
<name>NewContact</name>
<message>
<source>Add new contact</source>
<translatorcomment>Заголовок окна</translatorcomment>
<translation>Adicionar novo contato</translation>
</message>
<message>
<source>Account</source>
<translation>Conta</translation>
</message>
<message>
<source>An account that is going to have new contact</source>
<translation>A conta que terá um novo contato</translation>
</message>
<message>
<source>JID</source>
<translation>JID</translation>
</message>
<message>
<source>Jabber id of your new contact</source>
<translation>ID Jabber do seu novo contato</translation>
</message>
<message>
<source>name@server.dmn</source>
<translatorcomment>Placeholder поля ввода JID</translatorcomment>
<translation>nome@servidor.com.br</translation>
</message>
<message>
<source>Name</source>
<translation>Nome</translation>
</message>
<message>
<source>The way this new contact will be labeled in your roster (optional)</source>
<translation>A forma com que o novo contato será classificado em sua lista (opcional)</translation>
</message>
<message>
<source>John Smith</source>
<translation>José Silva</translation>
</message>
</context>
<context>
<name>Squawk</name>
<message>
<source>squawk</source>
<translation>Squawk</translation>
</message>
<message>
<source>Settings</source>
<translation>Configurações</translation>
</message>
<message>
<source>Squawk</source>
<translation>Squawk</translation>
</message>
<message>
<source>Accounts</source>
<translation>Contas</translation>
</message>
<message>
<source>Quit</source>
<translation>Sair</translation>
</message>
<message>
<source>Add contact</source>
<translation>Adicionar contato</translation>
</message>
<message>
<source>Add conference</source>
<translation>Adicionar conferência</translation>
</message>
<message>
<source>Disconnect</source>
<translation>Desconectar</translation>
</message>
<message>
<source>Connect</source>
<translation>Conectar</translation>
</message>
<message>
<source>VCard</source>
<translation>VCard</translation>
</message>
<message>
<source>Remove</source>
<translation>Remover</translation>
</message>
<message>
<source>Open dialog</source>
<translation>Abrir caixa de diálogo</translation>
</message>
<message>
<source>Unsubscribe</source>
<translation>Cancelar inscrição</translation>
</message>
<message>
<source>Subscribe</source>
<translation>Inscrever-se</translation>
</message>
<message>
<source>Rename</source>
<translation>Renomear</translation>
</message>
<message>
<source>Input new name for %1
or leave it empty for the contact
to be displayed as %1</source>
<translation>Digite um novo nome para %1
ou o deixe em branco para o contato
ser exibido com %1</translation>
</message>
<message>
<source>Renaming %1</source>
<translation>Renomeando %1</translation>
</message>
<message>
<source>Groups</source>
<translation>Grupos</translation>
</message>
<message>
<source>New group</source>
<translation>Novo grupo</translation>
</message>
<message>
<source>New group name</source>
<translation>Novo nome do grupo</translation>
</message>
<message>
<source>Add %1 to a new group</source>
<translation>Adicionar %1 a um novo grupo</translation>
</message>
<message>
<source>Open conversation</source>
<translation>Abrir conversa</translation>
</message>
<message>
<source>%1 account card</source>
<translation>cartão da conta %1</translation>
</message>
<message>
<source>%1 contact card</source>
<translation>cartão de contato %1</translation>
</message>
<message>
<source>Downloading vCard</source>
<translation>Baixando vCard</translation>
</message>
<message>
<source>Attached file</source>
<translation>Arquivo anexado</translation>
</message>
<message>
<source>Input the password for account %1</source>
<translation>Digite a senha para a conta %1</translation>
</message>
<message>
<source>Password for account %1</source>
<translation>Senha para a conta %1</translation>
</message>
<message>
<source>Please select a contact to start chatting</source>
<translation>Por favor selecione um contato para começar a conversar</translation>
</message>
</context>
<context>
<name>VCard</name>
<message>
<source>Received 12.07.2007 at 17.35</source>
<translation>Recebido 12/07/2007 às 17:35</translation>
</message>
<message>
<source>General</source>
<translation>Geral</translation>
</message>
<message>
<source>Organization</source>
<translation>Empresa</translation>
</message>
<message>
<source>Middle name</source>
<translation>Nome do meio</translation>
</message>
<message>
<source>First name</source>
<translation>Primeiro nome</translation>
</message>
<message>
<source>Last name</source>
<translation>Sobrenome</translation>
</message>
<message>
<source>Nick name</source>
<translation>Apelido</translation>
</message>
<message>
<source>Birthday</source>
<translation>Data de aniversário</translation>
</message>
<message>
<source>Organization name</source>
<translation>Nome da empresa</translation>
</message>
<message>
<source>Unit / Department</source>
<translation>Unidade/Departamento</translation>
</message>
<message>
<source>Role / Profession</source>
<translation>Profissão</translation>
</message>
<message>
<source>Job title</source>
<translation>Cargo</translation>
</message>
<message>
<source>Full name</source>
<translation>Nome completo</translation>
</message>
<message>
<source>Personal information</source>
<translation>Informações pessoais</translation>
</message>
<message>
<source>Addresses</source>
<translation>Endereços</translation>
</message>
<message>
<source>E-Mail addresses</source>
<translation>Endereços de e-mail</translation>
</message>
<message>
<source>Phone numbers</source>
<translation>Números de telefone</translation>
</message>
<message>
<source>Contact</source>
<translation>Contato</translation>
</message>
<message>
<source>Jabber ID</source>
<translation>ID Jabber</translation>
</message>
<message>
<source>Web site</source>
<translation>Site web</translation>
</message>
<message>
<source>Description</source>
<translation>Descrição</translation>
</message>
<message>
<source>Set avatar</source>
<translation>Definir avatar</translation>
</message>
<message>
<source>Clear avatar</source>
<translation>Apagar avatar</translation>
</message>
<message>
<source>Account %1 card</source>
<translation>Cartão da conta %1</translation>
</message>
<message>
<source>Contact %1 card</source>
<translation>Cartão do contato %1</translation>
</message>
<message>
<source>Received %1 at %2</source>
<translation>Recebido %1 em %2</translation>
</message>
<message>
<source>Chose your new avatar</source>
<translation>Escolha um novo avatar</translation>
</message>
<message>
<source>Images (*.png *.jpg *.jpeg)</source>
<translation>Imagens (*.png *.jpg *.jpeg)</translation>
</message>
<message>
<source>Add email address</source>
<translation>Adicionar endereço de e-mail</translation>
</message>
<message>
<source>Unset this email as preferred</source>
<translation>Desmarcar este e-mail como preferido</translation>
</message>
<message>
<source>Set this email as preferred</source>
<translation>Marcar este e-mail como preferido</translation>
</message>
<message>
<source>Remove selected email addresses</source>
<translation>Remover endereço de e-mail selecionado</translation>
</message>
<message>
<source>Copy selected emails to clipboard</source>
<translation>Copiar endereços de e-mails selecionados para a área de transferência</translation>
</message>
<message>
<source>Add phone number</source>
<translation>Adicionar número de telefone</translation>
</message>
<message>
<source>Unset this phone as preferred</source>
<translation>Desmarcar este número de telefone como preferido</translation>
</message>
<message>
<source>Set this phone as preferred</source>
<translation>Marcar este número de telefone como preferido</translation>
</message>
<message>
<source>Remove selected phone numbers</source>
<translation>Remover os números de telefones selecionados</translation>
</message>
<message>
<source>Copy selected phones to clipboard</source>
<translation>Copiar os números de telefone selecionados para a área de transferência</translation>
</message>
</context>
</TS>

5
ui/models/item.cpp

@ -215,9 +215,8 @@ void Models::Item::_removeChild(int index)
void Models::Item::changed(int col)
{
if (parent != nullptr) {
emit childChanged(this, row(), col);
}
emit childChanged(this, row(), col);
}
void Models::Item::toOfflineState()

16
ui/widgets/conversation.cpp

@ -54,6 +54,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
{
m_ui->setupUi(this);
connect(acc, &Models::Account::childChanged, this, &Conversation::onAccountChanged);
filesLayout = new FlowLayout(m_ui->filesPanel, 0);
m_ui->filesPanel->setLayout(filesLayout);
@ -121,6 +123,20 @@ Conversation::~Conversation()
{
}
void Conversation::onAccountChanged(Models::Item* item, int row, int col)
{
if (item == account) {
if (col == 2 && account->getState() == Shared::ConnectionState::connected) {
if (!requestingHistory) {
requestingHistory = true;
line->showBusyIndicator();
emit requestArchive("");
scroll = down;
}
}
}
}
void Conversation::applyVisualEffects()
{
DropShadowEffect *e1 = new DropShadowEffect;

1
ui/widgets/conversation.h

@ -121,6 +121,7 @@ protected slots:
void onBadgeClose();
void onClearButton();
void onTextEditDocSizeChanged(const QSizeF& size);
void onAccountChanged(Models::Item* item, int row, int col);
public:
const bool isMuc;

Loading…
Cancel
Save