1
0
forked from blue/squawk

first compiling prototype, doesnt work yet

This commit is contained in:
Blue 2020-08-12 01:49:51 +03:00
parent ef1a9846bf
commit 38159eafeb
21 changed files with 662 additions and 734 deletions

View File

@ -9,6 +9,10 @@ set(CMAKE_AUTOUIC ON)
# Find the QtWidgets library
find_package(Qt5Widgets CONFIG REQUIRED)
find_package(Qt5DBus CONFIG REQUIRED)
find_package(Boost 1.36.0 CONFIG REQUIRED)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
add_subdirectory(widgets)
@ -25,6 +29,8 @@ set(squawkUI_SRC
models/abstractparticipant.cpp
models/participant.cpp
models/reference.cpp
models/messagefeed.cpp
models/element.cpp
utils/messageline.cpp
utils//message.cpp
utils/resizer.cpp

View File

@ -17,55 +17,26 @@
*/
#include "contact.h"
#include "account.h"
#include <QDebug>
Models::Contact::Contact(const Account* acc, const QString& p_jid ,const QMap<QString, QVariant> &data, Item *parentItem):
Item(Item::contact, data, parentItem),
jid(p_jid),
Element(Item::contact, acc, p_jid, data, parentItem),
availability(Shared::Availability::offline),
state(Shared::SubscriptionState::none),
avatarState(Shared::Avatar::empty),
presences(),
messages(),
childMessages(0),
status(),
avatarPath(),
account(acc)
status()
{
QMap<QString, QVariant>::const_iterator itr = data.find("state");
if (itr != data.end()) {
setState(itr.value().toUInt());
}
itr = data.find("avatarState");
if (itr != data.end()) {
setAvatarState(itr.value().toUInt());
}
itr = data.find("avatarPath");
if (itr != data.end()) {
setAvatarPath(itr.value().toString());
}
}
Models::Contact::~Contact()
{
}
QString Models::Contact::getJid() const
{
return jid;
}
void Models::Contact::setJid(const QString p_jid)
{
if (jid != p_jid) {
jid = p_jid;
changed(1);
}
}
void Models::Contact::setAvailability(unsigned int p_state)
{
setAvailability(Shared::Global::fromInt<Shared::Availability>(p_state));
@ -144,16 +115,12 @@ void Models::Contact::update(const QString& field, const QVariant& value)
{
if (field == "name") {
setName(value.toString());
} else if (field == "jid") {
setJid(value.toString());
} else if (field == "availability") {
setAvailability(value.toUInt());
} else if (field == "state") {
setState(value.toUInt());
} else if (field == "avatarState") {
setAvatarState(value.toUInt());
} else if (field == "avatarPath") {
setAvatarPath(value.toString());
} else {
Element::update(field, value);
}
}
@ -192,11 +159,9 @@ void Models::Contact::refresh()
{
QDateTime lastActivity;
Presence* presence = 0;
unsigned int count = 0;
for (QMap<QString, Presence*>::iterator itr = presences.begin(), end = presences.end(); itr != end; ++itr) {
Presence* pr = itr.value();
QDateTime la = pr->getLastActivity();
count += pr->getMessagesCount();
if (la > lastActivity) {
lastActivity = la;
@ -211,11 +176,6 @@ void Models::Contact::refresh()
setAvailability(Shared::Availability::offline);
setStatus("");
}
if (childMessages != count) {
childMessages = count;
changed(4);
}
}
void Models::Contact::_removeChild(int index)
@ -257,81 +217,6 @@ QIcon Models::Contact::getStatusIcon(bool big) const
}
}
void Models::Contact::addMessage(const Shared::Message& data)
{
const QString& res = data.getPenPalResource();
if (res.size() > 0) {
QMap<QString, Presence*>::iterator itr = presences.find(res);
if (itr == presences.end()) {
// this is actually the place when I can spot someone's invisible presence, and there is nothing criminal in it, cuz the sender sent us a message
// therefore he have revealed himself
// the only issue is to find out when the sender is gone offline
Presence* pr = new Presence({});
pr->setName(res);
pr->setAvailability(Shared::Availability::invisible);
pr->setLastActivity(QDateTime::currentDateTimeUtc());
presences.insert(res, pr);
appendChild(pr);
pr->addMessage(data);
return;
}
itr.value()->addMessage(data);
} else {
messages.emplace_back(data);
changed(4);
}
}
void Models::Contact::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
bool found = false;
for (Shared::Message& msg : messages) {
if (msg.getId() == id) {
msg.change(data);
found = true;
break;
}
}
if (!found) {
for (Presence* pr : presences) {
found = pr->changeMessage(id, data);
if (found) {
break;
}
}
}
}
unsigned int Models::Contact::getMessagesCount() const
{
return messages.size() + childMessages;
}
void Models::Contact::dropMessages()
{
if (messages.size() > 0) {
messages.clear();
changed(4);
}
for (QMap<QString, Presence*>::iterator itr = presences.begin(), end = presences.end(); itr != end; ++itr) {
itr.value()->dropMessages();
}
}
void Models::Contact::getMessages(Models::Contact::Messages& container) const
{
for (Messages::const_iterator itr = messages.begin(), end = messages.end(); itr != end; ++itr) {
const Shared::Message& msg = *itr;
container.push_back(msg);
}
for (QMap<QString, Presence*>::const_iterator itr = presences.begin(), end = presences.end(); itr != end; ++itr) {
itr.value()->getMessages(container);
}
}
void Models::Contact::toOfflineState()
{
std::deque<Item*>::size_type size = childItems.size();
@ -355,75 +240,3 @@ QString Models::Contact::getDisplayedName() const
return getContactName();
}
bool Models::Contact::columnInvolvedInDisplay(int col)
{
return Item::columnInvolvedInDisplay(col) && col == 1;
}
Models::Contact * Models::Contact::copy() const
{
Contact* cnt = new Contact(*this);
return cnt;
}
Models::Contact::Contact(const Models::Contact& other):
Item(other),
jid(other.jid),
availability(other.availability),
state(other.state),
presences(),
messages(other.messages),
childMessages(0),
account(other.account)
{
for (const Presence* pres : other.presences) {
Presence* pCopy = new Presence(*pres);
presences.insert(pCopy->getName(), pCopy);
Item::appendChild(pCopy);
connect(pCopy, &Item::childChanged, this, &Contact::refresh);
}
refresh();
}
QString Models::Contact::getAvatarPath() const
{
return avatarPath;
}
Shared::Avatar Models::Contact::getAvatarState() const
{
return avatarState;
}
void Models::Contact::setAvatarPath(const QString& path)
{
if (path != avatarPath) {
avatarPath = path;
changed(7);
}
}
void Models::Contact::setAvatarState(Shared::Avatar p_state)
{
if (avatarState != p_state) {
avatarState = p_state;
changed(6);
}
}
void Models::Contact::setAvatarState(unsigned int p_state)
{
if (p_state <= static_cast<quint8>(Shared::Avatar::valid)) {
Shared::Avatar state = static_cast<Shared::Avatar>(p_state);
setAvatarState(state);
} else {
qDebug() << "An attempt to set invalid avatar state" << p_state << "to the contact" << jid << ", skipping";
}
}
const Models::Account * Models::Contact::getParentAccount() const
{
return account;
}

View File

@ -19,7 +19,7 @@
#ifndef MODELS_CONTACT_H
#define MODELS_CONTACT_H
#include "item.h"
#include "element.h"
#include "presence.h"
#include "shared/enums.h"
#include "shared/message.h"
@ -31,49 +31,34 @@
#include <deque>
namespace Models {
class Account;
class Contact : public Item
class Contact : public Element
{
Q_OBJECT
public:
typedef std::deque<Shared::Message> Messages;
Contact(const Account* acc, const QString& p_jid, const QMap<QString, QVariant> &data, Item *parentItem = 0);
Contact(const Contact& other);
~Contact();
QString getJid() const;
Shared::Availability getAvailability() const;
Shared::SubscriptionState getState() const;
Shared::Avatar getAvatarState() const;
QString getAvatarPath() const;
QIcon getStatusIcon(bool big = false) const;
int columnCount() const override;
QVariant data(int column) const override;
void update(const QString& field, const QVariant& value);
void update(const QString& field, const QVariant& value) override;
void addPresence(const QString& name, const QMap<QString, QVariant>& data);
void removePresence(const QString& name);
QString getContactName() const;
QString getStatus() const;
void addMessage(const Shared::Message& data);
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
unsigned int getMessagesCount() const;
void dropMessages();
void getMessages(Messages& container) const;
QString getDisplayedName() const override;
Contact* copy() const;
protected:
void _removeChild(int index) override;
void _appendChild(Models::Item * child) override;
bool columnInvolvedInDisplay(int col) override;
const Account* getParentAccount() const override;
protected slots:
void refresh();
@ -84,23 +69,13 @@ protected:
void setAvailability(unsigned int p_state);
void setState(Shared::SubscriptionState p_state);
void setState(unsigned int p_state);
void setAvatarState(Shared::Avatar p_state);
void setAvatarState(unsigned int p_state);
void setAvatarPath(const QString& path);
void setJid(const QString p_jid);
void setStatus(const QString& p_state);
private:
QString jid;
Shared::Availability availability;
Shared::SubscriptionState state;
Shared::Avatar avatarState;
QMap<QString, Presence*> presences;
Messages messages;
unsigned int childMessages;
QString status;
QString avatarPath;
const Account* account;
};
}

151
ui/models/element.cpp Normal file
View File

@ -0,0 +1,151 @@
/*
* 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 "element.h"
#include "account.h"
#include <QDebug>
Models::Element::Element(Type p_type, const Models::Account* acc, const QString& p_jid, const QMap<QString, QVariant>& data, Models::Item* parentItem):
Item(p_type, data, parentItem),
jid(p_jid),
avatarPath(),
avatarState(Shared::Avatar::empty),
account(acc),
feed(new MessageFeed())
{
connect(feed, &MessageFeed::requestArchive, this, &Element::requestArchive);
QMap<QString, QVariant>::const_iterator itr = data.find("avatarState");
if (itr != data.end()) {
setAvatarState(itr.value().toUInt());
}
itr = data.find("avatarPath");
if (itr != data.end()) {
setAvatarPath(itr.value().toString());
}
}
Models::Element::~Element()
{
delete feed;
}
QString Models::Element::getJid() const
{
return jid;
}
void Models::Element::setJid(const QString& p_jid)
{
if (jid != p_jid) {
jid = p_jid;
changed(1);
}
}
void Models::Element::update(const QString& field, const QVariant& value)
{
if (field == "jid") {
setJid(value.toString());
} else if (field == "avatarState") {
setAvatarState(value.toUInt());
} else if (field == "avatarPath") {
setAvatarPath(value.toString());
}
}
QString Models::Element::getAvatarPath() const
{
return avatarPath;
}
Shared::Avatar Models::Element::getAvatarState() const
{
return avatarState;
}
void Models::Element::setAvatarPath(const QString& path)
{
if (path != avatarPath) {
avatarPath = path;
if (type == contact) {
changed(7);
} else if (type == room) {
changed(8);
}
}
}
void Models::Element::setAvatarState(Shared::Avatar p_state)
{
if (avatarState != p_state) {
avatarState = p_state;
if (type == contact) {
changed(6);
} else if (type == room) {
changed(7);
}
}
}
void Models::Element::setAvatarState(unsigned int p_state)
{
if (p_state <= static_cast<quint8>(Shared::Avatar::valid)) {
Shared::Avatar state = static_cast<Shared::Avatar>(p_state);
setAvatarState(state);
} else {
qDebug() << "An attempt to set invalid avatar state" << p_state << "to the element" << jid << ", skipping";
}
}
bool Models::Element::columnInvolvedInDisplay(int col)
{
return Item::columnInvolvedInDisplay(col) && col == 1;
}
const Models::Account * Models::Element::getParentAccount() const
{
return account;
}
unsigned int Models::Element::getMessagesCount() const
{
return feed->unreadMessagesCount();
}
void Models::Element::addMessage(const Shared::Message& data)
{
feed->addMessage(data);
if (type == contact) {
changed(4);
} else if (type == room) {
changed(5);
}
}
void Models::Element::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
}
void Models::Element::responseArchive(const std::list<Shared::Message> list)
{
feed->responseArchive(list);
}

70
ui/models/element.h Normal file
View File

@ -0,0 +1,70 @@
/*
* 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 ELEMENT_H
#define ELEMENT_H
#include "item.h"
#include "messagefeed.h"
namespace Models {
class Element : public Item
{
Q_OBJECT
protected:
Element(Type p_type, const Account* acc, const QString& p_jid, const QMap<QString, QVariant> &data, Item *parentItem = 0);
~Element();
public:
QString getJid() const;
Shared::Avatar getAvatarState() const;
QString getAvatarPath() const;
virtual void update(const QString& field, const QVariant& value);
void addMessage(const Shared::Message& data);
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
unsigned int getMessagesCount() const;
void responseArchive(const std::list<Shared::Message> list);
signals:
void requestArchive(const QString& before);
protected:
void setJid(const QString& p_jid);
void setAvatarState(Shared::Avatar p_state);
void setAvatarState(unsigned int p_state);
void setAvatarPath(const QString& path);
bool columnInvolvedInDisplay(int col) override;
const Account* getParentAccount() const override;
protected:
QString jid;
QString avatarPath;
Shared::Avatar avatarState;
const Account* account;
public:
MessageFeed* feed;
};
}
#endif // ELEMENT_H

145
ui/models/messagefeed.cpp Normal file
View File

@ -0,0 +1,145 @@
/*
* 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 "messagefeed.h"
#include <QDebug>
MessageFeed::MessageFeed(QObject* parent):
QAbstractListModel(parent),
storage(),
indexById(storage.get<id>()),
indexByTime(storage.get<time>()),
syncState(incomplete)
{
}
MessageFeed::~MessageFeed()
{
for (Shared::Message* message : storage) {
delete message;
}
}
void MessageFeed::addMessage(const Shared::Message& msg)
{
QString id = msg.getId();
StorageById::const_iterator itr = indexById.find(id);
if (itr != indexById.end()) {
qDebug() << "received more then one message with the same id, skipping yet the new one";
return;
}
Shared::Message* copy = new Shared::Message(msg);
StorageByTime::const_iterator tItr = indexByTime.upper_bound(msg.getTime());
int position;
if (tItr == indexByTime.end()) {
position = storage.size();
} else {
position = indexByTime.rank(tItr);
}
beginInsertRows(QModelIndex(), position, position);
storage.insert(copy);
endInsertRows();
}
void MessageFeed::changeMessage(const QString& id, const Shared::Message& msg)
{
}
void MessageFeed::removeMessage(const QString& id)
{
}
QVariant MessageFeed::data(const QModelIndex& index, int role) const
{
int i = index.row();
if (syncState == syncing) {
--i;
}
QVariant answer;
switch (role) {
case Qt::DisplayRole: {
if (i == -1) {
return "Loading...";
}
StorageByTime::const_iterator itr = indexByTime.nth(i);
if (itr != indexByTime.end()) {
const Shared::Message* msg = *itr;
answer = msg->getFrom() + ": " + msg->getBody();
}
}
break;
default:
break;
}
return answer;
}
int MessageFeed::rowCount(const QModelIndex& parent) const
{
int count = storage.size();
if (syncState == syncing) {
count++;
}
return count;
}
unsigned int MessageFeed::unreadMessagesCount() const
{
return storage.size(); //let's say they are all new for now =)
}
bool MessageFeed::canFetchMore(const QModelIndex& parent) const
{
return syncState == incomplete;
}
void MessageFeed::fetchMore(const QModelIndex& parent)
{
if (syncState == incomplete) {
beginInsertRows(QModelIndex(), 0, 0);
syncState = syncing;
endInsertRows();
if (storage.size() == 0) {
emit requestArchive("");
} else {
emit requestArchive((*indexByTime.nth(0))->getId());
}
}
}
void MessageFeed::responseArchive(const std::list<Shared::Message> list)
{
if (syncState == syncing) {
beginRemoveRows(QModelIndex(), 0, 0);
syncState = incomplete;
endRemoveRows();
}
beginInsertRows(QModelIndex(), 0, list.size() - 1);
for (const Shared::Message& msg : list) {
Shared::Message* copy = new Shared::Message(msg);
storage.insert(copy);
}
endInsertRows();
}

100
ui/models/messagefeed.h Normal file
View File

@ -0,0 +1,100 @@
/*
* 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 MESSAGEFEED_H
#define MESSAGEFEED_H
#include <QAbstractListModel>
#include <QDateTime>
#include <QString>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/ranked_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <shared/message.h>
class MessageFeed : public QAbstractListModel
{
Q_OBJECT
public:
MessageFeed(QObject *parent = nullptr);
~MessageFeed();
void addMessage(const Shared::Message& msg);
void changeMessage(const QString& id, const Shared::Message& msg);
void removeMessage(const QString& id);
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
bool canFetchMore(const QModelIndex & parent) const override;
void fetchMore(const QModelIndex & parent) override;
void responseArchive(const std::list<Shared::Message> list);
unsigned int unreadMessagesCount() const;
signals:
void requestArchive(const QString& before);
private:
enum SyncState {
incomplete,
syncing,
complete
};
//tags
struct id {};
struct time {};
typedef boost::multi_index_container<
Shared::Message*,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::tag<id>,
boost::multi_index::const_mem_fun<
Shared::Message,
QString,
&Shared::Message::getId
>
>,
boost::multi_index::ranked_non_unique<
boost::multi_index::tag<time>,
boost::multi_index::const_mem_fun<
Shared::Message,
QDateTime,
&Shared::Message::getTime
>
>
>
> Storage;
typedef Storage::index<id>::type StorageById;
typedef Storage::index<time>::type StorageByTime;
Storage storage;
StorageById& indexById;
StorageByTime& indexByTime;
SyncState syncState;
};
#endif // MESSAGEFEED_H

View File

@ -20,82 +20,15 @@
#include "shared/icons.h"
Models::Presence::Presence(const QMap<QString, QVariant>& data, Item* parentItem):
AbstractParticipant(Item::presence, data, parentItem),
messages()
AbstractParticipant(Item::presence, data, parentItem)
{
}
Models::Presence::Presence(const Models::Presence& other):
AbstractParticipant(other),
messages(other.messages)
{
}
Models::Presence::~Presence()
{
}
int Models::Presence::columnCount() const
{
return 5;
}
QVariant Models::Presence::data(int column) const
{
switch (column) {
case 4:
return getMessagesCount();
default:
return AbstractParticipant::data(column);
}
}
unsigned int Models::Presence::getMessagesCount() const
{
return messages.size();
}
void Models::Presence::addMessage(const Shared::Message& data)
{
messages.emplace_back(data);
changed(4);
}
bool Models::Presence::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
bool found = false;
for (Shared::Message& msg : messages) {
if (msg.getId() == id) {
msg.change(data);
found = true;
break;
}
}
return found;
}
void Models::Presence::dropMessages()
{
if (messages.size() > 0) {
messages.clear();
changed(4);
}
}
QIcon Models::Presence::getStatusIcon(bool big) const
{
if (getMessagesCount() > 0) {
return Shared::icon("mail-message", big);
} else {
return AbstractParticipant::getStatusIcon();
}
}
void Models::Presence::getMessages(Models::Presence::Messages& container) const
{
for (Messages::const_iterator itr = messages.begin(), end = messages.end(); itr != end; ++itr) {
const Shared::Message& msg = *itr;
container.push_back(msg);
}
return 4;
}

View File

@ -32,25 +32,10 @@ class Presence : public Models::AbstractParticipant
{
Q_OBJECT
public:
typedef std::deque<Shared::Message> Messages;
explicit Presence(const QMap<QString, QVariant> &data, Item *parentItem = 0);
Presence(const Presence& other);
~Presence();
int columnCount() const override;
QVariant data(int column) const override;
QIcon getStatusIcon(bool big = false) const override;
unsigned int getMessagesCount() const;
void dropMessages();
void addMessage(const Shared::Message& data);
bool changeMessage(const QString& id, const QMap<QString, QVariant>& data);
void getMessages(Messages& container) const;
private:
Messages messages;
};
}

View File

@ -22,16 +22,12 @@
#include <QIcon>
#include <QDebug>
Models::Room::Room(const QString& p_jid, const QMap<QString, QVariant>& data, Models::Item* parentItem):
Item(room, data, parentItem),
Models::Room::Room(const Account* acc, const QString& p_jid, const QMap<QString, QVariant>& data, Models::Item* parentItem):
Element(room, acc, p_jid, data, parentItem),
autoJoin(false),
joined(false),
jid(p_jid),
nick(""),
subject(""),
avatarState(Shared::Avatar::empty),
avatarPath(""),
messages(),
participants(),
exParticipantAvatars()
{
@ -55,16 +51,6 @@ Models::Room::Room(const QString& p_jid, const QMap<QString, QVariant>& data, Mo
setSubject(itr.value().toString());
}
itr = data.find("avatarState");
if (itr != data.end()) {
setAvatarState(itr.value().toUInt());
}
itr = data.find("avatarPath");
if (itr != data.end()) {
setAvatarPath(itr.value().toString());
}
itr = data.find("avatars");
if (itr != data.end()) {
QMap<QString, QVariant> avs = itr.value().toMap();
@ -78,21 +64,11 @@ Models::Room::~Room()
{
}
unsigned int Models::Room::getUnreadMessagesCount() const
{
return messages.size();
}
int Models::Room::columnCount() const
{
return 7;
}
QString Models::Room::getJid() const
{
return jid;
}
bool Models::Room::getAutoJoin() const
{
return autoJoin;
@ -151,14 +127,6 @@ void Models::Room::setAutoJoin(bool p_autoJoin)
}
}
void Models::Room::setJid(const QString& p_jid)
{
if (jid != p_jid) {
jid = p_jid;
changed(1);
}
}
void Models::Room::setJoined(bool p_joined)
{
if (joined != p_joined) {
@ -182,8 +150,6 @@ void Models::Room::update(const QString& field, const QVariant& value)
{
if (field == "name") {
setName(value.toString());
} else if (field == "jid") {
setJid(value.toString());
} else if (field == "joined") {
setJoined(value.toBool());
} else if (field == "autoJoin") {
@ -192,16 +158,14 @@ void Models::Room::update(const QString& field, const QVariant& value)
setNick(value.toString());
} else if (field == "subject") {
setSubject(value.toString());
} else if (field == "avatarState") {
setAvatarState(value.toUInt());
} else if (field == "avatarPath") {
setAvatarPath(value.toString());
} else {
Element::update(field, value);
}
}
QIcon Models::Room::getStatusIcon(bool big) const
{
if (messages.size() > 0) {
if (getMessagesCount() > 0) {
return Shared::icon("mail-message", big);
} else {
if (autoJoin) {
@ -237,42 +201,6 @@ QString Models::Room::getStatusText() const
}
}
unsigned int Models::Room::getMessagesCount() const
{
return messages.size();
}
void Models::Room::addMessage(const Shared::Message& data)
{
messages.emplace_back(data);
changed(5);
}
void Models::Room::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
for (Shared::Message& msg : messages) {
if (msg.getId() == id) {
msg.change(data);
break;
}
}
}
void Models::Room::dropMessages()
{
if (messages.size() > 0) {
messages.clear();
changed(5);
}
}
void Models::Room::getMessages(Models::Room::Messages& container) const
{
for (Messages::const_iterator itr = messages.begin(), end = messages.end(); itr != end; ++itr) {
const Shared::Message& msg = *itr;
container.push_back(msg);
}
}
void Models::Room::toOfflineState()
{
@ -367,47 +295,6 @@ QString Models::Room::getDisplayedName() const
return getRoomName();
}
bool Models::Room::columnInvolvedInDisplay(int col)
{
return Item::columnInvolvedInDisplay(col) && col == 1;
}
QString Models::Room::getAvatarPath() const
{
return avatarPath;
}
Shared::Avatar Models::Room::getAvatarState() const
{
return avatarState;
}
void Models::Room::setAvatarPath(const QString& path)
{
if (avatarPath != path) {
avatarPath = path;
changed(8);
}
}
void Models::Room::setAvatarState(Shared::Avatar p_state)
{
if (avatarState != p_state) {
avatarState = p_state;
changed(7);
}
}
void Models::Room::setAvatarState(unsigned int p_state)
{
if (p_state <= static_cast<quint8>(Shared::Avatar::valid)) {
Shared::Avatar state = static_cast<Shared::Avatar>(p_state);
setAvatarState(state);
} else {
qDebug() << "An attempt to set invalid avatar state" << p_state << "to the room" << jid << ", skipping";
}
}
std::map<QString, const Models::Participant &> Models::Room::getParticipants() const
{
std::map<QString, const Models::Participant&> result;

View File

@ -19,7 +19,7 @@
#ifndef MODELS_ROOM_H
#define MODELS_ROOM_H
#include "item.h"
#include "element.h"
#include "participant.h"
#include "shared/enums.h"
#include "shared/message.h"
@ -29,21 +29,18 @@ namespace Models {
/**
* @todo write docs
*/
class Room : public Models::Item
class Room : public Element
{
Q_OBJECT
public:
typedef std::deque<Shared::Message> Messages;
Room(const QString& p_jid, const QMap<QString, QVariant> &data, Item *parentItem = 0);
Room(const Account* acc, const QString& p_jid, const QMap<QString, QVariant> &data, Item *parentItem = 0);
~Room();
int columnCount() const override;
QVariant data(int column) const override;
unsigned int getUnreadMessagesCount() const;
bool getJoined() const;
bool getAutoJoin() const;
QString getJid() const;
QString getNick() const;
QString getRoomName() const;
QString getSubject() const;
@ -53,17 +50,10 @@ public:
void setJoined(bool p_joined);
void setAutoJoin(bool p_autoJoin);
void setJid(const QString& p_jid);
void setNick(const QString& p_nick);
void setSubject(const QString& sub);
void update(const QString& field, const QVariant& value);
void addMessage(const Shared::Message& data);
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
unsigned int getMessagesCount() const;
void dropMessages();
void getMessages(Messages& container) const;
void update(const QString& field, const QVariant& value) override;
void addParticipant(const QString& name, const QMap<QString, QVariant>& data);
void changeParticipant(const QString& name, const QMap<QString, QVariant>& data);
@ -71,8 +61,6 @@ public:
void toOfflineState() override;
QString getDisplayedName() const override;
Shared::Avatar getAvatarState() const;
QString getAvatarPath() const;
std::map<QString, const Participant&> getParticipants() const;
QString getParticipantIconPath(const QString& name) const;
std::map<QString, QString> getExParticipantAvatars() const;
@ -84,24 +72,14 @@ signals:
private:
void handleParticipantUpdate(std::map<QString, Participant*>::const_iterator itr, const QMap<QString, QVariant>& data);
protected:
bool columnInvolvedInDisplay(int col) override;
void setAvatarState(Shared::Avatar p_state);
void setAvatarState(unsigned int p_state);
void setAvatarPath(const QString& path);
private:
bool autoJoin;
bool joined;
QString jid;
QString nick;
QString subject;
Shared::Avatar avatarState;
QString avatarPath;
Messages messages;
std::map<QString, Participant*> participants;
std::map<QString, QString> exParticipantAvatars;
};
}

View File

@ -215,11 +215,7 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
break;
case Item::presence: {
Presence* contact = static_cast<Presence*>(item);
QString str("");
int mc = contact->getMessagesCount();
if (mc > 0) {
str += tr("New messages: ") + std::to_string(mc).c_str() + "\n";
}
QString str;
Shared::Availability av = contact->getAvailability();
str += tr("Availability: ") + Shared::Global::getName(av);
QString s = contact->getStatus();
@ -232,7 +228,7 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
break;
case Item::participant: {
Participant* p = static_cast<Participant*>(item);
QString str("");
QString str;
Shared::Availability av = p->getAvailability();
str += tr("Availability: ") + Shared::Global::getName(av) + "\n";
QString s = p->getStatus();
@ -260,7 +256,7 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
break;
case Item::room: {
Room* rm = static_cast<Room*>(item);
unsigned int count = rm->getUnreadMessagesCount();
unsigned int count = rm->getMessagesCount();
QString str("");
if (count > 0) {
str += tr("New messages: ") + std::to_string(count).c_str() + "\n";
@ -450,6 +446,7 @@ void Models::Roster::addContact(const QString& account, const QString& jid, cons
std::map<ElId, Contact*>::iterator itr = contacts.find(id);
if (itr == contacts.end()) {
contact = new Contact(acc, jid, data);
connect(contact, &Contact::requestArchive, this, &Roster::onElementRequestArchive);
contacts.insert(std::make_pair(id, contact));
} else {
contact = itr->second;
@ -720,20 +717,6 @@ void Models::Roster::addMessage(const QString& account, const Shared::Message& d
}
}
void Models::Roster::dropMessages(const QString& account, const QString& jid)
{
ElId id(account, jid);
std::map<ElId, Contact*>::iterator itr = contacts.find(id);
if (itr != contacts.end()) {
itr->second->dropMessages();
} else {
std::map<ElId, Room*>::const_iterator rItr = rooms.find(id);
if (rItr != rooms.end()) {
rItr->second->dropMessages();
}
}
}
void Models::Roster::removeAccount(const QString& account)
{
std::map<QString, Account*>::const_iterator itr = accounts.find(account);
@ -821,7 +804,8 @@ void Models::Roster::addRoom(const QString& account, const QString jid, const QM
return;
}
Room* room = new Room(jid, data);
Room* room = new Room(acc, jid, data);
connect(room, &Contact::requestArchive, this, &Roster::onElementRequestArchive);
rooms.insert(std::make_pair(id, room));
acc->appendChild(room);
}
@ -974,3 +958,23 @@ QModelIndex Models::Roster::getGroupIndex(const QString& account, const QString&
}
}
}
void Models::Roster::onElementRequestArchive(const QString& before)
{
Element* el = static_cast<Element*>(sender());
emit requestArchive(el->getAccountName(), el->getJid(), before);
}
void Models::Roster::responseArchive(const QString& account, const QString& jid, const std::list<Shared::Message>& list)
{
ElId id(account, jid);
std::map<ElId, Contact*>::iterator itr = contacts.find(id);
if (itr != contacts.end()) {
itr->second->responseArchive(list);
} else {
std::map<ElId, Room*>::const_iterator rItr = rooms.find(id);
if (rItr != rooms.end()) {
rItr->second->responseArchive(list);
}
}
}

View File

@ -58,7 +58,6 @@ public:
void removePresence(const QString& account, const QString& jid, const QString& name);
void addMessage(const QString& account, const Shared::Message& data);
void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
void dropMessages(const QString& account, const QString& jid);
void addRoom(const QString& account, const QString jid, const QMap<QString, QVariant>& data);
void changeRoom(const QString& account, const QString jid, const QMap<QString, QVariant>& data);
void removeRoom(const QString& account, const QString jid);
@ -81,9 +80,13 @@ public:
Account* getAccount(const QString& name);
QModelIndex getAccountIndex(const QString& name);
QModelIndex getGroupIndex(const QString& account, const QString& name);
void responseArchive(const QString& account, const QString& jid, const std::list<Shared::Message>& list);
Accounts* accountsModel;
signals:
void requestArchive(const QString& account, const QString& jid, const QString& before);
private:
Item* root;
std::map<QString, Account*> accounts;
@ -100,6 +103,7 @@ private slots:
void onChildRemoved();
void onChildIsAboutToBeMoved(Item* source, int first, int last, Item* destination, int newIndex);
void onChildMoved();
void onElementRequestArchive(const QString& before);
public:
class ElId {

View File

@ -62,6 +62,7 @@ Squawk::Squawk(QWidget *parent) :
connect(m_ui->roster->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &Squawk::onRosterSelectionChanged);
connect(rosterModel.accountsModel, &Models::Accounts::sizeChanged, this, &Squawk::onAccountsSizeChanged);
connect(&rosterModel, &Models::Roster::requestArchive, this, &Squawk::onConversationRequestArchive);
connect(contextMenu, &QMenu::aboutToHide, this, &Squawk::onContextAboutToHide);
//m_ui->mainToolBar->addWidget(m_ui->comboBox);
@ -336,17 +337,14 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
Models::Account* acc = rosterModel.getAccount(id->account);
Conversation* conv = 0;
bool created = false;
Models::Contact::Messages deque;
if (itr != conversations.end()) {
conv = itr->second;
} else if (contact != 0) {
created = true;
conv = new Chat(acc, contact);
contact->getMessages(deque);
} else if (room != 0) {
created = true;
conv = new Room(acc, room);
room->getMessages(deque);
if (!room->getJoined()) {
emit setRoomJoined(id->account, id->name, true);
@ -358,12 +356,6 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
conv->setAttribute(Qt::WA_DeleteOnClose);
subscribeConversation(conv);
conversations.insert(std::make_pair(*id, conv));
if (created) {
for (Models::Contact::Messages::const_iterator itr = deque.begin(), end = deque.end(); itr != end; ++itr) {
conv->addMessage(*itr);
}
}
}
conv->show();
@ -380,12 +372,6 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
}
}
void Squawk::onConversationShown()
{
Conversation* conv = static_cast<Conversation*>(sender());
rosterModel.dropMessages(conv->getAccount(), conv->getJid());
}
void Squawk::onConversationClosed(QObject* parent)
{
Conversation* conv = static_cast<Conversation*>(sender());
@ -505,8 +491,9 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data)
Conversations::iterator itr = conversations.find(id);
bool found = false;
rosterModel.addMessage(account, data);
if (currentConversation != 0 && currentConversation->getId() == id) {
currentConversation->addMessage(data);
QApplication::alert(this);
if (!isVisible() && !data.getForwarded()) {
notify(account, data);
@ -516,11 +503,7 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data)
if (itr != conversations.end()) {
Conversation* conv = itr->second;
conv->addMessage(data);
QApplication::alert(conv);
if (!found && conv->isMinimized()) {
rosterModel.addMessage(account, data);
}
if (!conv->isVisible() && !data.getForwarded()) {
notify(account, data);
}
@ -528,7 +511,6 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data)
}
if (!found) {
rosterModel.addMessage(account, data);
if (!data.getForwarded()) {
QApplication::alert(this);
notify(account, data);
@ -599,16 +581,7 @@ void Squawk::onConversationMessage(const Shared::Message& msg)
emit sendMessage(conv->getAccount(), msg);
Models::Roster::ElId id = conv->getId();
if (currentConversation != 0 && currentConversation->getId() == id) {
if (conv == currentConversation) {
Conversations::iterator itr = conversations.find(id);
if (itr != conversations.end()) {
itr->second->addMessage(msg);
}
} else {
currentConversation->addMessage(msg);
}
}
rosterModel.addMessage(conv->getAccount(), msg);
}
void Squawk::onConversationMessage(const Shared::Message& msg, const QString& path)
@ -632,24 +605,14 @@ void Squawk::onConversationMessage(const Shared::Message& msg, const QString& pa
emit sendMessage(conv->getAccount(), msg, path);
}
void Squawk::onConversationRequestArchive(const QString& before)
void Squawk::onConversationRequestArchive(const QString& account, const QString& jid, const QString& before)
{
Conversation* conv = static_cast<Conversation*>(sender());
requestArchive(conv->getAccount(), conv->getJid(), 20, before); //TODO amount as a settings value
emit requestArchive(account, jid, 20, before); //TODO amount as a settings value
}
void Squawk::responseArchive(const QString& account, const QString& jid, const std::list<Shared::Message>& list)
{
Models::Roster::ElId id(account, jid);
if (currentConversation != 0 && currentConversation->getId() == id) {
currentConversation->responseArchive(list);
}
Conversations::const_iterator itr = conversations.find(id);
if (itr != conversations.end()) {
itr->second->responseArchive(list);
}
rosterModel.responseArchive(account, jid, list);
}
void Squawk::removeAccount(const QString& account)
@ -661,8 +624,6 @@ void Squawk::removeAccount(const QString& account)
++itr;
Conversation* conv = lItr->second;
disconnect(conv, &Conversation::destroyed, this, &Squawk::onConversationClosed);
disconnect(conv, &Conversation::requestArchive, this, &Squawk::onConversationRequestArchive);
disconnect(conv, &Conversation::shown, this, &Squawk::onConversationShown);
conv->close();
conversations.erase(lItr);
} else {
@ -926,7 +887,6 @@ void Squawk::onActivateVCard(const QString& account, const QString& jid, bool ed
{
std::map<QString, VCard*>::const_iterator itr = vCards.find(jid);
VCard* card;
Models::Contact::Messages deque;
if (itr != vCards.end()) {
card = itr->second;
} else {
@ -1095,10 +1055,8 @@ void Squawk::subscribeConversation(Conversation* conv)
connect(conv, qOverload<const Shared::Message&>(&Conversation::sendMessage), this, qOverload<const Shared::Message&>(&Squawk::onConversationMessage));
connect(conv, qOverload<const Shared::Message&, const QString&>(&Conversation::sendMessage),
this, qOverload<const Shared::Message&, const QString&>(&Squawk::onConversationMessage));
connect(conv, &Conversation::requestArchive, this, &Squawk::onConversationRequestArchive);
connect(conv, &Conversation::requestLocalFile, this, &Squawk::onConversationRequestLocalFile);
connect(conv, &Conversation::downloadFile, this, &Squawk::onConversationDownloadFile);
connect(conv, &Conversation::shown, this, &Squawk::onConversationShown);
}
void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous)
@ -1168,13 +1126,10 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
}
Models::Account* acc = rosterModel.getAccount(id->account);
Models::Contact::Messages deque;
if (contact != 0) {
currentConversation = new Chat(acc, contact);
contact->getMessages(deque);
} else if (room != 0) {
currentConversation = new Room(acc, room);
room->getMessages(deque);
if (!room->getJoined()) {
emit setRoomJoined(id->account, id->name, true);
@ -1185,9 +1140,6 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
}
subscribeConversation(currentConversation);
for (Models::Contact::Messages::const_iterator itr = deque.begin(), end = deque.end(); itr != end; ++itr) {
currentConversation->addMessage(*itr);
}
if (res.size() > 0) {
currentConversation->setPalResource(res);

View File

@ -148,9 +148,8 @@ private slots:
void onRosterItemDoubleClicked(const QModelIndex& item);
void onConversationMessage(const Shared::Message& msg);
void onConversationMessage(const Shared::Message& msg, const QString& path);
void onConversationRequestArchive(const QString& before);
void onConversationRequestArchive(const QString& account, const QString& jid, const QString& before);
void onRosterContextMenu(const QPoint& point);
void onConversationShown();
void onConversationRequestLocalFile(const QString& messageId, const QString& url);
void onConversationDownloadFile(const QString& messageId, const QString& url);
void onItemCollepsed(const QModelIndex& index);

View File

@ -28,6 +28,8 @@ Chat::Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent):
setAvatar(p_contact->getAvatarPath());
connect(contact, &Models::Contact::childChanged, this, &Chat::onContactChanged);
feed->setModel(p_contact->feed);
}
Chat::~Chat()
@ -71,31 +73,15 @@ Shared::Message Chat::createMessage() const
return msg;
}
void Chat::addMessage(const Shared::Message& data)
{
Conversation::addMessage(data);
if (!data.getOutgoing()) { //TODO need to check if that was the last message
const QString& res = data.getPenPalResource();
if (res.size() > 0) {
setPalResource(res);
}
}
}
void Chat::setName(const QString& name)
{
Conversation::setName(name);
line->setPalName(getJid(), name);
}
void Chat::setAvatar(const QString& path)
{
Conversation::setAvatar(path);
if (path.size() == 0) {
line->dropPalAvatar(contact->getJid());
} else {
line->setPalAvatar(contact->getJid(), path);
}
}
// TODO
// void Chat::addMessage(const Shared::Message& data)
// {
// Conversation::addMessage(data);
//
// if (!data.getOutgoing()) { //TODO need to check if that was the last message
// const QString& res = data.getPenPalResource();
// if (res.size() > 0) {
// setPalResource(res);
// }
// }
// }

View File

@ -35,14 +35,12 @@ public:
Chat(Models::Account* acc, Models::Contact* p_contact, QWidget* parent = 0);
~Chat();
void addMessage(const Shared::Message & data) override;
void setAvatar(const QString& path) override;
//void addMessage(const Shared::Message & data) override;
protected slots:
void onContactChanged(Models::Item* item, int row, int col);
protected:
void setName(const QString & name) override;
Shared::Message createMessage() const override;
private:

View File

@ -35,7 +35,6 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
account(acc),
palJid(pJid),
activePalResource(pRes),
line(new MessageLine(muc)),
m_ui(new Ui::Conversation()),
ker(),
scrollResizeCatcher(),
@ -46,6 +45,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
filesLayout(0),
overlay(new QWidget()),
filesToAttach(),
feed(0),
scroll(down),
manualSliderChange(false),
requestingHistory(false),
@ -53,6 +53,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1)
{
m_ui->setupUi(this);
feed = m_ui->feed;
connect(acc, &Models::Account::childChanged, this, &Conversation::onAccountChanged);
@ -67,10 +68,10 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
connect(&vis, &VisibilityCatcher::shown, this, &Conversation::onScrollResize);
connect(&vis, &VisibilityCatcher::hidden, this, &Conversation::onScrollResize);
connect(m_ui->sendButton, &QPushButton::clicked, this, &Conversation::onEnterPressed);
connect(line, &MessageLine::resize, this, &Conversation::onMessagesResize);
connect(line, &MessageLine::downloadFile, this, &Conversation::downloadFile);
connect(line, &MessageLine::uploadFile, this, qOverload<const Shared::Message&, const QString&>(&Conversation::sendMessage));
connect(line, &MessageLine::requestLocalFile, this, &Conversation::requestLocalFile);
//connect(line, &MessageLine::resize, this, &Conversation::onMessagesResize);
//connect(line, &MessageLine::downloadFile, this, &Conversation::downloadFile);
//connect(line, &MessageLine::uploadFile, this, qOverload<const Shared::Message&, const QString&>(&Conversation::sendMessage));
//connect(line, &MessageLine::requestLocalFile, this, &Conversation::requestLocalFile);
connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach);
connect(m_ui->clearButton, &QPushButton::clicked, this, &Conversation::onClearButton);
connect(m_ui->messageEditor->document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged,
@ -78,22 +79,22 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
m_ui->messageEditor->installEventFilter(&ker);
QScrollBar* vs = m_ui->scrollArea->verticalScrollBar();
m_ui->scrollArea->setWidget(line);
vs->installEventFilter(&vis);
//QScrollBar* vs = m_ui->scrollArea->verticalScrollBar();
//m_ui->scrollArea->setWidget(line);
//vs->installEventFilter(&vis);
line->setAutoFillBackground(false);
if (testAttribute(Qt::WA_TranslucentBackground)) {
m_ui->scrollArea->setAutoFillBackground(false);
} else {
m_ui->scrollArea->setBackgroundRole(QPalette::Base);
}
//line->setAutoFillBackground(false);
//if (testAttribute(Qt::WA_TranslucentBackground)) {
//m_ui->scrollArea->setAutoFillBackground(false);
//} else {
//m_ui->scrollArea->setBackgroundRole(QPalette::Base);
//}
connect(vs, &QScrollBar::valueChanged, this, &Conversation::onSliderValueChanged);
m_ui->scrollArea->installEventFilter(&scrollResizeCatcher);
//connect(vs, &QScrollBar::valueChanged, this, &Conversation::onSliderValueChanged);
//m_ui->scrollArea->installEventFilter(&scrollResizeCatcher);
line->setMyAvatarPath(acc->getAvatarPath());
line->setMyName(acc->getName());
//line->setMyAvatarPath(acc->getAvatarPath());
//line->setMyName(acc->getName());
QGridLayout* gr = static_cast<QGridLayout*>(layout());
QLabel* progressLabel = new QLabel(tr("Drop files here to attach them to your message"));
@ -129,9 +130,9 @@ void Conversation::onAccountChanged(Models::Item* item, int row, int col)
if (col == 2 && account->getState() == Shared::ConnectionState::connected) {
if (!requestingHistory) {
requestingHistory = true;
line->showBusyIndicator();
emit requestArchive("");
scroll = down;
//line->showBusyIndicator();
//emit requestArchive("");
//scroll = down;
}
}
}
@ -139,12 +140,12 @@ void Conversation::onAccountChanged(Models::Item* item, int row, int col)
void Conversation::applyVisualEffects()
{
DropShadowEffect *e1 = new DropShadowEffect;
e1->setBlurRadius(10);
e1->setColor(Qt::black);
e1->setThickness(1);
e1->setFrame(true, false, true, false);
m_ui->scrollArea->setGraphicsEffect(e1);
// DropShadowEffect *e1 = new DropShadowEffect;
// e1->setBlurRadius(10);
// e1->setColor(Qt::black);
// e1->setThickness(1);
// e1->setFrame(true, false, true, false);
// m_ui->scrollArea->setGraphicsEffect(e1);
}
void Conversation::setName(const QString& name)
@ -163,20 +164,9 @@ QString Conversation::getJid() const
return palJid;
}
void Conversation::addMessage(const Shared::Message& data)
{
int pos = m_ui->scrollArea->verticalScrollBar()->sliderPosition();
int max = m_ui->scrollArea->verticalScrollBar()->maximum();
MessageLine::Position place = line->message(data);
if (place == MessageLine::invalid) {
return;
}
}
void Conversation::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
line->changeMessage(id, data);
// line->changeMessage(id, data);
}
KeyEnterReceiver::KeyEnterReceiver(QObject* parent): QObject(parent), ownEvent(false) {}
@ -226,86 +216,86 @@ void Conversation::onEnterPressed()
m_ui->messageEditor->clear();
Shared::Message msg = createMessage();
msg.setBody(body);
addMessage(msg);
//addMessage(msg);
emit sendMessage(msg);
}
if (filesToAttach.size() > 0) {
for (Badge* badge : filesToAttach) {
Shared::Message msg = createMessage();
line->appendMessageWithUpload(msg, badge->id);
usleep(1000); //this is required for the messages not to have equal time when appending into messageline
}
clearAttachedFiles();
// for (Badge* badge : filesToAttach) {
// Shared::Message msg = createMessage();
// line->appendMessageWithUpload(msg, badge->id);
// usleep(1000); //this is required for the messages not to have equal time when appending into messageline
// }
// clearAttachedFiles();
}
}
void Conversation::appendMessageWithUpload(const Shared::Message& data, const QString& path)
{
line->appendMessageWithUploadNoSiganl(data, path);
// line->appendMessageWithUploadNoSiganl(data, path);
}
void Conversation::onMessagesResize(int amount)
{
manualSliderChange = true;
switch (scroll) {
case down:
m_ui->scrollArea->verticalScrollBar()->setValue(m_ui->scrollArea->verticalScrollBar()->maximum());
break;
case keep: {
int max = m_ui->scrollArea->verticalScrollBar()->maximum();
int value = m_ui->scrollArea->verticalScrollBar()->value() + amount;
m_ui->scrollArea->verticalScrollBar()->setValue(value);
if (value == max) {
scroll = down;
} else {
scroll = nothing;
}
}
break;
default:
break;
}
manualSliderChange = false;
// manualSliderChange = true;
// switch (scroll) {
// case down:
// m_ui->scrollArea->verticalScrollBar()->setValue(m_ui->scrollArea->verticalScrollBar()->maximum());
// break;
// case keep: {
// int max = m_ui->scrollArea->verticalScrollBar()->maximum();
// int value = m_ui->scrollArea->verticalScrollBar()->value() + amount;
// m_ui->scrollArea->verticalScrollBar()->setValue(value);
//
// if (value == max) {
// scroll = down;
// } else {
// scroll = nothing;
// }
// }
// break;
// default:
// break;
// }
// manualSliderChange = false;
}
void Conversation::onSliderValueChanged(int value)
{
if (!manualSliderChange) {
if (value == m_ui->scrollArea->verticalScrollBar()->maximum()) {
scroll = down;
} else {
if (!requestingHistory && value == 0) {
requestingHistory = true;
line->showBusyIndicator();
emit requestArchive(line->firstMessageId());
scroll = keep;
} else {
scroll = nothing;
}
}
}
// if (!manualSliderChange) {
// if (value == m_ui->scrollArea->verticalScrollBar()->maximum()) {
// scroll = down;
// } else {
// if (!requestingHistory && value == 0) {
// requestingHistory = true;
// line->showBusyIndicator();
// emit requestArchive(line->firstMessageId());
// scroll = keep;
// } else {
// scroll = nothing;
// }
// }
// }
}
void Conversation::responseArchive(const std::list<Shared::Message> list)
{
requestingHistory = false;
scroll = keep;
line->hideBusyIndicator();
for (std::list<Shared::Message>::const_iterator itr = list.begin(), end = list.end(); itr != end; ++itr) {
addMessage(*itr);
}
// requestingHistory = false;
// scroll = keep;
//
// line->hideBusyIndicator();
// for (std::list<Shared::Message>::const_iterator itr = list.begin(), end = list.end(); itr != end; ++itr) {
// addMessage(*itr);
// }
}
void Conversation::showEvent(QShowEvent* event)
{
if (!everShown) {
everShown = true;
line->showBusyIndicator();
// line->showBusyIndicator();
requestingHistory = true;
scroll = keep;
emit requestArchive(line->firstMessageId());
emit requestArchive("");
}
emit shown();
@ -342,30 +332,30 @@ void Conversation::setStatus(const QString& status)
void Conversation::onScrollResize()
{
if (everShown) {
int size = m_ui->scrollArea->width();
QScrollBar* bar = m_ui->scrollArea->verticalScrollBar();
if (bar->isVisible() && !tsb) {
size -= bar->width();
}
line->setMaximumWidth(size);
}
// if (everShown) {
// int size = m_ui->scrollArea->width();
// QScrollBar* bar = m_ui->scrollArea->verticalScrollBar();
// if (bar->isVisible() && !tsb) {
// size -= bar->width();
//
// }
// line->setMaximumWidth(size);
// }
}
void Conversation::responseFileProgress(const QString& messageId, qreal progress)
{
line->fileProgress(messageId, progress);
// line->fileProgress(messageId, progress);
}
void Conversation::fileError(const QString& messageId, const QString& error)
{
line->fileError(messageId, error);
// line->fileError(messageId, error);
}
void Conversation::responseLocalFile(const QString& messageId, const QString& path)
{
line->responseLocalFile(messageId, path);
// line->responseLocalFile(messageId, path);
}
Models::Roster::ElId Conversation::getId() const
@ -444,7 +434,7 @@ void Conversation::onTextEditDocSizeChanged(const QSizeF& size)
void Conversation::setFeedFrames(bool top, bool right, bool bottom, bool left)
{
static_cast<DropShadowEffect*>(m_ui->scrollArea->graphicsEffect())->setFrame(top, right, bottom, left);
//static_cast<DropShadowEffect*>(m_ui->scrollArea->graphicsEffect())->setFrame(top, right, bottom, left);
}
void Conversation::dragEnterEvent(QDragEnterEvent* event)

View File

@ -24,6 +24,7 @@
#include <QMap>
#include <QMimeData>
#include <QFileInfo>
#include <QListView>
#include "shared/message.h"
#include "order.h"
@ -78,7 +79,6 @@ public:
QString getAccount() const;
QString getPalResource() const;
Models::Roster::ElId getId() const;
virtual void addMessage(const Shared::Message& data);
void setPalResource(const QString& res);
void responseArchive(const std::list<Shared::Message> list);
@ -135,7 +135,6 @@ protected:
Models::Account* account;
QString palJid;
QString activePalResource;
MessageLine* line;
QScopedPointer<Ui::Conversation> m_ui;
KeyEnterReceiver ker;
Resizer scrollResizeCatcher;
@ -146,6 +145,7 @@ protected:
FlowLayout* filesLayout;
QWidget* overlay;
W::Order<Badge*, Badge::Comparator> filesToAttach;
QListView* feed;
Scroll scroll;
bool manualSliderChange;
bool requestingHistory;

View File

@ -215,60 +215,37 @@
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<widget class="QListView" name="feed">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="widgetResizable">
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerItem</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>false</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>520</width>
<height>385</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</widget>
</item>
</layout>
<zorder>scrollArea</zorder>
<zorder>widget_3</zorder>
</widget>
</item>
<item row="1" column="0">

View File

@ -23,7 +23,6 @@ Room::Room(Models::Account* acc, Models::Room* p_room, QWidget* parent):
room(p_room)
{
setName(p_room->getName());
line->setMyName(room->getNick());
setStatus(room->getSubject());
setAvatar(room->getAvatarPath());
@ -31,15 +30,7 @@ Room::Room(Models::Account* acc, Models::Room* p_room, QWidget* parent):
connect(room, &Models::Room::participantJoined, this, &Room::onParticipantJoined);
connect(room, &Models::Room::participantLeft, this, &Room::onParticipantLeft);
std::map<QString, const Models::Participant&> members = room->getParticipants();
for (std::pair<QString, const Models::Participant&> pair : members) {
QString aPath = pair.second.getAvatarPath();
if (aPath.size() > 0) {
line->setPalAvatar(pair.first, aPath);
}
}
line->setExPalAvatars(room->getExParticipantAvatars());
feed->setModel(p_room->feed);
}
Room::~Room()
@ -75,30 +66,14 @@ void Room::onRoomChanged(Models::Item* item, int row, int col)
setAvatar(room->getAvatarPath());
break;
}
} else {
switch (col) {
case 7: {
Models::Participant* mem = static_cast<Models::Participant*>(item);
QString aPath = mem->getAvatarPath();
if (aPath.size() > 0) {
line->setPalAvatar(mem->getName(), aPath);
} else {
line->dropPalAvatar(mem->getName());
}
}
}
}
}
void Room::onParticipantJoined(const Models::Participant& participant)
{
QString aPath = participant.getAvatarPath();
if (aPath.size() > 0) {
line->setPalAvatar(participant.getName(), aPath);
}
}
void Room::onParticipantLeft(const QString& name)
{
line->movePalAvatarToEx(name);
}