26#include <QImageReader>
27#include <QInputDialog>
35#include "moc_qgsfilecontentsourcelineedit.cpp"
37using namespace Qt::StringLiterals;
46 QHBoxLayout *layout =
new QHBoxLayout(
this );
47 layout->setContentsMargins( 0, 0, 0, 0 );
51 mFileToolButton =
new QToolButton(
this );
52 mFileToolButton->setText( QString( QChar( 0x2026 ) ) );
55 layout->addWidget( mFileToolButton );
56 layout->addWidget( mPropertyOverrideButton );
59 QMenu *sourceMenu =
new QMenu( mFileToolButton );
61 QAction *selectFileAction =
new QAction( tr(
"Select File…" ), sourceMenu );
62 connect( selectFileAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::selectFile );
63 sourceMenu->addAction( selectFileAction );
65 QAction *embedFileAction =
new QAction( tr(
"Embed File…" ), sourceMenu );
66 connect( embedFileAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::embedFile );
67 sourceMenu->addAction( embedFileAction );
69 QAction *extractFileAction =
new QAction( tr(
"Extract Embedded File…" ), sourceMenu );
70 connect( extractFileAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::extractFile );
71 sourceMenu->addAction( extractFileAction );
73 connect( sourceMenu, &QMenu::aboutToShow,
this, [
this, extractFileAction] { extractFileAction->setEnabled( mMode == ModeBase64 ); } );
75 QAction *enterUrlAction =
new QAction( tr(
"From URL…" ), sourceMenu );
76 connect( enterUrlAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::selectUrl );
77 sourceMenu->addAction( enterUrlAction );
79 mFileToolButton->setMenu( sourceMenu );
80 mFileToolButton->setPopupMode( QToolButton::MenuButtonPopup );
81 connect( mFileToolButton, &QToolButton::clicked,
this, &QgsAbstractFileContentSourceLineEdit::selectFile );
83 connect(
mFileLineEdit, &QLineEdit::textEdited,
this, &QgsAbstractFileContentSourceLineEdit::mFileLineEdit_textEdited );
91 connect(
mFileLineEdit, &QgsFileDropEdit::fileDropped,
this, [
this](
const QString &file ) {
96 const QFileInfo fi( file );
101 mPropertyOverrideButton->setVisible( mPropertyOverrideButtonVisible );
125 mPropertyOverrideButtonVisible = visible;
126 mPropertyOverrideButton->setVisible( visible );
131 const bool isBase64 =
source.startsWith(
"base64:"_L1, Qt::CaseInsensitive );
154void QgsAbstractFileContentSourceLineEdit::selectFile()
157 const QString file = QFileDialog::getOpenFileName(
nullptr, selectFileTitle(), defaultPath(), fileFilter(
true ) );
158 const QFileInfo fi( file );
159 if ( file.isEmpty() || !fi.exists() || file ==
source() )
167 s.
setValue( settingsKey(), fi.absolutePath() );
171void QgsAbstractFileContentSourceLineEdit::selectUrl()
174 const QString path = QInputDialog::getText(
this, fileFromUrlTitle(), fileFromUrlText(), QLineEdit::Normal,
mFileLineEdit->text(), &ok );
175 if ( ok && path !=
source() )
185void QgsAbstractFileContentSourceLineEdit::embedFile()
188 const QString file = QFileDialog::getOpenFileName(
nullptr, embedFileTitle(), defaultPath(), fileFilter(
true ) );
189 const QFileInfo fi( file );
190 if ( file.isEmpty() || !fi.exists() )
195 s.
setValue( settingsKey(), fi.absolutePath() );
198 QFile fileSource( file );
199 if ( !fileSource.open( QIODevice::ReadOnly ) )
204 const QByteArray blob = fileSource.readAll();
205 const QByteArray encoded = blob.toBase64();
207 QString path( encoded );
208 path.prepend(
"base64:"_L1 );
221void QgsAbstractFileContentSourceLineEdit::extractFile()
224 const QString file = QFileDialog::getSaveFileName(
nullptr, extractFileTitle(), defaultPath(), fileFilter(
true ) );
228 if ( file.isEmpty() )
233 const QFileInfo fi( file );
234 s.
setValue( settingsKey(), fi.absolutePath() );
237 const QByteArray base64 = mBase64.mid( 7 ).toLocal8Bit();
238 const QByteArray decoded = QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
240 QFile fileOut( file );
241 if ( fileOut.open( QIODevice::WriteOnly ) )
243 fileOut.write( decoded );
249 ->pushMessage( extractFileTitle(), tr(
"Successfully extracted file to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( file ).toString(), QDir::toNativeSeparators( file ) ),
Qgis::MessageLevel::Success, 0 );
252 else if ( mMessageBar )
254 mMessageBar->pushMessage( extractFileTitle(), tr(
"Error opening %1 for write" ).arg( QDir::toNativeSeparators( file ) ),
Qgis::MessageLevel::Critical );
258void QgsAbstractFileContentSourceLineEdit::mFileLineEdit_textEdited(
const QString &text )
263 if ( !text.isEmpty() && !QFileInfo::exists( text ) )
265 const QUrl url( text );
266 if ( !url.isValid() )
274QString QgsAbstractFileContentSourceLineEdit::defaultPath()
const
276 if ( QFileInfo::exists(
source() ) )
279 return QgsSettings().value( settingsKey(), QDir::homePath() ).toString();
282QString QgsAbstractFileContentSourceLineEdit::settingsKey()
const
284 return mLastPathKey.isEmpty() ? defaultSettingsKey() : mLastPathKey;
312QString QgsPictureSourceLineEditBase::fileFilter(
bool includeAllFiles )
const
317 return tr(
"SVG files" ) +
" (*.svg)";
320 QStringList formatsFilter;
321 const QByteArrayList supportedFormats = QImageReader::supportedImageFormats();
322 for (
const auto &format : supportedFormats )
324 formatsFilter.append( QString( u
"*.%1"_s ).arg( QString( format ) ) );
326 return QString(
"%1 (%2) " ).arg( tr(
"Images" ), formatsFilter.join(
' '_L1 ) ) + ( includeAllFiles ? QString(
";;%1 (*.*)" ).arg( tr(
"All files" ) ) : QString() );
331 QStringList formatsFilter;
332 const QByteArrayList supportedFormats = QMovie::supportedFormats();
333 for (
const auto &format : supportedFormats )
335 formatsFilter.append( QString( u
"*.%1"_s ).arg( QString( format ) ) );
337 return QString(
"%1 (%2)" ).arg( tr(
"Animated Images" ), formatsFilter.join(
' '_L1 ) ) + ( includeAllFiles ? QString(
";;%1 (*.*)" ).arg( tr(
"All files" ) ) : QString() );
344QString QgsPictureSourceLineEditBase::selectFileTitle()
const
349 return tr(
"Select SVG File" );
351 return tr(
"Select Image File" );
353 return tr(
"Select Animated Image File" );
358QString QgsPictureSourceLineEditBase::fileFromUrlTitle()
const
363 return tr(
"SVG From URL" );
365 return tr(
"Image From URL" );
367 return tr(
"Animated Image From URL" );
372QString QgsPictureSourceLineEditBase::fileFromUrlText()
const
377 return tr(
"Enter SVG URL" );
379 return tr(
"Enter image URL" );
381 return tr(
"Enter animated image URL" );
386QString QgsPictureSourceLineEditBase::embedFileTitle()
const
391 return tr(
"Embed SVG File" );
393 return tr(
"Embed Image File" );
395 return tr(
"Embed Animated Image File" );
400QString QgsPictureSourceLineEditBase::extractFileTitle()
const
405 return tr(
"Extract SVG File" );
407 return tr(
"Extract Image File" );
409 return tr(
"Extract Animated Image File" );
414QString QgsPictureSourceLineEditBase::defaultSettingsKey()
const
419 return u
"/UI/lastSVGDir"_s;
421 return u
"/UI/lastImageDir"_s;
423 return u
"/UI/lastAnimatedImageDir"_s;
@ Critical
Critical/error message.
@ Success
Used for reporting a successful operation.
Abstract base class for widgets which allow users to select content from a file, embedding a file,...
void setLastPathSettingsKey(const QString &key)
Sets a specific settings key to use when storing the last used path for the file source.
void sourceChanged(const QString &source)
Emitted whenever the file source is changed in the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
QgsFileDropEdit * mFileLineEdit
void setPropertyOverrideToolButtonVisible(bool visible)
Sets the visibility of the property override tool button.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
void setSource(const QString &source)
Sets a new source to show in the widget.
QgsAbstractFileContentSourceLineEdit(QWidget *parent=nullptr)
Constructor for QgsAbstractFileContentSourceLineEdit, with the specified parent widget.
void cleared()
Emitted when the widget is cleared.
A bar for displaying non-blocking messages to the user.
@ AnimatedImage
Animated image.
QgsPictureSourceLineEditBase(QWidget *parent=nullptr)
Constructor for QgsImageSourceLineEdit, with the specified parent widget.
Stores settings for use within QGIS.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define BUILTIN_UNREACHABLE