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] {
72 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 );
86 mFileLineEdit->setPlaceholderText( QString() );
91 mPropertyOverrideButton->setVisible( mPropertyOverrideButtonVisible );
99 return mFileLineEdit->text();
115 mPropertyOverrideButtonVisible = visible;
116 mPropertyOverrideButton->setVisible( visible );
121 const bool isBase64 =
source.startsWith(
"base64:"_L1, Qt::CaseInsensitive );
123 if ( ( !isBase64 &&
source == mFileLineEdit->text() && mBase64.isEmpty() ) || ( isBase64 &&
source == mBase64 ) )
130 mFileLineEdit->clear();
131 mFileLineEdit->setPlaceholderText( tr(
"Embedded file" ) );
137 mFileLineEdit->setText(
source );
138 mFileLineEdit->setPlaceholderText( QString() );
144void QgsAbstractFileContentSourceLineEdit::selectFile()
147 const QString file = QFileDialog::getOpenFileName(
nullptr, selectFileTitle(), defaultPath(), fileFilter() );
148 const QFileInfo fi( file );
149 if ( file.isEmpty() || !fi.exists() || file ==
source() )
155 mFileLineEdit->setText( file );
156 mFileLineEdit->setPlaceholderText( QString() );
157 s.
setValue( settingsKey(), fi.absolutePath() );
161void QgsAbstractFileContentSourceLineEdit::selectUrl()
164 const QString path = QInputDialog::getText(
this, fileFromUrlTitle(), fileFromUrlText(), QLineEdit::Normal, mFileLineEdit->text(), &ok );
165 if ( ok && path !=
source() )
169 mFileLineEdit->setText( path );
170 mFileLineEdit->setPlaceholderText( QString() );
175void QgsAbstractFileContentSourceLineEdit::embedFile()
178 const QString file = QFileDialog::getOpenFileName(
nullptr, embedFileTitle(), defaultPath(), fileFilter() );
179 const QFileInfo fi( file );
180 if ( file.isEmpty() || !fi.exists() )
185 s.
setValue( settingsKey(), fi.absolutePath() );
188 QFile fileSource( file );
189 if ( !fileSource.open( QIODevice::ReadOnly ) )
194 const QByteArray blob = fileSource.readAll();
195 const QByteArray encoded = blob.toBase64();
197 QString path( encoded );
198 path.prepend(
"base64:"_L1 );
205 mFileLineEdit->clear();
206 mFileLineEdit->setPlaceholderText( tr(
"Embedded file" ) );
211void QgsAbstractFileContentSourceLineEdit::extractFile()
214 const QString file = QFileDialog::getSaveFileName(
nullptr, extractFileTitle(), defaultPath(), fileFilter() );
218 if ( file.isEmpty() )
223 const QFileInfo fi( file );
224 s.
setValue( settingsKey(), fi.absolutePath() );
227 const QByteArray base64 = mBase64.mid( 7 ).toLocal8Bit();
228 const QByteArray decoded = QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
230 QFile fileOut( file );
231 if ( fileOut.open( QIODevice::WriteOnly ) )
233 fileOut.write( decoded );
238 mMessageBar->pushMessage( extractFileTitle(), tr(
"Successfully extracted file to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( file ).toString(), QDir::toNativeSeparators( file ) ),
Qgis::MessageLevel::Success, 0 );
241 else if ( mMessageBar )
243 mMessageBar->pushMessage( extractFileTitle(), tr(
"Error opening %1 for write" ).arg( QDir::toNativeSeparators( file ) ),
Qgis::MessageLevel::Critical );
247void QgsAbstractFileContentSourceLineEdit::mFileLineEdit_textEdited(
const QString &text )
249 mFileLineEdit->setPlaceholderText( QString() );
252 if ( !text.isEmpty() && !QFileInfo::exists( text ) )
254 const QUrl url( text );
255 if ( !url.isValid() )
263QString QgsAbstractFileContentSourceLineEdit::defaultPath()
const
265 if ( QFileInfo::exists(
source() ) )
268 return QgsSettings().value( settingsKey(), QDir::homePath() ).toString();
271QString QgsAbstractFileContentSourceLineEdit::settingsKey()
const
273 return mLastPathKey.isEmpty() ? defaultSettingsKey() : mLastPathKey;
294QString QgsPictureSourceLineEditBase::fileFilter()
const
299 return tr(
"SVG files" ) +
" (*.svg)";
302 QStringList formatsFilter;
303 const QByteArrayList supportedFormats = QImageReader::supportedImageFormats();
304 for (
const auto &format : supportedFormats )
306 formatsFilter.append( QString( u
"*.%1"_s ).arg( QString( format ) ) );
308 return QString(
"%1 (%2);;%3 (*.*)" ).arg( tr(
"Images" ), formatsFilter.join(
' '_L1 ), tr(
"All files" ) );
313 QStringList formatsFilter;
314 const QByteArrayList supportedFormats = QMovie::supportedFormats();
315 for (
const auto &format : supportedFormats )
317 formatsFilter.append( QString( u
"*.%1"_s ).arg( QString( format ) ) );
319 return QString(
"%1 (%2);;%3 (*.*)" ).arg( tr(
"Animated Images" ), formatsFilter.join(
' '_L1 ), tr(
"All files" ) );
325QString QgsPictureSourceLineEditBase::selectFileTitle()
const
330 return tr(
"Select SVG File" );
332 return tr(
"Select Image File" );
334 return tr(
"Select Animated Image File" );
339QString QgsPictureSourceLineEditBase::fileFromUrlTitle()
const
344 return tr(
"SVG From URL" );
346 return tr(
"Image From URL" );
348 return tr(
"Animated Image From URL" );
353QString QgsPictureSourceLineEditBase::fileFromUrlText()
const
358 return tr(
"Enter SVG URL" );
360 return tr(
"Enter image URL" );
362 return tr(
"Enter animated image URL" );
367QString QgsPictureSourceLineEditBase::embedFileTitle()
const
372 return tr(
"Embed SVG File" );
374 return tr(
"Embed Image File" );
376 return tr(
"Embed Animated Image File" );
381QString QgsPictureSourceLineEditBase::extractFileTitle()
const
386 return tr(
"Extract SVG File" );
388 return tr(
"Extract Image File" );
390 return tr(
"Extract Animated Image File" );
395QString QgsPictureSourceLineEditBase::defaultSettingsKey()
const
400 return u
"/UI/lastSVGDir"_s;
402 return u
"/UI/lastImageDir"_s;
404 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