Closed alexhochreiter closed 8 years ago
How did you include the library? Which installation method did you choose?
If you went with the "Per-project installation using git submodules" all you need to do is ass the following code in your .pro
project file:
OPTIONS += roboto
DEFINES += QPM_INIT
include(material/material.pri)
And in your main.cpp
:
QQmlApplicationEngine engine( &app );
engine.addImportPath( "qrc:///" );
Which is pretty bad when i don't want it packed into the application statically. Anyways, thank you, i ll gibe it a try!
Works like a charm, so thank you! Would be nice to still have n option to load it the "old fashioned qml include" way.
You could do that if you add the QML files in corresponding directories according to the prefix specified in the resource files. Make sure that the qmldir
file is there too. Add the directory that contains the Material
directory to your import path. Then you will have to add the following files to your project:
src/core/device.h
src/core/device.cpp
src/core/units.h
src/core/units.cpp
include the headers in your main and register the components:
// in your main before the QQmlApplicationEngine initialization
qmlRegisterSingletonType<Device>(uri, 0, 1, "Device", Device::qmlSingleton);
qmlRegisterUncreatableType<Units>(uri, 0, 3, "Units", QStringLiteral("Units can only be used via the attached property."));
You will need the #include <QtQml>
header for that.
This will work too. But as you can see the library isn't really meant to be used that way. But then again including all of the qml-material
elements statically won't increase the size of your app with more than a few hundred kilobytes. It's barely worth mentioning.
P.S. If this solves your issue close it so we don't bother the authors.
Thank you kindly for the detailed guide, would be awesome to have something like that in the readme! One last question though, I packed qml-material into a custom QtPlugin (because i need special plugin-interfaces) and tried to initialize alle the qrc files and register the qml types from there, which resulted in a
\"Material\" is ambiguous. Found in qrc://///Material/ and in qrc://///Material/\n
Where this is basically the code:
inline void initResources() {
Q_INIT_RESOURCE(material);
Q_INIT_RESOURCE(components);
Q_INIT_RESOURCE(controls);
Q_INIT_RESOURCE(core);
Q_INIT_RESOURCE(extras);
Q_INIT_RESOURCE(listitems);
Q_INIT_RESOURCE(popups);
Q_INIT_RESOURCE(styles);
Q_INIT_RESOURCE(window);
Q_INIT_RESOURCE(core_icons);
Q_INIT_RESOURCE(fonts);
}
bool QmlMaterialLib::initialize(QQmlEngine *qmlEngine) {
initResources();
qmlRegisterSingletonType<Device>("Material", 0, 1, "Device", Device::qmlSingleton);
qmlRegisterUncreatableType<Units>("Material", 0, 3, "Units", QStringLiteral("Units can only be used via the attached property."));
qmlEngine->addImportPath( "qrc:///" );
return true;
}
The plugin is built with the instruction you posted above,
OPTIONS += roboto
DEFINES += QPM_INIT
include(material/material.pri)
HEADERS -= $$_PRO_FILE_PWD_/qml-material/src/plugin.h
SOURCES -= $$_PRO_FILE_PWD_/qml-material/src/plugin.cpp
I also tried different variations, like not defining "QPM_INIT" and finally ended up with a question about:
qmlRegisterSingletonType<Device>("Material", 0, 1, "Device", Device::qmlSingleton);
is "Material" the right uri?
It should be. You would like those to be available under the Material
namespace in QML.
If you define QPM_INIT, the MaterialRegisterHelper
in src/plugin.cpp
should register those for you, but you have removed them so there is no need to use it.
I was already afraid of that, removed the QPM_INIT define and registered everything as stated above. Through some more research i found this related bug: https://bugreports.qt.io/browse/QTBUG-27645 which pretty much matches the situation. Using the "named import" workaround resolved the problem pretty much, but it's still a workaround and might be of interest when the developers want people to be able to create plugins containing/distributing qml-material.
Following your issue #442, i renamed the prefixes in the qrc files to /qml-material/Material (except for core_icons.qrc) This actually resolves the issue, but now i'm getting tons of different
qrc://///qml-material/Material/Icon.qml:54:5: QML Image: Cannot open: qrc:/icons/action/favorite.svg
qrc://///qml-material/Material/Icon.qml:54:5: QML Image: Cannot open: qrc:/icons/action/build.svg
messages. And actually ... there are only a few svgs in this repo's ./icons/ directory. So are we forced now to download all the svgs from the google material design icon collection on ourselfs, or is the FontAwesome method the new favourite way to? If FontAwesome IS the new way, are there any usage examples? Last but not least, even with the guide you wrote and the implementation excerp i wrote, i still get these messages:
ReferenceError: Units is not defined
Does the Device and Units class need any special treatment other then just registering their types with qmlRegisterSingletonType and qmlRegisterUncreatableType ? The qmlRegisterUncreatableType's last argument should be thrown when i try something like this in qml:
Units {
}
But instead of the intended error message "Units can only be used via the attached property.", i get:
Units is not a type
Put all your icon names in a file called icons.yml
. Follow the structure of the icons.yml
in the root of the repo. Then call the scripts/icons.py
which will download all of the specified icons and bundle them in your repo. This is all documented in the README.
As for the ReferenceError: Units is not defined
apparently you haven't registered the Units
class under the correct prefix.
P.S. Given how little documentation is available you should at least read it. I am referring to the README.md
.
Thanks for the guide on the icons issue!
I thought we settled on "Material" beeing the right prefix?
So what's wrong with qmlRegisterUncreatableType<Units>("Material", 0, 3, "Units", QStringLiteral("Units can only be used via the attached property."));
then ?
Nothing. Did you include that in your code before you initialize the QQmlApplicationEngine
?
I'm not using QQmlApplicationEngine
- just QQmlEngine
as it is.
I'm registering all things before the first qml file evaluation, while an instance of an QQmlEngine already exists at that point, all other registered types don't seem to have any problem with this.
I'm also checking their typeId which is beeing returned by qmlRegisterUncreatableType and qmlRegisterSingletonType and equals to -1 when they could not be registered; neither is -1.
When you changed the prefixes to /qml-material/Material
did you do the same for the Units
?
Also my issue #442 has nothing to do with the resource files prefixes. It has to do with the filenames.
What exactly should i change there?
I thought we registered the Units
type via c++?
In case you meant the UnitsHelper.qml, located in src/core, src/core.qrc, there sould be no additional steps necessary as the file has been moved to the /qml-material/
prefix with the other files, which are imported just fine.
No I meant the Units
type which you registered from C++. Now that you changed the prefix of the resource files of qml-material, did you change the uri of the Unit's type?
I am sorry, but i don't see the link between the prefix change and the Unit type's uri.
I changed the addImportPath url from qrc:///
to qrc:///qml-material
as the Units type is not an actual qml component, the uri should not change though.
Try it.
And to what exactly?
qml-material/Material
qmlRegisterUncreatableType<Units>("qml-material/Material", 0, 3, "Units", QStringLiteral("Units can only be used via the attached property."));
qmlRegisterUncreatableType<Units>("qrc:///qml-material/Material", 0, 3, "Units", QStringLiteral("Units can only be used via the attached property."));
Both resulted in the same as before.
Publish your code somewhere.
See my post number 4 - i ain't touchin qml-material any differently from the c++ side. Even with a clear/fresh proof of concept app the Units type is unkown.
In this case i didn't even apply the qml-material prefix for the qrc files.
qmlmaterialtest.pto
TEMPLATE = app
QT += qml quick
CONFIG += c++11
SOURCES += main.cpp
RESOURCES += qml.qrc
include(deployment.pri)
OPTIONS += roboto
#DEFINES += QPM_INIT
include(/Users/alex/git/qml-material/material.pri)
changes to material.pri
HEADERS += \ #$$PWD/src/plugin.h \
$$PWD/src/core/device.h \
$$PWD/src/core/units.h
SOURCES += \ #$$PWD/src/plugin.cpp \
$$PWD/src/core/device.cpp \
$$PWD/src/core/units.cpp
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QDebug>
#include </Users/alex/git/qml-material/src/core/device.h>
#include </Users/alex/git/qml-material/src/core/units.h>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
qDebug() << qmlRegisterSingletonType<Device>("Material", 0, 1, "Device", Device::qmlSingleton);
qDebug() << qmlRegisterUncreatableType<Units>("Material", 0, 3, "Units", QStringLiteral("Units can only be used via the attached property."));
QQmlApplicationEngine engine;
engine.addImportPath( "qrc:///" );
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Registering the types before QGuiApplication app(argc, argv);
does not make a difference.
main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
import Material 0.2
ApplicationWindow {
visible: true
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
Text {
text: qsTr("Hello World")
anchors.centerIn: parent
}
Component.onCompleted: {
Units.dp(2) // should not throw error, but does
}
Units {
// should throw "Units can only be used via the attached property." error
// actually throws "Units is not a type"
}
}
Update:
Using import Material 0.3
instead of 0.2 would have made total sense when registering the Units type for Material 0.3 anyways.
Now to the explaination of all the strange behaviours: looks like the Singleton type Units, Device etc is not available when creating components dynamically (eg Loader {}).
Is this some QML issue, or an QML-Material bug?
Hi guys, I'm really sorry that the new usage wasn't better documented. I've added more detailed documentation. There are three ways you can use QML Material:
So to be clear, you can statically include it or install it globally, depending on what you want. App developers for Android, OS X, or Windows will likely find the static installation method the easiest to work with. For Linux developers, the best option is to use the global installation method, preferably with a distro-specific package. This is also the best option for packaging using Flatpack, as dynamically linked/loaded libraries and QML modules will be deduped during download and locally on user's systems.
Please reopen this if anything isn't clear or you need further help. Thanks!
So whats the new intended way of usage/inclusion since the project structure changed? A simple
myQmlEngine->addImportPath("/path/to/qml-material/src/");
is just resulting in somemodule \"Material\" is not installed module \"Material.ListItems\" is not installed\
So what's the updated guide/intention on that?