Fix segfault when leaving certain rooms.

square-messages
Black Hat 2018-11-07 16:29:24 +08:00
parent 6e44347efd
commit 06983a506c
12 changed files with 74 additions and 86 deletions

View File

@ -24,7 +24,7 @@ class AccountListModel : public QAbstractListModel {
void setController(Controller* value);
private:
Controller* m_controller;
Controller* m_controller = nullptr;
QVector<Connection*> m_connections;
signals:

View File

@ -40,13 +40,6 @@ Controller::Controller(QObject* parent)
QTimer::singleShot(0, this, SLOT(invokeLogin()));
}
Controller::~Controller() {
for (auto c : qAsConst(m_connections)) {
c->saveState();
c->stopSync();
}
}
inline QString accessTokenFileName(const AccountSettings& account) {
QString fileName = account.userId();
fileName.replace(':', '_');
@ -109,7 +102,10 @@ void Controller::addConnection(Connection* c) {
m_connections.push_back(c);
connect(c, &Connection::syncDone, this, [=] { c->sync(30000); });
connect(c, &Connection::syncDone, this, [=] {
c->saveState();
c->sync(30000);
});
connect(c, &Connection::loggedOut, this, [=] { dropConnection(c); });
using namespace QMatrixClient;

View File

@ -23,7 +23,7 @@ class Controller : public QObject {
public:
explicit Controller(QObject* parent = nullptr);
~Controller();
~Controller(){};
// All the Q_INVOKABLEs.
Q_INVOKABLE void loginWithCredentials(QString, QString, QString);

View File

@ -6,7 +6,7 @@
ImageItem::ImageItem(QQuickItem *parent) : QQuickPaintedItem(parent) {}
inline QString stringtoColor(QString string) {
inline static QString stringtoColor(QString string) {
int hash = 0;
for (int i = 0; i < string.length(); i++)
hash = string.at(i).unicode() + ((hash << 5) - hash);
@ -16,68 +16,64 @@ inline QString stringtoColor(QString string) {
return colour;
}
inline static QImage getImageFromPaintable(QPointer<Paintable> p, QRectF b) {
if (p.isNull()) return {};
QImage image(p->image(int(b.width()), int(b.height())));
if (image.isNull()) return {};
return image;
}
void ImageItem::paint(QPainter *painter) {
QRectF bounding_rect = boundingRect();
painter->setRenderHint(QPainter::Antialiasing, true);
if (!m_paintable) {
paintHint(painter, bounding_rect);
return;
}
QImage image = m_paintable->image(int(bounding_rect.width()),
int(bounding_rect.height()));
QImage image(getImageFromPaintable(m_paintable, bounding_rect));
if (image.isNull()) {
paintHint(painter, bounding_rect);
return;
painter->setPen(Qt::NoPen);
if (m_color.isEmpty())
painter->setBrush(QColor(stringtoColor(m_hint)));
else
painter->setBrush(QColor(m_color));
if (m_round)
painter->drawEllipse(0, 0, int(bounding_rect.width()),
int(bounding_rect.height()));
else
painter->drawRect(0, 0, int(bounding_rect.width()),
int(bounding_rect.height()));
painter->setPen(QPen(Qt::white, 2));
QFont font;
font.setStyleHint(QFont::SansSerif);
font.setPixelSize(int(bounding_rect.width() / 2));
font.setBold(true);
painter->setFont(font);
painter->drawText(
QRect(0, 0, int(bounding_rect.width()), int(bounding_rect.height())),
Qt::AlignCenter, m_hint.at(0).toUpper());
} else {
QImage scaled = image.scaled(
int(bounding_rect.width()) + 1, int(bounding_rect.height()) + 1,
Qt::KeepAspectRatioByExpanding, Qt::FastTransformation);
QPointF center = bounding_rect.center() - scaled.rect().center();
if (m_round) {
QPainterPath clip;
clip.addEllipse(
0, 0, bounding_rect.width(),
bounding_rect.height()); // this is the shape we want to clip to
painter->setClipPath(clip);
}
painter->drawImage(center, scaled);
}
QImage scaled = image.scaled(
int(bounding_rect.width()) + 1, int(bounding_rect.height()) + 1,
Qt::KeepAspectRatioByExpanding, Qt::FastTransformation);
QPointF center = bounding_rect.center() - scaled.rect().center();
if (m_round) {
QPainterPath clip;
clip.addEllipse(
0, 0, bounding_rect.width(),
bounding_rect.height()); // this is the shape we want to clip to
painter->setClipPath(clip);
}
painter->drawImage(center, scaled);
}
void ImageItem::paintHint(QPainter *painter, QRectF bounding_rect) {
painter->setPen(Qt::NoPen);
if (m_color.isEmpty())
painter->setBrush(QColor(stringtoColor(m_hint)));
else
painter->setBrush(QColor(m_color));
if (m_round)
painter->drawEllipse(0, 0, int(bounding_rect.width()),
int(bounding_rect.height()));
else
painter->drawRect(0, 0, int(bounding_rect.width()),
int(bounding_rect.height()));
painter->setPen(QPen(Qt::white, 2));
QFont font;
font.setStyleHint(QFont::SansSerif);
font.setPixelSize(int(bounding_rect.width() / 2));
font.setBold(true);
painter->setFont(font);
painter->drawText(
QRect(0, 0, int(bounding_rect.width()), int(bounding_rect.height())),
Qt::AlignCenter, m_hint.at(0).toUpper());
}
void ImageItem::setPaintable(Paintable *paintable) {
if (!paintable) return;
disconnect(m_paintable);
if (!m_paintable.isNull()) m_paintable->disconnect(this);
m_paintable = paintable;
connect(m_paintable, &Paintable::paintableChanged, this,
[=] { this->update(); });

View File

@ -1,6 +1,7 @@
#ifndef IMAGEITEM_H
#define IMAGEITEM_H
#include <QPointer>
#include <QImage>
#include <QObject>
#include <QPainter>
@ -42,12 +43,10 @@ class ImageItem : public QQuickPaintedItem {
void roundChanged();
private:
Paintable* m_paintable = nullptr;
QPointer<Paintable> m_paintable;
QString m_hint = "H";
QString m_color;
bool m_round = true;
void paintHint(QPainter* painter, QRectF bounding_rect);
};
#endif // IMAGEITEM_H

View File

@ -32,7 +32,7 @@ class ImageProvider : public QObject, public QQuickImageProvider {
private:
QReadWriteLock m_lock;
QMatrixClient::Connection* m_connection;
QMatrixClient::Connection* m_connection = nullptr;
};
#endif // IMAGEPROVIDER_H

View File

@ -23,9 +23,7 @@
using namespace QMatrixClient;
int main(int argc, char *argv[]) {
#if defined(Q_OS_WIN)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);

View File

@ -72,8 +72,6 @@ void RoomListModel::connectRoomSignals(SpectralRoom* room) {
[=] { unreadMessagesChanged(room); });
connect(room, &Room::tagsChanged, this, [=] { refresh(room); });
connect(room, &Room::joinStateChanged, this, [=] { refresh(room); });
connect(room, &Room::avatarChanged, this,
[=] { refresh(room, {PaintableRole}); });
connect(room, &Room::addedMessages, this,
[=] { refresh(room, {LastEventRole}); });
connect(room, &Room::aboutToAddNewMessages, this,

View File

@ -16,7 +16,7 @@
SpectralRoom::SpectralRoom(Connection* connection, QString roomId,
JoinState joinState)
: Room(connection, std::move(roomId), joinState) {
: Room(connection, std::move(roomId), joinState), m_paintable(this) {
connect(this, &SpectralRoom::notificationCountChanged, this,
&SpectralRoom::countChanged);
connect(this, &SpectralRoom::highlightCountChanged, this,

View File

@ -6,6 +6,7 @@
#include "spectraluser.h"
#include <QObject>
#include <QPointer>
#include <QTimer>
using namespace QMatrixClient;
@ -18,16 +19,11 @@ class RoomPaintable : public Paintable {
}
QImage image(int dimension) override {
if (!m_room) {
qDebug() << "Room is null";
return QImage();
}
if (!m_room) return QImage();
return m_room->avatar(dimension);
}
QImage image(int width, int height) override {
if (!m_room) {
return QImage();
}
if (!m_room) return QImage();
return m_room->avatar(width, height);
}
@ -52,7 +48,7 @@ class SpectralRoom : public Room {
explicit SpectralRoom(Connection* connection, QString roomId,
JoinState joinState = {});
Paintable* paintable() { return new RoomPaintable(this); }
Paintable* paintable() { return &m_paintable; }
const QString& cachedInput() const { return m_cachedInput; }
void setCachedInput(const QString& input) {
@ -110,7 +106,7 @@ class SpectralRoom : public Room {
bool m_hasFileUploading = false;
int m_fileUploadingProgress = 0;
bool m_busy;
bool m_busy = false;
QString getMIME(const QUrl& fileUrl) const;
void postFile(const QUrl& localFile, const QUrl& mxcUrl);
@ -137,6 +133,9 @@ class SpectralRoom : public Room {
void sendTypingNotification(bool isTyping);
void sendReply(QString userId, QString eventId, QString replyContent,
QString sendContent);
private:
RoomPaintable m_paintable;
};
#endif // SpectralRoom_H

View File

@ -6,15 +6,14 @@
#include "user.h"
#include <QObject>
#include <QPointer>
using namespace QMatrixClient;
class UserPaintable : public Paintable {
Q_OBJECT
public:
UserPaintable(User* parent) : Paintable(parent), m_user(parent) {
connect(m_user, &User::avatarChanged, [=] { emit paintableChanged(); });
}
UserPaintable(User* parent) : Paintable(parent), m_user(parent) {}
QImage image(int dimension) override {
if (!m_user) return QImage();
@ -34,9 +33,12 @@ class SpectralUser : public User {
Q_PROPERTY(Paintable* paintable READ paintable CONSTANT)
public:
SpectralUser(QString userId, Connection* connection)
: User(userId, connection) {}
: User(userId, connection), m_paintable(this) {}
Paintable* paintable() { return new UserPaintable(this); }
Paintable* paintable() { return &m_paintable; }
private:
UserPaintable m_paintable;
};
#endif // SpectralUser_H

View File

@ -18,9 +18,9 @@ void UserListModel::setRoom(QMatrixClient::Room* room) {
using namespace QMatrixClient;
beginResetModel();
if (m_currentRoom && m_currentRoom->connection()) {
m_currentRoom->connection()->disconnect(this);
if (m_currentRoom) {
m_currentRoom->disconnect(this);
// m_currentRoom->connection()->disconnect(this);
for (User* user : m_users) user->disconnect(this);
m_users.clear();
}