forked from blue/squawk
context menu now doesn't select items, just temporarily, statuses and messahes html wrapping fix
This commit is contained in:
parent
a77dfd191a
commit
29c7d31c89
@ -2,16 +2,18 @@
|
||||
|
||||
## Squawk 0.1.4 (UNRELEASED)
|
||||
### New features
|
||||
- message line now is in the same window with roster (new window dialog is still able to opened on double click)
|
||||
- several ways to manage your account password:
|
||||
- message line now is in the same window with roster (new window dialog is still able to opened on context menu)
|
||||
- several new ways to manage your account password:
|
||||
- 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)
|
||||
- ask the account password on each program launch
|
||||
- store it in KWallet which is dynamically loaded
|
||||
|
||||
### Bug fixes
|
||||
- never updating MUC avatars now update
|
||||
- never updating MUC avatars now get updated
|
||||
- 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)
|
||||
|
@ -27,3 +27,22 @@ QString Shared::generateUUID()
|
||||
uuid_unparse_lower(uuid, 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 <QColor>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <uuid/uuid.h>
|
||||
#include <vector>
|
||||
@ -28,6 +29,7 @@
|
||||
namespace Shared {
|
||||
|
||||
QString generateUUID();
|
||||
QString processMessageBody(const QString& msg);
|
||||
|
||||
static const std::vector<QColor> colorPalette = {
|
||||
QColor(244, 27, 63),
|
||||
|
@ -33,7 +33,8 @@ Squawk::Squawk(QWidget *parent) :
|
||||
vCards(),
|
||||
requestedAccountsForPasswords(),
|
||||
prompt(0),
|
||||
currentConversation(0)
|
||||
currentConversation(0),
|
||||
restoreSelection()
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
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->actionAddConference, &QAction::triggered, this, &Squawk::onNewConference);
|
||||
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::collapsed, this, &Squawk::onItemCollepsed);
|
||||
connect(m_ui->roster->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &Squawk::onRosterSelectionChanged);
|
||||
|
||||
connect(rosterModel.accountsModel, &Models::Accounts::sizeChanged, this, &Squawk::onAccountsSizeChanged);
|
||||
connect(contextMenu, &QMenu::aboutToHide, this, &Squawk::onContextAboutToHide);
|
||||
//m_ui->mainToolBar->addWidget(m_ui->comboBox);
|
||||
|
||||
setWindowTitle(tr("Contact list"));
|
||||
@ -1095,12 +1097,18 @@ void Squawk::subscribeConversation(Conversation* conv)
|
||||
|
||||
void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous)
|
||||
{
|
||||
if (restoreSelection.isValid() && restoreSelection == current) {
|
||||
restoreSelection = QModelIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
if (current.isValid()) {
|
||||
Models::Item* node = static_cast<Models::Item*>(current.internalPointer());
|
||||
Models::Contact* contact = 0;
|
||||
Models::Room* room = 0;
|
||||
QString res;
|
||||
Models::Roster::ElId* id = 0;
|
||||
bool hasContext = true;
|
||||
switch (node->type) {
|
||||
case Models::Item::contact:
|
||||
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());
|
||||
id = new Models::Roster::ElId(contact->getAccountName(), contact->getJid());
|
||||
res = node->getName();
|
||||
hasContext = false;
|
||||
break;
|
||||
case Models::Item::room:
|
||||
room = static_cast<Models::Room*>(node);
|
||||
id = new Models::Roster::ElId(room->getAccountName(), room->getJid());
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasContext && QGuiApplication::mouseButtons() & Qt::RightButton) {
|
||||
if (id != 0) {
|
||||
delete id;
|
||||
}
|
||||
restoreSelection = previous;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id != 0) {
|
||||
if (currentConversation != 0) {
|
||||
if (currentConversation->getJid() == id->name) {
|
||||
if (currentConversation->getId() == *id) {
|
||||
if (contact != 0) {
|
||||
currentConversation->setPalResource(res);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
currentConversation->deleteLater();
|
||||
}
|
||||
@ -1168,5 +1193,16 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
|
||||
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;
|
||||
QInputDialog* prompt;
|
||||
Conversation* currentConversation;
|
||||
QModelIndex restoreSelection;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent * event) override;
|
||||
@ -155,6 +156,7 @@ private slots:
|
||||
void onPasswordPromptAccepted();
|
||||
void onPasswordPromptRejected();
|
||||
void onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||
void onContextAboutToHide();
|
||||
|
||||
private:
|
||||
void checkNextAccountForPassword();
|
||||
|
@ -81,6 +81,12 @@
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -23,18 +23,6 @@
|
||||
#include <QFileInfo>
|
||||
#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):
|
||||
QWidget(parent),
|
||||
outgoing(p_outgoing),
|
||||
@ -66,12 +54,9 @@ Message::Message(const Shared::Message& source, bool p_outgoing, const QString&
|
||||
body->setBackgroundRole(QPalette::AlternateBase);
|
||||
body->setAutoFillBackground(true);
|
||||
|
||||
QString bd = msg.getBody();
|
||||
//bd.replace(imgReg, "<img src=\"\\1\"/>");
|
||||
bd.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
||||
//bd.replace("\n", "<br>");
|
||||
QString bd = Shared::processMessageBody(msg.getBody());
|
||||
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->setWordWrap(true);
|
||||
text->setOpenExternalLinks(true);
|
||||
@ -308,13 +293,13 @@ bool Message::change(const QMap<QString, QVariant>& data)
|
||||
{
|
||||
bool idChanged = msg.change(data);
|
||||
|
||||
QString bd = msg.getBody();
|
||||
//bd.replace(imgReg, "<img src=\"\\1\"/>");
|
||||
bd.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
||||
text->setText(bd);
|
||||
if (bd.size() > 0) {
|
||||
QString body = msg.getBody();
|
||||
QString bd = Shared::processMessageBody(body);
|
||||
if (body.size() > 0) {
|
||||
text->setText(bd);
|
||||
text->show();
|
||||
} else {
|
||||
text->setText(body);
|
||||
text->hide();
|
||||
}
|
||||
if (msg.getEdited()) {
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "shared/message.h"
|
||||
#include "shared/icons.h"
|
||||
#include "shared/global.h"
|
||||
#include "shared/utils.h"
|
||||
#include "resizer.h"
|
||||
#include "image.h"
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "conversation.h"
|
||||
#include "ui_conversation.h"
|
||||
#include "ui/utils/dropshadoweffect.h"
|
||||
#include "shared/icons.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QScrollBar>
|
||||
@ -308,7 +307,7 @@ void Conversation::onFileSelected()
|
||||
|
||||
void Conversation::setStatus(const QString& status)
|
||||
{
|
||||
statusLabel->setText(status);
|
||||
statusLabel->setText(Shared::processMessageBody(status));
|
||||
}
|
||||
|
||||
void Conversation::onScrollResize()
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "ui/utils/resizer.h"
|
||||
#include "ui/utils/flowlayout.h"
|
||||
#include "ui/utils/badge.h"
|
||||
#include "shared/icons.h"
|
||||
#include "shared/utils.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
@ -122,9 +122,24 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
@ -134,9 +149,12 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
|
Loading…
Reference in New Issue
Block a user