QGIS API Documentation 3.41.0-Master (45a0abf3bec)
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#include "moc_qgsimagedroptextedit.cpp"
33#include "qgsguiutils.h"
34
35#include <QMimeData>
36#include <QBuffer>
37#include <QFileInfo>
38#include <QImageReader>
39#include <QMouseEvent>
40#include <QApplication>
41#include <QDesktopServices>
42
44QgsImageDropTextEdit::QgsImageDropTextEdit( QWidget *parent )
45 : QTextEdit( parent )
46{
47 setTextInteractionFlags( Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse );
48}
49
50QgsImageDropTextEdit::~QgsImageDropTextEdit() = default;
51
52bool QgsImageDropTextEdit::canInsertFromMimeData( const QMimeData *source ) const
53{
54 if ( source->hasImage() || QTextEdit::canInsertFromMimeData( source ) )
55 return true;
56
57 const QList<QUrl> urls = source->urls();
58 QStringList files;
59 files.reserve( urls.size() );
60 for ( const QUrl &url : urls )
61 {
62 QString fileName = url.toLocalFile();
63 // seems that some drag and drop operations include an empty url
64 // so we test for length to make sure we have something
65 if ( !fileName.isEmpty() )
66 {
67 files << fileName;
68 }
69 }
70
71 bool matched = false;
72 for ( const QString &file : std::as_const( files ) )
73 {
74 QFileInfo fi( file );
75 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
76 for ( const QByteArray &format : formats )
77 {
78 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
79 {
80 matched = true;
81 break;
82 }
83 }
84 }
85
86 return matched;
87}
88
89void QgsImageDropTextEdit::insertFromMimeData( const QMimeData *source )
90{
91 if ( source->hasImage() )
92 {
93 const QStringList formats = source->formats();
94 QString format;
95 for ( const QString &string : formats )
96 {
97 if ( string == QLatin1String( "image/bmp" ) )
98 {
99 format = QStringLiteral( "BMP" );
100 break;
101 }
102 if ( string == QLatin1String( "image/jpeg" ) )
103 {
104 format = QStringLiteral( "JPG" );
105 break;
106 }
107 if ( string == QLatin1String( "image/jpg" ) )
108 {
109 format = QStringLiteral( "JPG" );
110 break;
111 }
112 if ( string == QLatin1String( "image/gif" ) )
113 {
114 format = QStringLiteral( "GIF" );
115 break;
116 }
117 if ( string == QLatin1String( "image/png" ) )
118 {
119 format = QStringLiteral( "PNG" );
120 break;
121 }
122 if ( string == QLatin1String( "image/pbm" ) )
123 {
124 format = QStringLiteral( "PBM" );
125 break;
126 }
127 if ( string == QLatin1String( "image/pgm" ) )
128 {
129 format = QStringLiteral( "PGM" );
130 break;
131 }
132 if ( string == QLatin1String( "image/ppm" ) )
133 {
134 format = QStringLiteral( "PPM" );
135 break;
136 }
137 if ( string == QLatin1String( "image/tiff" ) )
138 {
139 format = QStringLiteral( "TIFF" );
140 break;
141 }
142 if ( string == QLatin1String( "image/xbm" ) )
143 {
144 format = QStringLiteral( "XBM" );
145 break;
146 }
147 if ( string == QLatin1String( "image/xpm" ) )
148 {
149 format = QStringLiteral( "XPM" );
150 break;
151 }
152 }
153 if ( !format.isEmpty() )
154 {
155 dropImage( qvariant_cast<QImage>( source->imageData() ), format );
156 return;
157 }
158 }
159 else
160 {
161 const QList<QUrl> urls = source->urls();
162 QStringList files;
163 files.reserve( urls.size() );
164 for ( const QUrl &url : urls )
165 {
166 if ( url.isLocalFile() )
167 {
168 QString fileName = url.toLocalFile();
169 // seems that some drag and drop operations include an empty url
170 // so we test for length to make sure we have something
171 if ( !fileName.isEmpty() )
172 {
173 files << fileName;
174 }
175 }
176 else
177 {
178 dropLink( url );
179 }
180 }
181
182 for ( const QString &file : std::as_const( files ) )
183 {
184 const QFileInfo fi( file );
185 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
186 bool isImage = false;
187 for ( const QByteArray &format : formats )
188 {
189 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
190 {
191 const QImage image( file );
192 dropImage( image, format );
193 isImage = true;
194 break;
195 }
196 }
197 if ( !isImage )
198 {
199 dropLink( QUrl::fromLocalFile( file ) );
200 }
201 }
202 if ( !files.empty() )
203 return;
204 }
205
206 QTextEdit::insertFromMimeData( source );
207}
208
209void QgsImageDropTextEdit::mouseMoveEvent( QMouseEvent *e )
210{
211 QTextEdit::mouseMoveEvent( e );
212 mActiveAnchor = anchorAt( e->pos() );
213 if ( !mActiveAnchor.isEmpty() && !mCursorOverride )
214 mCursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::PointingHandCursor );
215 else if ( mActiveAnchor.isEmpty() && mCursorOverride )
216 mCursorOverride.reset();
217}
218
219void QgsImageDropTextEdit::mouseReleaseEvent( QMouseEvent *e )
220{
221 if ( e->button() == Qt::LeftButton && !mActiveAnchor.isEmpty() )
222 {
223 QDesktopServices::openUrl( QUrl( mActiveAnchor ) );
224 if ( mCursorOverride )
225 mCursorOverride.reset();
226 mActiveAnchor.clear();
227 }
228 else
229 {
230 QTextEdit::mouseReleaseEvent( e );
231 }
232}
233
234void QgsImageDropTextEdit::dropImage( const QImage &image, const QString &format )
235{
236 QByteArray bytes;
237 QBuffer buffer( &bytes );
238 buffer.open( QIODevice::WriteOnly );
239 image.save( &buffer, format.toLocal8Bit().data() );
240 buffer.close();
241 QByteArray base64 = bytes.toBase64();
242 QByteArray base64l;
243 for ( int i = 0; i < base64.size(); i++ )
244 {
245 base64l.append( base64[i] );
246 if ( i % 80 == 0 )
247 {
248 base64l.append( "\n" );
249 }
250 }
251
252 QTextCursor cursor = textCursor();
253 QTextImageFormat imageFormat;
254 imageFormat.setWidth( image.width() );
255 imageFormat.setHeight( image.height() );
256 imageFormat.setName( QStringLiteral( "data:image/%1;base64,%2" )
257 .arg( QStringLiteral( "%1.%2" ).arg( rand() ).arg( format ),
258 base64l.data() )
259 );
260 cursor.insertImage( imageFormat );
261}
262
263void QgsImageDropTextEdit::dropLink( const QUrl &url )
264{
265 QTextCursor cursor = textCursor();
266 cursor.insertHtml( QStringLiteral( "<a href=\"%1\">%1</a>" ).arg( url.toString() ) );
267}
268
CORE_EXPORT const QStringList files(const QString &zip)
Returns the list of files within a zip file.