22 #include <QFileDialog> 
   23 #include <QHBoxLayout> 
   24 #include <QImageReader> 
   25 #include <QInputDialog> 
   28 #include <QToolButton> 
   39   QHBoxLayout *layout = 
new QHBoxLayout( 
this );
 
   40   layout->setContentsMargins( 0, 0, 0, 0 );
 
   43   mFileToolButton = 
new QToolButton( 
this );
 
   44   mFileToolButton->setText( QString( QChar( 0x2026 ) ) );
 
   46   layout->addWidget( mFileLineEdit, 1 );
 
   47   layout->addWidget( mFileToolButton );
 
   48   layout->addWidget( mPropertyOverrideButton );
 
   51   QMenu *sourceMenu = 
new QMenu( mFileToolButton );
 
   53   QAction *selectFileAction = 
new QAction( tr( 
"Select File…" ), sourceMenu );
 
   54   connect( selectFileAction, &QAction::triggered, 
this, &QgsAbstractFileContentSourceLineEdit::selectFile );
 
   55   sourceMenu->addAction( selectFileAction );
 
   57   QAction *embedFileAction = 
new QAction( tr( 
"Embed File…" ), sourceMenu );
 
   58   connect( embedFileAction, &QAction::triggered, 
this, &QgsAbstractFileContentSourceLineEdit::embedFile );
 
   59   sourceMenu->addAction( embedFileAction );
 
   61   QAction *extractFileAction = 
new QAction( tr( 
"Extract Embedded File…" ), sourceMenu );
 
   62   connect( extractFileAction, &QAction::triggered, 
this, &QgsAbstractFileContentSourceLineEdit::extractFile );
 
   63   sourceMenu->addAction( extractFileAction );
 
   65   connect( sourceMenu, &QMenu::aboutToShow, 
this, [
this, extractFileAction]
 
   67     extractFileAction->setEnabled( mMode == ModeBase64 );
 
   70   QAction *enterUrlAction = 
new QAction( tr( 
"From URL…" ), sourceMenu );
 
   71   connect( enterUrlAction, &QAction::triggered, 
this, &QgsAbstractFileContentSourceLineEdit::selectUrl );
 
   72   sourceMenu->addAction( enterUrlAction );
 
   74   mFileToolButton->setMenu( sourceMenu );
 
   75   mFileToolButton->setPopupMode( QToolButton::MenuButtonPopup );
 
   76   connect( mFileToolButton, &QToolButton::clicked, 
this, &QgsAbstractFileContentSourceLineEdit::selectFile );
 
   78   connect( mFileLineEdit, &QLineEdit::textEdited, 
this, &QgsAbstractFileContentSourceLineEdit::mFileLineEdit_textEdited );
 
   82     mFileLineEdit->setPlaceholderText( QString() );
 
   87   mPropertyOverrideButton->setVisible( mPropertyOverrideButtonVisible );
 
   96       return mFileLineEdit->text();
 
  112   mPropertyOverrideButtonVisible = visible;
 
  113   mPropertyOverrideButton->setVisible( visible );
 
  118   const bool isBase64 = 
source.startsWith( QLatin1String( 
"base64:" ), Qt::CaseInsensitive );
 
  120   if ( ( !isBase64 && 
source == mFileLineEdit->text() && mBase64.isEmpty() ) || ( isBase64 && 
source == mBase64 ) )
 
  127     mFileLineEdit->clear();
 
  128     mFileLineEdit->setPlaceholderText( tr( 
"Embedded file" ) );
 
  134     mFileLineEdit->setText( 
source );
 
  135     mFileLineEdit->setPlaceholderText( QString() );
 
  141 void QgsAbstractFileContentSourceLineEdit::selectFile()
 
  144   const QString file = QFileDialog::getOpenFileName( 
nullptr,
 
  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() );
 
  161 void 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() );
 
  175 void QgsAbstractFileContentSourceLineEdit::embedFile()
 
  178   const QString file = QFileDialog::getOpenFileName( 
nullptr,
 
  182   const QFileInfo fi( file );
 
  183   if ( file.isEmpty() || !fi.exists() )
 
  188   s.
setValue( settingsKey(), fi.absolutePath() );
 
  191   QFile fileSource( file );
 
  192   if ( !fileSource.open( QIODevice::ReadOnly ) )
 
  197   const QByteArray blob = fileSource.readAll();
 
  198   const QByteArray encoded = blob.toBase64();
 
  200   QString path( encoded );
 
  201   path.prepend( QLatin1String( 
"base64:" ) );
 
  208   mFileLineEdit->clear();
 
  209   mFileLineEdit->setPlaceholderText( tr( 
"Embedded file" ) );
 
  214 void QgsAbstractFileContentSourceLineEdit::extractFile()
 
  217   const QString file = QFileDialog::getSaveFileName( 
nullptr,
 
  221   if ( file.isEmpty() )
 
  226   const QFileInfo fi( file );
 
  227   s.
setValue( settingsKey(), fi.absolutePath() );
 
  230   const QByteArray base64 = mBase64.mid( 7 ).toLocal8Bit(); 
 
  231   const QByteArray decoded = QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
 
  233   QFile fileOut( file );
 
  234   fileOut.open( QIODevice::WriteOnly );
 
  235   fileOut.write( decoded );
 
  241                               tr( 
"Successfully extracted file to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( file ).toString(), QDir::toNativeSeparators( file ) ),
 
  242                               Qgis::MessageLevel::Success, 0 );
 
  246 void 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() )
 
  262 QString QgsAbstractFileContentSourceLineEdit::defaultPath()
 const 
  264   if ( QFileInfo::exists( 
source() ) )
 
  270 QString QgsAbstractFileContentSourceLineEdit::settingsKey()
 const 
  272   return mLastPathKey.isEmpty() ? defaultSettingsKey() : mLastPathKey;
 
  294 QString 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( QStringLiteral( 
"*.%1" ) ).arg( QString( format ) ) );
 
  308       return QString( 
"%1 (%2);;%3 (*.*)" ).arg( tr( 
"Images" ), formatsFilter.join( QLatin1Char( 
' ' ) ), tr( 
"All files" ) );
 
  313       QStringList formatsFilter;
 
  314       const QByteArrayList supportedFormats = QMovie::supportedFormats();
 
  315       for ( 
const auto &format : supportedFormats )
 
  317         formatsFilter.append( QString( QStringLiteral( 
"*.%1" ) ).arg( QString( format ) ) );
 
  319       return QString( 
"%1 (%2);;%3 (*.*)" ).arg( tr( 
"Animated Images" ), formatsFilter.join( QLatin1Char( 
' ' ) ), tr( 
"All files" ) );
 
  325 QString QgsPictureSourceLineEditBase::selectFileTitle()
 const 
  330       return tr( 
"Select SVG File" );
 
  332       return tr( 
"Select Image File" );
 
  334       return tr( 
"Select Animated Image File" );
 
  339 QString QgsPictureSourceLineEditBase::fileFromUrlTitle()
 const 
  344       return tr( 
"SVG From URL" );
 
  346       return tr( 
"Image From URL" );
 
  348       return tr( 
"Animated Image From URL" );
 
  353 QString QgsPictureSourceLineEditBase::fileFromUrlText()
 const 
  358       return tr( 
"Enter SVG URL" );
 
  360       return tr( 
"Enter image URL" );
 
  362       return tr( 
"Enter animated image URL" );
 
  367 QString QgsPictureSourceLineEditBase::embedFileTitle()
 const 
  372       return tr( 
"Embed SVG File" );
 
  374       return tr( 
"Embed Image File" );
 
  376       return tr( 
"Embed Animated Image File" );
 
  381 QString QgsPictureSourceLineEditBase::extractFileTitle()
 const 
  386       return tr( 
"Extract SVG File" );
 
  388       return tr( 
"Extract Image File" );
 
  390       return tr( 
"Extract Animated Image File" );
 
  395 QString QgsPictureSourceLineEditBase::defaultSettingsKey()
 const 
  400       return QStringLiteral( 
"/UI/lastSVGDir" );
 
  402       return QStringLiteral( 
"/UI/lastImageDir" );
 
  404       return QStringLiteral( 
"/UI/lastAnimatedImageDir" );