safePasswords #36
@ -2,16 +2,18 @@
|
|||||||
|
|
||||||
## Squawk 0.1.4 (UNRELEASED)
|
## Squawk 0.1.4 (UNRELEASED)
|
||||||
### New features
|
### New features
|
||||||
- message line now is in the same window with roster (new window dialog is still able to opened on double click)
|
- message line now is in the same window with roster (new window dialog is still able to opened on context menu)
|
||||||
- several ways to manage your account password:
|
- several new ways to manage your account password:
|
||||||
- store it in plain text with the config (like it always was)
|
- store it in plain text with the config (like it always was)
|
||||||
- store it in config jammed (local hashing with the constant seed, not secure at all but might look like it is)
|
- store it in config jammed (local hashing with the constant seed, not secure at all but might look like it is)
|
||||||
- ask the account password on each program launch
|
- ask the account password on each program launch
|
||||||
- store it in KWallet which is dynamically loaded
|
- store it in KWallet which is dynamically loaded
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
- never updating MUC avatars now update
|
- never updating MUC avatars now get updated
|
||||||
- going offline related segfault fix
|
- going offline related segfault fix
|
||||||
|
- statuses now behave better: they wrap if they don't fit, you can select them, you can follow links from there
|
||||||
|
- messages and statuses don't loose content if you use < ore > symbols
|
||||||
|
|
||||||
|
|
||||||
## Squawk 0.1.3 (Mar 31, 2020)
|
## Squawk 0.1.3 (Mar 31, 2020)
|
||||||
|
@ -27,3 +27,22 @@ QString Shared::generateUUID()
|
|||||||
uuid_unparse_lower(uuid, uuid_str);
|
uuid_unparse_lower(uuid, uuid_str);
|
||||||
return uuid_str;
|
return uuid_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const QRegularExpression urlReg("(?<!<a\\shref=['\"])(?<!<img\\ssrc=['\"])("
|
||||||
|
"(?:https?|ftp):\\/\\/"
|
||||||
|
"\\w+"
|
||||||
|
"(?:"
|
||||||
|
"[\\w\\.\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]?"
|
||||||
|
"(?:"
|
||||||
|
"\\([\\w\\.\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]+\\)"
|
||||||
|
")?"
|
||||||
|
")*"
|
||||||
|
")");
|
||||||
|
|
||||||
|
QString Shared::processMessageBody(const QString& msg)
|
||||||
|
{
|
||||||
|
QString processed = msg.toHtmlEscaped();
|
||||||
|
processed.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
||||||
|
return "<p style=\"white-space: pre-wrap;\">" + processed + "</p>";
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -28,6 +29,7 @@
|
|||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
QString generateUUID();
|
QString generateUUID();
|
||||||
|
QString processMessageBody(const QString& msg);
|
||||||
|
|
||||||
static const std::vector<QColor> colorPalette = {
|
static const std::vector<QColor> colorPalette = {
|
||||||
QColor(244, 27, 63),
|
QColor(244, 27, 63),
|
||||||
|
@ -33,7 +33,8 @@ Squawk::Squawk(QWidget *parent) :
|
|||||||
vCards(),
|
vCards(),
|
||||||
requestedAccountsForPasswords(),
|
requestedAccountsForPasswords(),
|
||||||
prompt(0),
|
prompt(0),
|
||||||
currentConversation(0)
|
currentConversation(0),
|
||||||
|
restoreSelection()
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
m_ui->roster->setModel(&rosterModel);
|
m_ui->roster->setModel(&rosterModel);
|
||||||
@ -53,12 +54,13 @@ Squawk::Squawk(QWidget *parent) :
|
|||||||
connect(m_ui->actionAddContact, &QAction::triggered, this, &Squawk::onNewContact);
|
connect(m_ui->actionAddContact, &QAction::triggered, this, &Squawk::onNewContact);
|
||||||
connect(m_ui->actionAddConference, &QAction::triggered, this, &Squawk::onNewConference);
|
connect(m_ui->actionAddConference, &QAction::triggered, this, &Squawk::onNewConference);
|
||||||
connect(m_ui->comboBox, qOverload<int>(&QComboBox::activated), this, &Squawk::onComboboxActivated);
|
connect(m_ui->comboBox, qOverload<int>(&QComboBox::activated), this, &Squawk::onComboboxActivated);
|
||||||
connect(m_ui->roster, &QTreeView::doubleClicked, this, &Squawk::onRosterItemDoubleClicked);
|
//connect(m_ui->roster, &QTreeView::doubleClicked, this, &Squawk::onRosterItemDoubleClicked);
|
||||||
connect(m_ui->roster, &QTreeView::customContextMenuRequested, this, &Squawk::onRosterContextMenu);
|
connect(m_ui->roster, &QTreeView::customContextMenuRequested, this, &Squawk::onRosterContextMenu);
|
||||||
connect(m_ui->roster, &QTreeView::collapsed, this, &Squawk::onItemCollepsed);
|
connect(m_ui->roster, &QTreeView::collapsed, this, &Squawk::onItemCollepsed);
|
||||||
connect(m_ui->roster->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &Squawk::onRosterSelectionChanged);
|
connect(m_ui->roster->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &Squawk::onRosterSelectionChanged);
|
||||||
|
|
||||||
connect(rosterModel.accountsModel, &Models::Accounts::sizeChanged, this, &Squawk::onAccountsSizeChanged);
|
connect(rosterModel.accountsModel, &Models::Accounts::sizeChanged, this, &Squawk::onAccountsSizeChanged);
|
||||||
|
connect(contextMenu, &QMenu::aboutToHide, this, &Squawk::onContextAboutToHide);
|
||||||
//m_ui->mainToolBar->addWidget(m_ui->comboBox);
|
//m_ui->mainToolBar->addWidget(m_ui->comboBox);
|
||||||
|
|
||||||
setWindowTitle(tr("Contact list"));
|
setWindowTitle(tr("Contact list"));
|
||||||
@ -1095,12 +1097,18 @@ void Squawk::subscribeConversation(Conversation* conv)
|
|||||||
|
|
||||||
void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous)
|
void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous)
|
||||||
{
|
{
|
||||||
|
if (restoreSelection.isValid() && restoreSelection == current) {
|
||||||
|
restoreSelection = QModelIndex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (current.isValid()) {
|
if (current.isValid()) {
|
||||||
Models::Item* node = static_cast<Models::Item*>(current.internalPointer());
|
Models::Item* node = static_cast<Models::Item*>(current.internalPointer());
|
||||||
Models::Contact* contact = 0;
|
Models::Contact* contact = 0;
|
||||||
Models::Room* room = 0;
|
Models::Room* room = 0;
|
||||||
QString res;
|
QString res;
|
||||||
Models::Roster::ElId* id = 0;
|
Models::Roster::ElId* id = 0;
|
||||||
|
bool hasContext = true;
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case Models::Item::contact:
|
case Models::Item::contact:
|
||||||
contact = static_cast<Models::Contact*>(node);
|
contact = static_cast<Models::Contact*>(node);
|
||||||
@ -1110,21 +1118,38 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
|
|||||||
contact = static_cast<Models::Contact*>(node->parentItem());
|
contact = static_cast<Models::Contact*>(node->parentItem());
|
||||||
id = new Models::Roster::ElId(contact->getAccountName(), contact->getJid());
|
id = new Models::Roster::ElId(contact->getAccountName(), contact->getJid());
|
||||||
res = node->getName();
|
res = node->getName();
|
||||||
|
hasContext = false;
|
||||||
break;
|
break;
|
||||||
case Models::Item::room:
|
case Models::Item::room:
|
||||||
room = static_cast<Models::Room*>(node);
|
room = static_cast<Models::Room*>(node);
|
||||||
id = new Models::Roster::ElId(room->getAccountName(), room->getJid());
|
id = new Models::Roster::ElId(room->getAccountName(), room->getJid());
|
||||||
break;
|
break;
|
||||||
|
case Models::Item::participant:
|
||||||
|
room = static_cast<Models::Room*>(node->parentItem());
|
||||||
|
id = new Models::Roster::ElId(room->getAccountName(), room->getJid());
|
||||||
|
hasContext = false;
|
||||||
|
break;
|
||||||
|
case Models::Item::group:
|
||||||
|
hasContext = false;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasContext && QGuiApplication::mouseButtons() & Qt::RightButton) {
|
||||||
|
if (id != 0) {
|
||||||
|
delete id;
|
||||||
|
}
|
||||||
|
restoreSelection = previous;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (id != 0) {
|
if (id != 0) {
|
||||||
if (currentConversation != 0) {
|
if (currentConversation != 0) {
|
||||||
if (currentConversation->getJid() == id->name) {
|
if (currentConversation->getId() == *id) {
|
||||||
if (contact != 0) {
|
if (contact != 0) {
|
||||||
currentConversation->setPalResource(res);
|
currentConversation->setPalResource(res);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
currentConversation->deleteLater();
|
currentConversation->deleteLater();
|
||||||
}
|
}
|
||||||
@ -1168,5 +1193,16 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
|
|||||||
m_ui->filler->show();
|
m_ui->filler->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (currentConversation != 0) {
|
||||||
|
currentConversation->deleteLater();
|
||||||
|
currentConversation = 0;
|
||||||
|
m_ui->filler->show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Squawk::onContextAboutToHide()
|
||||||
|
{
|
||||||
|
m_ui->roster->selectionModel()->setCurrentIndex(restoreSelection, QItemSelectionModel::ClearAndSelect);
|
||||||
|
}
|
||||||
|
@ -125,6 +125,7 @@ private:
|
|||||||
std::deque<QString> requestedAccountsForPasswords;
|
std::deque<QString> requestedAccountsForPasswords;
|
||||||
QInputDialog* prompt;
|
QInputDialog* prompt;
|
||||||
Conversation* currentConversation;
|
Conversation* currentConversation;
|
||||||
|
QModelIndex restoreSelection;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent * event) override;
|
void closeEvent(QCloseEvent * event) override;
|
||||||
@ -155,6 +156,7 @@ private slots:
|
|||||||
void onPasswordPromptAccepted();
|
void onPasswordPromptAccepted();
|
||||||
void onPasswordPromptRejected();
|
void onPasswordPromptRejected();
|
||||||
void onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous);
|
void onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||||
|
void onContextAboutToHide();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkNextAccountForPassword();
|
void checkNextAccountForPassword();
|
||||||
|
@ -81,6 +81,12 @@
|
|||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="uniformRowHeights">
|
<property name="uniformRowHeights">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -23,18 +23,6 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
const QRegularExpression urlReg("(?<!<a\\shref=['\"])(?<!<img\\ssrc=['\"])("
|
|
||||||
"(?:https?|ftp):\\/\\/"
|
|
||||||
"\\w+"
|
|
||||||
"(?:"
|
|
||||||
"[\\w\\.\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]?"
|
|
||||||
"(?:"
|
|
||||||
"\\([\\w\\.\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]+\\)"
|
|
||||||
")?"
|
|
||||||
")*"
|
|
||||||
")");
|
|
||||||
const QRegularExpression imgReg("((?:https?|ftp)://\\S+\\.(?:jpg|jpeg|png|svg|gif))");
|
|
||||||
|
|
||||||
Message::Message(const Shared::Message& source, bool p_outgoing, const QString& p_sender, const QString& avatarPath, QWidget* parent):
|
Message::Message(const Shared::Message& source, bool p_outgoing, const QString& p_sender, const QString& avatarPath, QWidget* parent):
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
outgoing(p_outgoing),
|
outgoing(p_outgoing),
|
||||||
@ -66,12 +54,9 @@ Message::Message(const Shared::Message& source, bool p_outgoing, const QString&
|
|||||||
body->setBackgroundRole(QPalette::AlternateBase);
|
body->setBackgroundRole(QPalette::AlternateBase);
|
||||||
body->setAutoFillBackground(true);
|
body->setAutoFillBackground(true);
|
||||||
|
|
||||||
QString bd = msg.getBody();
|
QString bd = Shared::processMessageBody(msg.getBody());
|
||||||
//bd.replace(imgReg, "<img src=\"\\1\"/>");
|
|
||||||
bd.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
|
||||||
//bd.replace("\n", "<br>");
|
|
||||||
text->setTextFormat(Qt::RichText);
|
text->setTextFormat(Qt::RichText);
|
||||||
text->setText("<p style=\"white-space: pre-wrap;\">" + bd + "</p>");;
|
text->setText(bd);;
|
||||||
text->setTextInteractionFlags(text->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
|
text->setTextInteractionFlags(text->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
|
||||||
text->setWordWrap(true);
|
text->setWordWrap(true);
|
||||||
text->setOpenExternalLinks(true);
|
text->setOpenExternalLinks(true);
|
||||||
@ -308,13 +293,13 @@ bool Message::change(const QMap<QString, QVariant>& data)
|
|||||||
{
|
{
|
||||||
bool idChanged = msg.change(data);
|
bool idChanged = msg.change(data);
|
||||||
|
|
||||||
QString bd = msg.getBody();
|
QString body = msg.getBody();
|
||||||
//bd.replace(imgReg, "<img src=\"\\1\"/>");
|
QString bd = Shared::processMessageBody(body);
|
||||||
bd.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
if (body.size() > 0) {
|
||||||
text->setText(bd);
|
text->setText(bd);
|
||||||
if (bd.size() > 0) {
|
|
||||||
text->show();
|
text->show();
|
||||||
} else {
|
} else {
|
||||||
|
text->setText(body);
|
||||||
text->hide();
|
text->hide();
|
||||||
}
|
}
|
||||||
if (msg.getEdited()) {
|
if (msg.getEdited()) {
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "shared/message.h"
|
#include "shared/message.h"
|
||||||
#include "shared/icons.h"
|
#include "shared/icons.h"
|
||||||
#include "shared/global.h"
|
#include "shared/global.h"
|
||||||
|
#include "shared/utils.h"
|
||||||
#include "resizer.h"
|
#include "resizer.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "conversation.h"
|
#include "conversation.h"
|
||||||
#include "ui_conversation.h"
|
#include "ui_conversation.h"
|
||||||
#include "ui/utils/dropshadoweffect.h"
|
#include "ui/utils/dropshadoweffect.h"
|
||||||
#include "shared/icons.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
@ -308,7 +307,7 @@ void Conversation::onFileSelected()
|
|||||||
|
|
||||||
void Conversation::setStatus(const QString& status)
|
void Conversation::setStatus(const QString& status)
|
||||||
{
|
{
|
||||||
statusLabel->setText(status);
|
statusLabel->setText(Shared::processMessageBody(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Conversation::onScrollResize()
|
void Conversation::onScrollResize()
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include "ui/utils/resizer.h"
|
#include "ui/utils/resizer.h"
|
||||||
#include "ui/utils/flowlayout.h"
|
#include "ui/utils/flowlayout.h"
|
||||||
#include "ui/utils/badge.h"
|
#include "ui/utils/badge.h"
|
||||||
|
#include "shared/icons.h"
|
||||||
|
#include "shared/utils.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
|
@ -122,9 +122,24 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="statusLabel">
|
<widget class="QLabel" name="statusLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -134,9 +149,12 @@
|
|||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>0</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
Loading…
Reference in New Issue
Block a user