mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
new chat beginning
This commit is contained in:
parent
502229a6f2
commit
25ee6a24d9
274
filetransferinstance.cpp
Normal file
274
filetransferinstance.cpp
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "filetransferinstance.h"
|
||||
#include "widget/widget.h"
|
||||
#include "core.h"
|
||||
#include "math.h"
|
||||
#include "style.h"
|
||||
#include <QFileDialog>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
#include <QBuffer>
|
||||
|
||||
uint FileTransferInstance::Idconter = 0;
|
||||
|
||||
FileTransferInstance::FileTransferInstance(ToxFile File)
|
||||
: lastUpdate{QDateTime::currentDateTime()}, lastBytesSent{0},
|
||||
fileNum{File.fileNum}, friendId{File.friendId}, direction{File.direction}
|
||||
{
|
||||
id = Idconter++;
|
||||
state = tsPending;
|
||||
|
||||
filename = File.fileName;
|
||||
size = getHumanReadableSize(File.filesize);
|
||||
speed = "0B/s";
|
||||
eta = "00:00";
|
||||
if (File.direction == ToxFile::SENDING)
|
||||
{
|
||||
QImage preview;
|
||||
File.file->seek(0);
|
||||
if (preview.loadFromData(File.file->readAll()))
|
||||
{
|
||||
pic = preview.scaledToHeight(40);
|
||||
}
|
||||
File.file->seek(0);
|
||||
}
|
||||
}
|
||||
|
||||
QString FileTransferInstance::getHumanReadableSize(unsigned long long size)
|
||||
{
|
||||
static const char* suffix[] = {"B","kiB","MiB","GiB","TiB"};
|
||||
int exp = 0;
|
||||
if (size)
|
||||
exp = std::min( (int) (log(size) / log(1024)), (int) (sizeof(suffix) / sizeof(suffix[0]) - 1));
|
||||
return QString().setNum(size / pow(1024, exp),'f',2).append(suffix[exp]);
|
||||
}
|
||||
|
||||
void FileTransferInstance::onFileTransferInfo(int FriendId, int FileNum, int64_t Filesize, int64_t BytesSent, ToxFile::FileDirection Direction)
|
||||
{
|
||||
if (FileNum != fileNum || FriendId != friendId || Direction != direction)
|
||||
return;
|
||||
|
||||
// state = tsProcessing;
|
||||
QDateTime newtime = QDateTime::currentDateTime();
|
||||
int timediff = lastUpdate.secsTo(newtime);
|
||||
if (timediff <= 0)
|
||||
return;
|
||||
qint64 diff = BytesSent - lastBytesSent;
|
||||
if (diff < 0)
|
||||
{
|
||||
qWarning() << "FileTransferInstance::onFileTransferInfo: Negative transfer speed !";
|
||||
diff = 0;
|
||||
}
|
||||
long rawspeed = diff / timediff;
|
||||
speed = getHumanReadableSize(rawspeed)+"/s";
|
||||
size = getHumanReadableSize(Filesize);
|
||||
if (!rawspeed)
|
||||
return;
|
||||
int etaSecs = (Filesize - BytesSent) / rawspeed;
|
||||
QTime etaTime(0,0);
|
||||
etaTime = etaTime.addSecs(etaSecs);
|
||||
eta = etaTime.toString("mm:ss");
|
||||
lastUpdate = newtime;
|
||||
lastBytesSent = BytesSent;
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransferInstance::onFileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection Direction)
|
||||
{
|
||||
if (FileNum != fileNum || FriendId != friendId || Direction != direction)
|
||||
return;
|
||||
disconnect(Widget::getInstance()->getCore(),0,this,0);
|
||||
state = tsCanceled;
|
||||
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransferInstance::onFileTransferFinished(ToxFile File)
|
||||
{
|
||||
if (File.fileNum != fileNum || File.friendId != friendId || File.direction != direction)
|
||||
return;
|
||||
disconnect(Widget::getInstance()->getCore(),0,this,0);
|
||||
|
||||
if (File.direction == ToxFile::RECEIVING)
|
||||
{
|
||||
QPixmap preview;
|
||||
QFile previewFile(File.filePath);
|
||||
if (previewFile.open(QIODevice::ReadOnly) && previewFile.size() <= 1024*1024*25) // Don't preview big (>25MiB) images
|
||||
{
|
||||
if (preview.loadFromData(previewFile.readAll()))
|
||||
{
|
||||
preview = preview.scaledToHeight(40);
|
||||
// pic->setPixmap(preview);
|
||||
}
|
||||
previewFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
state = tsFinished;
|
||||
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransferInstance::cancelTransfer()
|
||||
{
|
||||
Widget::getInstance()->getCore()->cancelFileSend(friendId, fileNum);
|
||||
state = tsCanceled;
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransferInstance::rejectRecvRequest()
|
||||
{
|
||||
Widget::getInstance()->getCore()->rejectFileRecvRequest(friendId, fileNum);
|
||||
onFileTransferCancelled(friendId, fileNum, direction);
|
||||
state = tsCanceled;
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
// for whatever the fuck reason, QFileInfo::isWritable() always fails for files that don't exist
|
||||
// which makes it useless for our case
|
||||
// since QDir doesn't have an isWritable(), the only option I can think of is to make/delete the file
|
||||
// surely this is a common problem that has a qt-implemented solution?
|
||||
bool isFileWritable(QString& path)
|
||||
{
|
||||
QFile file(path);
|
||||
bool exists = file.exists();
|
||||
bool out = file.open(QIODevice::WriteOnly);
|
||||
file.close();
|
||||
if (!exists)
|
||||
file.remove();
|
||||
return out;
|
||||
}
|
||||
|
||||
void FileTransferInstance::acceptRecvRequest()
|
||||
{
|
||||
QString path;
|
||||
while (true)
|
||||
{
|
||||
path = QFileDialog::getSaveFileName(Widget::getInstance(), tr("Save a file","Title of the file saving dialog"), QDir::current().filePath(filename));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
else
|
||||
{
|
||||
//bool savable = QFileInfo(path).isWritable();
|
||||
//qDebug() << path << " is writable: " << savable;
|
||||
//qDebug() << "/home/bill/bliss.pdf writable: " << QFileInfo("/home/bill/bliss.pdf").isWritable();
|
||||
if (isFileWritable(path))
|
||||
break;
|
||||
else
|
||||
QMessageBox::warning(Widget::getInstance(), tr("Location not writable","Title of permissions popup"), tr("You do not have permission to write that location. Choose another, or cancel the save dialog.", "text of permissions popup"));
|
||||
}
|
||||
}
|
||||
|
||||
savePath = path;
|
||||
|
||||
Widget::getInstance()->getCore()->acceptFileRecvRequest(friendId, fileNum, path);
|
||||
state = tsProcessing;
|
||||
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransferInstance::pauseResumeRecv()
|
||||
{
|
||||
Widget::getInstance()->getCore()->pauseResumeFileRecv(friendId, fileNum);
|
||||
if (state == tsProcessing)
|
||||
state = tsPaused;
|
||||
else state = tsProcessing;
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransferInstance::pauseResumeSend()
|
||||
{
|
||||
Widget::getInstance()->getCore()->pauseResumeFileSend(friendId, fileNum);
|
||||
if (state == tsProcessing)
|
||||
state = tsPaused;
|
||||
else state = tsProcessing;
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
QString FileTransferInstance::getHtmlImage()
|
||||
{
|
||||
qDebug() << "QString FileTransferInstance::getHtmlImage()";
|
||||
auto QImage2base64 = [](const QImage &img)
|
||||
{
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG"); // writes image into ba in PNG format
|
||||
return ba.toBase64();
|
||||
};
|
||||
|
||||
QString res;
|
||||
if (state == tsPending || state == tsProcessing || state == tsPaused)
|
||||
{
|
||||
QImage rightUp(":ui/stopFileButton/default.png");
|
||||
QImage rightDown(":ui/acceptFileButton/default.png");
|
||||
|
||||
QString widgetId = QString::number(getId());
|
||||
QString strUp = "<img src=\"data:ftrans." + widgetId + ".top/png;base64," + QImage2base64(rightUp) + "\">";
|
||||
QString strDown = "<img src=\"data:ftrans." + widgetId + ".bottom/png;base64," + QImage2base64(rightDown) + "\">";
|
||||
|
||||
res = "<table widht=100% cellspacing=\"2\">\n";
|
||||
res += "<tr>\n<td width=100%>\n";
|
||||
res += "<div class=quote><p>PROCESSING</p><p>" + filename + "</p><p>" + size + "</p></div>\n";
|
||||
res += "</td>\n<td>\n";
|
||||
res += "<table cellspacing=\"0\"><tr valign=top><td>" + strUp + "</td></tr><tr valign=bottom><td>" + strDown + "</td></tr></table>\n";
|
||||
res += "</td>\n</tr>\n";
|
||||
res += "</table>\n";
|
||||
} else if (state == tsCanceled)
|
||||
{
|
||||
res = "<table widht=100% cellspacing=\"2\">\n";
|
||||
res += "<tr>\n<td width=100%>\n";
|
||||
res += "<div class=quote><p>CANCELED</p><p>" + filename + "</p><p>" + size + "</p></div>\n";
|
||||
res += "</td>\n</tr>\n";
|
||||
res += "</table>\n";
|
||||
} else if (state == tsFinished)
|
||||
{
|
||||
res = "<table widht=100% cellspacing=\"2\">\n";
|
||||
res += "<tr>\n<td width=100%>\n";
|
||||
res += "<div class=quote><p>FINISHED</p><p>" + filename + "</p><p>" + size + "</p></div>\n";
|
||||
res += "</td>\n</tr>\n";
|
||||
res += "</table>\n";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void FileTransferInstance::pressFromHtml(QString code)
|
||||
{
|
||||
if (state == tsFinished || state == tsCanceled)
|
||||
return;
|
||||
|
||||
if (direction == ToxFile::SENDING)
|
||||
{
|
||||
if (code == "top")
|
||||
cancelTransfer();
|
||||
else if (code == "bottom")
|
||||
pauseResumeSend();
|
||||
} else {
|
||||
if (code == "top")
|
||||
rejectRecvRequest();
|
||||
else if (code == "bottom")
|
||||
{
|
||||
if (state == tsPending)
|
||||
acceptRecvRequest();
|
||||
else
|
||||
pauseResumeRecv();
|
||||
}
|
||||
}
|
||||
}
|
76
filetransferinstance.h
Normal file
76
filetransferinstance.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre 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 COPYING file for more details.
|
||||
*/
|
||||
#ifndef FILETRANSFERINSTANCE_H
|
||||
#define FILETRANSFERINSTANCE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QProgressBar>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
struct ToxFile;
|
||||
|
||||
class FileTransferInstance : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FileTransferInstance(ToxFile File);
|
||||
QString getHtmlImage();
|
||||
uint getId(){return id;}
|
||||
|
||||
public slots:
|
||||
void onFileTransferInfo(int FriendId, int FileNum, int64_t Filesize, int64_t BytesSent, ToxFile::FileDirection Direction);
|
||||
void onFileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection Direction);
|
||||
void onFileTransferFinished(ToxFile File);
|
||||
void pressFromHtml(QString);
|
||||
|
||||
signals:
|
||||
void stateUpdated();
|
||||
|
||||
private slots:
|
||||
void cancelTransfer();
|
||||
void rejectRecvRequest();
|
||||
void acceptRecvRequest();
|
||||
void pauseResumeRecv();
|
||||
void pauseResumeSend();
|
||||
|
||||
private:
|
||||
QString getHumanReadableSize(unsigned long long size);
|
||||
|
||||
private:
|
||||
enum TransfState {tsPending, tsProcessing, tsPaused, tsFinished, tsCanceled};
|
||||
|
||||
static uint Idconter;
|
||||
uint id;
|
||||
|
||||
TransfState state;
|
||||
QImage pic;
|
||||
QString filename, size, speed, eta;
|
||||
QDateTime lastUpdate;
|
||||
long long lastBytesSent;
|
||||
int fileNum;
|
||||
int friendId;
|
||||
QString savePath;
|
||||
ToxFile::FileDirection direction;
|
||||
QString stopFileButtonStylesheet, pauseFileButtonStylesheet, acceptFileButtonStylesheet;
|
||||
};
|
||||
|
||||
#endif // FILETRANSFERINSTANCE_H
|
10
qtox.pro
10
qtox.pro
@ -102,7 +102,10 @@ HEADERS += widget/form/addfriendform.h \
|
||||
widget/croppinglabel.h \
|
||||
widget/friendlistwidget.h \
|
||||
widget/genericchatroomwidget.h \
|
||||
widget/form/genericchatform.h
|
||||
widget/form/genericchatform.h \
|
||||
widget/tool/genericchataction.h \
|
||||
widget/chatareawidget.h \
|
||||
filetransferinstance.h
|
||||
|
||||
SOURCES += \
|
||||
widget/form/addfriendform.cpp \
|
||||
@ -136,4 +139,7 @@ SOURCES += \
|
||||
widget/friendlistwidget.cpp \
|
||||
coreav.cpp \
|
||||
widget/genericchatroomwidget.cpp \
|
||||
widget/form/genericchatform.cpp
|
||||
widget/form/genericchatform.cpp \
|
||||
widget/tool/genericchataction.cpp \
|
||||
widget/chatareawidget.cpp \
|
||||
filetransferinstance.cpp
|
||||
|
3
res.qrc
3
res.qrc
@ -42,6 +42,7 @@
|
||||
<file>ui/callButton/callButtonYellowHover.png</file>
|
||||
<file>ui/callButton/callButtonYellowPressed.png</file>
|
||||
<file>ui/chatArea/chatArea.css</file>
|
||||
<file>ui/chatArea/innerStyle.css</file>
|
||||
<file>ui/chatArea/scrollBarDownArrow.png</file>
|
||||
<file>ui/chatArea/scrollBarDownArrowHover.png</file>
|
||||
<file>ui/chatArea/scrollBarDownArrowPressed.png</file>
|
||||
@ -57,6 +58,7 @@
|
||||
<file>ui/fileButton/fileButton.png</file>
|
||||
<file>ui/fileButton/fileButtonHover.png</file>
|
||||
<file>ui/fileButton/fileButtonPressed.png</file>
|
||||
<file>ui/fileButton/fileButtonDisabled.png</file>
|
||||
<file>ui/msgEdit/msgEdit.css</file>
|
||||
<file>ui/pauseFileButton/default.png</file>
|
||||
<file>ui/pauseFileButton/hover.png</file>
|
||||
@ -124,6 +126,5 @@
|
||||
<file>ui/micButton/micButtonPressed.png</file>
|
||||
<file>ui/micButton/micButton.css</file>
|
||||
<file>ui/volButton/volButton.css</file>
|
||||
<file>ui/fileButton/fileButtonDisabled.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
37
ui/chatArea/innerStyle.css
Normal file
37
ui/chatArea/innerStyle.css
Normal file
@ -0,0 +1,37 @@
|
||||
div.name_me {
|
||||
color: #646464;
|
||||
font-weight: bold;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
div.message_me {
|
||||
color: #646464;
|
||||
padding-right: 3px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
div.date_me {
|
||||
color: #646464;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
div.quote {
|
||||
background-color: #6bc260;
|
||||
}
|
||||
|
||||
div.name {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
div.message {
|
||||
color: #000000;
|
||||
padding-right: 3px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
div.date {
|
||||
color: #000000;
|
||||
padding-left: 3px;
|
||||
}
|
56
widget/chatareawidget.cpp
Normal file
56
widget/chatareawidget.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "chatareawidget.h"
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QMessageBox>
|
||||
|
||||
ChatAreaWidget::ChatAreaWidget(QWidget *parent) :
|
||||
QTextEdit(parent)
|
||||
{
|
||||
setReadOnly(true);
|
||||
viewport()->setCursor(Qt::ArrowCursor);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
}
|
||||
|
||||
void ChatAreaWidget::mouseReleaseEvent(QMouseEvent * event)
|
||||
{
|
||||
QTextEdit::mouseReleaseEvent(event);
|
||||
int pos = this->document()->documentLayout()->hitTest(event->pos(), Qt::ExactHit);
|
||||
if (pos > 0)
|
||||
{
|
||||
QTextCursor cursor(document());
|
||||
cursor.setPosition(pos);
|
||||
if( ! cursor.atEnd() )
|
||||
{
|
||||
cursor.setPosition(pos+1);
|
||||
|
||||
QTextFormat format = cursor.charFormat();
|
||||
if (format.isImageFormat())
|
||||
{
|
||||
QString image = format.toImageFormat().name();
|
||||
if (QRegExp("^data:ftrans.*").exactMatch(image))
|
||||
{
|
||||
image = image.right(image.length() - 12);
|
||||
int endpos = image.indexOf("/png;base64");
|
||||
image = image.left(endpos);
|
||||
int middlepos = image.indexOf(".");
|
||||
emit onFileTranfertInterract(image.left(middlepos),image.right(image.length() - middlepos - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
widget/chatareawidget.h
Normal file
38
widget/chatareawidget.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef CHATAREAWIDGET_H
|
||||
#define CHATAREAWIDGET_H
|
||||
|
||||
#include <QTextEdit>
|
||||
|
||||
class ChatAreaWidget : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ChatAreaWidget(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
void onFileTranfertInterract(QString widgetName, QString buttonName);
|
||||
|
||||
protected:
|
||||
void mouseReleaseEvent(QMouseEvent * event);
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // CHATAREAWIDGET_H
|
@ -23,11 +23,15 @@
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
#include <QBuffer>
|
||||
|
||||
uint FileTransfertWidget::Idconter = 0;
|
||||
|
||||
FileTransfertWidget::FileTransfertWidget(ToxFile File)
|
||||
: lastUpdate{QDateTime::currentDateTime()}, lastBytesSent{0},
|
||||
fileNum{File.fileNum}, friendId{File.friendId}, direction{File.direction}
|
||||
{
|
||||
id = Idconter++;
|
||||
pic=new QLabel(), filename=new QLabel(), size=new QLabel(), speed=new QLabel(), eta=new QLabel();
|
||||
topright = new QPushButton(), bottomright = new QPushButton();
|
||||
progress = new QProgressBar();
|
||||
@ -182,6 +186,7 @@ void FileTransfertWidget::onFileTransferInfo(int FriendId, int FileNum, int64_t
|
||||
}
|
||||
lastUpdate = newtime;
|
||||
lastBytesSent = BytesSent;
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::onFileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection Direction)
|
||||
@ -206,6 +211,8 @@ void FileTransfertWidget::onFileTransferCancelled(int FriendId, int FileNum, Tox
|
||||
//Toggle window visibility to fix draw order bug
|
||||
this->hide();
|
||||
this->show();
|
||||
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::onFileTransferFinished(ToxFile File)
|
||||
@ -245,17 +252,21 @@ void FileTransfertWidget::onFileTransferFinished(ToxFile File)
|
||||
previewFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::cancelTransfer()
|
||||
{
|
||||
Widget::getInstance()->getCore()->cancelFileSend(friendId, fileNum);
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::rejectRecvRequest()
|
||||
{
|
||||
Widget::getInstance()->getCore()->rejectFileRecvRequest(friendId, fileNum);
|
||||
onFileTransferCancelled(friendId, fileNum, direction);
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
// for whatever the fuck reason, QFileInfo::isWritable() always fails for files that don't exist
|
||||
@ -299,16 +310,20 @@ void FileTransfertWidget::acceptRecvRequest()
|
||||
bottomright->disconnect();
|
||||
connect(bottomright, SIGNAL(clicked()), this, SLOT(pauseResumeRecv()));
|
||||
Widget::getInstance()->getCore()->acceptFileRecvRequest(friendId, fileNum, path);
|
||||
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::pauseResumeRecv()
|
||||
{
|
||||
Widget::getInstance()->getCore()->pauseResumeFileRecv(friendId, fileNum);
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::pauseResumeSend()
|
||||
{
|
||||
Widget::getInstance()->getCore()->pauseResumeFileSend(friendId, fileNum);
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
void FileTransfertWidget::paintEvent(QPaintEvent *)
|
||||
@ -317,4 +332,56 @@ void FileTransfertWidget::paintEvent(QPaintEvent *)
|
||||
opt.init(this);
|
||||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
emit stateUpdated();
|
||||
}
|
||||
|
||||
QString FileTransfertWidget::getHtmlImage()
|
||||
{
|
||||
qDebug() << "QString FileTransfertWidget::getHtmlImage()";
|
||||
auto QImage2base64 = [](const QImage &img)
|
||||
{
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG"); // writes image into ba in PNG format
|
||||
return ba.toBase64();
|
||||
};
|
||||
|
||||
auto renderButton = [](QPushButton *pb)
|
||||
{
|
||||
QImage bitmap(pb->size(), QImage::Format_ARGB32);
|
||||
bitmap.fill(Qt::transparent);
|
||||
QPainter painter(&bitmap);
|
||||
|
||||
pb->render(&painter, QPoint(), QRegion(), QWidget::DrawChildren);
|
||||
return bitmap;
|
||||
};
|
||||
|
||||
// QImage rightUp = renderButton(topright);
|
||||
// QImage rightDown = renderButton(bottomright);
|
||||
QImage rightUp(":ui/stopFileButton/default.png");
|
||||
QImage rightDown(":ui/acceptFileButton/default.png");
|
||||
|
||||
QString res;
|
||||
QString widgetId = QString::number(getId());
|
||||
QString strUp = "<img src=\"data:ftrans." + widgetId + ".top/png;base64," + QImage2base64(rightUp) + "\">";
|
||||
QString strDown = "<img src=\"data:ftrans." + widgetId + ".bottom/png;base64," + QImage2base64(rightDown) + "\">";
|
||||
|
||||
res = "<table widht=100% cellspacing=\"2\">\n";
|
||||
res += "<tr>\n<td width=100%>\n";
|
||||
res += "<div class=quote></div>\n";
|
||||
res += "</td>\n<td>\n";
|
||||
if (topright->isVisible() && bottomright->isVisible())
|
||||
res += "<table cellspacing=\"0\"><tr valign=top><td>" + strUp + "</td></tr><tr valign=bottom><td>" + strDown + "</td></tr></table>\n";
|
||||
res += "</td>\n</tr>\n";
|
||||
res += "</table>\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
void FileTransfertWidget::pressFromHtml(QString code)
|
||||
{
|
||||
if (code == "top")
|
||||
topright->clicked();
|
||||
else if (code == "bottom")
|
||||
bottomright->clicked();
|
||||
}
|
||||
|
@ -35,12 +35,19 @@ class FileTransfertWidget : public QWidget
|
||||
|
||||
public:
|
||||
FileTransfertWidget(ToxFile File);
|
||||
QString getHtmlImage();
|
||||
uint getId(){return id;}
|
||||
|
||||
public slots:
|
||||
void onFileTransferInfo(int FriendId, int FileNum, int64_t Filesize, int64_t BytesSent, ToxFile::FileDirection Direction);
|
||||
void onFileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection Direction);
|
||||
void onFileTransferFinished(ToxFile File);
|
||||
|
||||
void pressFromHtml(QString);
|
||||
|
||||
signals:
|
||||
void stateUpdated();
|
||||
|
||||
private slots:
|
||||
void cancelTransfer();
|
||||
void rejectRecvRequest();
|
||||
@ -52,6 +59,10 @@ private:
|
||||
QString getHumanReadableSize(unsigned long long size);
|
||||
|
||||
private:
|
||||
static uint Idconter;
|
||||
uint id;
|
||||
|
||||
|
||||
QLabel *pic, *filename, *size, *speed, *eta;
|
||||
QPushButton *topright, *bottomright;
|
||||
QProgressBar *progress;
|
||||
|
@ -43,6 +43,7 @@ ChatForm::ChatForm(Friend* chatFriend)
|
||||
connect(videoButton, &QPushButton::clicked, this, &ChatForm::onVideoCallTriggered);
|
||||
connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered);
|
||||
connect(micButton, SIGNAL(clicked()), this, SLOT(onMicMuteToggle()));
|
||||
connect(newChatForm, SIGNAL(onFileTranfertInterract(QString,QString)), this, SLOT(onFileTansBtnClicked(QString,QString)));
|
||||
}
|
||||
|
||||
ChatForm::~ChatForm()
|
||||
@ -94,36 +95,42 @@ void ChatForm::startFileSend(ToxFile file)
|
||||
if (file.friendId != f->friendId)
|
||||
return;
|
||||
|
||||
QLabel *author = new QLabel(Widget::getInstance()->getUsername());
|
||||
QLabel *date = new QLabel(QTime::currentTime().toString("hh:mm"));
|
||||
QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
author->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||
date->setAlignment(Qt::AlignTop);
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::WindowText, Qt::gray);
|
||||
author->setPalette(pal);
|
||||
if (previousName.isEmpty() || previousName != author->text())
|
||||
{
|
||||
if (curRow)
|
||||
{
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
|
||||
curRow++;
|
||||
}
|
||||
mainChatLayout->addWidget(author, curRow, 0);
|
||||
}
|
||||
FileTransfertWidget* fileTrans = new FileTransfertWidget(file);
|
||||
previousName = author->text();
|
||||
mainChatLayout->addWidget(fileTrans, curRow, 1);
|
||||
mainChatLayout->addWidget(date, curRow, 3);
|
||||
mainChatLayout->setRowStretch(curRow+1, 1);
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
curRow++;
|
||||
// QLabel *author = new QLabel(Widget::getInstance()->getUsername());
|
||||
// QLabel *date = new QLabel(QTime::currentTime().toString("hh:mm"));
|
||||
// QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
// lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
// author->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||
// date->setAlignment(Qt::AlignTop);
|
||||
// QPalette pal;
|
||||
// pal.setColor(QPalette::WindowText, Qt::gray);
|
||||
// author->setPalette(pal);
|
||||
// if (previousName.isEmpty() || previousName != author->text())
|
||||
// {
|
||||
// if (curRow)
|
||||
// {
|
||||
// mainChatLayout->setRowStretch(curRow, 0);
|
||||
// mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
|
||||
// curRow++;
|
||||
// }
|
||||
// mainChatLayout->addWidget(author, curRow, 0);
|
||||
// }
|
||||
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferInfo, fileTrans, &FileTransfertWidget::onFileTransferInfo);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferCancelled, fileTrans, &FileTransfertWidget::onFileTransferCancelled);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferFinished, fileTrans, &FileTransfertWidget::onFileTransferFinished);
|
||||
FileTransferInstance* fileTrans = new FileTransferInstance(file);
|
||||
ftransWidgets.insert(fileTrans->getId(), fileTrans);
|
||||
// previousName = author->text();
|
||||
// mainChatLayout->addWidget(fileTrans, curRow, 1);
|
||||
// mainChatLayout->addWidget(date, curRow, 3);
|
||||
// mainChatLayout->setRowStretch(curRow+1, 1);
|
||||
// mainChatLayout->setRowStretch(curRow, 0);
|
||||
// curRow++;
|
||||
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferInfo, fileTrans, &FileTransferInstance::onFileTransferInfo);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferCancelled, fileTrans, &FileTransferInstance::onFileTransferCancelled);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferFinished, fileTrans, &FileTransferInstance::onFileTransferFinished);
|
||||
connect(fileTrans, SIGNAL(stateUpdated()), this, SLOT(updateChatContent()));
|
||||
|
||||
messages.append(new FileTransferAction(fileTrans, Widget::getInstance()->getUsername(), QTime::currentTime().toString("hh:mm")));
|
||||
updateChatContent();
|
||||
}
|
||||
|
||||
void ChatForm::onFileRecvRequest(ToxFile file)
|
||||
@ -131,33 +138,35 @@ void ChatForm::onFileRecvRequest(ToxFile file)
|
||||
if (file.friendId != f->friendId)
|
||||
return;
|
||||
|
||||
QLabel *author = new QLabel(f->getName());
|
||||
QLabel *date = new QLabel(QTime::currentTime().toString("hh:mm"));
|
||||
QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
author->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||
date->setAlignment(Qt::AlignTop);
|
||||
if (previousName.isEmpty() || previousName != author->text())
|
||||
{
|
||||
if (curRow)
|
||||
{
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
|
||||
curRow++;
|
||||
}
|
||||
mainChatLayout->addWidget(author, curRow, 0);
|
||||
}
|
||||
FileTransfertWidget* fileTrans = new FileTransfertWidget(file);
|
||||
previousName = author->text();
|
||||
mainChatLayout->addWidget(fileTrans, curRow, 1);
|
||||
mainChatLayout->addWidget(date, curRow, 3);
|
||||
mainChatLayout->setRowStretch(curRow+1, 1);
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
curRow++;
|
||||
// QLabel *author = new QLabel(f->getName());
|
||||
// QLabel *date = new QLabel(QTime::currentTime().toString("hh:mm"));
|
||||
// QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
// lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
// author->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||
// date->setAlignment(Qt::AlignTop);
|
||||
// if (previousName.isEmpty() || previousName != author->text())
|
||||
// {
|
||||
// if (curRow)
|
||||
// {
|
||||
// mainChatLayout->setRowStretch(curRow, 0);
|
||||
// mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
|
||||
// curRow++;
|
||||
// }
|
||||
// mainChatLayout->addWidget(author, curRow, 0);
|
||||
// }
|
||||
FileTransferInstance* fileTrans = new FileTransferInstance(file);
|
||||
ftransWidgets.insert(fileTrans->getId(), fileTrans);
|
||||
// previousName = author->text();
|
||||
// mainChatLayout->addWidget(fileTrans, curRow, 1);
|
||||
// mainChatLayout->addWidget(date, curRow, 3);
|
||||
// mainChatLayout->setRowStretch(curRow+1, 1);
|
||||
// mainChatLayout->setRowStretch(curRow, 0);
|
||||
// curRow++;
|
||||
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferInfo, fileTrans, &FileTransfertWidget::onFileTransferInfo);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferCancelled, fileTrans, &FileTransfertWidget::onFileTransferCancelled);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferFinished, fileTrans, &FileTransfertWidget::onFileTransferFinished);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferInfo, fileTrans, &FileTransferInstance::onFileTransferInfo);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferCancelled, fileTrans, &FileTransferInstance::onFileTransferCancelled);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferFinished, fileTrans, &FileTransferInstance::onFileTransferFinished);
|
||||
connect(fileTrans, SIGNAL(stateUpdated()), this, SLOT(updateChatContent()));
|
||||
|
||||
Widget* w = Widget::getInstance();
|
||||
if (!w->isFriendWidgetCurActiveWidget(f)|| w->getIsWindowMinimized() || !w->isActiveWindow())
|
||||
@ -166,6 +175,9 @@ void ChatForm::onFileRecvRequest(ToxFile file)
|
||||
f->hasNewEvents=true;
|
||||
f->widget->updateStatusLight();
|
||||
}
|
||||
|
||||
messages.append(new FileTransferAction(fileTrans, f->getName(), QTime::currentTime().toString("hh:mm")));
|
||||
updateChatContent();
|
||||
}
|
||||
|
||||
void ChatForm::onAvInvite(int FriendId, int CallId, bool video)
|
||||
@ -461,3 +473,16 @@ void ChatForm::onMicMuteToggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::onFileTansBtnClicked(QString widgetName, QString buttonName)
|
||||
{
|
||||
uint id = widgetName.toUInt();
|
||||
|
||||
auto it = ftransWidgets.find(id);
|
||||
if (it != ftransWidgets.end())
|
||||
it.value()->pressFromHtml(buttonName);
|
||||
else
|
||||
qDebug() << "no filetransferwidget: " << id;
|
||||
|
||||
// QMessageBox::information(nullptr, message, message);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "widget/netcamview.h"
|
||||
|
||||
struct Friend;
|
||||
class FileTransferInstance;
|
||||
|
||||
class ChatForm : public GenericChatForm
|
||||
{
|
||||
@ -63,6 +64,7 @@ private slots:
|
||||
void onAnswerCallTriggered();
|
||||
void onHangupCallTriggered();
|
||||
void onCancelCallTriggered();
|
||||
void onFileTansBtnClicked(QString widgetName, QString buttonName);
|
||||
|
||||
private:
|
||||
Friend* f;
|
||||
@ -70,6 +72,8 @@ private:
|
||||
NetCamView* netcam;
|
||||
bool audioInputFlag;
|
||||
int callId;
|
||||
|
||||
QHash<uint, FileTransferInstance*> ftransWidgets;
|
||||
};
|
||||
|
||||
#endif // CHATFORM_H
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "widget/emoticonswidget.h"
|
||||
#include "style.h"
|
||||
#include "widget/widget.h"
|
||||
#include "settings.h"
|
||||
|
||||
GenericChatForm::GenericChatForm(QObject *parent) :
|
||||
QObject(parent)
|
||||
@ -40,6 +41,10 @@ GenericChatForm::GenericChatForm(QObject *parent) :
|
||||
QVBoxLayout *footButtonsSmall = new QVBoxLayout(), *volMicLayout = new QVBoxLayout();
|
||||
mainChatLayout = new QGridLayout();
|
||||
|
||||
newChatForm = new ChatAreaWidget();
|
||||
newChatForm->document()->setDefaultStyleSheet(Style::get(":ui/chatArea/innerStyle.css"));
|
||||
newChatForm->setStyleSheet(Style::get(":/ui/chatArea/chatArea.css"));
|
||||
|
||||
msgEdit = new ChatTextEdit();
|
||||
|
||||
sendButton = new QPushButton();
|
||||
@ -112,6 +117,7 @@ GenericChatForm::GenericChatForm(QObject *parent) :
|
||||
|
||||
mainWidget->setLayout(mainLayout);
|
||||
mainLayout->addWidget(chatArea);
|
||||
mainLayout->addWidget(newChatForm);
|
||||
mainLayout->addLayout(mainFootLayout);
|
||||
mainLayout->setMargin(0);
|
||||
|
||||
@ -147,8 +153,8 @@ GenericChatForm::GenericChatForm(QObject *parent) :
|
||||
emoteButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
|
||||
|
||||
connect(emoteButton, SIGNAL(clicked()), this, SLOT(onEmoteButtonClicked()));
|
||||
connect(chatArea, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
|
||||
connect(chatArea->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(onSliderRangeChanged()));
|
||||
connect(newChatForm, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
|
||||
connect(newChatForm->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(onSliderRangeChanged()));
|
||||
}
|
||||
|
||||
void GenericChatForm::setName(const QString &newName)
|
||||
@ -176,7 +182,7 @@ void GenericChatForm::onChatContextMenuRequested(QPoint pos)
|
||||
|
||||
void GenericChatForm::onSliderRangeChanged()
|
||||
{
|
||||
QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
QScrollBar* scroll = newChatForm->verticalScrollBar();
|
||||
if (lockSliderToBottom)
|
||||
scroll->setValue(scroll->maximum());
|
||||
}
|
||||
@ -192,96 +198,28 @@ void GenericChatForm::onSaveLogClicked()
|
||||
return;
|
||||
|
||||
QString log;
|
||||
QList<QLabel*> labels = chatAreaWidget->findChildren<QLabel*>();
|
||||
int i=0;
|
||||
for (QLabel* label : labels)
|
||||
{
|
||||
log += label->text();
|
||||
if (i==2)
|
||||
{
|
||||
i=0;
|
||||
log += '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
log += '\t';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
log = newChatForm->toPlainText();
|
||||
|
||||
file.write(log.toUtf8());
|
||||
file.close();
|
||||
}
|
||||
|
||||
void GenericChatForm::addMessage(QString author, QString message, QString date)
|
||||
void GenericChatForm::addMessage(QString author, QString message, QDateTime datetime)
|
||||
{
|
||||
QLabel *authorLabel = new QLabel(author);
|
||||
QLabel *messageLabel = new QLabel();
|
||||
QLabel *dateLabel = new QLabel(date);
|
||||
|
||||
QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
authorLabel->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||
dateLabel->setAlignment(Qt::AlignTop);
|
||||
messageLabel->setWordWrap(true);
|
||||
messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
authorLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
dateLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
if (author == Widget::getInstance()->getUsername())
|
||||
{
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::WindowText, QColor(100,100,100));
|
||||
authorLabel->setPalette(pal);
|
||||
messageLabel->setPalette(pal);
|
||||
}
|
||||
if (previousName.isEmpty() || previousName != author)
|
||||
{
|
||||
if (curRow)
|
||||
{
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
|
||||
}
|
||||
QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
|
||||
if (previousName == author)
|
||||
messages.append(new MessageAction("", message, date));
|
||||
else messages.append(new MessageAction(author , message, date));
|
||||
previousName = author;
|
||||
curRow++;
|
||||
}
|
||||
else if (curRow)// onSaveLogClicked expects 0 or 3 QLabel per line
|
||||
authorLabel->setText("");
|
||||
|
||||
QColor greentext(61,204,61);
|
||||
QString fontTemplate = "<font color='%1'>%2</font>";
|
||||
|
||||
QString finalMessage;
|
||||
QStringList messageLines = message.split("\n");
|
||||
for (QString& s : messageLines)
|
||||
{
|
||||
if (QRegExp("^[ ]*>.*").exactMatch(s))
|
||||
finalMessage += fontTemplate.arg(greentext.name(), toHtmlChars(s));
|
||||
else
|
||||
finalMessage += toHtmlChars(s);
|
||||
finalMessage += "<br>";
|
||||
}
|
||||
messageLabel->setText(finalMessage.left(finalMessage.length()-4));
|
||||
messageLabel->setText(SmileyPack::getInstance().smileyfied(messageLabel->text()));
|
||||
messageLabel->setTextFormat(Qt::RichText);
|
||||
|
||||
mainChatLayout->addWidget(authorLabel, curRow, 0);
|
||||
mainChatLayout->addWidget(messageLabel, curRow, 1);
|
||||
mainChatLayout->addWidget(dateLabel, curRow, 3);
|
||||
mainChatLayout->setRowStretch(curRow+1, 1);
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
curRow++;
|
||||
authorLabel->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
messageLabel->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
dateLabel->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(authorLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
|
||||
connect(messageLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
|
||||
connect(dateLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
|
||||
updateChatContent();
|
||||
}
|
||||
|
||||
GenericChatForm::~GenericChatForm()
|
||||
{
|
||||
delete mainWidget;
|
||||
delete headWidget;
|
||||
for (ChatAction *it : messages)
|
||||
delete it;
|
||||
}
|
||||
|
||||
void GenericChatForm::onEmoteButtonClicked()
|
||||
@ -311,13 +249,22 @@ void GenericChatForm::onEmoteInsertRequested(QString str)
|
||||
msgEdit->setFocus(); // refocus so that we can continue typing
|
||||
}
|
||||
|
||||
QString GenericChatForm::toHtmlChars(const QString &str)
|
||||
QString GenericChatForm::getHtmledMessages()
|
||||
{
|
||||
static QList<QPair<QString, QString>> replaceList = {{"&","&"}, {" "," "}, {">",">"}, {"<","<"}};
|
||||
QString res = str;
|
||||
|
||||
for (auto &it : replaceList)
|
||||
res = res.replace(it.first,it.second);
|
||||
QString res("<table width=100%>\n");
|
||||
|
||||
for (ChatAction *it : messages)
|
||||
{
|
||||
res += it->getHtml();
|
||||
}
|
||||
res += "</table>";
|
||||
return res;
|
||||
}
|
||||
|
||||
void GenericChatForm::updateChatContent()
|
||||
{
|
||||
QScrollBar* scroll = newChatForm->verticalScrollBar();
|
||||
lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
|
||||
newChatForm->setHtml(getHtmledMessages());
|
||||
}
|
||||
|
@ -28,7 +28,9 @@
|
||||
#include <QPushButton>
|
||||
#include <QGridLayout>
|
||||
|
||||
#include "widget/chatareawidget.h"
|
||||
#include "widget/tool/chattextedit.h"
|
||||
#include "widget/tool/genericchataction.h"
|
||||
|
||||
// Spacing in px inserted when the author of the last message changes
|
||||
#define AUTHOR_CHANGE_SPACING 5
|
||||
@ -46,7 +48,7 @@ public:
|
||||
|
||||
virtual void setName(const QString &newName);
|
||||
virtual void show(Ui::MainWindow &ui);
|
||||
void addMessage(QString author, QString message, QString date=QTime::currentTime().toString("hh:mm"));
|
||||
void addMessage(QString author, QString message, QDateTime datetime=QDateTime::currentDateTime());
|
||||
|
||||
signals:
|
||||
void sendMessage(int, QString);
|
||||
@ -59,6 +61,7 @@ protected slots:
|
||||
void onSaveLogClicked();
|
||||
void onEmoteButtonClicked();
|
||||
void onEmoteInsertRequested(QString str);
|
||||
void updateChatContent();
|
||||
|
||||
protected:
|
||||
QLabel *nameLabel, *avatarLabel;
|
||||
@ -70,11 +73,14 @@ protected:
|
||||
ChatTextEdit *msgEdit;
|
||||
QPushButton *sendButton;
|
||||
QString previousName;
|
||||
ChatAreaWidget *newChatForm;
|
||||
int curRow;
|
||||
bool lockSliderToBottom;
|
||||
|
||||
QList<ChatAction*> messages;
|
||||
|
||||
private:
|
||||
QString toHtmlChars(const QString &str);
|
||||
QString getHtmledMessages();
|
||||
};
|
||||
|
||||
#endif // GENERICCHATFORM_H
|
||||
|
116
widget/tool/genericchataction.cpp
Normal file
116
widget/tool/genericchataction.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "genericchataction.h"
|
||||
#include "smileypack.h"
|
||||
#include <QStringList>
|
||||
#include <QBuffer>
|
||||
|
||||
QString ChatAction::toHtmlChars(const QString &str)
|
||||
{
|
||||
static QList<QPair<QString, QString>> replaceList = {{"&","&"}, {" "," "}, {">",">"}, {"<","<"}};
|
||||
QString res = str;
|
||||
|
||||
for (auto &it : replaceList)
|
||||
res = res.replace(it.first,it.second);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QString ChatAction::QImage2base64(const QImage &img)
|
||||
{
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG"); // writes image into ba in PNG format
|
||||
return ba.toBase64();
|
||||
}
|
||||
|
||||
QString ChatAction::wrapName(const QString &name)
|
||||
{
|
||||
QString res = "<td><div class=name>" + name + "</div></td>\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
QString ChatAction::wrapDate(const QString &date)
|
||||
{
|
||||
QString res = "<td align=right><div class=date>" + date + "</div></td>\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
QString ChatAction::wrapMessage(const QString &message)
|
||||
{
|
||||
QString res = "<td width=100%><div class=message>" + message + "</div></td>\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
QString ChatAction::wrapWholeLine(const QString &line)
|
||||
{
|
||||
QString res = "<tr>\n" + line + "</tr>\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
MessageAction::MessageAction(const QString &author, const QString &message, const QString &date)
|
||||
{
|
||||
QString message_ = SmileyPack::getInstance().smileyfied(toHtmlChars(message));
|
||||
|
||||
QStringList messageLines = message_.split("\n");
|
||||
message_ = "";
|
||||
for (QString& s : messageLines)
|
||||
{
|
||||
if (QRegExp("^[ ]*>.*").exactMatch(s))
|
||||
message_ += "<div class=quote>" + s.right(s.length()-4) + "</div><br>";
|
||||
else
|
||||
message_ += s + "<br>";
|
||||
}
|
||||
message_ = message_.left(message_.length()-4);
|
||||
|
||||
content = wrapWholeLine(wrapName(author) + wrapMessage(message_) + wrapDate(date));
|
||||
}
|
||||
|
||||
QString MessageAction::getHtml()
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
FileTransferAction::FileTransferAction(FileTransferInstance *widget, const QString &author, const QString &date) :
|
||||
sender(author),
|
||||
timestamp(date)
|
||||
{
|
||||
w = widget;
|
||||
}
|
||||
|
||||
FileTransferAction::~FileTransferAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString FileTransferAction::getHtml()
|
||||
{
|
||||
QString widgetHtml;
|
||||
if (w != nullptr)
|
||||
widgetHtml = w->getHtmlImage();
|
||||
else
|
||||
widgetHtml = "<div class=quote>EMPTY CONTENT</div>";
|
||||
QString res = wrapWholeLine(wrapName(sender) + wrapMessage(widgetHtml) + wrapDate(timestamp));;
|
||||
return res;
|
||||
}
|
||||
|
||||
QString FileTransferAction::wrapMessage(const QString &message)
|
||||
{
|
||||
QString res = "<td width=100%>" + message + "</td>\n";
|
||||
return res;
|
||||
}
|
63
widget/tool/genericchataction.h
Normal file
63
widget/tool/genericchataction.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef CHATACTION_H
|
||||
#define CHATACTION_H
|
||||
|
||||
#include <QString>
|
||||
#include "filetransferinstance.h"
|
||||
|
||||
class ChatAction
|
||||
{
|
||||
public:
|
||||
virtual ~ChatAction(){;}
|
||||
virtual QString getHtml() = 0;
|
||||
|
||||
protected:
|
||||
QString toHtmlChars(const QString &str);
|
||||
QString QImage2base64(const QImage &img);
|
||||
|
||||
virtual QString wrapName(const QString &name);
|
||||
virtual QString wrapDate(const QString &date);
|
||||
virtual QString wrapMessage(const QString &message);
|
||||
virtual QString wrapWholeLine(const QString &line);
|
||||
};
|
||||
|
||||
class MessageAction : public ChatAction
|
||||
{
|
||||
public:
|
||||
MessageAction(const QString &author, const QString &message, const QString &date);
|
||||
virtual ~MessageAction(){;}
|
||||
virtual QString getHtml();
|
||||
|
||||
private:
|
||||
QString content;
|
||||
};
|
||||
|
||||
class FileTransferAction : public ChatAction
|
||||
{
|
||||
public:
|
||||
FileTransferAction(FileTransferInstance *widget, const QString &author, const QString &date);
|
||||
virtual ~FileTransferAction();
|
||||
virtual QString getHtml();
|
||||
virtual QString wrapMessage(const QString &message);
|
||||
|
||||
private:
|
||||
FileTransferInstance *w;
|
||||
QString sender, timestamp;
|
||||
};
|
||||
|
||||
#endif // CHATACTION_H
|
Loading…
x
Reference in New Issue
Block a user