Defer font download handling until QgsApplication is fully initialized

and make opt-in for non-app clients

There's a tricky initialization balancing act happening here -- but
if we try to load the default style on a system missing the fonts
referenced in that style, then we risk trying to download those
fonts before the QgsNetworkAccessManager is ready.

So play it safe and defer all font download handling until the
QGIS app is fully launched.
This commit is contained in:
Nyall Dawson 2022-06-17 03:30:50 +10:00
parent 7955f02287
commit dae637a67c
4 changed files with 54 additions and 1 deletions

View File

@ -126,12 +126,26 @@ The actual download operation occurs in a background task, and this method
returns immediately. Connect to :py:func:`~QgsFontManager.fontDownloaded` in order to respond when the
font is installed and available for use.
.. warning::
Before calling this method a :py:class:`QgsApplication` must be fully initialized
and a call to :py:func:`~QgsFontManager.enableFontDownloadsForSession` made.
:param family: input font family name to try to match to known fonts
:return: - ``True`` if match was successful and the download will occur
- matchedFamily: will be set to found font family if a match was successful
%End
void enableFontDownloadsForSession();
%Docstring
Enables font downloads the the current QGIS session.
.. warning::
Ensure that the :py:class:`QgsApplication` is fully initialized before calling this method.
%End
QString urlForFontDownload( const QString &family, QString &matchedFamily /Out/ ) const;
%Docstring
Returns the URL at which the font ``family`` can be downloaded.

View File

@ -1941,6 +1941,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipBadLayers
}
messageBar()->pushWidget( messageWidget, Qgis::MessageLevel::Warning, 0 );
} );
QgsApplication::fontManager()->enableFontDownloadsForSession();
}
QgisApp::QgisApp()

View File

@ -151,10 +151,36 @@ bool QgsFontManager::tryToDownloadFontFamily( const QString &family, QString &ma
locker.changeMode( QgsReadWriteLocker::Write );
mPendingFontDownloads.insert( family, matchedFamily );
downloadAndInstallFont( QUrl( url ), family );
if ( !mEnableFontDownloads )
{
mDeferredFontDownloads.insert( url, family );
}
else
{
locker.unlock();
downloadAndInstallFont( QUrl( url ), family );
}
return true;
}
void QgsFontManager::enableFontDownloadsForSession()
{
if ( mEnableFontDownloads )
return;
mEnableFontDownloads = true;
QgsReadWriteLocker locker( mReplacementLock, QgsReadWriteLocker::Read );
if ( !mDeferredFontDownloads.isEmpty() )
{
locker.changeMode( QgsReadWriteLocker::Write );
for ( auto it = mDeferredFontDownloads.constBegin(); it != mDeferredFontDownloads.constEnd(); ++it )
{
downloadAndInstallFont( QUrl( it.key() ), it.value() );
}
mDeferredFontDownloads.clear();
}
}
QString QgsFontManager::urlForFontDownload( const QString &family, QString &matchedFamily ) const
{
const thread_local QStringList sGoogleFonts

View File

@ -139,12 +139,22 @@ class CORE_EXPORT QgsFontManager : public QObject
* returns immediately. Connect to fontDownloaded() in order to respond when the
* font is installed and available for use.
*
* \warning Before calling this method a QgsApplication must be fully initialized
* and a call to enableFontDownloadsForSession() made.
*
* \param family input font family name to try to match to known fonts
* \param matchedFamily will be set to found font family if a match was successful
* \returns TRUE if match was successful and the download will occur
*/
bool tryToDownloadFontFamily( const QString &family, QString &matchedFamily SIP_OUT );
/**
* Enables font downloads the the current QGIS session.
*
* \warning Ensure that the QgsApplication is fully initialized before calling this method.
*/
void enableFontDownloadsForSession();
/**
* Returns the URL at which the font \a family can be downloaded.
*
@ -239,7 +249,9 @@ class CORE_EXPORT QgsFontManager : public QObject
mutable QReadWriteLock mReplacementLock;
QStringList mUserFontDirectories;
bool mEnableFontDownloads = false;
QMap< QString, QString > mPendingFontDownloads;
QMap< QString, QString > mDeferredFontDownloads;
void storeFamilyReplacements();
};