feature: paste image in chat #51
@ -378,7 +378,32 @@ void Core::NetworkAccess::onUploadFinished()
|
||||
qDebug() << "upload success for" << url;
|
||||
|
||||
storage.addFile(upl->messages, upl->url, upl->path);
|
||||
emit uploadFileComplete(upl->messages, upl->url);
|
||||
emit uploadFileComplete(upl->messages, upl->url, upl->path);
|
||||
|
||||
// Copy file to Download folder if it is a temp file. See Conversation::onImagePasted.
|
||||
if (upl->path.startsWith(QDir::tempPath() + QStringLiteral("/squawk_img_attach_")) && upl->path.endsWith(".png")) {
|
||||
QString err = "";
|
||||
QString downloadDirPath = prepareDirectory(upl->messages.front().jid);
|
||||
if (downloadDirPath.size() > 0) {
|
||||
QString newPath = downloadDirPath + "/" + upl->path.mid(QDir::tempPath().length() + 1);
|
||||
|
||||
// Copy {TEMPDIR}/squawk_img_attach_XXXXXX.png to Download folder
|
||||
bool copyResult = QFile::copy(upl->path, newPath);
|
||||
|
||||
if (copyResult) {
|
||||
// Change storage
|
||||
storage.setPath(upl->url, newPath);
|
||||
} else {
|
||||
err = "copying to " + newPath + " failed";
|
||||
}
|
||||
} else {
|
||||
err = "Couldn't prepare a directory for file";
|
||||
}
|
||||
|
||||
if (err.size() != 0) {
|
||||
qDebug() << "failed to copy temporary upload file " << upl->path << " to download folder:" << err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upl->reply->deleteLater();
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
signals:
|
||||
void loadFileProgress(const std::list<Shared::MessageInfo>& msgs, qreal value, bool up);
|
||||
void loadFileError(const std::list<Shared::MessageInfo>& msgs, const QString& text, bool up);
|
||||
void uploadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& url);
|
||||
void uploadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& url, const QString& path);
|
||||
void downloadFileComplete(const std::list<Shared::MessageInfo>& msgs, const QString& path);
|
||||
|
||||
public slots:
|
||||
|
@ -82,7 +82,7 @@ signals:
|
||||
void fileError(const std::list<Shared::MessageInfo> msgs, const QString& error, bool up);
|
||||
void fileProgress(const std::list<Shared::MessageInfo> msgs, qreal value, bool up);
|
||||
void fileDownloadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path);
|
||||
void fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path);
|
||||
void fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& url, const QString& path);
|
||||
|
||||
void responseVCard(const QString& jid, const Shared::VCard& card);
|
||||
void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
|
||||
|
@ -405,7 +405,7 @@ void Squawk::fileError(const std::list<Shared::MessageInfo> msgs, const QString&
|
||||
rosterModel.fileError(msgs, error, up);
|
||||
}
|
||||
|
||||
void Squawk::fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path)
|
||||
void Squawk::fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& url, const QString& path)
|
||||
{
|
||||
rosterModel.fileComplete(msgs, true);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public slots:
|
||||
void fileError(const std::list<Shared::MessageInfo> msgs, const QString& error, bool up);
|
||||
void fileProgress(const std::list<Shared::MessageInfo> msgs, qreal value, bool up);
|
||||
void fileDownloadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path);
|
||||
void fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& path);
|
||||
void fileUploadComplete(const std::list<Shared::MessageInfo> msgs, const QString& url, const QString& path);
|
||||
void responseVCard(const QString& jid, const Shared::VCard& card);
|
||||
void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data);
|
||||
void requestPassword(const QString& account);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "ui_conversation.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QClipboard>
|
||||
#include <QScrollBar>
|
||||
#include <QTimer>
|
||||
#include <QFileDialog>
|
||||
@ -27,6 +28,9 @@
|
||||
#include <unistd.h>
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QCoreApplication>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
#include <QMenu>
|
||||
|
||||
Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el, const QString pJid, const QString pRes, QWidget* parent):
|
||||
QWidget(parent),
|
||||
@ -47,6 +51,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
||||
delegate(new MessageDelegate(this)),
|
||||
manualSliderChange(false),
|
||||
tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1),
|
||||
pasteImageAction(new QAction(tr("Paste Image"), this)),
|
||||
shadow(10, 1, Qt::black, this),
|
||||
contextMenu(new QMenu())
|
||||
{
|
||||
@ -75,6 +80,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
||||
statusLabel = m_ui->statusLabel;
|
||||
|
||||
connect(&ker, &KeyEnterReceiver::enterPressed, this, &Conversation::onEnterPressed);
|
||||
connect(&ker, &KeyEnterReceiver::imagePasted, this, &Conversation::onImagePasted);
|
||||
connect(m_ui->sendButton, &QPushButton::clicked, this, &Conversation::onEnterPressed);
|
||||
connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach);
|
||||
connect(m_ui->clearButton, &QPushButton::clicked, this, &Conversation::onClearButton);
|
||||
@ -82,7 +88,10 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
||||
this, &Conversation::onTextEditDocSizeChanged);
|
||||
|
||||
m_ui->messageEditor->installEventFilter(&ker);
|
||||
m_ui->messageEditor->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
blue marked this conversation as resolved
|
||||
connect(m_ui->messageEditor, &QTextEdit::customContextMenuRequested, this, &Conversation::onMessageEditorContext);
|
||||
connect(pasteImageAction, &QAction::triggered, this, &Conversation::onImagePasted);
|
||||
|
||||
//line->setAutoFillBackground(false);
|
||||
//if (testAttribute(Qt::WA_TranslucentBackground)) {
|
||||
@ -183,10 +192,20 @@ bool KeyEnterReceiver::eventFilter(QObject* obj, QEvent* event)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (k == Qt::Key_V && key->modifiers() & Qt::CTRL) {
|
||||
if (Conversation::checkClipboardImage()) {
|
||||
emit imagePasted();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
bool Conversation::checkClipboardImage() {
|
||||
return !QApplication::clipboard()->image().isNull();
|
||||
}
|
||||
|
||||
QString Conversation::getPalResource() const
|
||||
{
|
||||
return activePalResource;
|
||||
@ -218,6 +237,24 @@ void Conversation::onEnterPressed()
|
||||
}
|
||||
}
|
||||
|
||||
void Conversation::onImagePasted()
|
||||
{
|
||||
QImage image = QApplication::clipboard()->image();
|
||||
if (image.isNull()) {
|
||||
return;
|
||||
}
|
||||
QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + QStringLiteral("/squawk_img_attach_XXXXXX.png"), QApplication::instance());
|
||||
tempFile->open();
|
||||
image.save(tempFile, "PNG");
|
||||
tempFile->close();
|
||||
qDebug() << "image on paste temp file: " << tempFile->fileName();
|
||||
addAttachedFile(tempFile->fileName());
|
||||
|
||||
// The file, if successfully uploaded, will be copied to Download folder.
|
||||
// On application closing, this temporary file will be automatically removed by Qt.
|
||||
// See Core::NetworkAccess::onUploadFinished.
|
||||
}
|
||||
|
||||
void Conversation::onAttach()
|
||||
{
|
||||
QFileDialog* d = new QFileDialog(this, tr("Chose a file to send"));
|
||||
@ -443,3 +480,14 @@ void Conversation::onFeedContext(const QPoint& pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Conversation::onMessageEditorContext(const QPoint& pos)
|
||||
{
|
||||
pasteImageAction->setEnabled(Conversation::checkClipboardImage());
|
||||
|
||||
QMenu *editorMenu = m_ui->messageEditor->createStandardContextMenu();
|
||||
editorMenu->addSeparator();
|
||||
editorMenu->addAction(pasteImageAction);
|
||||
|
||||
editorMenu->exec(this->m_ui->messageEditor->mapToGlobal(pos));
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ protected:
|
||||
|
||||
signals:
|
||||
void enterPressed();
|
||||
void imagePasted();
|
||||
};
|
||||
|
||||
class Conversation : public QWidget
|
||||
@ -77,6 +78,7 @@ public:
|
||||
void setPalResource(const QString& res);
|
||||
virtual void setAvatar(const QString& path);
|
||||
void setFeedFrames(bool top, bool right, bool bottom, bool left);
|
||||
static bool checkClipboardImage();
|
||||
|
||||
signals:
|
||||
void sendMessage(const Shared::Message& message);
|
||||
@ -102,6 +104,7 @@ protected:
|
||||
|
||||
protected slots:
|
||||
void onEnterPressed();
|
||||
void onImagePasted();
|
||||
void onAttach();
|
||||
void onFileSelected();
|
||||
void onBadgeClose();
|
||||
@ -111,6 +114,7 @@ protected slots:
|
||||
void onFeedMessage(const Shared::Message& msg);
|
||||
void positionShadow();
|
||||
void onFeedContext(const QPoint &pos);
|
||||
void onMessageEditorContext(const QPoint &pos);
|
||||
|
||||
public:
|
||||
const bool isMuc;
|
||||
@ -133,6 +137,8 @@ protected:
|
||||
bool manualSliderChange;
|
||||
bool tsb; //transient scroll bars
|
||||
|
||||
QAction* pasteImageAction;
|
||||
|
||||
ShadowOverlay shadow;
|
||||
QMenu* contextMenu;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user
Do you mind if we better move it to initialization block? Cuz, since you declare here that variable again as QAction* it might be even considered like another variable rather than that one declared as a property...
How about this change?
52551c1ce0
That's good, thank you!