context menu now doesn't select items, just temporarily, statuses and messahes html wrapping fix

This commit is contained in:
Blue 2020-04-12 18:55:05 +03:00
parent a77dfd191a
commit 29c7d31c89
11 changed files with 104 additions and 32 deletions

View File

@ -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)

View File

@ -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>";
}

View File

@ -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),

View File

@ -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"));
@ -1094,13 +1096,19 @@ 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);
}

View File

@ -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();

View File

@ -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>

View File

@ -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()) {

View File

@ -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"

View File

@ -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()

View File

@ -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
{

View File

@ -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>