1 /***************************************************************************
2 qgslayoutimagedrophandler.cpp
3 ------------------------------
4 begin : November 2019
5 copyright : (C) 2019 by nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "qgslayoutimagedrophandler.h"
17 #include "qgslayoutdesignerinterface.h"
18 #include "qgslayout.h"
19 #include "qgslayoutview.h"
20 #include "qgslayoutitempicture.h"
21
22 #include <QImageReader>
23
QgsLayoutImageDropHandler(QObject * parent)24 QgsLayoutImageDropHandler::QgsLayoutImageDropHandler( QObject *parent )
25 : QgsLayoutCustomDropHandler( parent )
26 {
27
28 }
29
handleFileDrop(QgsLayoutDesignerInterface * iface,QPointF point,const QString & file)30 bool QgsLayoutImageDropHandler::handleFileDrop( QgsLayoutDesignerInterface *iface, QPointF point, const QString &file )
31 {
32 QFileInfo fi( file );
33 bool matched = false;
34 bool svg = false;
35 if ( fi.suffix().compare( "svg", Qt::CaseInsensitive ) == 0 )
36 {
37 matched = true;
38 svg = true;
39 }
40 else
41 {
42 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
43 for ( const QByteArray &format : formats )
44 {
45 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
46 {
47 matched = true;
48 break;
49 }
50 }
51 }
52
53 if ( !matched )
54 return false;
55
56 if ( !iface->layout() )
57 return false;
58
59 std::unique_ptr< QgsLayoutItemPicture > item = qgis::make_unique< QgsLayoutItemPicture >( iface->layout() );
60
61 QgsLayoutPoint layoutPoint = iface->layout()->convertFromLayoutUnits( point, iface->layout()->units() );
62
63 item->setPicturePath( file, svg ? QgsLayoutItemPicture::FormatSVG : QgsLayoutItemPicture::FormatRaster );
64
65 // force a resize to the image's actual size
66 item->setResizeMode( QgsLayoutItemPicture::FrameToImageSize );
67 // and then move back to standard freeform image sizing
68 item->setResizeMode( QgsLayoutItemPicture::Zoom );
69
70 // we want the drop location to be the center of the placed item, because drag thumbnails are usually centered on the mouse cursor
71 item->setReferencePoint( QgsLayoutItem::Middle );
72 item->attemptMove( layoutPoint );
73
74 // reset to standard top-left reference point location
75 item->setReferencePoint( QgsLayoutItem::UpperLeft );
76
77 // and auto select new item for convenience
78 QList< QgsLayoutItem * > newSelection;
79 newSelection << item.get();
80 iface->layout()->addLayoutItem( item.release() );
81 iface->layout()->deselectAll();
82 iface->selectItems( newSelection );
83
84 return true;
85 }
86
handlePaste(QgsLayoutDesignerInterface * iface,QPointF pastePoint,const QMimeData * data,QList<QgsLayoutItem * > & pastedItems)87 bool QgsLayoutImageDropHandler::handlePaste( QgsLayoutDesignerInterface *iface, QPointF pastePoint, const QMimeData *data, QList<QgsLayoutItem *> &pastedItems )
88 {
89 if ( !data->hasImage() )
90 return false;
91
92 QgsLayoutPoint layoutPoint = iface->layout()->convertFromLayoutUnits( pastePoint, iface->layout()->units() );
93 std::unique_ptr< QgsLayoutItemPicture > item = qgis::make_unique< QgsLayoutItemPicture >( iface->layout() );
94
95 const QByteArray imageData = data->data( QStringLiteral( "application/x-qt-image" ) );
96 if ( imageData.isEmpty() )
97 return false;
98
99 const QByteArray encoded = imageData.toBase64();
100
101 QString path( encoded );
102 path.prepend( QLatin1String( "base64:" ) );
103
104 item->setPicturePath( path, QgsLayoutItemPicture::FormatRaster );
105
106 // force a resize to the image's actual size
107 item->setResizeMode( QgsLayoutItemPicture::FrameToImageSize );
108 // and then move back to standard freeform image sizing
109 item->setResizeMode( QgsLayoutItemPicture::Zoom );
110
111 // we want the drop location to be the center of the placed item, because drag thumbnails are usually centered on the mouse cursor
112 item->setReferencePoint( QgsLayoutItem::Middle );
113 item->attemptMove( layoutPoint );
114
115 // reset to standard top-left reference point location
116 item->setReferencePoint( QgsLayoutItem::UpperLeft );
117
118 pastedItems << item.get();
119 iface->layout()->addLayoutItem( item.release() );
120
121 return true;
122 }
123