25#include <QImageReader>
26#include <QInputDialog>
34#include "moc_qgsfilecontentsourcelineedit.cpp"
36using namespace Qt::StringLiterals;
45 QHBoxLayout *layout =
new QHBoxLayout(
this );
46 layout->setContentsMargins( 0, 0, 0, 0 );
48 mFileLineEdit->setShowClearButton(
true );
49 mFileToolButton =
new QToolButton(
this );
50 mFileToolButton->setText( QString( QChar( 0x2026 ) ) );
52 layout->addWidget( mFileLineEdit, 1 );
53 layout->addWidget( mFileToolButton );
54 layout->addWidget( mPropertyOverrideButton );
57 QMenu *sourceMenu =
new QMenu( mFileToolButton );
59 QAction *selectFileAction =
new QAction( tr(
"Select File…" ), sourceMenu );
60 connect( selectFileAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::selectFile );
61 sourceMenu->addAction( selectFileAction );
63 QAction *embedFileAction =
new QAction( tr(
"Embed File…" ), sourceMenu );
64 connect( embedFileAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::embedFile );
65 sourceMenu->addAction( embedFileAction );
67 QAction *extractFileAction =
new QAction( tr(
"Extract Embedded File…" ), sourceMenu );
68 connect( extractFileAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::extractFile );
69 sourceMenu->addAction( extractFileAction );
71 connect( sourceMenu, &QMenu::aboutToShow,
this, [
this, extractFileAction] { extractFileAction->setEnabled( mMode == ModeBase64 ); } );
73 QAction *enterUrlAction =
new QAction( tr(
"From URL…" ), sourceMenu );
74 connect( enterUrlAction, &QAction::triggered,
this, &QgsAbstractFileContentSourceLineEdit::selectUrl );
75 sourceMenu->addAction( enterUrlAction );
77 mFileToolButton->setMenu( sourceMenu );
78 mFileToolButton->setPopupMode( QToolButton::MenuButtonPopup );
79 connect( mFileToolButton, &QToolButton::clicked,
this, &QgsAbstractFileContentSourceLineEdit::selectFile );
81 connect( mFileLineEdit, &QLineEdit::textEdited,
this, &QgsAbstractFileContentSourceLineEdit::mFileLineEdit_textEdited );
84 mFileLineEdit->setPlaceholderText( QString() );
89 mPropertyOverrideButton->setVisible( mPropertyOverrideButtonVisible );
97 return mFileLineEdit->text();
113 mPropertyOverrideButtonVisible = visible;
114 mPropertyOverrideButton->setVisible( visible );
119 const bool isBase64 =
source.startsWith(
"base64:"_L1, Qt::CaseInsensitive );
121 if ( ( !isBase64 &&
source == mFileLineEdit->text() && mBase64.isEmpty() ) || ( isBase64 &&
source == mBase64 ) )
128 mFileLineEdit->clear();
129 mFileLineEdit->setPlaceholderText( tr(
"Embedded file" ) );
135 mFileLineEdit->setText(
source );
136 mFileLineEdit->setPlaceholderText( QString() );
142void QgsAbstractFileContentSourceLineEdit::selectFile()
145 const QString file = QFileDialog::getOpenFileName(
nullptr, selectFileTitle(), defaultPath(), fileFilter() );
146 const QFileInfo fi( file );
147 if ( file.isEmpty() || !fi.exists() || file ==
source() )
153 mFileLineEdit->setText( file );
154 mFileLineEdit->setPlaceholderText( QString() );
155 s.
setValue( settingsKey(), fi.absolutePath() );
159void QgsAbstractFileContentSourceLineEdit::selectUrl()
162 const QString path = QInputDialog::getText(
this, fileFromUrlTitle(), fileFromUrlText(), QLineEdit::Normal, mFileLineEdit->text(), &ok );
163 if ( ok && path !=
source() )
167 mFileLineEdit->setText( path );
168 mFileLineEdit->setPlaceholderText( QString() );
173void QgsAbstractFileContentSourceLineEdit::embedFile()
176 const QString file = QFileDialog::getOpenFileName(
nullptr, embedFileTitle(), defaultPath(), fileFilter() );
177 const QFileInfo fi( file );
178 if ( file.isEmpty() || !fi.exists() )
183 s.
setValue( settingsKey(), fi.absolutePath() );
186 QFile fileSource( file );
187 if ( !fileSource.open( QIODevice::ReadOnly ) )
192 const QByteArray blob = fileSource.readAll();
193 const QByteArray encoded = blob.toBase64();
195 QString path( encoded );
196 path.prepend(
"base64:"_L1 );
203 mFileLineEdit->clear();
204 mFileLineEdit->setPlaceholderText( tr(
"Embedded file" ) );
209void QgsAbstractFileContentSourceLineEdit::extractFile()
212 const QString file = QFileDialog::getSaveFileName(
nullptr, extractFileTitle(), defaultPath(), fileFilter() );
216 if ( file.isEmpty() )
221 const QFileInfo fi( file );
222 s.
setValue( settingsKey(), fi.absolutePath() );
225 const QByteArray base64 = mBase64.mid( 7 ).toLocal8Bit();
226 const QByteArray decoded = QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
228 QFile fileOut( file );
229 if ( fileOut.open( QIODevice::WriteOnly ) )
231 fileOut.write( decoded );
237 ->pushMessage( extractFileTitle(), tr(
"Successfully extracted file to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( file ).toString(), QDir::toNativeSeparators( file ) ),
Qgis::MessageLevel::Success, 0 );
240 else if ( mMessageBar )
242 mMessageBar->pushMessage( extractFileTitle(), tr(
"Error opening %1 for write" ).arg( QDir::toNativeSeparators( file ) ),
Qgis::MessageLevel::Critical );
246void QgsAbstractFileContentSourceLineEdit::mFileLineEdit_textEdited(
const QString &text )
248 mFileLineEdit->setPlaceholderText( QString() );
251 if ( !text.isEmpty() && !QFileInfo::exists( text ) )
253 const QUrl url( text );
254 if ( !url.isValid() )
262QString QgsAbstractFileContentSourceLineEdit::defaultPath()
const
264 if ( QFileInfo::exists(
source() ) )
267 return QgsSettings().value( settingsKey(), QDir::homePath() ).toString();
270QString QgsAbstractFileContentSourceLineEdit::settingsKey()
const
272 return mLastPathKey.isEmpty() ? defaultSettingsKey() : mLastPathKey;
293QString QgsPictureSourceLineEditBase::fileFilter()
const
298 return tr(
"SVG files" ) +
" (*.svg)";
301 QStringList formatsFilter;
302 const QByteArrayList supportedFormats = QImageReader::supportedImageFormats();
303 for (
const auto &format : supportedFormats )
305 formatsFilter.append( QString( u
"*.%1"_s ).arg( QString( format ) ) );
307 return QString(
"%1 (%2);;%3 (*.*)" ).arg( tr(
"Images" ), formatsFilter.join(
' '_L1 ), tr(
"All files" ) );
312 QStringList formatsFilter;
313 const QByteArrayList supportedFormats = QMovie::supportedFormats();
314 for (
const auto &format : supportedFormats )
316 formatsFilter.append( QString( u
"*.%1"_s ).arg( QString( format ) ) );
318 return QString(
"%1 (%2);;%3 (*.*)" ).arg( tr(
"Animated Images" ), formatsFilter.join(
' '_L1 ), tr(
"All files" ) );
324QString QgsPictureSourceLineEditBase::selectFileTitle()
const
329 return tr(
"Select SVG File" );
331 return tr(
"Select Image File" );
333 return tr(
"Select Animated Image File" );
338QString QgsPictureSourceLineEditBase::fileFromUrlTitle()
const
343 return tr(
"SVG From URL" );
345 return tr(
"Image From URL" );
347 return tr(
"Animated Image From URL" );
352QString QgsPictureSourceLineEditBase::fileFromUrlText()
const
357 return tr(
"Enter SVG URL" );
359 return tr(
"Enter image URL" );
361 return tr(
"Enter animated image URL" );
366QString QgsPictureSourceLineEditBase::embedFileTitle()
const
371 return tr(
"Embed SVG File" );
373 return tr(
"Embed Image File" );
375 return tr(
"Embed Animated Image File" );
380QString QgsPictureSourceLineEditBase::extractFileTitle()
const
385 return tr(
"Extract SVG File" );
387 return tr(
"Extract Image File" );
389 return tr(
"Extract Animated Image File" );
394QString QgsPictureSourceLineEditBase::defaultSettingsKey()
const
399 return u
"/UI/lastSVGDir"_s;
401 return u
"/UI/lastImageDir"_s;
403 return u
"/UI/lastAnimatedImageDir"_s;
@ Critical
Critical/error message.
@ Success
Used for reporting a successful operation.
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.
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.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
void cleared()
Emitted when the widget is cleared.
A bar for displaying non-blocking messages to the user.
@ AnimatedImage
Animated image.
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