diff --git a/include/ignition/gui/Helpers.hh b/include/ignition/gui/Helpers.hh
index d9ec7b979..b99b1822d 100644
--- a/include/ignition/gui/Helpers.hh
+++ b/include/ignition/gui/Helpers.hh
@@ -89,6 +89,15 @@ namespace ignition
IGNITION_GUI_VISIBLE
std::string renderEngineName();
+ /// \brief Import path for ign-gui QML modules added to the Qt resource
+ /// system. This helper function returns the QRC resource path where custom
+ /// ignition QML modules can be imported from. To import an ignition QML
+ /// module, add this path to the QML engine's import path list before
+ /// attempting to load a QML file that imports ignition QML modules.
+ /// \return Resousrce path prefix as a string
+ IGNITION_GUI_VISIBLE
+ const QString qmlQrcImportPath();
+
/// \brief Returns the first element on a QList which matches the given
/// property.
/// \param[in] _list The list to search through.
diff --git a/include/ignition/gui/qml/qmldir b/include/ignition/gui/qml/qmldir
new file mode 100644
index 000000000..f4f66ebc1
--- /dev/null
+++ b/include/ignition/gui/qml/qmldir
@@ -0,0 +1,3 @@
+module ignition.gui
+
+IgnSpinBox 1.0 IgnSpinBox.qml
\ No newline at end of file
diff --git a/include/ignition/gui/resources.qrc b/include/ignition/gui/resources.qrc
index 6d54c9f0c..7ec777bf9 100644
--- a/include/ignition/gui/resources.qrc
+++ b/include/ignition/gui/resources.qrc
@@ -23,4 +23,10 @@
qml/images/export_icon.png
qml/images/search.svg
+
+
+ qml/qmldir
+
+ qml/IgnSpinBox.qml
+
diff --git a/src/Application.cc b/src/Application.cc
index 57104b09b..9b8d0c79b 100644
--- a/src/Application.cc
+++ b/src/Application.cc
@@ -28,6 +28,7 @@
#include "ignition/gui/Application.hh"
#include "ignition/gui/config.hh"
#include "ignition/gui/Dialog.hh"
+#include "ignition/gui/Helpers.hh"
#include "ignition/gui/MainWindow.hh"
#include "ignition/gui/Plugin.hh"
@@ -91,6 +92,7 @@ Application::Application(int &_argc, char **_argv, const WindowType _type)
// QML engine
this->dataPtr->engine = new QQmlApplicationEngine();
+ this->dataPtr->engine->addImportPath(qmlQrcImportPath());
// Install signal handler for graceful shutdown
this->dataPtr->signalHandler.AddCallback(
@@ -387,6 +389,9 @@ bool Application::LoadPlugin(const std::string &_filename,
else
plugin->Load(_pluginElem);
+ if (nullptr == plugin->CardItem())
+ return false;
+
// Store plugin in queue to be added to the window
this->dataPtr->pluginsToAdd.push(plugin);
diff --git a/src/Application_TEST.cc b/src/Application_TEST.cc
index 265a86220..8d26c6936 100644
--- a/src/Application_TEST.cc
+++ b/src/Application_TEST.cc
@@ -136,6 +136,14 @@ TEST(ApplicationTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(LoadPlugin))
EXPECT_FALSE(app.LoadPlugin("TestNotRegisteredPlugin"));
}
+
+ // Plugin with invalid QML
+ {
+ Application app(g_argc, g_argv);
+ app.AddPluginPath(std::string(PROJECT_BINARY_PATH) + "/lib");
+
+ EXPECT_FALSE(app.LoadPlugin("TestInvalidQmlPlugin"));
+ }
}
//////////////////////////////////////////////////
diff --git a/src/Helpers.cc b/src/Helpers.cc
index 37ef34649..286b45f56 100644
--- a/src/Helpers.cc
+++ b/src/Helpers.cc
@@ -194,3 +194,9 @@ std::string ignition::gui::renderEngineName()
return renderEngineNameVariant.toString().toStdString();
}
+
+/////////////////////////////////////////////////
+const QString ignition::gui::qmlQrcImportPath()
+{
+ return "qrc:/ign-gui-qml/";
+}
diff --git a/src/ign.cc b/src/ign.cc
index 12ef07713..faba5dcc3 100644
--- a/src/ign.cc
+++ b/src/ign.cc
@@ -33,6 +33,18 @@ char* g_argv[] =
reinterpret_cast(const_cast("./ignition")),
};
+//////////////////////////////////////////////////
+void startConsoleLog()
+{
+ std::string home;
+ ignition::common::env(IGN_HOMEDIR, home);
+
+ std::string logPathMod = ignition::common::joinPaths(home,
+ ".ignition", "gui", "log",
+ ignition::common::timeToIso(IGN_SYSTEM_TIME()));
+ ignLogInit(logPathMod, "console.log");
+}
+
//////////////////////////////////////////////////
extern "C" IGNITION_GUI_VISIBLE char *ignitionVersion()
{
@@ -42,6 +54,8 @@ extern "C" IGNITION_GUI_VISIBLE char *ignitionVersion()
//////////////////////////////////////////////////
extern "C" IGNITION_GUI_VISIBLE void cmdPluginList()
{
+ startConsoleLog();
+
ignition::gui::Application app(g_argc, g_argv);
auto pluginsList = app.PluginList();
@@ -65,6 +79,8 @@ extern "C" IGNITION_GUI_VISIBLE void cmdPluginList()
//////////////////////////////////////////////////
extern "C" IGNITION_GUI_VISIBLE void cmdStandalone(const char *_filename)
{
+ startConsoleLog();
+
ignition::gui::Application app(g_argc, g_argv,
ignition::gui::WindowType::kDialog);
@@ -79,6 +95,8 @@ extern "C" IGNITION_GUI_VISIBLE void cmdStandalone(const char *_filename)
//////////////////////////////////////////////////
extern "C" IGNITION_GUI_VISIBLE void cmdConfig(const char *_config)
{
+ startConsoleLog();
+
ignition::gui::Application app(g_argc, g_argv);
if (!app.findChild())
@@ -103,6 +121,8 @@ extern "C" IGNITION_GUI_VISIBLE void cmdVerbose(const char *_verbosity)
//////////////////////////////////////////////////
extern "C" IGNITION_GUI_VISIBLE void cmdEmptyWindow()
{
+ startConsoleLog();
+
ignition::gui::Application app(g_argc, g_argv);
if (!app.findChild())
diff --git a/src/ign_TEST.cc b/src/ign_TEST.cc
index 80a240ac8..cf3ba5ea7 100644
--- a/src/ign_TEST.cc
+++ b/src/ign_TEST.cc
@@ -21,6 +21,8 @@
#include
+#include
+#include
#include
#include "test_config.h" // NOLINT(build/include)
@@ -52,10 +54,45 @@ std::string custom_exec_str(std::string _cmd)
return result;
}
+using namespace ignition;
+
+class CmdLine : public ::testing::Test
+{
+ // Documentation inherited
+ protected: void SetUp() override
+ {
+ // Change environment variable so that test files aren't written to $HOME
+ common::env(IGN_HOMEDIR, this->realHome);
+ EXPECT_TRUE(common::setenv(IGN_HOMEDIR, this->kFakeHome.c_str()));
+ }
+
+ // Documentation inherited
+ protected: void TearDown() override
+ {
+ // Restore $HOME
+ EXPECT_TRUE(common::setenv(IGN_HOMEDIR, this->realHome.c_str()));
+ }
+
+ /// \brief Directory to act as $HOME for tests
+ public: const std::string kFakeHome = common::joinPaths(PROJECT_BINARY_PATH,
+ "test", "fake_home");
+
+ /// \brief Store user's real $HOME to set it back at the end of tests.
+ public: std::string realHome;
+};
+
// See https://github.com/ignitionrobotics/ign-gui/issues/75
-TEST(CmdLine, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(list))
+TEST_F(CmdLine, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(list))
{
+ // Clear home if it exists
+ common::removeAll(this->kFakeHome);
+
+ EXPECT_FALSE(common::exists(this->kFakeHome));
+
std::string output = custom_exec_str("ign gui -l");
EXPECT_NE(output.find("TopicEcho"), std::string::npos) << output;
EXPECT_NE(output.find("Publisher"), std::string::npos) << output;
+
+ EXPECT_TRUE(common::exists(common::joinPaths(this->kFakeHome, ".ignition",
+ "gui")));
}
diff --git a/src/plugins/teleop/Teleop.qml b/src/plugins/teleop/Teleop.qml
index 74f9eed9d..f4001a578 100644
--- a/src/plugins/teleop/Teleop.qml
+++ b/src/plugins/teleop/Teleop.qml
@@ -20,7 +20,7 @@ import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
-import "qrc:/qml"
+import ignition.gui 1.0
Rectangle {
color:"transparent"
diff --git a/src/plugins/topic_echo/TopicEcho.qml b/src/plugins/topic_echo/TopicEcho.qml
index e1b91543c..aef2cd3a5 100644
--- a/src/plugins/topic_echo/TopicEcho.qml
+++ b/src/plugins/topic_echo/TopicEcho.qml
@@ -97,8 +97,8 @@ Rectangle {
currentIndex: -1
delegate: ItemDelegate {
- width: parent.width
- text: display
+ width: listView.width
+ text: model.display
}
model: TopicEchoMsgList
diff --git a/test/plugins/CMakeLists.txt b/test/plugins/CMakeLists.txt
index 7451a7329..5381233cc 100644
--- a/test/plugins/CMakeLists.txt
+++ b/test/plugins/CMakeLists.txt
@@ -11,6 +11,7 @@ link_directories(
set (plugins
TestBadInheritancePlugin
+ TestInvalidQmlPlugin
TestNotRegisteredPlugin
TestPlugin
)
diff --git a/test/plugins/TestInvalidQmlPlugin.cc b/test/plugins/TestInvalidQmlPlugin.cc
new file mode 100644
index 000000000..c4b604799
--- /dev/null
+++ b/test/plugins/TestInvalidQmlPlugin.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include
+
+#include "TestInvalidQmlPlugin.hh"
+
+using namespace ignition;
+using namespace gui;
+
+/////////////////////////////////////////////////
+TestInvalidQmlPlugin::TestInvalidQmlPlugin()
+ : Plugin()
+{
+}
+
+/////////////////////////////////////////////////
+TestInvalidQmlPlugin::~TestInvalidQmlPlugin()
+{
+}
+
+// Register this plugin
+IGNITION_ADD_PLUGIN(ignition::gui::TestInvalidQmlPlugin,
+ ignition::gui::Plugin)
diff --git a/test/plugins/TestInvalidQmlPlugin.hh b/test/plugins/TestInvalidQmlPlugin.hh
new file mode 100644
index 000000000..412dbd1e6
--- /dev/null
+++ b/test/plugins/TestInvalidQmlPlugin.hh
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#ifndef IGNITION_GUI_TEST_MALFORMEDPLUGIN_HH_
+#define IGNITION_GUI_TEST_MALFORMEDPLUGIN_HH_
+
+#include
+
+namespace ignition
+{
+ namespace gui
+ {
+ class TestInvalidQmlPlugin : public Plugin
+ {
+ Q_OBJECT
+
+ /// \brief Constructor
+ public: TestInvalidQmlPlugin();
+
+ /// \brief Destructor
+ public: virtual ~TestInvalidQmlPlugin();
+ };
+ }
+}
+
+#endif
diff --git a/test/plugins/TestInvalidQmlPlugin.qml b/test/plugins/TestInvalidQmlPlugin.qml
new file mode 100644
index 000000000..17cdc890e
--- /dev/null
+++ b/test/plugins/TestInvalidQmlPlugin.qml
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+import QtQuick 2.9
+
+Rectangle {
+ banana: fail
+}
diff --git a/test/plugins/TestInvalidQmlPlugin.qrc b/test/plugins/TestInvalidQmlPlugin.qrc
new file mode 100644
index 000000000..c48ea9d64
--- /dev/null
+++ b/test/plugins/TestInvalidQmlPlugin.qrc
@@ -0,0 +1,5 @@
+
+
+ TestInvalidQmlPlugin.qml
+
+
diff --git a/tutorials/02_commandline.md b/tutorials/02_commandline.md
index daa19ab4e..978021331 100644
--- a/tutorials/02_commandline.md
+++ b/tutorials/02_commandline.md
@@ -32,3 +32,6 @@ If you have Ignition Tools installed, you can use the `ign gui` command line too
--force-version Use a specific library version.
--versions Show the available versions.
+
+When using the command line tool, all console messages are logged to
+`$HOME/.ignition/gui/log/`.