feat/tray_pictogram #70
@ -14,6 +14,7 @@
|
||||
|
||||
### New features
|
||||
- new "About" window with links, license, gratitudes
|
||||
- if the authentication failed Squawk will ask againg for your password and login
|
||||
|
||||
## Squawk 0.2.1 (Apr 02, 2022)
|
||||
### Bug fixes
|
||||
|
@ -43,6 +43,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
reconnectTimer(new QTimer),
|
||||
network(p_net),
|
||||
passwordType(Shared::AccountPassword::plain),
|
||||
lastError(Error::none),
|
||||
pepSupport(false),
|
||||
active(p_active),
|
||||
notReadyPassword(false),
|
||||
@ -183,6 +184,7 @@ void Core::Account::onClientStateChange(QXmppClient::State st)
|
||||
dm->requestItems(getServer());
|
||||
dm->requestInfo(getServer());
|
||||
}
|
||||
lastError = Error::none;
|
||||
emit connectionStateChanged(state);
|
||||
}
|
||||
} else {
|
||||
@ -415,6 +417,7 @@ void Core::Account::onClientError(QXmppClient::Error err)
|
||||
qDebug() << "Error";
|
||||
QString errorText;
|
||||
QString errorType;
|
||||
lastError = Error::other;
|
||||
switch (err) {
|
||||
case QXmppClient::SocketError:
|
||||
errorText = client.socketErrorString();
|
||||
@ -456,6 +459,7 @@ void Core::Account::onClientError(QXmppClient::Error err)
|
||||
break;
|
||||
case QXmppStanza::Error::NotAuthorized:
|
||||
errorText = "Authentication error";
|
||||
lastError = Error::authentication;
|
||||
break;
|
||||
#if (QXMPP_VERSION) < QT_VERSION_CHECK(1, 3, 0)
|
||||
case QXmppStanza::Error::PaymentRequired:
|
||||
@ -750,3 +754,6 @@ void Core::Account::renameContactRequest(const QString& jid, const QString& newN
|
||||
void Core::Account::invalidatePassword() {
|
||||
notReadyPassword = true;}
|
||||
|
||||
Core::Account::Error Core::Account::getLastError() const {
|
||||
return lastError;}
|
||||
|
||||
|
@ -61,6 +61,12 @@ class Account : public QObject
|
||||
friend class RosterHandler;
|
||||
friend class VCardHandler;
|
||||
public:
|
||||
enum class Error {
|
||||
authentication,
|
||||
other,
|
||||
none
|
||||
};
|
||||
|
||||
Account(
|
||||
const QString& p_login,
|
||||
const QString& p_server,
|
||||
@ -82,6 +88,7 @@ public:
|
||||
QString getFullJid() const;
|
||||
Shared::Availability getAvailability() const;
|
||||
Shared::AccountPassword getPasswordType() const;
|
||||
Error getLastError() const;
|
||||
bool getActive() const;
|
||||
|
||||
void setName(const QString& p_name);
|
||||
@ -166,6 +173,7 @@ private:
|
||||
|
||||
NetworkAccess* network;
|
||||
Shared::AccountPassword passwordType;
|
||||
Error lastError;
|
||||
bool pepSupport;
|
||||
bool active;
|
||||
bool notReadyPassword;
|
||||
|
@ -260,7 +260,10 @@ void Core::Squawk::disconnectAccount(const QString& account)
|
||||
void Core::Squawk::onAccountConnectionStateChanged(Shared::ConnectionState p_state)
|
||||
{
|
||||
Account* acc = static_cast<Account*>(sender());
|
||||
emit changeAccount(acc->getName(), {{"state", QVariant::fromValue(p_state)}});
|
||||
emit changeAccount(acc->getName(), {
|
||||
{"state", QVariant::fromValue(p_state)},
|
||||
{"error", ""}
|
||||
});
|
||||
|
||||
#ifdef WITH_KWALLET
|
||||
if (p_state == Shared::ConnectionState::connected) {
|
||||
@ -398,6 +401,7 @@ void Core::Squawk::modifyAccountRequest(const QString& name, const QMap<QString,
|
||||
Shared::ConnectionState st = acc->getState();
|
||||
QMap<QString, QVariant>::const_iterator mItr;
|
||||
bool needToReconnect = false;
|
||||
bool wentReconnecting = false;
|
||||
|
||||
mItr = map.find("login");
|
||||
if (mItr != map.end()) {
|
||||
@ -428,6 +432,7 @@ void Core::Squawk::modifyAccountRequest(const QString& name, const QMap<QString,
|
||||
if (mItr == map.end() || mItr->toBool() == acc->getActive()) {
|
||||
if (needToReconnect && st != Shared::ConnectionState::disconnected) {
|
||||
acc->reconnect();
|
||||
wentReconnecting = true;
|
||||
}
|
||||
} else {
|
||||
acc->setActive(mItr->toBool());
|
||||
@ -468,8 +473,12 @@ void Core::Squawk::modifyAccountRequest(const QString& name, const QMap<QString,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (activeChanged && acc->getActive() && state != Shared::Availability::offline) {
|
||||
acc->connect();
|
||||
if (state != Shared::Availability::offline) {
|
||||
if (activeChanged && acc->getActive()) {
|
||||
acc->connect();
|
||||
} else if (!wentReconnecting && acc->getActive() && acc->getLastError() == Account::Error::authentication) {
|
||||
acc->connect();
|
||||
}
|
||||
}
|
||||
|
||||
emit changeAccount(name, map);
|
||||
@ -479,6 +488,10 @@ void Core::Squawk::onAccountError(const QString& text)
|
||||
{
|
||||
Account* acc = static_cast<Account*>(sender());
|
||||
emit changeAccount(acc->getName(), {{"error", text}});
|
||||
|
||||
if (acc->getLastError() == Account::Error::authentication) {
|
||||
emit requestPassword(acc->getName(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Squawk::removeAccountRequest(const QString& name)
|
||||
@ -733,7 +746,7 @@ void Core::Squawk::onAccountNeedPassword()
|
||||
Account* acc = static_cast<Account*>(sender());
|
||||
switch (acc->getPasswordType()) {
|
||||
case Shared::AccountPassword::alwaysAsk:
|
||||
emit requestPassword(acc->getName());
|
||||
emit requestPassword(acc->getName(), false);
|
||||
break;
|
||||
case Shared::AccountPassword::kwallet: {
|
||||
#ifdef WITH_KWALLET
|
||||
@ -741,7 +754,7 @@ void Core::Squawk::onAccountNeedPassword()
|
||||
kwallet.requestReadPassword(acc->getName());
|
||||
} else {
|
||||
#endif
|
||||
emit requestPassword(acc->getName());
|
||||
emit requestPassword(acc->getName(), false);
|
||||
#ifdef WITH_KWALLET
|
||||
}
|
||||
#endif
|
||||
@ -754,7 +767,7 @@ void Core::Squawk::onAccountNeedPassword()
|
||||
|
||||
void Core::Squawk::onWalletRejectPassword(const QString& login)
|
||||
{
|
||||
emit requestPassword(login);
|
||||
emit requestPassword(login, false);
|
||||
}
|
||||
|
||||
void Core::Squawk::responsePassword(const QString& account, const QString& password)
|
||||
|
@ -86,7 +86,7 @@ signals:
|
||||
|
||||
void responseVCard(const QString& jid, const Shared::VCard& card);
|
||||
void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
|
||||
void requestPassword(const QString& account);
|
||||
void requestPassword(const QString& account, bool authernticationError);
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
|
@ -76,16 +76,31 @@ void DialogQueue::performNextAction()
|
||||
case none:
|
||||
actionDone();
|
||||
break;
|
||||
case askPassword:
|
||||
prompt = new QInputDialog(squawk);
|
||||
connect(prompt, &QDialog::accepted, this, &DialogQueue::onPropmtAccepted);
|
||||
connect(prompt, &QDialog::rejected, this, &DialogQueue::onPropmtRejected);
|
||||
prompt->setInputMode(QInputDialog::TextInput);
|
||||
prompt->setTextEchoMode(QLineEdit::Password);
|
||||
prompt->setLabelText(tr("Input the password for account %1").arg(currentSource));
|
||||
prompt->setWindowTitle(tr("Password for account %1").arg(currentSource));
|
||||
prompt->setTextValue("");
|
||||
prompt->exec();
|
||||
case askPassword: {
|
||||
QInputDialog* dialog = new QInputDialog(squawk);
|
||||
prompt = dialog;
|
||||
connect(dialog, &QDialog::accepted, this, &DialogQueue::onPropmtAccepted);
|
||||
connect(dialog, &QDialog::rejected, this, &DialogQueue::onPropmtRejected);
|
||||
dialog->setInputMode(QInputDialog::TextInput);
|
||||
dialog->setTextEchoMode(QLineEdit::Password);
|
||||
dialog->setLabelText(tr("Input the password for account %1").arg(currentSource));
|
||||
dialog->setWindowTitle(tr("Password for account %1").arg(currentSource));
|
||||
dialog->setTextValue("");
|
||||
dialog->exec();
|
||||
}
|
||||
break;
|
||||
case askCredentials: {
|
||||
CredentialsPrompt* dialog = new CredentialsPrompt(squawk);
|
||||
prompt = dialog;
|
||||
connect(dialog, &QDialog::accepted, this, &DialogQueue::onPropmtAccepted);
|
||||
connect(dialog, &QDialog::rejected, this, &DialogQueue::onPropmtRejected);
|
||||
Models::Account* acc = squawk->rosterModel.getAccount(currentSource);
|
||||
dialog->setAccount(currentSource);
|
||||
dialog->setLogin(acc->getLogin());
|
||||
dialog->setPassword(acc->getPassword());
|
||||
dialog->exec();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,8 +109,18 @@ void DialogQueue::onPropmtAccepted()
|
||||
switch (currentAction) {
|
||||
case none:
|
||||
break;
|
||||
case askPassword:
|
||||
emit squawk->responsePassword(currentSource, prompt->textValue());
|
||||
case askPassword: {
|
||||
QInputDialog* dialog = static_cast<QInputDialog*>(prompt);
|
||||
emit squawk->responsePassword(currentSource, dialog->textValue());
|
||||
}
|
||||
break;
|
||||
case askCredentials: {
|
||||
CredentialsPrompt* dialog = static_cast<CredentialsPrompt*>(prompt);
|
||||
emit squawk->modifyAccountRequest(currentSource, {
|
||||
{"login", dialog->getLogin()},
|
||||
{"password", dialog->getPassword()}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
actionDone();
|
||||
@ -107,6 +132,7 @@ void DialogQueue::onPropmtRejected()
|
||||
case none:
|
||||
break;
|
||||
case askPassword:
|
||||
case askCredentials:
|
||||
emit squawk->disconnectAccount(currentSource);
|
||||
break;
|
||||
}
|
||||
|
@ -24,9 +24,7 @@
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/sequenced_index.hpp>
|
||||
|
||||
/**
|
||||
* @todo write docs
|
||||
*/
|
||||
#include <ui/widgets/accounts/credentialsprompt.h>
|
||||
|
||||
class Squawk;
|
||||
|
||||
@ -36,7 +34,8 @@ class DialogQueue : public QObject
|
||||
public:
|
||||
enum Action {
|
||||
none,
|
||||
askPassword
|
||||
askPassword,
|
||||
askCredentials
|
||||
};
|
||||
|
||||
DialogQueue(Squawk* squawk);
|
||||
@ -85,7 +84,7 @@ private:
|
||||
Collection& collection;
|
||||
Sequence& sequence;
|
||||
|
||||
QInputDialog* prompt;
|
||||
QDialog* prompt;
|
||||
Squawk* squawk;
|
||||
};
|
||||
|
||||
|
@ -880,8 +880,14 @@ void Squawk::onItemCollepsed(const QModelIndex& index)
|
||||
}
|
||||
}
|
||||
|
||||
void Squawk::requestPassword(const QString& account) {
|
||||
dialogueQueue.addAction(account, DialogQueue::askPassword);}
|
||||
void Squawk::requestPassword(const QString& account, bool authenticationError) {
|
||||
if (authenticationError) {
|
||||
dialogueQueue.addAction(account, DialogQueue::askCredentials);
|
||||
} else {
|
||||
dialogueQueue.addAction(account, DialogQueue::askPassword);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Squawk::subscribeConversation(Conversation* conv)
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ class Squawk;
|
||||
class Squawk : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class DialogQueue;
|
||||
public:
|
||||
explicit Squawk(QWidget *parent = nullptr);
|
||||
~Squawk() override;
|
||||
@ -114,7 +114,7 @@ public slots:
|
||||
void fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& url, const QString& path);
|
||||
void responseVCard(const QString& jid, const Shared::VCard& card);
|
||||
void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
|
||||
void requestPassword(const QString& account);
|
||||
void requestPassword(const QString& account, bool authenticationError);
|
||||
|
||||
private:
|
||||
typedef std::map<Models::Roster::ElId, Conversation*> Conversations;
|
||||
|
@ -5,4 +5,7 @@ target_sources(squawk PRIVATE
|
||||
accounts.cpp
|
||||
accounts.h
|
||||
accounts.ui
|
||||
credentialsprompt.cpp
|
||||
credentialsprompt.h
|
||||
credentialsprompt.ui
|
||||
)
|
||||
|
60
ui/widgets/accounts/credentialsprompt.cpp
Normal file
60
ui/widgets/accounts/credentialsprompt.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Squawk messenger.
|
||||
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||
//
|
||||
// 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "credentialsprompt.h"
|
||||
#include "ui_credentialsprompt.h"
|
||||
|
||||
CredentialsPrompt::CredentialsPrompt(QWidget* parent):
|
||||
QDialog(parent),
|
||||
m_ui(new Ui::CredentialsPrompt),
|
||||
title(),
|
||||
message()
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
title = windowTitle();
|
||||
message = m_ui->message->text();
|
||||
}
|
||||
|
||||
CredentialsPrompt::~CredentialsPrompt()
|
||||
{
|
||||
}
|
||||
|
||||
void CredentialsPrompt::setAccount(const QString& account)
|
||||
{
|
||||
m_ui->message->setText(message.arg(account));
|
||||
setWindowTitle(title.arg(account));
|
||||
}
|
||||
|
||||
QString CredentialsPrompt::getLogin() const
|
||||
{
|
||||
return m_ui->login->text();
|
||||
}
|
||||
|
||||
QString CredentialsPrompt::getPassword() const
|
||||
{
|
||||
return m_ui->password->text();
|
||||
}
|
||||
|
||||
void CredentialsPrompt::setLogin(const QString& login)
|
||||
{
|
||||
m_ui->login->setText(login);
|
||||
}
|
||||
|
||||
void CredentialsPrompt::setPassword(const QString& password)
|
||||
{
|
||||
m_ui->password->setText(password);
|
||||
}
|
52
ui/widgets/accounts/credentialsprompt.h
Normal file
52
ui/widgets/accounts/credentialsprompt.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Squawk messenger.
|
||||
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||
//
|
||||
// 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CREDENTIALSPROMPT_H
|
||||
#define CREDENTIALSPROMPT_H
|
||||
|
||||
#include <qdialog.h>
|
||||
#include <QScopedPointer>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CredentialsPrompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo write docs
|
||||
*/
|
||||
class CredentialsPrompt : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CredentialsPrompt(QWidget* parent = nullptr);
|
||||
~CredentialsPrompt();
|
||||
|
||||
void setAccount(const QString& account);
|
||||
void setLogin(const QString& login);
|
||||
void setPassword(const QString& password);
|
||||
|
||||
QString getLogin() const;
|
||||
QString getPassword() const;
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::CredentialsPrompt> m_ui;
|
||||
QString title;
|
||||
QString message;
|
||||
};
|
||||
|
||||
#endif // CREDENTIALSPROMPT_H
|
144
ui/widgets/accounts/credentialsprompt.ui
Normal file
144
ui/widgets/accounts/credentialsprompt.ui
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CredentialsPrompt</class>
|
||||
<widget class="QDialog" name="CredentialsPrompt">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>318</width>
|
||||
<height>229</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Authentication error: %1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="message">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Couldn't authenticate account %1: login or password is icorrect.
|
||||
Would you like to check them and try again?</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="loginLabel">
|
||||
<property name="text">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="login">
|
||||
<property name="toolTip">
|
||||
<string>Your account login (without @server.domain)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="passwordLabel">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="toolTip">
|
||||
<string>Your password</string>
|
||||
</property>
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhHiddenText|Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText|Qt::ImhSensitiveData</set>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CredentialsPrompt</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CredentialsPrompt</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user