Skip to content

Commit

Permalink
Make QtScript optional
Browse files Browse the repository at this point in the history
since QtScript has been deprecated for a while and will be removed in
Qt6. The QJSEngine-based ECMAScript is always available anyway.
  • Loading branch information
stloeffler committed Oct 26, 2020
1 parent afa18c2 commit b122ecf
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 26 deletions.
10 changes: 8 additions & 2 deletions CMakeLists.txt
Expand Up @@ -233,8 +233,13 @@ use_cxx11()
# ========================

# Check for Qt5
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui UiTools Concurrent Script ScriptTools Xml LinguistTools Qml)
set(QT_LIBRARIES Qt5::Core Qt5::Widgets Qt5::Gui Qt5::UiTools Qt5::Concurrent Qt5::ScriptTools Qt5::Script Qt5::Xml Qt5::Qml)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui UiTools Concurrent Xml LinguistTools Qml OPTIONAL_COMPONENTS Script ScriptTools)
set(QT_LIBRARIES Qt5::Core Qt5::Widgets Qt5::Gui Qt5::UiTools Qt5::Concurrent Qt5::Xml Qt5::Qml)

if (Qt5Script_FOUND AND Qt5ScriptTools_FOUND)
list(APPEND QT_LIBRARIES Qt5::ScriptTools Qt5::Script)
set(WITH_QTSCRIPT ON)
endif()

if (UNIX AND NOT APPLE)
find_package(Qt5 REQUIRED COMPONENTS DBus)
Expand Down Expand Up @@ -494,6 +499,7 @@ message("")

CONFIG_INFO("Build ID" ${TW_BUILD_ID})
CONFIG_INFO("Compiler optimization" ${CMAKE_BUILD_TYPE})
CONFIG_YESNO("QtScript scripting" ${WITH_QTSCRIPT})
CONFIG_YESNO("Lua scripting plugin" LUA_FOUND)
CONFIG_YESNO("Python scripting plugin" PYTHONLIBS_FOUND)
IF( APPLE )
Expand Down
10 changes: 6 additions & 4 deletions src/CMakeLists.txt
Expand Up @@ -37,10 +37,8 @@ set(TEXWORKS_SRCS BibTeXFile.cpp
document/TeXDocument.cpp
scripting/ECMAScriptInterface.cpp
scripting/ECMAScript.cpp
scripting/JSScriptInterface.cpp
scripting/ScriptAPI.cpp
scripting/Script.cpp
scripting/JSScript.cpp
ui/ClickableLabel.cpp
ui/ClosableTabWidget.cpp
ui/LineNumberWidget.cpp
Expand Down Expand Up @@ -88,8 +86,6 @@ set(TEXWORKS_HDRS BibTeXFile.h
scripting/ScriptLanguageInterface.h
scripting/ScriptAPI.h
scripting/Script.h
scripting/JSScriptInterface.h
scripting/JSScript.h
ui/ClickableLabel.h
ui/ClosableTabWidget.h
ui/LineNumberWidget.h
Expand All @@ -112,6 +108,12 @@ else ()
list(APPEND TEXWORKS_SRCS InterProcessCommunicatorDBus.cpp)
endif ()

if (WITH_QTSCRIPT)
list(APPEND TEXWORKS_SRCS scripting/JSScriptInterface.cpp scripting/JSScript.cpp)
list(APPEND TEXWORKS_HDRS scripting/JSScriptInterface.h scripting/JSScript.h)
add_definitions(-DWITH_QTSCRIPT)
endif (WITH_QTSCRIPT)

set(TEXWORKS_UIS CitationSelectDialog.ui
CompletingEdit.ui
ConfirmDelete.ui
Expand Down
2 changes: 1 addition & 1 deletion src/PrefsDialog.cpp
Expand Up @@ -660,7 +660,7 @@ QDialog::DialogCode PrefsDialog::doPrefsDialog(QWidget *parent)
dlg.allowScriptFileWriting->setChecked(settings.value(QString::fromLatin1("allowScriptFileWriting"), kDefault_AllowScriptFileWriting).toBool());
dlg.allowSystemCommands->setChecked(settings.value(QString::fromLatin1("allowSystemCommands"), kDefault_AllowSystemCommands).toBool());
dlg.enableScriptingPlugins->setChecked(settings.value(QString::fromLatin1("enableScriptingPlugins"), kDefault_EnableScriptingPlugins).toBool());
// there is always at least JSScriptInterface
// there is always at least one built-in ScriptInterface
if (TWApp::instance()->getScriptManager()->languages().size() <= 1)
dlg.enableScriptingPlugins->setEnabled(false);
dlg.scriptDebugger->setChecked(settings.value(QString::fromLatin1("scriptDebugger"), kDefault_ScriptDebugger).toBool());
Expand Down
27 changes: 23 additions & 4 deletions src/TWScriptManager.cpp
Expand Up @@ -23,7 +23,9 @@
#include "Settings.h"
#include "TWScriptManager.h"
#include "scripting/ECMAScriptInterface.h"
#include "scripting/JSScriptInterface.h"
#if WITH_QTSCRIPT
# include "scripting/JSScriptInterface.h"
#endif
#include "scripting/ScriptAPI.h"
#include "scripting/ScriptLanguageInterface.h"
#include "utils/ResourcesLibrary.h"
Expand Down Expand Up @@ -77,7 +79,9 @@ TWScriptManager::saveDisabledList()
void TWScriptManager::loadPlugins()
{
// the JSScript interface isn't really a plugin, but provides the same interface
#if WITH_QTSCRIPT
scriptLanguages += new Tw::Scripting::JSScriptInterface();
#endif
scriptLanguages += new Tw::Scripting::ECMAScriptInterface();

// get any static plugins
Expand Down Expand Up @@ -170,7 +174,12 @@ void TWScriptManager::reloadScriptsInList(TWScriptList * list, QStringList & pro
continue;
}
}
const bool needsPlugin = (qobject_cast<const Tw::Scripting::JSScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr && qobject_cast<const Tw::Scripting::ECMAScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr);
const bool needsPlugin = (
#if WITH_QTSCRIPT
qobject_cast<const Tw::Scripting::JSScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr &&
#endif
qobject_cast<const Tw::Scripting::ECMAScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr
);
if (needsPlugin && !enableScriptsPlugins) {
// the plugin necessary to execute this scripts has been disabled
delete s;
Expand Down Expand Up @@ -286,7 +295,12 @@ void TWScriptManager::addScriptsInDirectory(TWScriptList *scriptList,
Tw::Scripting::ScriptLanguageInterface * i = qobject_cast<Tw::Scripting::ScriptLanguageInterface*>(plugin);
if (!i)
continue;
const bool isPlugin = (qobject_cast<Tw::Scripting::JSScriptInterface*>(plugin) == nullptr && qobject_cast<Tw::Scripting::ECMAScriptInterface*>(plugin) == nullptr);
const bool isPlugin = (
#if WITH_QTSCRIPT
qobject_cast<Tw::Scripting::JSScriptInterface*>(plugin) == nullptr &&
#endif
qobject_cast<Tw::Scripting::ECMAScriptInterface*>(plugin) == nullptr
);
if (isPlugin && !scriptingPluginsEnabled)
continue;
if (!i->canHandleFile(info))
Expand Down Expand Up @@ -378,7 +392,12 @@ TWScriptManager::runScript(QObject* script, QObject * context, QVariant & result
if (!s || s->getType() != scriptType)
return false;

const bool needsPlugin = (qobject_cast<const Tw::Scripting::JSScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr && qobject_cast<const Tw::Scripting::ECMAScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr);
const bool needsPlugin = (
#if WITH_QTSCRIPT
qobject_cast<const Tw::Scripting::JSScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr &&
#endif
qobject_cast<const Tw::Scripting::ECMAScriptInterface*>(s->getScriptLanguagePlugin()) == nullptr
);
if (needsPlugin && !settings.value(QString::fromLatin1("enableScriptingPlugins"), false).toBool())
return false;

Expand Down
13 changes: 11 additions & 2 deletions src/TWScriptableWindow.cpp
Expand Up @@ -26,7 +26,10 @@
#include "TWApp.h"
#include "TWScriptManager.h"
#include "TWUtils.h"
#include "scripting/JSScriptInterface.h"
#include "scripting/ECMAScriptInterface.h"
#if WITH_QTSCRIPT
# include "scripting/JSScriptInterface.h"
#endif
#include "scripting/ScriptAPI.h"
#include "scripting/ScriptLanguageInterface.h"

Expand Down Expand Up @@ -180,8 +183,14 @@ TWScriptableWindow::doAboutScripts()
TWApp::instance()->getScriptManager()->languages()) {
const Tw::Scripting::ScriptLanguageInterface * i = qobject_cast<Tw::Scripting::ScriptLanguageInterface*>(plugin);
if(!i) continue;
const bool isPlugin = (
#if WITH_QTSCRIPT
qobject_cast<const Tw::Scripting::JSScriptInterface*>(plugin) == nullptr &&
#endif
qobject_cast<const Tw::Scripting::ECMAScriptInterface*>(plugin) == nullptr
);
aboutText += QString::fromLatin1("<li><a href=\"%1\">%2</a>").arg(i->scriptLanguageURL(), i->scriptLanguageName());
if (!enableScriptsPlugins && !qobject_cast<const Tw::Scripting::JSScriptInterface*>(plugin)) {
if (isPlugin && !enableScriptsPlugins) {
//: This string is appended to a script language name to indicate it is currently disabled
aboutText += QChar::fromLatin1(' ') + tr("(disabled in the preferences)");
}
Expand Down
9 changes: 7 additions & 2 deletions unit-tests/CMakeLists.txt
Expand Up @@ -16,10 +16,15 @@ add_executable(test_Scripting
"${CMAKE_SOURCE_DIR}/src/scripting/Script.cpp"
"${CMAKE_SOURCE_DIR}/src/scripting/ECMAScriptInterface.cpp"
"${CMAKE_SOURCE_DIR}/src/scripting/ECMAScript.cpp"
"${CMAKE_SOURCE_DIR}/src/scripting/JSScriptInterface.cpp"
"${CMAKE_SOURCE_DIR}/src/scripting/JSScript.cpp"
"${CMAKE_SOURCE_DIR}/src/Settings.cpp"
)
if (WITH_QTSCRIPT)
target_sources(test_Scripting
PRIVATE "${CMAKE_SOURCE_DIR}/src/scripting/JSScriptInterface.cpp"
PRIVATE "${CMAKE_SOURCE_DIR}/src/scripting/JSScript.cpp"
)
target_compile_definitions(test_Scripting PRIVATE WITH_QTSCRIPT)
endif (WITH_QTSCRIPT)
target_compile_options(test_Scripting PRIVATE ${WARNING_OPTIONS})
target_link_libraries(test_Scripting ${QT_LIBRARIES} ${ZLIB_LIBRARIES} ${TEXWORKS_ADDITIONAL_LIBS})
add_test(NAME test_Scripting COMMAND test_Scripting WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/testcases")
Expand Down
41 changes: 30 additions & 11 deletions unit-tests/Scripting_test.cpp
Expand Up @@ -24,8 +24,10 @@
#include "MockScriptingAPI.h"
#include "scripting/ECMAScript.h"
#include "scripting/ECMAScriptInterface.h"
#include "scripting/JSScript.h"
#include "scripting/JSScriptInterface.h"
#if WITH_QTSCRIPT
# include "scripting/JSScript.h"
# include "scripting/JSScriptInterface.h"
#endif

using namespace Tw::Scripting;

Expand All @@ -36,17 +38,21 @@ namespace UnitTest {

void TestScripting::scriptLanguageName()
{
#if WITH_QTSCRIPT
Tw::Scripting::JSScriptInterface js;
QCOMPARE(js.scriptLanguageName(), QStringLiteral("QtScript"));
#endif

Tw::Scripting::ECMAScriptInterface es;
QCOMPARE(es.scriptLanguageName(), QStringLiteral("ECMAScript"));
}

void TestScripting::scriptLanguageURL()
{
#if WITH_QTSCRIPT
Tw::Scripting::JSScriptInterface js;
QCOMPARE(js.scriptLanguageURL(), QStringLiteral("http://doc.qt.io/qt-5/qtscript-index.html"));
#endif

Tw::Scripting::ECMAScriptInterface es;
QCOMPARE(es.scriptLanguageURL(), QStringLiteral("https://doc.qt.io/qt-5/qjsengine.html"));
Expand All @@ -61,13 +67,15 @@ void TestScripting::canHandleFile()
QFileInfo fiLua(QStringLiteral("file.lua"));
QFileInfo fiTex(QStringLiteral("file.tex"));

#if WITH_QTSCRIPT
Tw::Scripting::JSScriptInterface js;
QVERIFY(js.canHandleFile(fiNull) == false);
QVERIFY(js.canHandleFile(fiEs) == false);
QVERIFY(js.canHandleFile(fiJs));
QVERIFY(js.canHandleFile(fiPy) == false);
QVERIFY(js.canHandleFile(fiLua) == false);
QVERIFY(js.canHandleFile(fiTex) == false);
#endif

Tw::Scripting::ECMAScriptInterface es;
QVERIFY(es.canHandleFile(fiNull) == false);
Expand All @@ -80,6 +88,7 @@ void TestScripting::canHandleFile()

void TestScripting::isEnabled()
{
#if WITH_QTSCRIPT
JSScriptInterface jsi;
Script * js = jsi.newScript(QString());

Expand All @@ -88,32 +97,37 @@ void TestScripting::isEnabled()
QVERIFY(js->isEnabled() == false);
js->setEnabled(true);
QVERIFY(js->isEnabled());
#endif
}

void TestScripting::getScriptLanguagePlugin()
{
#if WITH_QTSCRIPT
JSScriptInterface jsi;

QCOMPARE(jsi.newScript(QString())->getScriptLanguagePlugin(), &jsi);
#endif
}

void TestScripting::getFilename()
{
JSScriptInterface jsi;
QString invalid = QStringLiteral("does-not-exist");
#if WITH_QTSCRIPT
JSScriptInterface jsi;

QCOMPARE(jsi.newScript(QString())->getFilename(), QString());
QCOMPARE(jsi.newScript(invalid)->getFilename(), invalid);
#endif
}

void TestScripting::globals()
{
JSScriptInterface jsi;
QSharedPointer<Script> js = QSharedPointer<Script>(jsi.newScript(QString()));

QString key = QStringLiteral("myGlobal");
QVariant val(42.f);

#if WITH_QTSCRIPT
JSScriptInterface jsi;
QSharedPointer<Script> js = QSharedPointer<Script>(jsi.newScript(QString()));

QVERIFY(js->hasGlobal(key) == false);
QCOMPARE(js->getGlobal(key), QVariant());
QVERIFY(js->hasGlobal(key) == false);
Expand All @@ -124,6 +138,7 @@ void TestScripting::globals()
QCOMPARE(js->getGlobal(key), val);
js->unsetGlobal(key);
QVERIFY(js->hasGlobal(key) == false);
#endif
}

void TestScripting::parseHeader_data()
Expand All @@ -139,9 +154,10 @@ void TestScripting::parseHeader_data()
QTest::addColumn<QString>("context");
QTest::addColumn<QKeySequence>("keySequence");

#if WITH_QTSCRIPT
JSScriptInterface jsi;

QTest::newRow("invalid") << QSharedPointer<Script>(jsi.newScript(QString()))
QTest::newRow("invalid (JS)") << QSharedPointer<Script>(jsi.newScript(QString()))
<< false
<< Script::ScriptType::ScriptUnknown
<< QString()
Expand All @@ -151,7 +167,7 @@ void TestScripting::parseHeader_data()
<< QString()
<< QString()
<< QKeySequence();
QTest::newRow("script1.js") << QSharedPointer<Script>(jsi.newScript(QStringLiteral("script1.js")))
QTest::newRow("script1.js (JS)") << QSharedPointer<Script>(jsi.newScript(QStringLiteral("script1.js")))
<< true
<< Script::ScriptType::ScriptStandalone
<< QStringLiteral("Tw.insertText test")
Expand All @@ -161,7 +177,7 @@ void TestScripting::parseHeader_data()
<< QString()
<< QStringLiteral("TeXDocument")
<< QKeySequence(QStringLiteral("Ctrl+Alt+Shift+I"));
QTest::newRow("script2.js") << QSharedPointer<Script>(jsi.newScript(QStringLiteral("script2.js")))
QTest::newRow("script2.js (JS)") << QSharedPointer<Script>(jsi.newScript(QStringLiteral("script2.js")))
<< false
<< Script::ScriptType::ScriptUnknown
<< QStringLiteral("Exception test")
Expand All @@ -171,6 +187,7 @@ void TestScripting::parseHeader_data()
<< QString()
<< QString()
<< QKeySequence();
#endif
}

void TestScripting::parseHeader()
Expand Down Expand Up @@ -200,7 +217,7 @@ void TestScripting::parseHeader()

void TestScripting::mocks()
{
Script * s = JSScriptInterface().newScript(QString());
Script * s = ECMAScriptInterface().newScript(QString());
MockAPI api(s);

QCOMPARE(api.self(), &api);
Expand Down Expand Up @@ -269,6 +286,7 @@ void TestScripting::mocks()

void TestScripting::execute()
{
#if WITH_QTSCRIPT
JSScriptInterface jsi;

QSharedPointer<Script> js1 = QSharedPointer<Script>(jsi.newScript(QStringLiteral("does-not-exist")));
Expand All @@ -290,6 +308,7 @@ void TestScripting::execute()
QVERIFY(js3->run(api) == false);
QCOMPARE(api.GetResult(), QVariant(QStringLiteral("an exception")));
}
#endif
}

} // namespace UnitTest
Expand Down

0 comments on commit b122ecf

Please sign in to comment.