diff --git a/src/FontManager.cpp b/src/FontManager.cpp index f1659b5556b..477e6a1e8c3 100644 --- a/src/FontManager.cpp +++ b/src/FontManager.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2009-2014 by Vadim Peretokin - vperetokin@gmail.com * + * Copyright (C) 2009, 2018 by Vadim Peretokin - vperetokin@gmail.com * * Copyright (C) 2014 by Ahmed Charles - acharles@outlook.com * * Copyright (C) 2017 by Stephen Lyons - slysven@viginmedia.com * * * @@ -21,12 +21,12 @@ #include "FontManager.h" - #include "mudlet.h" #include "pre_guard.h" -#include #include +#include +#include #include #include #include @@ -56,17 +56,48 @@ void FontManager::loadFonts(const QString& folder) { // Check what happens with this: "Adding application fonts on Unix/X11 platforms without fontconfig is currently not supported." QStringList filters; - filters << QStringLiteral("*.ttf") - << QStringLiteral("*.otf"); + filters << QStringLiteral("*.ttf") << QStringLiteral("*.otf"); QDir dir = folder; dir.setNameFilters(filters); - foreach (QString fontfile, dir.entryList(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot)) { - QString fontFilePathName = QStringLiteral("%1/%2").arg(dir.absolutePath(), fontfile); - if (QFontDatabase::addApplicationFont(fontFilePathName) == -1) { - // At the point that addFonts() is called we have a GUI application - // in the making and can use qDebug() and not rely on iostream class - qWarning() << "FontManager::loadFonts() ERROR - Could not load the font in the file: " << fontFilePathName; - } + foreach (QString fontFile, dir.entryList(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot)) { + QString fontFilePathName = QStringLiteral("%1/%2").arg(dir.absolutePath(), fontFile); + loadFont(fontFilePathName); + } +} + +void FontManager::loadFont(const QString& filePath) +{ + if (fontAlreadyLoaded(filePath)) { + return; + } + + auto fontID = QFontDatabase::addApplicationFont(filePath); + + // remember even if the font failed to load so we don't spam messages on fonts that repeat + rememberFont(filePath, fontID); + + if (fontID == -1) { + qWarning() << "FontManager::loadFonts() warning - Could not load the font(s) in the file: " << filePath; } } + +bool FontManager::fontAlreadyLoaded(const QString& filePath) +{ + QFileInfo fontFile(filePath); + auto fileName = fontFile.fileName(); + + return loadedFonts.contains(fileName); +} + +void FontManager::rememberFont(const QString& filePath, int fontID) +{ + QFileInfo fontFile(filePath); + auto fileName = fontFile.fileName(); + + if (loadedFonts.contains(fileName)) { + return; + } + + loadedFonts.insert(fileName, fontID); +} diff --git a/src/FontManager.h b/src/FontManager.h index e164b30eddd..1275a5f7b96 100644 --- a/src/FontManager.h +++ b/src/FontManager.h @@ -21,6 +21,9 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include "pre_guard.h" +#include +#include "post_guard.h" class QString; @@ -29,9 +32,15 @@ class FontManager { public: void addFonts(); + void loadFont(const QString& filePath); + bool fontAlreadyLoaded(const QString& filePath); private: void loadFonts(const QString& folder); + void rememberFont(const QString& fileName, int fontID); + + QMap loadedFonts; + }; #endif // MUDLET_FONTMANAGER_H diff --git a/src/Host.cpp b/src/Host.cpp index e24788690d4..ea3ad9e1d31 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include "post_guard.h" @@ -755,7 +756,7 @@ bool Host::installPackage(const QString& fileName, int module) { // As the pointed to dialog is only used now WITHIN this method and this // method can be re-entered, it is best to use a local rather than a class - // pointer just in case we accidently reenter this method in the future. + // pointer just in case we accidentally reenter this method in the future. QDialog* pUnzipDialog = Q_NULLPTR; // Module notes: @@ -927,6 +928,11 @@ bool Host::installPackage(const QString& fileName, int module) // reorder permanent and temporary triggers: perm first, temp second mTriggerUnit.reorderTriggersAfterPackageImport(); + // make any fonts in the package available to Mudlet for use + if (module != 2) { + installPackageFonts(packageName); + } + // raise 2 events - a generic one and a more detailed one to serve both // a simple need ("I just want the install event") and a more specific need // ("I specifically need to know when the module was synced") @@ -1194,6 +1200,32 @@ QString Host::readProfileData(const QString& item) return ret; } +// makes fonts in a given package/module be available for Mudlet scripting +// does not install font system-wide +void Host::installPackageFonts(const QString &packageName) +{ + auto packagePath = mudlet::getMudletPath(mudlet::profilePackagePath, getName(), packageName); + + QDirIterator it(packagePath, QDirIterator::Subdirectories); + while (it.hasNext()) { + auto filePath = it.next(); + + if (filePath.endsWith(QLatin1String(".otf"), Qt::CaseInsensitive) || filePath.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive) || + filePath.endsWith(QLatin1String(".ttc"), Qt::CaseInsensitive) || filePath.endsWith(QLatin1String(".otc"), Qt::CaseInsensitive)) { + + mudlet::self()->mFontManager.loadFont(filePath); + } + } +} + +// ensures fonts from all installed packages are loaded in Mudlet +void Host::refreshPackageFonts() +{ + for (const auto& package : mInstalledPackages) { + installPackageFonts(package); + } +} + void Host::setWideAmbiguousEAsianGlyphs(const Qt::CheckState state) { bool localState = false; diff --git a/src/Host.h b/src/Host.h index 14abddad470..8720b792a43 100644 --- a/src/Host.h +++ b/src/Host.h @@ -145,6 +145,7 @@ class Host : public QObject void saveModules(int); void reloadModule(const QString& moduleName); bool blockScripts() { return mBlockScriptCompile; } + void refreshPackageFonts(); void registerEventHandler(const QString&, TScript*); void registerAnonymousEventHandler(const QString& name, const QString& fun); @@ -416,6 +417,8 @@ class Host : public QObject // keeps track of all of the array writers we're currently operating with QHash writers; + + void installPackageFonts(const QString &packageName); }; #endif // MUDLET_HOST_H diff --git a/src/TLuaInterpreter.cpp b/src/TLuaInterpreter.cpp index c25d6c9a750..f95ca2a2bd1 100644 --- a/src/TLuaInterpreter.cpp +++ b/src/TLuaInterpreter.cpp @@ -11952,6 +11952,19 @@ double TLuaInterpreter::condenseMapLoad() return loadTime; } +int TLuaInterpreter::getAvailableFonts(lua_State* L) +{ + auto fontList = mudlet::self()->getAvailableFonts(); + + lua_newtable(L); + for (auto& font : fontList) { + lua_pushstring(L, font.toUtf8().constData()); + lua_pushboolean(L, true); + lua_settable(L, -3); + } + return 1; +} + void TLuaInterpreter::set_lua_table(const QString& tableName, QStringList& variableList) { lua_State* L = pGlobalLua; @@ -12391,6 +12404,7 @@ void TLuaInterpreter::initLuaGlobals() lua_register(pGlobalLua, "getColumnCount", TLuaInterpreter::getColumnCount); lua_register(pGlobalLua, "getRowCount", TLuaInterpreter::getRowCount); lua_register(pGlobalLua, "getOS", TLuaInterpreter::getOS); + lua_register(pGlobalLua, "getAvailableFonts", TLuaInterpreter::getAvailableFonts); // PLACEMARKER: End of main Lua interpreter functions registration diff --git a/src/TLuaInterpreter.h b/src/TLuaInterpreter.h index 2a69415faf4..65b7c7e5a85 100644 --- a/src/TLuaInterpreter.h +++ b/src/TLuaInterpreter.h @@ -428,6 +428,7 @@ class TLuaInterpreter : public QThread static int getColumnCount(lua_State*); static int getRowCount(lua_State*); static int getOS(lua_State*); + static int getAvailableFonts(lua_State* L); // PLACEMARKER: End of Lua functions declarations static const QMap mMouseButtons; void freeLuaRegistryIndex(int index); diff --git a/src/dlgConnectionProfiles.cpp b/src/dlgConnectionProfiles.cpp index d7a71efb8a1..0d62904b83f 100644 --- a/src/dlgConnectionProfiles.cpp +++ b/src/dlgConnectionProfiles.cpp @@ -1505,6 +1505,7 @@ void dlgConnectionProfiles::slot_connectToServer() XMLimport importer(pHost); qDebug() << "[LOADING PROFILE]:" << file.fileName(); importer.importPackage(&file, nullptr); // TODO: Missing false return value handler + pHost->refreshPackageFonts(); } else { needsGenericPackagesInstall = true; } diff --git a/src/main.cpp b/src/main.cpp index 87c4d10d46c..15a7cb803b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,7 +21,6 @@ ***************************************************************************/ -#include "FontManager.h" #include "HostManager.h" #include "mudlet.h" @@ -544,8 +543,6 @@ int main(int argc, char* argv[]) #endif mudlet::debugMode = false; - FontManager fm; - fm.addFonts(); if (show_splash) { splash_message.append("Done.\n\n" diff --git a/src/mudlet.cpp b/src/mudlet.cpp index 05f7bf8a8e9..70f13132a50 100644 --- a/src/mudlet.cpp +++ b/src/mudlet.cpp @@ -71,6 +71,7 @@ #include #include #include +#include #include "post_guard.h" #include @@ -139,6 +140,7 @@ mudlet* mudlet::self() mudlet::mudlet() : QMainWindow() +, mFontManager() , mToolbarIconSize(0) , mEditorTreeWidgetIconSize(0) , mWindowMinimized(false) @@ -498,6 +500,9 @@ mudlet::mudlet() #endif // Edbee has a singleton that needs some initialisation initEdbee(); + + // load bundled fonts + mFontManager.addFonts(); } QSettings* mudlet::getQSettings() @@ -2861,6 +2866,7 @@ void mudlet::doAutoLogin(const QString& profile_name) XMLimport importer(pHost); qDebug() << "[LOADING PROFILE]:" << file.fileName(); importer.importPackage(&file); // TODO: Missing false return value handler + pHost->refreshPackageFonts(); } pHost->setLogin(readProfileData(profile_name, QStringLiteral("login"))); @@ -3692,3 +3698,10 @@ void mudlet::slot_newDataOnHost(const QString& hostName, const bool isLowerPrior } } } + +QStringList mudlet::getAvailableFonts() +{ + QFontDatabase database; + + return database.families(QFontDatabase::Any); +} diff --git a/src/mudlet.h b/src/mudlet.h index a48540bfe02..eb5502cb18c 100644 --- a/src/mudlet.h +++ b/src/mudlet.h @@ -27,6 +27,7 @@ #include "HostManager.h" +#include "FontManager.h" #include "edbee/views/texttheme.h" #include "ui_main_window.h" @@ -85,7 +86,8 @@ class mudlet : public QMainWindow, public Ui::main_window static mudlet* self(); // This method allows better debugging when mudlet::self() is called inappropriately. static void start(); - HostManager& getHostManager() { return mHostManager; } + HostManager& getHostManager() { return mHostManager; } + FontManager mFontManager; QPointer mpSettings; void addSubWindow(TConsole* p); int getColumnNumber(Host* pHost, QString& name); @@ -199,6 +201,7 @@ class mudlet : public QMainWindow, public Ui::main_window void playSound(QString s, int); int getColumnCount(Host* pHost, QString& name); int getRowCount(Host* pHost, QString& name); + QStringList getAvailableFonts(); static const bool scmIsDevelopmentVersion; QTime mReplayTime;