diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index 6a0117f00..03f954964 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -627,7 +627,7 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event) QString toolTipText = ui->textBrowser->anchorForPosition(helpEvent->pos()); if (toolTipText.isEmpty() && !ui->textBrowser->getShowImages()){ QString imageStr; - if (ui->textBrowser->checkImage(helpEvent->pos(), imageStr)) { + if (ImageUtil::checkImage(ui->textBrowser, helpEvent->pos(), imageStr)) { toolTipText = imageStr; } } else if (toolTipText.startsWith(PERSONID)){ @@ -1158,7 +1158,7 @@ void ChatWidget::contextMenuTextBrowser(QPoint point) contextMnu->addAction(ui->actionQuote); contextMnu->addAction(ui->actionDropPlacemark); - if(ui->textBrowser->checkImage(point)) + if(ImageUtil::checkImage(ui->textBrowser, point)) { if (! ui->textBrowser->getShowImages()) contextMnu->addAction(ui->actionShow_Hidden_Images); diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.cpp b/retroshare-gui/src/gui/common/MimeTextEdit.cpp index b24a65879..3d3398b0c 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.cpp +++ b/retroshare-gui/src/gui/common/MimeTextEdit.cpp @@ -32,6 +32,7 @@ #include "MimeTextEdit.h" #include "util/HandleRichText.h" #include "gui/RetroShareLink.h" +#include "util/imageutil.h" #include @@ -246,6 +247,18 @@ void MimeTextEdit::contextMenuEvent(QContextMenuEvent *e) QMenu *contextMenu = createStandardContextMenu(e->pos()); + if (ImageUtil::checkImage(this, e->pos())) { + contextMenu->addSeparator(); + + QAction *a = contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/document_save.png"), tr("Save image"), this, SLOT(saveImage())); + a->setData(e->pos()); + + a = contextMenu->addAction( tr("Copy image"), this, SLOT(copyImage())); + a->setData(e->pos()); + + contextMenu->addSeparator(); + } + /* Add actions for pasting links */ contextMenu->addAction( tr("Paste as plain text"), this, SLOT(pastePlainText())); QAction *spoilerAction = contextMenu->addAction(tr("Spoiler"), this, SLOT(spoiler())); @@ -292,3 +305,27 @@ void MimeTextEdit::spoiler() { RsHtml::insertSpoilerText(this->textCursor()); } + +void MimeTextEdit::saveImage() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QPoint point = action->data().toPoint(); + QTextCursor cursor = cursorForPosition(point); + ImageUtil::extractImage(window(), cursor); +} + +void MimeTextEdit::copyImage() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QPoint point = action->data().toPoint(); + QTextCursor cursor = cursorForPosition(point); + ImageUtil::copyImage(window(), cursor); +} diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.h b/retroshare-gui/src/gui/common/MimeTextEdit.h index 9c47cac23..b575c1ac9 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.h +++ b/retroshare-gui/src/gui/common/MimeTextEdit.h @@ -75,6 +75,8 @@ private slots: void pasteOwnCertificateLink(); void pastePlainText(); void spoiler(); + void saveImage(); + void copyImage(); private: QString textUnderCursor() const; diff --git a/retroshare-gui/src/gui/common/RSTextBrowser.cpp b/retroshare-gui/src/gui/common/RSTextBrowser.cpp index c3aaaf454..c11d4edef 100644 --- a/retroshare-gui/src/gui/common/RSTextBrowser.cpp +++ b/retroshare-gui/src/gui/common/RSTextBrowser.cpp @@ -234,64 +234,6 @@ void RSTextBrowser::activateLinkClick(bool active) mLinkClickActive = active; } -/** - * @brief RSTextBrowser::checkImage - * @param pos where to check if image is shown in viewport coordinate - * @param imageStr return html source of cursor - * @return True if an image is under cursor - */ -bool RSTextBrowser::checkImage(QPoint pos, QString &imageStr) -{ - //Get text cursor under pos. But if pos is under text browser end line this return last cursor. - QTextCursor cursor = cursorForPosition(pos); - //First get rect of cursor (could be at left or right of image) - QRect cursorRectStart = cursorRect(cursor); - //Second get text - cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1);//To get character just before - QRect cursorRectLeft = cursorRect(cursor); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2); - QRect cursorRectRight = cursorRect(cursor); - imageStr = cursor.selection().toHtml(); -#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG - mCursorRectStart = cursorRectStart; - mCursorRectLeft = cursorRectLeft; - mCursorRectRight = cursorRectRight; - - std::cerr << "cursorRect LTRB :" << cursorRectStart.left() << ";" << cursorRectStart.top() << ";" << cursorRectStart.right() << ";" << cursorRectStart.bottom() << std::endl; - std::cerr << "cursorRectLeft :" << cursorRectLeft.left() << ";" << cursorRectLeft.top() << ";" << cursorRectLeft.right() << ";" << cursorRectLeft.bottom() << std::endl; - std::cerr << "cursorRectRight :" << cursorRectRight.left() << ";" << cursorRectRight.top() << ";" << cursorRectRight.right() << ";" << cursorRectRight.bottom() << std::endl; - std::cerr << "pos XY :" << pos.x() << ";" << pos.y() << std::endl; -#endif - QRect cursorRectEnd = cursorRectStart; - //Finally set left with right of precedent character. - if (cursorRectEnd.top() < cursorRectLeft.bottom()) - { - cursorRectEnd.setLeft(cursorRectLeft.right()); - } else { - //Image on new line - cursorRectEnd.setLeft(0); - } - //And set Right with left of next character. - if (cursorRectEnd.bottom() > cursorRectRight.top()) - { - cursorRectEnd.setRight(cursorRectRight.left()); - } else { - //New line after Image. - } -#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG - mCursorRectEnd = cursorRectEnd; - - std::cerr << "final cursorRect:" << cursorRectEnd.left() << ";" << cursorRectEnd.top() << ";" << cursorRectEnd.right() << ";" << cursorRectEnd.bottom() << std::endl; - viewport()->update(); -#endif - //If pos is on text rect - if (cursorRectEnd.contains(pos)) - { - return imageStr.indexOf("base64,") != -1; - } - return false; -} - /** * @brief RSTextBrowser::anchorForPosition Replace anchorAt that doesn't works as expected. * @param pos Where to get anchor from text @@ -351,16 +293,27 @@ QMenu *RSTextBrowser::createStandardContextMenuFromPoint(const QPoint &widgetPos QAction *a = menu->addAction(FilesDefs::getIconFromQtResourcePath("://icons/textedit/code.png"), tr("View &Source"), this, SLOT(viewSource())); a->setEnabled(!this->document()->isEmpty()); - if (checkImage(widgetPos)) { + if (ImageUtil::checkImage(this, widgetPos +#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG + , &mCursorRectStart, &mCursorRectLeft, &mCursorRectRight, &mCursorRectEnd +#endif + )) { a = menu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/document_save.png"), tr("Save image"), this, SLOT(saveImage())); a->setData(widgetPos); - } - if (checkImage(widgetPos)) { a = menu->addAction( tr("Copy image"), this, SLOT(copyImage())); a->setData(widgetPos); } +#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG + std::cerr << "cursorRect LTRB :" << mCursorRectStart.left() << ";" << mCursorRectStart.top() << ";" << mCursorRectStart.right() << ";" << mCursorRectStart.bottom() << std::endl; + std::cerr << "cursorRectLeft :" << mCursorRectLeft.left() << ";" << mCursorRectLeft.top() << ";" << mCursorRectLeft.right() << ";" << mCursorRectLeft.bottom() << std::endl; + std::cerr << "cursorRectRight :" << mCursorRectRight.left() << ";" << mCursorRectRight.top() << ";" << mCursorRectRight.right() << ";" << mCursorRectRight.bottom() << std::endl; + std::cerr << "pos XY :" << widgetPos.x() << ";" << widgetPos.y() << std::endl; + std::cerr << "final cursorRect:" << mCursorRectEnd.left() << ";" << mCursorRectEnd.top() << ";" << mCursorRectEnd.right() << ";" << mCursorRectEnd.bottom() << std::endl; + viewport()->update(); +#endif + return menu; } diff --git a/retroshare-gui/src/gui/common/RSTextBrowser.h b/retroshare-gui/src/gui/common/RSTextBrowser.h index 120dd22e8..a10a2b30a 100644 --- a/retroshare-gui/src/gui/common/RSTextBrowser.h +++ b/retroshare-gui/src/gui/common/RSTextBrowser.h @@ -45,8 +45,6 @@ public: void setImageBlockWidget(RSImageBlockWidget *widget); void resetImagesStatus(bool load); QPixmap getBlockedImage(); - bool checkImage(QPoint pos, QString &imageStr); - bool checkImage(QPoint pos) {QString imageStr; return checkImage(pos, imageStr); } QString anchorForPosition(const QPoint &pos) const; // Add QAction to context menu (action won't be deleted) diff --git a/retroshare-gui/src/util/imageutil.cpp b/retroshare-gui/src/util/imageutil.cpp index 9356ae3b2..3368db309 100644 --- a/retroshare-gui/src/util/imageutil.cpp +++ b/retroshare-gui/src/util/imageutil.cpp @@ -23,6 +23,8 @@ #include "util/rstime.h" #include +#include +#include #include #include #include @@ -39,6 +41,64 @@ ImageUtil::ImageUtil() {} +bool ImageUtil::checkImage(const QTextEdit *edit, const QPoint &pos, QRect *cursorRectStartOut, QRect *cursorRectLeftOut, QRect *cursorRectRightOut, QRect *cursorRectEndOut) +{ + QString imageStr; + return checkImage(edit, pos, imageStr, cursorRectStartOut, cursorRectLeftOut, cursorRectRightOut, cursorRectEndOut); +} + +bool ImageUtil::checkImage(const QTextEdit *edit, const QPoint &pos, QString &imageStr, QRect *cursorRectStartOut, QRect *cursorRectLeftOut, QRect *cursorRectRightOut, QRect *cursorRectEndOut) +{ + //Get text cursor under pos. But if pos is under text browser end line this return last cursor. + QTextCursor cursor = edit->cursorForPosition(pos); + //First get rect of cursor (could be at left or right of image) + QRect cursorRectStart = edit->cursorRect(cursor); + //Second get text + cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1);//To get character just before + QRect cursorRectLeft = edit->cursorRect(cursor); + cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2); + QRect cursorRectRight = edit->cursorRect(cursor); + imageStr = cursor.selection().toHtml(); + + if (cursorRectStartOut) { + *cursorRectStartOut = cursorRectStart; + } + if (cursorRectLeftOut) { + *cursorRectLeftOut = cursorRectLeft; + } + if (cursorRectRightOut) { + *cursorRectRightOut = cursorRectRight; + } + + QRect cursorRectEnd = cursorRectStart; + //Finally set left with right of precedent character. + if (cursorRectEnd.top() < cursorRectLeft.bottom()) + { + cursorRectEnd.setLeft(cursorRectLeft.right()); + } else { + //Image on new line + cursorRectEnd.setLeft(0); + } + //And set Right with left of next character. + if (cursorRectEnd.bottom() > cursorRectRight.top()) + { + cursorRectEnd.setRight(cursorRectRight.left()); + } else { + //New line after Image. + } + + if (cursorRectEndOut) { + *cursorRectEndOut = cursorRectEnd; + } + + //If pos is on text rect + if (cursorRectEnd.contains(pos)) + { + return imageStr.indexOf("base64,") != -1; + } + return false; +} + void ImageUtil::extractImage(QWidget *window, QTextCursor cursor, QString file) { cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1); diff --git a/retroshare-gui/src/util/imageutil.h b/retroshare-gui/src/util/imageutil.h index 137c0ea8e..8e7d26987 100644 --- a/retroshare-gui/src/util/imageutil.h +++ b/retroshare-gui/src/util/imageutil.h @@ -22,15 +22,19 @@ #define IMAGEUTIL_H #include -#include -#include #include +class QWidget; +class QTextEdit; +class QByteArray; + class ImageUtil { public: ImageUtil(); + static bool checkImage(const QTextEdit *edit, const QPoint &pos, QRect *cursorRectStartOut = NULL, QRect *cursorRectLeftOut = NULL, QRect *cursorRectRightOut = NULL, QRect *cursorRectEndOut = NULL); + static bool checkImage(const QTextEdit *edit, const QPoint &pos, QString &imageStr, QRect *cursorRectStartOut = NULL, QRect *cursorRectLeftOut = NULL, QRect *cursorRectRightOut = NULL, QRect *cursorRectEndOut = NULL); static void extractImage(QWidget *window, QTextCursor cursor, QString file = ""); static void copyImage(QWidget *window, QTextCursor cursor); static bool optimizeSizeHtml(QString &html, const QImage& original, QImage &optimized, int maxPixels = -1, int maxBytes = -1);