QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsimagedroptextedit.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** Copyright (C) 2013 Jiří Procházka (Hobrasoft)
4** Contact: http://www.hobrasoft.cz/
5**
6** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
7** Contact: http://www.qt-project.org/legal
8**
9** This library is free software; you can redistribute it and/or
10** modify it under the terms of the GNU Lesser General Public
11** License as published by the Free Software Foundation; either
12** version 2.1 of the License, or (at your option) any later version.
13**
14** $QT_BEGIN_LICENSE:LGPL$
15** GNU Lesser General Public License Usage
16** This file is under the terms of the GNU Lesser General Public License
17** version 2.1 as published by the Free Software Foundation and appearing
18** in the file LICENSE.LGPL included in the packaging of this file.
19** Please review the following information to ensure the
20** GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Digia gives you certain additional
24** rights. These rights are described in the Digia Qt LGPL Exception
25** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26**
27** $QT_END_LICENSE$
28**
29****************************************************************************/
30
32
33#include "qgsguiutils.h"
34
35#include <QApplication>
36#include <QBuffer>
37#include <QDesktopServices>
38#include <QFileInfo>
39#include <QImageReader>
40#include <QMimeData>
41#include <QMouseEvent>
42
43#include "moc_qgsimagedroptextedit.cpp"
44
46QgsImageDropTextEdit::QgsImageDropTextEdit( QWidget *parent )
47 : QTextEdit( parent )
48{
49 setTextInteractionFlags( Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse );
50}
51
52QgsImageDropTextEdit::~QgsImageDropTextEdit() = default;
53
54bool QgsImageDropTextEdit::canInsertFromMimeData( const QMimeData *source ) const
55{
56 if ( source->hasImage() || QTextEdit::canInsertFromMimeData( source ) )
57 return true;
58
59 const QList<QUrl> urls = source->urls();
60 QStringList files;
61 files.reserve( urls.size() );
62 for ( const QUrl &url : urls )
63 {
64 QString fileName = url.toLocalFile();
65 // seems that some drag and drop operations include an empty url
66 // so we test for length to make sure we have something
67 if ( !fileName.isEmpty() )
68 {
69 files << fileName;
70 }
71 }
72
73 bool matched = false;
74 for ( const QString &file : std::as_const( files ) )
75 {
76 QFileInfo fi( file );
77 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
78 for ( const QByteArray &format : formats )
79 {
80 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
81 {
82 matched = true;
83 break;
84 }
85 }
86 }
87
88 return matched;
89}
90
91void QgsImageDropTextEdit::insertFromMimeData( const QMimeData *source )
92{
93 if ( source->hasImage() )
94 {
95 const QStringList formats = source->formats();
96 QString format;
97 for ( const QString &string : formats )
98 {
99 if ( string == QLatin1String( "image/bmp" ) )
100 {
101 format = QStringLiteral( "BMP" );
102 break;
103 }
104 if ( string == QLatin1String( "image/jpeg" ) )
105 {
106 format = QStringLiteral( "JPG" );
107 break;
108 }
109 if ( string == QLatin1String( "image/jpg" ) )
110 {
111 format = QStringLiteral( "JPG" );
112 break;
113 }
114 if ( string == QLatin1String( "image/gif" ) )
115 {
116 format = QStringLiteral( "GIF" );
117 break;
118 }
119 if ( string == QLatin1String( "image/png" ) )
120 {
121 format = QStringLiteral( "PNG" );
122 break;
123 }
124 if ( string == QLatin1String( "image/pbm" ) )
125 {
126 format = QStringLiteral( "PBM" );
127 break;
128 }
129 if ( string == QLatin1String( "image/pgm" ) )
130 {
131 format = QStringLiteral( "PGM" );
132 break;
133 }
134 if ( string == QLatin1String( "image/ppm" ) )
135 {
136 format = QStringLiteral( "PPM" );
137 break;
138 }
139 if ( string == QLatin1String( "image/tiff" ) )
140 {
141 format = QStringLiteral( "TIFF" );
142 break;
143 }
144 if ( string == QLatin1String( "image/xbm" ) )
145 {
146 format = QStringLiteral( "XBM" );
147 break;
148 }
149 if ( string == QLatin1String( "image/xpm" ) )
150 {
151 format = QStringLiteral( "XPM" );
152 break;
153 }
154 }
155 if ( !format.isEmpty() )
156 {
157 dropImage( qvariant_cast<QImage>( source->imageData() ), format );
158 return;
159 }
160 }
161 else
162 {
163 const QList<QUrl> urls = source->urls();
164 QStringList files;
165 files.reserve( urls.size() );
166 for ( const QUrl &url : urls )
167 {
168 if ( url.isLocalFile() )
169 {
170 QString fileName = url.toLocalFile();
171 // seems that some drag and drop operations include an empty url
172 // so we test for length to make sure we have something
173 if ( !fileName.isEmpty() )
174 {
175 files << fileName;
176 }
177 }
178 else
179 {
180 dropLink( url );
181 }
182 }
183
184 for ( const QString &file : std::as_const( files ) )
185 {
186 const QFileInfo fi( file );
187 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
188 bool isImage = false;
189 for ( const QByteArray &format : formats )
190 {
191 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
192 {
193 const QImage image( file );
194 dropImage( image, format );
195 isImage = true;
196 break;
197 }
198 }
199 if ( !isImage )
200 {
201 dropLink( QUrl::fromLocalFile( file ) );
202 }
203 }
204 if ( !files.empty() )
205 return;
206 }
207
208 QTextEdit::insertFromMimeData( source );
209}
210
211void QgsImageDropTextEdit::mouseMoveEvent( QMouseEvent *e )
212{
213 QTextEdit::mouseMoveEvent( e );
214 mActiveAnchor = anchorAt( e->pos() );
215 if ( !mActiveAnchor.isEmpty() && !mCursorOverride )
216 mCursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::PointingHandCursor );
217 else if ( mActiveAnchor.isEmpty() && mCursorOverride )
218 mCursorOverride.reset();
219}
220
221void QgsImageDropTextEdit::mouseReleaseEvent( QMouseEvent *e )
222{
223 if ( e->button() == Qt::LeftButton && !mActiveAnchor.isEmpty() )
224 {
225 QDesktopServices::openUrl( QUrl( mActiveAnchor ) );
226 if ( mCursorOverride )
227 mCursorOverride.reset();
228 mActiveAnchor.clear();
229 }
230 else
231 {
232 QTextEdit::mouseReleaseEvent( e );
233 }
234}
235
236void QgsImageDropTextEdit::dropImage( const QImage &image, const QString &format )
237{
238 QByteArray bytes;
239 QBuffer buffer( &bytes );
240 buffer.open( QIODevice::WriteOnly );
241 image.save( &buffer, format.toLocal8Bit().data() );
242 buffer.close();
243 QByteArray base64 = bytes.toBase64();
244 QByteArray base64l;
245 for ( int i = 0; i < base64.size(); i++ )
246 {
247 base64l.append( base64[i] );
248 if ( i % 80 == 0 )
249 {
250 base64l.append( "\n" );
251 }
252 }
253
254 QTextCursor cursor = textCursor();
255 QTextImageFormat imageFormat;
256 imageFormat.setWidth( image.width() );
257 imageFormat.setHeight( image.height() );
258 imageFormat.setName( QStringLiteral( "data:image/%1;base64,%2" )
259 .arg( QStringLiteral( "%1.%2" ).arg( rand() ).arg( format ), base64l.data() )
260 );
261 cursor.insertImage( imageFormat );
262}
263
264void QgsImageDropTextEdit::dropLink( const QUrl &url )
265{
266 QTextCursor cursor = textCursor();
267 cursor.insertHtml( QStringLiteral( "<a href=\"%1\">%1</a>" ).arg( url.toString() ) );
268}
269