mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Merge pull request #2346 from PKEv:save_avatar_in_DB
Save avatar in DB add import avatars update delete avatar action correct import avatar for user without history add multithreaded make import run once
This commit is contained in:
commit
c07aee18ad
|
@ -292,7 +292,7 @@ void Core::start()
|
|||
emit idSet(id);
|
||||
|
||||
// tox core is already decrypted
|
||||
if (Settings::getInstance().getEnableLogging() && Nexus::getProfile()->isEncrypted())
|
||||
if (Nexus::getProfile()->isEncrypted())
|
||||
checkEncryptedHistory();
|
||||
|
||||
loadFriends();
|
||||
|
@ -329,6 +329,7 @@ void Core::start()
|
|||
toxav_register_audio_callback(toxav, playCallAudio, this);
|
||||
toxav_register_video_callback(toxav, playCallVideo, this);
|
||||
|
||||
HistoryKeeper::getInstance()->importAvatarToDatabase(getSelfId().toString().left(64));
|
||||
QPixmap pic = Settings::getInstance().getSavedAvatar(getSelfId().toString());
|
||||
if (!pic.isNull() && !pic.size().isEmpty())
|
||||
{
|
||||
|
|
|
@ -144,7 +144,6 @@ void Core::checkEncryptedHistory()
|
|||
if (pw.isEmpty())
|
||||
{
|
||||
Settings::getInstance().setEnableLogging(false);
|
||||
HistoryKeeper::resetInstance();
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "widget/gui.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/persistence/settings.h"
|
||||
#include "src/persistence/historykeeper.h"
|
||||
|
||||
Friend::Friend(uint32_t FriendId, const ToxId &UserId)
|
||||
: userName{Core::getInstance()->getPeerName(UserId)},
|
||||
|
@ -39,6 +40,7 @@ Friend::Friend(uint32_t FriendId, const ToxId &UserId)
|
|||
|
||||
widget = new FriendWidget(friendId, getDisplayedName());
|
||||
chatForm = new ChatForm(this);
|
||||
HistoryKeeper::getInstance()->importAvatarToDatabase(UserId.publicKey);
|
||||
}
|
||||
|
||||
Friend::~Friend()
|
||||
|
|
|
@ -26,17 +26,21 @@ PlainDb::PlainDb(const QString &db_name, QList<QString> initList)
|
|||
{
|
||||
db = new QSqlDatabase();
|
||||
*db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
db->setConnectOptions("QSQLITE_ENABLE_SHARED_CACHE=1");
|
||||
db->setDatabaseName(db_name);
|
||||
|
||||
if (!db->open())
|
||||
{
|
||||
qWarning() << QString("Can't open file: %1, history will not be saved!").arg(db_name);
|
||||
db->setDatabaseName(":memory:");
|
||||
db->setConnectOptions();
|
||||
db->open();
|
||||
}
|
||||
|
||||
for (const QString &cmd : initList)
|
||||
{
|
||||
db->exec(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
PlainDb::~PlainDb()
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <QDir>
|
||||
#include <QSqlQuery>
|
||||
#include <QVariant>
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
|
@ -35,9 +36,11 @@
|
|||
#include "src/persistence/db/encrypteddb.h"
|
||||
|
||||
static HistoryKeeper *historyInstance = nullptr;
|
||||
QMutex HistoryKeeper::historyMutex;
|
||||
|
||||
HistoryKeeper *HistoryKeeper::getInstance()
|
||||
{
|
||||
historyMutex.lock();
|
||||
if (historyInstance == nullptr)
|
||||
{
|
||||
QList<QString> initLst;
|
||||
|
@ -50,8 +53,6 @@ HistoryKeeper *HistoryKeeper::getInstance()
|
|||
QString path(":memory:");
|
||||
GenericDdInterface *dbIntf;
|
||||
|
||||
if (Settings::getInstance().getEnableLogging())
|
||||
{
|
||||
if (Nexus::getProfile()->isEncrypted())
|
||||
{
|
||||
path = getHistoryPath();
|
||||
|
@ -64,11 +65,11 @@ HistoryKeeper *HistoryKeeper::getInstance()
|
|||
{
|
||||
path = getHistoryPath();
|
||||
}
|
||||
}
|
||||
|
||||
dbIntf = new PlainDb(path, initLst);
|
||||
historyInstance = new HistoryKeeper(dbIntf);
|
||||
}
|
||||
historyMutex.unlock();
|
||||
|
||||
return historyInstance;
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ bool HistoryKeeper::checkPassword(const TOX_PASS_KEY &passkey, int encrypted)
|
|||
if (!Settings::getInstance().getEnableLogging() && (encrypted == -1))
|
||||
return true;
|
||||
|
||||
if ((encrypted == 1) || (encrypted == -1 && Nexus::getProfile()->isEncrypted()))
|
||||
if ((encrypted == 1) || (encrypted == -1))
|
||||
return EncryptedDb::check(passkey, getHistoryPath(Nexus::getProfile()->getName(), encrypted));
|
||||
|
||||
return true;
|
||||
|
@ -95,10 +96,12 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) :
|
|||
name -- chat's name (for user to user conversation it is opposite user public key)
|
||||
ctype -- chat type, reserved for group chats
|
||||
|
||||
alisases:
|
||||
aliases:
|
||||
* user_id -> id map
|
||||
id -- auto-incrementing number
|
||||
name -- user's public key
|
||||
user_id -- user's public key
|
||||
av_hash -- hash of user's avatar
|
||||
avatar -- user's avatar
|
||||
|
||||
history:
|
||||
id -- auto-incrementing number
|
||||
|
@ -126,14 +129,33 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) :
|
|||
}
|
||||
}
|
||||
//check table stuct
|
||||
ans = db->exec("PRAGMA table_info(\"history\")");
|
||||
ans = db->exec("PRAGMA table_info (\"history\")");
|
||||
ans.seek(5);
|
||||
if (!ans.value(1).toString().contains("alias"))
|
||||
{
|
||||
//add collum in table
|
||||
db->exec("ALTER TABLE history ADD COLUMN alias TEXT");
|
||||
qDebug() << "Struct DB updated: Added column alias in table history.";
|
||||
}
|
||||
|
||||
ans.clear();
|
||||
ans = db->exec("PRAGMA table_info('aliases')");
|
||||
ans.seek(2);
|
||||
if (!ans.value(1).toString().contains("av_hash"))
|
||||
{
|
||||
//add collum in table
|
||||
db->exec("ALTER TABLE aliases ADD COLUMN av_hash BLOB");
|
||||
qDebug() << "Struct DB updated: Added column av_hash in table aliases.";
|
||||
}
|
||||
|
||||
ans.seek(3);
|
||||
if (!ans.value(1).toString().contains("avatar"))
|
||||
{
|
||||
//add collum in table
|
||||
needImport = true;
|
||||
db->exec("ALTER TABLE aliases ADD COLUMN avatar BLOB");
|
||||
qDebug() << "Struct DB updated: Added column avatar in table aliases.";
|
||||
}
|
||||
|
||||
updateChatsID();
|
||||
updateAliases();
|
||||
|
@ -146,6 +168,24 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) :
|
|||
messageID = sqlAnswer.value(0).toLongLong();
|
||||
}
|
||||
|
||||
void HistoryKeeper::importAvatarToDatabase(const QString& ownerId)
|
||||
{
|
||||
if (needImport)
|
||||
{
|
||||
QString puth (Settings::getInstance().getSettingsDirPath() +
|
||||
QString("avatars") + QDir::separator() +
|
||||
ownerId +".png");
|
||||
qDebug() << QString("Try import avatar for: %1.").arg(ownerId);
|
||||
getAliasID(ownerId);
|
||||
if (QFile::exists(puth) && !hasAvatar(ownerId))
|
||||
{
|
||||
QPixmap pic(puth);
|
||||
saveAvatar(pic,ownerId);
|
||||
qDebug() << QString("Import avatar for: %1.").arg(ownerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HistoryKeeper::~HistoryKeeper()
|
||||
{
|
||||
delete db;
|
||||
|
@ -455,21 +495,84 @@ bool HistoryKeeper::isFileExist()
|
|||
return file.exists();
|
||||
}
|
||||
|
||||
bool HistoryKeeper::removeHistory(int encrypted)
|
||||
void HistoryKeeper::removeHistory()
|
||||
{
|
||||
resetInstance();
|
||||
|
||||
QString path = getHistoryPath(QString(), encrypted);
|
||||
QFile DbFile(path);
|
||||
return DbFile.remove();
|
||||
db->exec("BEGIN TRANSACTION;");
|
||||
db->exec("DELETE FROM sent_status;");
|
||||
db->exec("DELETE FROM history;");
|
||||
db->exec("COMMIT TRANSACTION;");
|
||||
}
|
||||
|
||||
QList<HistoryKeeper::HistMessage> HistoryKeeper::exportMessagesDeleteFile(int encrypted)
|
||||
QList<HistoryKeeper::HistMessage> HistoryKeeper::exportMessagesDeleteFile()
|
||||
{
|
||||
auto msgs = getInstance()->exportMessages();
|
||||
qDebug() << "Messages exported";
|
||||
if (!removeHistory(encrypted))
|
||||
qWarning() << "couldn't delete old log file!";
|
||||
getInstance()->removeHistory();
|
||||
|
||||
return msgs;
|
||||
}
|
||||
|
||||
void HistoryKeeper::removeAvatar(const QString& ownerId)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("UPDATE aliases SET avatar=NULL, av_hash=NULL WHERE user_id = (:id)");
|
||||
query.bindValue(":id", ownerId.left(64));
|
||||
query.exec();
|
||||
}
|
||||
|
||||
bool HistoryKeeper::hasAvatar(const QString& ownerId)
|
||||
{
|
||||
QSqlQuery sqlAnswer = db->exec(QString("SELECT avatar FROM aliases WHERE user_id= '%1'").arg(ownerId.left(64)));
|
||||
if (sqlAnswer.first() && sqlAnswer.value(0).toByteArray()!=NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HistoryKeeper::saveAvatar(QPixmap& pic, const QString& ownerId)
|
||||
{
|
||||
QByteArray bArray;
|
||||
QBuffer buffer(&bArray);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
pic.save(&buffer, "PNG");
|
||||
|
||||
QSqlQuery query;
|
||||
query.prepare("UPDATE aliases SET avatar=:image WHERE user_id = (:id)");
|
||||
query.bindValue(":image", bArray);
|
||||
query.bindValue(":id", ownerId.left(64));
|
||||
query.exec();
|
||||
}
|
||||
|
||||
QPixmap HistoryKeeper::getSavedAvatar(const QString &ownerId)
|
||||
{
|
||||
QByteArray bArray;
|
||||
QPixmap pixmap = QPixmap();
|
||||
QSqlQuery sqlAnswer = db->exec(QString("SELECT avatar FROM aliases WHERE user_id= '%1'").arg(ownerId.left(64)));
|
||||
if (sqlAnswer.first())
|
||||
{
|
||||
bArray = sqlAnswer.value(0).toByteArray();
|
||||
pixmap.loadFromData(bArray);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void HistoryKeeper::saveAvatarHash(const QByteArray& hash, const QString& ownerId)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("UPDATE aliases SET av_hash=:hash WHERE user_id = (:id)");
|
||||
query.bindValue(":hash", QString(hash.toBase64()));
|
||||
query.bindValue(":id", ownerId.left(64));
|
||||
query.exec();
|
||||
}
|
||||
|
||||
QByteArray HistoryKeeper::getAvatarHash(const QString& ownerId)
|
||||
{
|
||||
QByteArray bArray;
|
||||
QSqlQuery sqlAnswer = db->exec(QString("SELECT avatar FROM aliases WHERE user_id= '%1'").arg(ownerId.left(64)));
|
||||
if (sqlAnswer.first())
|
||||
{
|
||||
bArray = sqlAnswer.value(0).toByteArray();
|
||||
}
|
||||
return bArray;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <QMap>
|
||||
#include <QList>
|
||||
#include <QDateTime>
|
||||
#include <QPixmap>
|
||||
#include <QMutex>
|
||||
#include <tox/toxencryptsave.h>
|
||||
|
||||
class GenericDdInterface;
|
||||
|
@ -32,6 +34,7 @@ class HistoryKeeper
|
|||
{
|
||||
public:
|
||||
enum ChatType {ctSingle = 0, ctGroup};
|
||||
static QMutex historyMutex;
|
||||
|
||||
struct HistMessage
|
||||
{
|
||||
|
@ -56,8 +59,8 @@ public:
|
|||
static bool checkPassword(const TOX_PASS_KEY& passkey, int encrypted = -1);
|
||||
static bool isFileExist();
|
||||
static void renameHistory(QString from, QString to);
|
||||
static bool removeHistory(int encrypted = -1);
|
||||
static QList<HistMessage> exportMessagesDeleteFile(int encrypted = -1);
|
||||
void removeHistory();
|
||||
static QList<HistMessage> exportMessagesDeleteFile();
|
||||
|
||||
void removeFriendHistory(const QString& chat);
|
||||
qint64 addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt, bool isSent, QString dispName);
|
||||
|
@ -71,6 +74,17 @@ public:
|
|||
|
||||
void setSyncType(Db::syncType sType);
|
||||
|
||||
void saveAvatar(QPixmap& pic, const QString& ownerId);
|
||||
QPixmap getSavedAvatar(const QString &ownerId);
|
||||
|
||||
void saveAvatarHash(const QByteArray& hash, const QString& ownerId);
|
||||
QByteArray getAvatarHash(const QString& ownerId);
|
||||
|
||||
void removeAvatar(const QString& ownerId);
|
||||
bool hasAvatar(const QString& ownerId);
|
||||
|
||||
void importAvatarToDatabase(const QString& ownerId); // may be deleted after all move to new db structure
|
||||
|
||||
private:
|
||||
HistoryKeeper(GenericDdInterface *db_);
|
||||
HistoryKeeper(HistoryKeeper &hk) = delete;
|
||||
|
@ -85,7 +99,7 @@ private:
|
|||
QList<QString> generateAddChatEntryCmd(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt, bool isSent, QString dispName);
|
||||
|
||||
ChatType convertToChatType(int);
|
||||
|
||||
bool needImport = false; // must be deleted with "importAvatarToDatabase"
|
||||
GenericDdInterface *db;
|
||||
QMap<QString, int> aliases;
|
||||
QMap<QString, QPair<int, ChatType>> chats;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "src/widget/gui.h"
|
||||
#include "src/persistence/profilelocker.h"
|
||||
#include "src/persistence/settingsserializer.h"
|
||||
#include "src/persistence/historykeeper.h"
|
||||
#include "src/nexus.h"
|
||||
#include "src/persistence/profile.h"
|
||||
#ifdef QTOX_PLATFORM_EXT
|
||||
|
@ -533,59 +534,22 @@ QString Settings::getSettingsDirPath()
|
|||
|
||||
QPixmap Settings::getSavedAvatar(const QString &ownerId)
|
||||
{
|
||||
QDir dir(getSettingsDirPath());
|
||||
QString filePath = dir.filePath("avatars/"+ownerId.left(64)+".png");
|
||||
QFileInfo info(filePath);
|
||||
QPixmap pic;
|
||||
if (!info.exists())
|
||||
{
|
||||
QString filePath = dir.filePath("avatar_"+ownerId.left(64));
|
||||
if (!QFileInfo(filePath).exists()) // try without truncation, for old self avatars
|
||||
filePath = dir.filePath("avatar_"+ownerId);
|
||||
|
||||
pic.load(filePath);
|
||||
saveAvatar(pic, ownerId);
|
||||
QFile::remove(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
pic.load(filePath);
|
||||
}
|
||||
return pic;
|
||||
return HistoryKeeper::getInstance()->getSavedAvatar(ownerId);
|
||||
}
|
||||
|
||||
void Settings::saveAvatar(QPixmap& pic, const QString& ownerId)
|
||||
{
|
||||
QDir dir(getSettingsDirPath());
|
||||
dir.mkdir("avatars/");
|
||||
// ignore nospam (good idea, and also the addFriend funcs which call getAvatar don't have it)
|
||||
QString filePath = dir.filePath("avatars/"+ownerId.left(64)+".png");
|
||||
pic.save(filePath, "png");
|
||||
HistoryKeeper::getInstance()->saveAvatar(pic,ownerId);
|
||||
}
|
||||
|
||||
void Settings::saveAvatarHash(const QByteArray& hash, const QString& ownerId)
|
||||
{
|
||||
QDir dir(getSettingsDirPath());
|
||||
dir.mkdir("avatars/");
|
||||
QFile file(dir.filePath("avatars/"+ownerId.left(64)+".hash"));
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
file.write(hash);
|
||||
file.close();
|
||||
HistoryKeeper::getInstance()->saveAvatarHash(hash,ownerId);
|
||||
}
|
||||
|
||||
QByteArray Settings::getAvatarHash(const QString& ownerId)
|
||||
{
|
||||
QDir dir(getSettingsDirPath());
|
||||
dir.mkdir("avatars/");
|
||||
QFile file(dir.filePath("avatars/"+ownerId.left(64)+".hash"));
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return QByteArray();
|
||||
|
||||
QByteArray out = file.readAll();
|
||||
file.close();
|
||||
return out;
|
||||
return HistoryKeeper::getInstance()->getAvatarHash(ownerId);
|
||||
}
|
||||
|
||||
const QList<DhtServer>& Settings::getDhtServerList() const
|
||||
|
|
|
@ -184,18 +184,13 @@ void ProfileForm::showProfilePictureContextMenu(const QPoint &point)
|
|||
QPoint pos = profilePicture->mapToGlobal(point);
|
||||
|
||||
QMenu contextMenu;
|
||||
QAction *removeAction = contextMenu.addAction(tr("Remove"));
|
||||
QAction *removeAction = contextMenu.addAction(style()->standardIcon(QStyle::SP_DialogCancelButton), tr("Remove"));
|
||||
QAction *selectedItem = contextMenu.exec(pos);
|
||||
|
||||
if (selectedItem == removeAction)
|
||||
{
|
||||
QString selfPubKey = Core::getInstance()->getSelfId().publicKey;
|
||||
if (!QFile::remove(Settings::getInstance().getSettingsDirPath()+"avatars/"+selfPubKey.left(64)+".png"))
|
||||
{
|
||||
GUI::showError(tr("Error"), tr("Could not remove avatar."));
|
||||
return;
|
||||
}
|
||||
|
||||
HistoryKeeper::getInstance()->removeAvatar(selfPubKey);
|
||||
Core::getInstance()->setAvatar({});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ PrivacyForm::~PrivacyForm()
|
|||
void PrivacyForm::onEnableLoggingUpdated()
|
||||
{
|
||||
Settings::getInstance().setEnableLogging(bodyUI->cbKeepHistory->isChecked());
|
||||
HistoryKeeper::resetInstance();
|
||||
Widget::getInstance()->clearAllReceipts();
|
||||
if (!bodyUI->cbKeepHistory->isChecked())
|
||||
{
|
||||
|
@ -64,10 +63,7 @@ void PrivacyForm::onEnableLoggingUpdated()
|
|||
QMessageBox::Yes|QMessageBox::No);
|
||||
if (dialogDelHistory == QMessageBox::Yes)
|
||||
{
|
||||
if (!HistoryKeeper::removeHistory())
|
||||
{
|
||||
QMessageBox::critical(0, tr("Error"), tr("Could not delete chat history"), QMessageBox::Ok);
|
||||
}
|
||||
HistoryKeeper::getInstance()->removeHistory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user