35#include <QApplication>
37#include <QDesktopServices>
39#include <QImageReader>
44#include "moc_qgsimagedroptextedit.cpp"
46using namespace Qt::StringLiterals;
49QgsImageDropTextEdit::QgsImageDropTextEdit( QWidget *parent )
52 setTextInteractionFlags( Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse );
55QgsImageDropTextEdit::~QgsImageDropTextEdit() =
default;
57bool QgsImageDropTextEdit::canInsertFromMimeData(
const QMimeData *source )
const
59 if ( source->hasImage() || QTextEdit::canInsertFromMimeData( source ) )
62 const QList<QUrl> urls = source->urls();
64 files.reserve( urls.size() );
65 for (
const QUrl &url : urls )
67 QString fileName = url.toLocalFile();
70 if ( !fileName.isEmpty() )
77 for (
const QString &file : std::as_const( files ) )
80 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
81 for (
const QByteArray &format : formats )
83 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
94void QgsImageDropTextEdit::insertFromMimeData(
const QMimeData *source )
96 if ( source->hasImage() )
98 const QStringList formats = source->formats();
100 for (
const QString &
string : formats )
102 if (
string ==
"image/bmp"_L1 )
107 if (
string ==
"image/jpeg"_L1 )
112 if (
string ==
"image/jpg"_L1 )
117 if (
string ==
"image/gif"_L1 )
122 if (
string ==
"image/png"_L1 )
127 if (
string ==
"image/pbm"_L1 )
132 if (
string ==
"image/pgm"_L1 )
137 if (
string ==
"image/ppm"_L1 )
142 if (
string ==
"image/tiff"_L1 )
147 if (
string ==
"image/xbm"_L1 )
152 if (
string ==
"image/xpm"_L1 )
158 if ( !format.isEmpty() )
160 dropImage( qvariant_cast<QImage>( source->imageData() ), format );
166 const QList<QUrl> urls = source->urls();
168 files.reserve( urls.size() );
169 for (
const QUrl &url : urls )
171 if ( url.isLocalFile() )
173 QString fileName = url.toLocalFile();
176 if ( !fileName.isEmpty() )
187 for (
const QString &file : std::as_const( files ) )
189 const QFileInfo fi( file );
190 const QList<QByteArray> formats = QImageReader::supportedImageFormats();
191 bool isImage =
false;
192 for (
const QByteArray &format : formats )
194 if ( fi.suffix().compare( format, Qt::CaseInsensitive ) == 0 )
196 const QImage image( file );
197 dropImage( image, format );
204 dropLink( QUrl::fromLocalFile( file ) );
207 if ( !files.empty() )
211 QTextEdit::insertFromMimeData( source );
214void QgsImageDropTextEdit::mouseMoveEvent( QMouseEvent *e )
216 QTextEdit::mouseMoveEvent( e );
217 mActiveAnchor = anchorAt( e->pos() );
218 if ( !mActiveAnchor.isEmpty() && !mCursorOverride )
219 mCursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::PointingHandCursor );
220 else if ( mActiveAnchor.isEmpty() && mCursorOverride )
221 mCursorOverride.reset();
224void QgsImageDropTextEdit::mouseReleaseEvent( QMouseEvent *e )
226 if ( e->button() == Qt::LeftButton && !mActiveAnchor.isEmpty() )
228 QDesktopServices::openUrl( QUrl( mActiveAnchor ) );
229 if ( mCursorOverride )
230 mCursorOverride.reset();
231 mActiveAnchor.clear();
235 QTextEdit::mouseReleaseEvent( e );
239void QgsImageDropTextEdit::dropImage(
const QImage &image,
const QString &format )
242 QBuffer buffer( &bytes );
243 buffer.open( QIODevice::WriteOnly );
244 image.save( &buffer, format.toLocal8Bit().data() );
246 QByteArray base64 = bytes.toBase64();
248 for (
int i = 0; i < base64.size(); i++ )
250 base64l.append( base64[i] );
253 base64l.append(
"\n" );
257 QTextCursor cursor = textCursor();
258 QTextImageFormat imageFormat;
259 imageFormat.setWidth( image.width() );
260 imageFormat.setHeight( image.height() );
261 imageFormat.setName( u
"data:image/%1;base64,%2"_s
262 .arg( u
"%1.%2"_s.arg( rand() ).arg( format ), base64l.data() )
264 cursor.insertImage( imageFormat );
267void QgsImageDropTextEdit::dropLink(
const QUrl &url )
269 QTextCursor cursor = textCursor();
270 cursor.insertHtml( u
"<a href=\"%1\">%1</a>"_s.arg( url.toString() ) );