feat: support basic image copy and paste

This commit is contained in:
Gary Wang 2020-01-01 14:51:46 +08:00
parent 4a5fe4c289
commit c51a603ec9
8 changed files with 183 additions and 32 deletions

View File

@ -8,6 +8,7 @@
#include <QGraphicsSvgItem>
#include <QMovie>
#include <QLabel>
#include <QPainter>
GraphicsScene::GraphicsScene(QObject *parent)
: QGraphicsScene(parent)
@ -58,3 +59,12 @@ void GraphicsScene::showGif(const QString &filepath)
QPen(Qt::transparent));
this->setSceneRect(m_theThing->boundingRect());
}
QPixmap GraphicsScene::renderToPixmap()
{
QPixmap pixmap(sceneRect().toRect().size());
QPainter p(&pixmap);
render(&p, sceneRect());
return pixmap;
}

View File

@ -15,6 +15,8 @@ public:
void showSvg(const QString &filepath);
void showGif(const QString &filepath);
QPixmap renderToPixmap();
private:
QGraphicsItem * m_theThing;
};

View File

@ -59,6 +59,13 @@ void GraphicsView::showImage(const QPixmap &pixmap)
checkAndDoFitInView();
}
void GraphicsView::showImage(const QImage &image)
{
resetTransform();
scene()->showImage(QPixmap::fromImage(image));
checkAndDoFitInView();
}
void GraphicsView::showText(const QString &text)
{
resetTransform();

View File

@ -14,6 +14,7 @@ public:
void showFileFromUrl(const QUrl &url, bool requestGallery = false);
void showImage(const QPixmap &pixmap);
void showImage(const QImage &image);
void showText(const QString &text);
void showSvg(const QString &filepath);
void showGif(const QString &filepath);

View File

@ -4,7 +4,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../graphicsscene.cpp" line="15"/>
<location filename="../graphicsscene.cpp" line="16"/>
<source>Drag image here</source>
<translation type="unfinished"></translation>
</message>
@ -12,22 +12,22 @@
<context>
<name>GraphicsView</name>
<message>
<location filename="../graphicsview.cpp" line="32"/>
<location filename="../graphicsview.cpp" line="239"/>
<source>File url list is empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphicsview.cpp" line="46"/>
<location filename="../graphicsview.cpp" line="44"/>
<source>File is not a valid image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphicsview.cpp" line="238"/>
<location filename="../graphicsview.cpp" line="247"/>
<source>Image data is invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphicsview.cpp" line="245"/>
<location filename="../graphicsview.cpp" line="254"/>
<source>Not supported mimedata: %1</source>
<translation type="unfinished"></translation>
</message>
@ -35,44 +35,74 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="229"/>
<location filename="../mainwindow.cpp" line="248"/>
<location filename="../mainwindow.cpp" line="143"/>
<source>File url list is empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="322"/>
<source>&amp;Copy</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="343"/>
<source>Copy &amp;Pixmap</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="348"/>
<source>Copy &amp;File Path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="358"/>
<source>&amp;Paste Image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="363"/>
<source>&amp;Paste Image File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="368"/>
<location filename="../mainwindow.cpp" line="387"/>
<source>Stay on top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="235"/>
<location filename="../mainwindow.cpp" line="249"/>
<location filename="../mainwindow.cpp" line="374"/>
<location filename="../mainwindow.cpp" line="388"/>
<source>Protected mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="241"/>
<location filename="../mainwindow.cpp" line="380"/>
<source>Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="244"/>
<location filename="../mainwindow.cpp" line="383"/>
<source>Launch application with image file path as argument to load the file.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="245"/>
<location filename="../mainwindow.cpp" line="384"/>
<source>Drag and drop image file onto the window is also supported.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="247"/>
<location filename="../mainwindow.cpp" line="386"/>
<source>Context menu option explanation:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="248"/>
<location filename="../mainwindow.cpp" line="387"/>
<source>Make window stay on top of all other windows.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="249"/>
<location filename="../mainwindow.cpp" line="388"/>
<source>Avoid close window accidentally. (eg. by double clicking the window)</source>
<translation type="unfinished"></translation>
</message>

View File

@ -4,7 +4,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../graphicsscene.cpp" line="15"/>
<location filename="../graphicsscene.cpp" line="16"/>
<source>Drag image here</source>
<translation></translation>
</message>
@ -12,22 +12,22 @@
<context>
<name>GraphicsView</name>
<message>
<location filename="../graphicsview.cpp" line="32"/>
<location filename="../graphicsview.cpp" line="239"/>
<source>File url list is empty</source>
<translation> URL </translation>
</message>
<message>
<location filename="../graphicsview.cpp" line="46"/>
<location filename="../graphicsview.cpp" line="44"/>
<source>File is not a valid image</source>
<translation></translation>
</message>
<message>
<location filename="../graphicsview.cpp" line="238"/>
<location filename="../graphicsview.cpp" line="247"/>
<source>Image data is invalid</source>
<translation></translation>
</message>
<message>
<location filename="../graphicsview.cpp" line="245"/>
<location filename="../graphicsview.cpp" line="254"/>
<source>Not supported mimedata: %1</source>
<translation> MimeData %1</translation>
</message>
@ -35,44 +35,74 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="229"/>
<location filename="../mainwindow.cpp" line="248"/>
<location filename="../mainwindow.cpp" line="143"/>
<source>File url list is empty</source>
<translation> URL </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="322"/>
<source>&amp;Copy</source>
<translation>(&amp;C)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="343"/>
<source>Copy &amp;Pixmap</source>
<translation>(&amp;P)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="348"/>
<source>Copy &amp;File Path</source>
<translation>(&amp;F)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="358"/>
<source>&amp;Paste Image</source>
<translation>(&amp;P)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="363"/>
<source>&amp;Paste Image File</source>
<translation>(&amp;P)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="368"/>
<location filename="../mainwindow.cpp" line="387"/>
<source>Stay on top</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="235"/>
<location filename="../mainwindow.cpp" line="249"/>
<location filename="../mainwindow.cpp" line="374"/>
<location filename="../mainwindow.cpp" line="388"/>
<source>Protected mode</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="241"/>
<location filename="../mainwindow.cpp" line="380"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="244"/>
<location filename="../mainwindow.cpp" line="383"/>
<source>Launch application with image file path as argument to load the file.</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="245"/>
<location filename="../mainwindow.cpp" line="384"/>
<source>Drag and drop image file onto the window is also supported.</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="247"/>
<location filename="../mainwindow.cpp" line="386"/>
<source>Context menu option explanation:</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="248"/>
<location filename="../mainwindow.cpp" line="387"/>
<source>Make window stay on top of all other windows.</source>
<translation>使</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="249"/>
<location filename="../mainwindow.cpp" line="388"/>
<source>Avoid close window accidentally. (eg. by double clicking the window)</source>
<translation></translation>
</message>

View File

@ -17,6 +17,8 @@
#include <QShortcut>
#include <QDir>
#include <QCollator>
#include <QClipboard>
#include <QMimeData>
#ifdef _WIN32
#include <windows.h>
@ -173,12 +175,22 @@ void MainWindow::adjustWindowSizeBySceneRect()
}
}
// can be empty if it is NOT from a local file.
QUrl MainWindow::currentImageFileUrl() const
{
if (m_currentFileIndex != -1) {
return m_files.value(m_currentFileIndex);
}
return QUrl();
}
void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
{
QFileInfo info(path);
QDir dir(info.path());
QString currentFileName = info.fileName();
QStringList entryList = dir.entryList({"*.jpg", "*.jpeg", "*.png", "*.gif", "*.svg"},
QStringList entryList = dir.entryList({"*.jpg", "*.jpeg", "*.png", "*.gif", "*.svg", "*.bmp"},
QDir::Files | QDir::NoSymLinks, QDir::NoSort);
QCollator collator;
@ -197,7 +209,7 @@ void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
}
}
qDebug() << m_files << m_currentFileIndex;
// qDebug() << m_files << m_currentFileIndex;
}
void MainWindow::galleryPrev()
@ -307,6 +319,52 @@ void MainWindow::resizeEvent(QResizeEvent *event)
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
QMenu * menu = new QMenu;
QMenu * copyMenu = new QMenu(tr("&Copy"));
QUrl currentFileUrl = currentImageFileUrl();
QImage clipboardImage;
QUrl clipboardFileUrl;
const QMimeData * clipboardData = QApplication::clipboard()->mimeData();
if (clipboardData->hasImage()) {
QVariant imageVariant(clipboardData->imageData());
if (imageVariant.isValid()) {
clipboardImage = qvariant_cast<QImage>(imageVariant);
}
} else if (clipboardData->hasText()) {
QString clipboardText(clipboardData->text());
if (clipboardText.startsWith("PICTURE:")) {
QString maybeFilename(clipboardText.mid(8));
if (QFile::exists(maybeFilename)) {
clipboardFileUrl = QUrl::fromLocalFile(maybeFilename);
}
}
}
QAction * copyPixmap = new QAction(tr("Copy &Pixmap"));
connect(copyPixmap, &QAction::triggered, this, [ = ](){
QClipboard *cb = QApplication::clipboard();
cb->setPixmap(m_graphicsView->scene()->renderToPixmap());
});
QAction * copyFilePath = new QAction(tr("Copy &File Path"));
connect(copyFilePath, &QAction::triggered, this, [ = ](){
QClipboard *cb = QApplication::clipboard();
cb->setText(currentFileUrl.toLocalFile());
});
copyMenu->addAction(copyPixmap);
if (currentFileUrl.isValid()) {
copyMenu->addAction(copyFilePath);
}
QAction * pasteImage = new QAction(tr("&Paste Image"));
connect(pasteImage, &QAction::triggered, this, [ = ](){
m_graphicsView->showImage(clipboardImage);
});
QAction * pasteImageFile = new QAction(tr("&Paste Image File"));
connect(pasteImageFile, &QAction::triggered, this, [ = ](){
m_graphicsView->showFileFromUrl(clipboardFileUrl, true);
});
QAction * stayOnTopMode = new QAction(tr("Stay on top"));
connect(stayOnTopMode, &QAction::triggered, this, [ = ](){
toggleStayOnTop();
@ -331,6 +389,18 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
};
m_graphicsView->showText(sl.join('\n'));
});
if (copyMenu->actions().count() == 1) {
menu->addActions(copyMenu->actions());
} else {
menu->addMenu(copyMenu);
}
if (!clipboardImage.isNull()) {
menu->addAction(pasteImage);
} else if (clipboardFileUrl.isValid()) {
menu->addAction(pasteImageFile);
}
menu->addSeparator();
menu->addAction(stayOnTopMode);
menu->addAction(protectedMode);
menu->addSeparator();

View File

@ -25,6 +25,7 @@ public:
void showUrls(const QList<QUrl> &urls);
void adjustWindowSizeBySceneRect();
QUrl currentImageFileUrl() const;
void loadGalleryBySingleLocalFile(const QString &path);
void galleryPrev();