mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Avatar support for ourselves
This commit is contained in:
parent
aa786b427a
commit
7ad6ad2731
46
core.cpp
46
core.cpp
|
@ -35,6 +35,7 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QBuffer>
|
||||||
|
|
||||||
const QString Core::CONFIG_FILE_NAME = "data";
|
const QString Core::CONFIG_FILE_NAME = "data";
|
||||||
QList<ToxFile> Core::fileSendQueue;
|
QList<ToxFile> Core::fileSendQueue;
|
||||||
|
@ -187,6 +188,8 @@ void Core::start()
|
||||||
tox_callback_file_send_request(tox, onFileSendRequestCallback, this);
|
tox_callback_file_send_request(tox, onFileSendRequestCallback, this);
|
||||||
tox_callback_file_control(tox, onFileControlCallback, this);
|
tox_callback_file_control(tox, onFileControlCallback, this);
|
||||||
tox_callback_file_data(tox, onFileDataCallback, this);
|
tox_callback_file_data(tox, onFileDataCallback, this);
|
||||||
|
tox_callback_avatar_info(tox, onAvatarInfoCallback, this);
|
||||||
|
tox_callback_avatar_data(tox, onAvatarDataCallback, this);
|
||||||
|
|
||||||
toxav_register_callstate_callback(toxav, onAvInvite, av_OnInvite, this);
|
toxav_register_callstate_callback(toxav, onAvInvite, av_OnInvite, this);
|
||||||
toxav_register_callstate_callback(toxav, onAvStart, av_OnStart, this);
|
toxav_register_callstate_callback(toxav, onAvStart, av_OnStart, this);
|
||||||
|
@ -205,9 +208,22 @@ void Core::start()
|
||||||
|
|
||||||
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
|
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
|
||||||
tox_get_address(tox, friendAddress);
|
tox_get_address(tox, friendAddress);
|
||||||
|
|
||||||
emit friendAddressGenerated(CFriendAddress::toString(friendAddress));
|
emit friendAddressGenerated(CFriendAddress::toString(friendAddress));
|
||||||
|
|
||||||
|
QPixmap pic = Settings::getInstance().getSavedAvatar();
|
||||||
|
if (!pic.isNull() && !pic.size().isEmpty())
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
QBuffer buffer(&data);
|
||||||
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
pic.save(&buffer);
|
||||||
|
buffer.close();
|
||||||
|
tox_set_avatar(tox, TOX_AVATARFORMAT_PNG, (uint8_t*)data.constData(), data.size());
|
||||||
|
emit selfAvatarChanged(pic);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qDebug() << "Core: Error loading self avatar";
|
||||||
|
|
||||||
bootstrapDht();
|
bootstrapDht();
|
||||||
|
|
||||||
toxTimer->start(tox_do_interval(tox));
|
toxTimer->start(tox_do_interval(tox));
|
||||||
|
@ -433,6 +449,18 @@ void Core::onFileDataCallback(Tox*, int32_t friendnumber, uint8_t filenumber, co
|
||||||
file->filesize, file->bytesSent, ToxFile::RECEIVING);
|
file->filesize, file->bytesSent, ToxFile::RECEIVING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::onAvatarInfoCallback(Tox* tox, int32_t friendnumber, uint8_t format,
|
||||||
|
uint8_t *hash, void *userdata)
|
||||||
|
{
|
||||||
|
qDebug() << "Core: Got avatar info from "<<friendnumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::onAvatarDataCallback(Tox* tox, int32_t friendnumber, uint8_t format,
|
||||||
|
uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata)
|
||||||
|
{
|
||||||
|
qDebug() << "Core: Got avatar data from "<<friendnumber;
|
||||||
|
}
|
||||||
|
|
||||||
void Core::acceptFriendRequest(const QString& userId)
|
void Core::acceptFriendRequest(const QString& userId)
|
||||||
{
|
{
|
||||||
int friendId = tox_add_friend_norequest(tox, CUserId(userId).data());
|
int friendId = tox_add_friend_norequest(tox, CUserId(userId).data());
|
||||||
|
@ -729,6 +757,22 @@ void Core::setUsername(const QString& username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::setAvatar(uint8_t format, const QByteArray& data)
|
||||||
|
{
|
||||||
|
if (tox_set_avatar(tox, format, (uint8_t*)data.constData(), data.size()) != 0)
|
||||||
|
{
|
||||||
|
qWarning() << "Core: Failed to set self avatar";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qDebug() << "Core: Set avatar, format:"<<format<<", size:"<<data.size();
|
||||||
|
|
||||||
|
QPixmap pic;
|
||||||
|
pic.loadFromData(data);
|
||||||
|
Settings::getInstance().saveAvatar(pic);
|
||||||
|
emit selfAvatarChanged(pic);
|
||||||
|
}
|
||||||
|
|
||||||
ToxID Core::getSelfId()
|
ToxID Core::getSelfId()
|
||||||
{
|
{
|
||||||
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
|
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
|
||||||
|
|
4
core.h
4
core.h
|
@ -71,6 +71,7 @@ public slots:
|
||||||
void setStatus(Status status);
|
void setStatus(Status status);
|
||||||
void setUsername(const QString& username);
|
void setUsername(const QString& username);
|
||||||
void setStatusMessage(const QString& message);
|
void setStatusMessage(const QString& message);
|
||||||
|
void setAvatar(uint8_t format, const QByteArray& data);
|
||||||
|
|
||||||
void sendMessage(int friendId, const QString& message);
|
void sendMessage(int friendId, const QString& message);
|
||||||
void sendGroupMessage(int groupId, const QString& message);
|
void sendGroupMessage(int groupId, const QString& message);
|
||||||
|
@ -123,6 +124,7 @@ signals:
|
||||||
void usernameSet(const QString& username);
|
void usernameSet(const QString& username);
|
||||||
void statusMessageSet(const QString& message);
|
void statusMessageSet(const QString& message);
|
||||||
void statusSet(Status status);
|
void statusSet(Status status);
|
||||||
|
void selfAvatarChanged(const QPixmap& pic);
|
||||||
|
|
||||||
void messageSentResult(int friendId, const QString& message, int messageId);
|
void messageSentResult(int friendId, const QString& message, int messageId);
|
||||||
void groupSentResult(int groupId, const QString& message, int result);
|
void groupSentResult(int groupId, const QString& message, int result);
|
||||||
|
@ -182,6 +184,8 @@ private:
|
||||||
static void onFileControlCallback(Tox *tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
|
static void onFileControlCallback(Tox *tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
|
||||||
uint8_t control_type, const uint8_t *data, uint16_t length, void *core);
|
uint8_t control_type, const uint8_t *data, uint16_t length, void *core);
|
||||||
static void onFileDataCallback(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata);
|
static void onFileDataCallback(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata);
|
||||||
|
static void onAvatarInfoCallback(Tox* tox, int32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata);
|
||||||
|
static void onAvatarDataCallback(Tox* tox, int32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata);
|
||||||
|
|
||||||
static void onAvInvite(void* toxav, int32_t call_index, void* core);
|
static void onAvInvite(void* toxav, int32_t call_index, void* core);
|
||||||
static void onAvStart(void* toxav, int32_t call_index, void* core);
|
static void onAvStart(void* toxav, int32_t call_index, void* core);
|
||||||
|
|
|
@ -1452,7 +1452,7 @@ QSplitter:handle{
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="profilePicture">
|
<widget class="ClickableLabel" name="profilePicture">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>40</width>
|
||||||
|
@ -2093,7 +2093,7 @@ QSplitter:handle{
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>263</width>
|
<width>263</width>
|
||||||
<height>373</height>
|
<height>378</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5"/>
|
<layout class="QVBoxLayout" name="verticalLayout_5"/>
|
||||||
|
@ -3228,7 +3228,7 @@ QSplitter:handle{
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>716</width>
|
<width>716</width>
|
||||||
<height>23</height>
|
<height>19</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -3254,6 +3254,11 @@ QSplitter:handle{
|
||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
<header>widget/croppinglabel.h</header>
|
<header>widget/croppinglabel.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ClickableLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header>widget/tool/clickablelabel.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="res.qrc"/>
|
<include location="res.qrc"/>
|
||||||
|
|
3
qtox.pro
3
qtox.pro
|
@ -116,7 +116,8 @@ HEADERS += widget/form/addfriendform.h \
|
||||||
widget/settingsdialog.h \
|
widget/settingsdialog.h \
|
||||||
widget/tool/chatactions/messageaction.h \
|
widget/tool/chatactions/messageaction.h \
|
||||||
widget/tool/chatactions/filetransferaction.h \
|
widget/tool/chatactions/filetransferaction.h \
|
||||||
widget/tool/chatactions/systemmessageaction.h
|
widget/tool/chatactions/systemmessageaction.h \
|
||||||
|
widget/tool/clickablelabel.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
widget/form/addfriendform.cpp \
|
widget/form/addfriendform.cpp \
|
||||||
|
|
15
settings.cpp
15
settings.cpp
|
@ -27,6 +27,7 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
const QString Settings::FILENAME = "settings.ini";
|
const QString Settings::FILENAME = "settings.ini";
|
||||||
|
const QString Settings::AVATAR_FILENAME = "avatar.dat";
|
||||||
bool Settings::makeToxPortable{false};
|
bool Settings::makeToxPortable{false};
|
||||||
|
|
||||||
Settings::Settings() :
|
Settings::Settings() :
|
||||||
|
@ -257,6 +258,20 @@ QString Settings::getSettingsDirPath()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap Settings::getSavedAvatar()
|
||||||
|
{
|
||||||
|
QString filePath = QDir(getSettingsDirPath()).filePath(AVATAR_FILENAME);
|
||||||
|
QPixmap pic;
|
||||||
|
pic.load(filePath);
|
||||||
|
return pic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::saveAvatar(QPixmap& pic)
|
||||||
|
{
|
||||||
|
QString filePath = QDir(getSettingsDirPath()).filePath(AVATAR_FILENAME);
|
||||||
|
pic.save(filePath, "png");
|
||||||
|
}
|
||||||
|
|
||||||
const QList<Settings::DhtServer>& Settings::getDhtServerList() const
|
const QList<Settings::DhtServer>& Settings::getDhtServerList() const
|
||||||
{
|
{
|
||||||
return dhtServerList;
|
return dhtServerList;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
class Settings : public QObject
|
class Settings : public QObject
|
||||||
{
|
{
|
||||||
|
@ -57,6 +58,9 @@ public:
|
||||||
bool getEncryptLogs() const;
|
bool getEncryptLogs() const;
|
||||||
void setEncryptLogs(bool newValue);
|
void setEncryptLogs(bool newValue);
|
||||||
|
|
||||||
|
QPixmap getSavedAvatar();
|
||||||
|
void saveAvatar(QPixmap& pic);
|
||||||
|
|
||||||
// Assume all widgets have unique names
|
// Assume all widgets have unique names
|
||||||
// Don't use it to save every single thing you want to save, use it
|
// Don't use it to save every single thing you want to save, use it
|
||||||
// for some general purpose widgets, such as MainWindows or Splitters,
|
// for some general purpose widgets, such as MainWindows or Splitters,
|
||||||
|
@ -138,6 +142,7 @@ private:
|
||||||
Settings& operator=(const Settings&) = delete;
|
Settings& operator=(const Settings&) = delete;
|
||||||
|
|
||||||
static const QString FILENAME;
|
static const QString FILENAME;
|
||||||
|
static const QString AVATAR_FILENAME;
|
||||||
|
|
||||||
bool loaded;
|
bool loaded;
|
||||||
|
|
||||||
|
|
22
widget/tool/clickablelabel.h
Normal file
22
widget/tool/clickablelabel.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef CLICKABLELABEL_H
|
||||||
|
#define CLICKABLELABEL_H
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
class QMouseEvent;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
|
class ClickableLabel : public QLabel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ClickableLabel(QWidget* parent = 0) : QLabel(parent) {}
|
||||||
|
signals:
|
||||||
|
void clicked();
|
||||||
|
protected:
|
||||||
|
void mousePressEvent (QMouseEvent*) {emit clicked();}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CLICKABLELABEL_H
|
|
@ -36,10 +36,12 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QBuffer>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
|
||||||
Widget *Widget::instance{nullptr};
|
Widget *Widget::instance{nullptr};
|
||||||
|
@ -180,6 +182,7 @@ Widget::Widget(QWidget *parent)
|
||||||
connect(core, &Core::statusSet, this, &Widget::onStatusSet);
|
connect(core, &Core::statusSet, this, &Widget::onStatusSet);
|
||||||
connect(core, &Core::usernameSet, this, &Widget::setUsername);
|
connect(core, &Core::usernameSet, this, &Widget::setUsername);
|
||||||
connect(core, &Core::statusMessageSet, this, &Widget::setStatusMessage);
|
connect(core, &Core::statusMessageSet, this, &Widget::setStatusMessage);
|
||||||
|
connect(core, &Core::selfAvatarChanged, this, &Widget::onSelfAvatarLoaded);
|
||||||
connect(core, SIGNAL(fileDownloadFinished(const QString&)), &filesForm, SLOT(onFileDownloadComplete(const QString&)));
|
connect(core, SIGNAL(fileDownloadFinished(const QString&)), &filesForm, SLOT(onFileDownloadComplete(const QString&)));
|
||||||
connect(core, SIGNAL(fileUploadFinished(const QString&)), &filesForm, SLOT(onFileUploadComplete(const QString&)));
|
connect(core, SIGNAL(fileUploadFinished(const QString&)), &filesForm, SLOT(onFileUploadComplete(const QString&)));
|
||||||
connect(core, &Core::friendAdded, this, &Widget::addFriend);
|
connect(core, &Core::friendAdded, this, &Widget::addFriend);
|
||||||
|
@ -210,6 +213,7 @@ Widget::Widget(QWidget *parent)
|
||||||
connect(ui->settingsButton, SIGNAL(clicked()), this, SLOT(onSettingsClicked()));
|
connect(ui->settingsButton, SIGNAL(clicked()), this, SLOT(onSettingsClicked()));
|
||||||
connect(ui->nameLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onUsernameChanged(QString,QString)));
|
connect(ui->nameLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onUsernameChanged(QString,QString)));
|
||||||
connect(ui->statusLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onStatusMessageChanged(QString,QString)));
|
connect(ui->statusLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onStatusMessageChanged(QString,QString)));
|
||||||
|
connect(ui->profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked()));
|
||||||
connect(setStatusOnline, SIGNAL(triggered()), this, SLOT(setStatusOnline()));
|
connect(setStatusOnline, SIGNAL(triggered()), this, SLOT(setStatusOnline()));
|
||||||
connect(setStatusAway, SIGNAL(triggered()), this, SLOT(setStatusAway()));
|
connect(setStatusAway, SIGNAL(triggered()), this, SLOT(setStatusAway()));
|
||||||
connect(setStatusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy()));
|
connect(setStatusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy()));
|
||||||
|
@ -271,6 +275,53 @@ Camera* Widget::getCamera()
|
||||||
return camera;
|
return camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::onAvatarClicked()
|
||||||
|
{
|
||||||
|
QString filename = QFileDialog::getOpenFileName(this, "Choose a profile picture");
|
||||||
|
QFile file(filename);
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
if (!file.isOpen())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "Error", "Unable to open this file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap pic;
|
||||||
|
if (!pic.loadFromData(file.readAll()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "Error", "Unable to read this image");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray bytes;
|
||||||
|
QBuffer buffer(&bytes);
|
||||||
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
pic.save(&buffer, "PNG");
|
||||||
|
buffer.close();
|
||||||
|
|
||||||
|
if (bytes.size() >= TOX_MAX_AVATAR_DATA_LENGTH)
|
||||||
|
{
|
||||||
|
pic = pic.scaledToWidth(64, Qt::SmoothTransformation);
|
||||||
|
bytes.clear();
|
||||||
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
pic.save(&buffer, "PNG");
|
||||||
|
buffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes.size() >= TOX_MAX_AVATAR_DATA_LENGTH)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "Error", "This image is too big");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
core->setAvatar(TOX_AVATARFORMAT_PNG, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::onSelfAvatarLoaded(const QPixmap& pic)
|
||||||
|
{
|
||||||
|
ui->profilePicture->setPixmap(pic);
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::onConnected()
|
void Widget::onConnected()
|
||||||
{
|
{
|
||||||
ui->statusButton->setEnabled(true);
|
ui->statusButton->setEnabled(true);
|
||||||
|
|
|
@ -80,6 +80,8 @@ private slots:
|
||||||
void onTransferClicked();
|
void onTransferClicked();
|
||||||
void onSettingsClicked();
|
void onSettingsClicked();
|
||||||
void onFailedToStartCore();
|
void onFailedToStartCore();
|
||||||
|
void onAvatarClicked();
|
||||||
|
void onSelfAvatarLoaded(const QPixmap &pic);
|
||||||
void onUsernameChanged(const QString& newUsername, const QString& oldUsername);
|
void onUsernameChanged(const QString& newUsername, const QString& oldUsername);
|
||||||
void onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage);
|
void onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage);
|
||||||
void setUsername(const QString& username);
|
void setUsername(const QString& username);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user