void AutoNavigator::recalculateParameters()
{
	// GameObject values
	f32 maa = environment()->getGoValue<f32>
	(
		ownerHandle(),
		ID::PV_MaxAngularAcceleration,
		pluginId()
	);

	mMaxAngularAcceleration = maa * radian_per_second_squared;

	f32 ms = environment()->getGoValue<f32>
	(
		ownerHandle(),
		ID::PV_MaxSpeed,
		pluginId()
	);
	
	mMaxSpeed = ms * si::meters_per_second;

	// Module values
	ModuleMapT::iterator it = mModules.begin();
	for (; it != mModules.end(); ++it)
	{
		mRadius = value<f32>(ID::PV_TriggerRadius, it->first) * si::meter;
	}
}
예제 #2
0
void WeaponRack::calculateVelocity(f32 startImpulse,
                                   v3& newVelocity,
                                   bool addShipVelocity) const
{
	const Location& go = getGoValue<Location>(ID::PV_Location, pluginId());

	newVelocity = go.orientation * v3(0, 0, startImpulse);

	if (addShipVelocity)
	{
		const v3& shipVelocity = getGoValue<v3>(ID::PV_Velocity, pluginId());
		newVelocity += shipVelocity;
	}
}
예제 #3
0
/******************************************************************************
* Loads a native plugin's library.
******************************************************************************/
void NativePlugin::loadPluginImpl()
{
	NativeOvitoObjectType* linkedListBefore = nullptr;
	if(isCore() == false) {
		linkedListBefore = NativeOvitoObjectType::_firstInfo;

		// Load dynamic library.
		if(_library == nullptr || _library->isLoaded() == false) {
			if(libraryFilename().isEmpty())
				throw Exception(QString("The manifest file of the native plugin %1 does not specify the library name.").arg(pluginId()));
			_library = new QLibrary(libraryFilename(), this);
			_library->setLoadHints(QLibrary::ExportExternalSymbolsHint);
			if(!_library->load()) {
				throw Exception(QString("Failed to load native plugin library.\nLibrary file: %1\nError: %2").arg(libraryFilename(), _library->errorString()));
			}
		}
	}
	NativeOvitoObjectType* linkedListAfter = NativeOvitoObjectType::_firstInfo;

	// Initialize all newly loaded classes and connect them with this plugin.
	for(NativeOvitoObjectType* clazz = linkedListAfter; clazz != linkedListBefore; clazz = clazz->_next) {
		if(clazz->pluginId() != pluginId())
			throw Exception(QString("Plugin ID %1 assigned to class %2 does not match plugin %3 that contains the class.").arg(clazz->pluginId()).arg(clazz->name()).arg(pluginId()));
		OVITO_ASSERT(clazz->plugin() == nullptr);
		clazz->initializeClassDescriptor(this);
		registerClass(clazz);
	}
}
예제 #4
0
Kopete::Account *JabberProtocol::createNewAccount (const QString & accountId)
{
	kdDebug (JABBER_DEBUG_GLOBAL) << "[Jabber Protocol] Create New Account. ID: " << accountId << "\n" << endl;
	if( Kopete::AccountManager::self()->findAccount( pluginId() , accountId ) )
		return 0L;  //the account may already exist if greated just above

	int slash=accountId.find('/');
	if(slash>=0)
	{
		QString realAccountId=accountId.left(slash);
		JabberAccount *realAccount=dynamic_cast<JabberAccount*>(Kopete::AccountManager::self()->findAccount( pluginId() , realAccountId ));
		if(!realAccount) //if it doesn't exist yet, create it
		{
			realAccount = new JabberAccount( this, realAccountId );
			if(!Kopete::AccountManager::self()->registerAccount(  realAccount ) )
				return 0L;
		}
		if(!realAccount)
			return 0L;
		return new JabberTransport( realAccount , accountId );
	}
	else
	{
		return new JabberAccount (this, accountId);
	}
}
예제 #5
0
    Q_FOREACH (const QString &plugindir, libraryPaths) {
        const QString &_ixfile = plugindir + QStringLiteral("kpluginindex.json");
        QFile indexFile(_ixfile);
        if (indexFile.exists()) {
            indexFile.open(QIODevice::ReadOnly);
            QJsonDocument jdoc = QJsonDocument::fromBinaryData(indexFile.readAll());
            indexFile.close();


            QJsonArray plugins = jdoc.array();

            for (QJsonArray::const_iterator iter = plugins.constBegin(); iter != plugins.constEnd(); ++iter) {
                const QJsonObject &obj = QJsonValue(*iter).toObject();
                const QString &candidate = obj.value(QStringLiteral("FileName")).toString();
                const KPluginMetaData m(obj, candidate);
                if (m.pluginId() == packageFormat) {
                    pluginFileName = candidate;
                    break;
                }
            }
        } else {
            QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(plugindir);
            QVectorIterator<KPluginMetaData> iter(plugins);
            while (iter.hasNext()) {
                auto md = iter.next();
                if (md.pluginId() == packageFormat) {
                    pluginFileName = md.fileName();
                    break;
                }
            }
        }
    }
예제 #6
0
void WeaponRack::calculateSpawnLocation(Location& spawnLocation,
                                        f32 spawnDistance) const
{
	const Location& go = getGoValue<Location>(ID::PV_Location, pluginId());
	
	spawnLocation.position = go.position + go.orientation.zAxis() * spawnDistance;
	spawnLocation.orientation = go.orientation;
}
void AutoNavigator::operate()
{
	GameHandle targetHandle = *mTargets.begin();

	// Check if target still exists
	if (! environment()->exists(targetHandle))
	{
		mTargets.erase(mTargets.begin());
		return;
	}
	
	const Location& own = getGoValue<Location>(ID::PV_Location, pluginId());
	Location target = environment()->getGoValue<Location>(targetHandle, ID::PV_Location, pluginId());
	
	if (nearEnough(own.position, target.position, mRadius.value()))
	{
		mTargets.erase(mTargets.begin());
		return;
	}

	const v3& targetVelocity = environment()->getGoValue<v3>(targetHandle, ID::PV_Velocity, pluginId());
	const v3& ownVelocity = getGoValue<v3>(ID::PV_Velocity, pluginId());
	
	// use two further frame positions because it takes 2 frames for the value to reach the physics
	v3 targetPositionEx(target.position + targetVelocity * 2.0f * mTime.value());
	v3 ownPositionEx(own.position + ownVelocity * 2.0f * mTime.value());
	
	// \todo use rotation velocity to approximate the orientation in the next frame
	v3 VectorToTarget(unitInverse(own.orientation) * (targetPositionEx - ownPositionEx));

	rotate( rotationTo(v3::UNIT_Z, VectorToTarget) );

	norm(VectorToTarget);

	// if the target lies behind the object, than z of VectorToTarget is negative
	// and the object slows down.
 	accelerate((f32)VectorToTarget.z * mMaxSpeed);
}
void AutoNavigator::rotate(const qv4& rotation)
{
	const v3& currentRotationVel = getGoValue<v3>(ID::PV_RelativeRotationVelocity, pluginId());

	// braking distance in radian
	v3 b = (currentRotationVel * currentRotationVel) / (2.0f * mMaxAngularAcceleration.value());

	// reduce the vibration caused by the time delay of 2 frames by using the braking distance * 3 
	b *= 2.0f;

	quantity<si::plane_angle,f32> pitch = rotation.getPitch(false) * si::radian;
	quantity<si::plane_angle,f32> yaw = rotation.getYaw(false) * si::radian;

	// get the sign
	f32 factor = sign(pitch.value());

	if ((factor * pitch) > (b.x * si::radian))
	{
		if ((factor * pitch) > mOptimalAngle)
			mRotationFactorPitch = 1.0f * factor;
		else
			mRotationFactorPitch = 0.05f * factor;
	}
	else
	{
		mRotationFactorPitch = 0.0f;
	}

	// get the sign
	factor = sign(yaw.value());

	if ((factor * yaw) > (b.y * si::radian))
	{
		if ((factor * yaw) > mOptimalAngle)
			mRotationFactorYaw = 1.0f * factor;
		else
			mRotationFactorYaw = 0.05f * factor;
	}
	else
		mRotationFactorYaw = 0.0f;
}
void AutoNavigator::rotate(const qv4& rotation) const
{
	const v3& currentRotationVel = getGoValue<v3>(ID::PV_RelativeRotationVelocity, pluginId());

	// braking distance in radian
	v3 b = (currentRotationVel * currentRotationVel) / (2.0f * mMaxAngularAcceleration.value());

	// reduce the vibration caused by the time delay of 2 frames by using the braking distance * 3 
	b *= 2.0f;

	quantity<si::plane_angle,f32> pitch = rotation.getPitch(false) * si::radian;
	quantity<si::plane_angle,f32> yaw = rotation.getYaw(false) * si::radian;

	// get the sign
	f32 factor = sign(pitch.value());

	if ((factor * pitch) > (b.x * si::radian))
	{
		if ((factor * pitch) > mOptimalAngle)
			emit<GameObjectEvent>(ID::GOE_CONTROL_PITCH, 1.0f * factor, ownerHandle());
		else
			emit<GameObjectEvent>(ID::GOE_CONTROL_PITCH, 0.05f * factor, ownerHandle());
	}
	else
	{
		emit<GameObjectEvent>(ID::GOE_CONTROL_PITCH, 0.0f, ownerHandle());
	}

	// get the sign
	factor = sign(yaw.value());

	if ((factor * yaw) > (b.y * si::radian))
	{
		if ((factor * yaw) > mOptimalAngle)
			emit<GameObjectEvent>(ID::GOE_CONTROL_YAW, 1.0f * factor, ownerHandle());
		else
			emit<GameObjectEvent>(ID::GOE_CONTROL_YAW, 0.05f * factor, ownerHandle());
	}
	else
		emit<GameObjectEvent>(ID::GOE_CONTROL_YAW, 0.0f, ownerHandle());
}
예제 #10
0
/*!  Return a list of \l{DeviceClass}{DeviceClasses} describing all the devices supported by this plugin. */
QList<DeviceClass> DevicePlugin::supportedDevices() const
{
    QList<DeviceClass> deviceClasses;
    foreach (const QJsonValue &vendorJson, m_metaData.value("vendors").toArray()) {
        bool broken = false;
        VendorId vendorId = vendorJson.toObject().value("id").toString();
        foreach (const QJsonValue &deviceClassJson, vendorJson.toObject().value("deviceClasses").toArray()) {
            QJsonObject jo = deviceClassJson.toObject();
            DeviceClass deviceClass(pluginId(), vendorId, jo.value("deviceClassId").toString());
            deviceClass.setName(jo.value("name").toString());
            DeviceClass::CreateMethods createMethods;
            foreach (const QJsonValue &createMethodValue, jo.value("createMethods").toArray()) {
                if (createMethodValue.toString() == "discovery") {
                    createMethods |= DeviceClass::CreateMethodDiscovery;
                } else if (createMethodValue.toString() == "auto") {
                    createMethods |= DeviceClass::CreateMethodAuto;
                } else {
                    createMethods |= DeviceClass::CreateMethodUser;
                }
            }
            deviceClass.setCreateMethods(createMethods);

            deviceClass.setDiscoveryParamTypes(parseParamTypes(jo.value("discoveryParamTypes").toArray()));

            QString setupMethod = jo.value("setupMethod").toString();
            if (setupMethod == "pushButton") {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodPushButton);
            } else if (setupMethod == "displayPin") {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodDisplayPin);
            } else if (setupMethod == "enterPin") {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodEnterPin);
            } else {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodJustAdd);
            }
            deviceClass.setPairingInfo(jo.value("pairingInfo").toString());
            deviceClass.setParamTypes(parseParamTypes(jo.value("paramTypes").toArray()));

            QList<ActionType> actionTypes;
            QList<StateType> stateTypes;
            foreach (const QJsonValue &stateTypesJson, jo.value("stateTypes").toArray()) {
                QJsonObject st = stateTypesJson.toObject();
                QStringList missingFields = verifyFields(QStringList() << "type" << "id" << "name", st);
                if (!missingFields.isEmpty()) {
                    qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in stateTypes";
                    broken = true;
                    break;
                }

                QVariant::Type t = QVariant::nameToType(st.value("type").toString().toLatin1().data());
                StateType stateType(st.value("id").toString());
                stateType.setName(st.value("name").toString());
                stateType.setType(t);
                stateType.setUnit(unitStringToUnit(st.value("unit").toString()));
                stateType.setDefaultValue(st.value("defaultValue").toVariant());
                stateTypes.append(stateType);

                // create ActionType if this StateType is writable
                if (st.contains("writable")) {
                    ActionType actionType(st.value("id").toString());
                    actionType.setName("set " + st.value("name").toString());
                    // Note: fields already checked in StateType
                    ParamType paramType(st.value("name").toString(), t, st.value("defaultValue").toVariant());
                    if (st.value("writable").toObject().contains("allowedValues")) {
                        QVariantList allowedValues;
                        foreach (const QJsonValue &allowedTypesJson, st.value("writable").toObject().value("allowedValues").toArray()) {
                            allowedValues.append(allowedTypesJson.toVariant());
                        }
                        paramType.setAllowedValues(allowedValues);
                    }
                    paramType.setInputType(inputTypeStringToInputType(st.value("writable").toObject().value("inputType").toString()));
                    paramType.setUnit(unitStringToUnit(st.value("unit").toString()));
                    paramType.setLimits(st.value("writable").toObject().value("minValue").toVariant(),
                                        st.value("writable").toObject().value("maxValue").toVariant());
                    actionType.setParamTypes(QList<ParamType>() << paramType);
                    actionTypes.append(actionType);
                }
            }
            deviceClass.setStateTypes(stateTypes);

            foreach (const QJsonValue &actionTypesJson, jo.value("actionTypes").toArray()) {
                QJsonObject at = actionTypesJson.toObject();
                QStringList missingFields = verifyFields(QStringList() << "id" << "name", at);
                if (!missingFields.isEmpty()) {
                    qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in actionTypes";
                    broken = true;
                    break;
                }

                ActionType actionType(at.value("id").toString());
                actionType.setName(at.value("name").toString());
                actionType.setParamTypes(parseParamTypes(at.value("paramTypes").toArray()));
                actionTypes.append(actionType);
            }
            deviceClass.setActionTypes(actionTypes);

            QList<EventType> eventTypes;
            foreach (const QJsonValue &eventTypesJson, jo.value("eventTypes").toArray()) {
                QJsonObject et = eventTypesJson.toObject();
                QStringList missingFields = verifyFields(QStringList() << "id" << "name", et);
                if (!missingFields.isEmpty()) {
                    qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in eventTypes";
                    broken = true;
                    break;
                }

                EventType eventType(et.value("id").toString());
                eventType.setName(et.value("name").toString());
                eventType.setParamTypes(parseParamTypes(et.value("paramTypes").toArray()));
                eventTypes.append(eventType);
            }
            deviceClass.setEventTypes(eventTypes);

            if (!broken) {
                deviceClasses.append(deviceClass);
            }
        }
예제 #11
0
QString KReportPluginMetaData::id() const
{
    return pluginId();
}
예제 #12
0
Extension *PluginManager::acquireExtension(const char *extensionId)
{
    std::string pluginId(extensionId, strrchr(extensionId, '/') - extensionId);
    PluginInfo *info = m_registry.find(pluginId.c_str())->second;

    // Retrieve the plugin if it is active, fetch the plugin from the cache if
    // it is cached or create it.
    Plugin *plugin;
    bool newPlugin;
    Table::const_iterator it = m_table.find(pluginId.c_str());
    if (it != m_table.end())
    {
        plugin = it->second;
        if (plugin->cached())
        {
            plugin->removeFromCache(m_lruCachedPlugin, m_mruCachedPlugin);
            --m_nCachedPlugins;
            newPlugin = true;
        }
        else
            newPlugin = false;
    }
    else
    {
        char *module = g_module_build_path(m_modulesDirName.c_str(),
                                           info->module.c_str());
        std::string error;
        plugin = Plugin::activate(*this, pluginId.c_str(), module, error);
        g_free(module);
        if (!plugin)
        {
            GtkWidget *dialog;
            dialog = gtk_message_dialog_new(
                NULL,
                GTK_DIALOG_DESTROY_WITH_PARENT,
                GTK_MESSAGE_ERROR,
                GTK_BUTTONS_CLOSE,
                _("Samoyed failed to activate plugin \"%s\"."),
                pluginId.c_str());
            if (!error.empty())
                Samoyed::gtkMessageDialogAddDetails(
                    dialog,
                    _("%s"),
                    error.c_str());
            gtk_dialog_set_default_response(GTK_DIALOG(dialog),
                                            GTK_RESPONSE_CLOSE);
            gtk_dialog_run(GTK_DIALOG(dialog));
            gtk_widget_destroy(dialog);
            return NULL;
        }
        m_table.insert(std::make_pair(plugin->id(), plugin));
        newPlugin = true;
    }

    // Acquire the extension from the plugin.
    Extension *ext = plugin->acquireExtension(extensionId);
    if (!ext && newPlugin)
    {
        plugin->addToCache(m_lruCachedPlugin, m_mruCachedPlugin);
        if (++m_nCachedPlugins > m_cacheSize)
        {
            Plugin *p = m_lruCachedPlugin;
            m_table.erase(p->id());
            p->removeFromCache(m_lruCachedPlugin, m_mruCachedPlugin);
            --m_nCachedPlugins;
            // Defer destroying the plugin.
            g_idle_add_full(G_PRIORITY_LOW,
                            destroyPluginDeferred,
                            new std::pair<PluginManager *, Plugin *>(this, p),
                            NULL);
        }
    }
    return ext;
}
QObject* WebPluginFactory::create (const QString& _mimeType, const QUrl& url, const QStringList& argumentNames, const QStringList& argumentValues) const
{
    //kDebug() << _mimeType << url << argumentNames;
    QString mimeType (_mimeType.trimmed());
    if (mimeType.isEmpty()) {
        extractGuessedMimeType (url, &mimeType);
    }

    const bool noPluginHandling = WebKitSettings::self()->isInternalPluginHandlingDisabled();

    if (!noPluginHandling && WebKitSettings::self()->isLoadPluginsOnDemandEnabled()) {
        const uint id = pluginId(url, argumentNames, argumentValues);
        if (!mPluginsLoadedOnDemand.contains(id)) {
            FakePluginWidget* widget = new FakePluginWidget(id, url, mimeType);
            connect(widget, SIGNAL(pluginLoaded(uint)), this, SLOT(loadedPlugin(uint)));
            return widget;
        }
    }

    Q_ASSERT(mPart); // should never happen!!
    KParts::ReadOnlyPart* part = 0;
    QWebView* view = (mPart ? mPart->view() : 0);

    if (noPluginHandling || !excludedMimeType(mimeType)) {
        QWebFrame* frame = (view ? view->page()->currentFrame() : 0);
        if (frame) {
            part = createPartInstanceFrom(mimeType, argumentNames, argumentValues, view, frame);
        }
    }

    kDebug() << "Asked for" << mimeType << "plugin, got" << part;

    if (part) {
        connect (part->browserExtension(), SIGNAL (openUrlNotify()),
                 mPart->browserExtension(), SIGNAL (openUrlNotify()));

        connect (part->browserExtension(), SIGNAL (openUrlRequest (KUrl, KParts::OpenUrlArguments, KParts::BrowserArguments)),
                 mPart->browserExtension(), SIGNAL (openUrlRequest (KUrl, KParts::OpenUrlArguments, KParts::BrowserArguments)));

        // Check if this part is scriptable
        KParts::ScriptableExtension* scriptExt = KParts::ScriptableExtension::childObject(part);
        if (!scriptExt) {
            // Try to fall back to LiveConnectExtension compat
            KParts::LiveConnectExtension* lc = KParts::LiveConnectExtension::childObject(part);
            if (lc) {
                scriptExt = KParts::ScriptableExtension::adapterFromLiveConnect(part, lc);
            }
        }

        if (scriptExt) {
            scriptExt->setHost(KParts::ScriptableExtension::childObject(mPart));
        }

        QMap<QString, QString> metaData = part->arguments().metaData();
        QString urlStr = url.toString (QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
        metaData.insert ("PropagateHttpHeader", "true");
        metaData.insert ("referrer", urlStr);
        metaData.insert ("cross-domain", urlStr);
        metaData.insert ("main_frame_request", "TRUE");
        metaData.insert ("ssl_activate_warnings", "TRUE");

        KWebPage *page = (view ? qobject_cast<KWebPage*>(view->page()) : 0);

        if (page) {
            const QString scheme = page->currentFrame()->url().scheme();
            if (page && (QString::compare (scheme, QL1S ("https"), Qt::CaseInsensitive) == 0 ||
                         QString::compare (scheme, QL1S ("webdavs"), Qt::CaseInsensitive) == 0))
                metaData.insert ("ssl_was_in_use", "TRUE");
            else
                metaData.insert ("ssl_was_in_use", "FALSE");
        }

        KParts::OpenUrlArguments openUrlArgs = part->arguments();
        openUrlArgs.metaData() = metaData;
        openUrlArgs.setMimeType(mimeType);
        part->setArguments(openUrlArgs);
        QMetaObject::invokeMethod(part, "openUrl", Qt::QueuedConnection, Q_ARG(KUrl, KUrl(url)));
        return part->widget();
    }

    return 0;
}
예제 #14
0
QString KexiPluginMetaData::id() const
{
    return pluginId();
}
예제 #15
0
void SearchDialog::accept() {
    Settings::setDefaultSearchPlugin(pluginId());
    QDialog::accept();
}
예제 #16
0
/*! Return a list of \l{DeviceClass}{DeviceClasses} describing all the devices supported by this plugin.
    If a DeviceClass has an invalid parameter it will be ignored.
*/
QList<DeviceClass> DevicePlugin::supportedDevices() const
{
    QList<DeviceClass> deviceClasses;
    foreach (const QJsonValue &vendorJson, m_metaData.value("vendors").toArray()) {
        bool broken = false;
        VendorId vendorId = vendorJson.toObject().value("id").toString();
        foreach (const QJsonValue &deviceClassJson, vendorJson.toObject().value("deviceClasses").toArray()) {
            QJsonObject jo = deviceClassJson.toObject();
            DeviceClass deviceClass(pluginId(), vendorId, jo.value("deviceClassId").toString());
            deviceClass.setName(jo.value("name").toString());
            DeviceClass::CreateMethods createMethods;
            foreach (const QJsonValue &createMethodValue, jo.value("createMethods").toArray()) {
                if (createMethodValue.toString() == "discovery") {
                    createMethods |= DeviceClass::CreateMethodDiscovery;
                } else if (createMethodValue.toString() == "auto") {
                    createMethods |= DeviceClass::CreateMethodAuto;
                } else if (createMethodValue.toString() == "user") {
                    createMethods |= DeviceClass::CreateMethodUser;
                } else {
                    qCWarning(dcDeviceManager) << "Unknown createMehtod" << createMethodValue.toString() <<
                                                  "in deviceClass " << deviceClass.name() << ". Falling back to CreateMethodUser.";
                    createMethods |= DeviceClass::CreateMethodUser;
                }
            }
            deviceClass.setCreateMethods(createMethods);
            deviceClass.setDeviceIcon(loadAndVerifyDeviceIcon(jo.value("deviceIcon").toString()));
            deviceClass.setDiscoveryParamTypes(parseParamTypes(jo.value("discoveryParamTypes").toArray()));

            QString setupMethod = jo.value("setupMethod").toString();
            if (setupMethod == "pushButton") {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodPushButton);
            } else if (setupMethod == "displayPin") {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodDisplayPin);
            } else if (setupMethod == "enterPin") {
                deviceClass.setSetupMethod(DeviceClass::SetupMethodEnterPin);
            } else if (setupMethod == "justAdd") {
                qCWarning(dcDeviceManager) << "Unknown setupMehtod" << setupMethod <<
                                              "in deviceClass " << deviceClass.name() << ". Falling back to SetupMethodJustAdd.";
                deviceClass.setSetupMethod(DeviceClass::SetupMethodJustAdd);
            }
            deviceClass.setPairingInfo(jo.value("pairingInfo").toString());
            deviceClass.setParamTypes(parseParamTypes(jo.value("paramTypes").toArray()));

            QList<DeviceClass::BasicTag> basicTags;
            foreach (const QJsonValue &basicTagJson, jo.value("basicTags").toArray()) {
                basicTags.append(loadAndVerifyBasicTag(basicTagJson.toString()));
            }
            deviceClass.setBasicTags(basicTags);

            QList<ActionType> actionTypes;
            QList<StateType> stateTypes;
            foreach (const QJsonValue &stateTypesJson, jo.value("stateTypes").toArray()) {
                QJsonObject st = stateTypesJson.toObject();
                QStringList missingFields = verifyFields(QStringList() << "type" << "id" << "name", st);
                if (!missingFields.isEmpty()) {
                    qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in stateTypes";
                    broken = true;
                    break;
                }

                QVariant::Type t = QVariant::nameToType(st.value("type").toString().toLatin1().data());
                StateType stateType(st.value("id").toString());
                stateType.setName(st.value("name").toString());
                stateType.setType(t);
                stateType.setUnit(loadAndVerifyUnit(st.value("unit").toString()));
                stateType.setDefaultValue(st.value("defaultValue").toVariant());
                if (st.contains("minValue"))
                    stateType.setMinValue(st.value("minValue").toVariant());

                if (st.contains("maxValue"))
                    stateType.setMaxValue(st.value("maxValue").toVariant());

                if (st.contains("possibleValues")) {
                    QVariantList possibleValues;
                    foreach (const QJsonValue &possibleValueJson, st.value("possibleValues").toArray()) {
                        possibleValues.append(possibleValueJson.toVariant());
                    }
                    stateType.setPossibleValues(possibleValues);

                    // inform the plugin developer about the error in the plugin json file
                    Q_ASSERT_X(stateType.possibleValues().contains(stateType.defaultValue()),
                               QString("\"%1\" plugin").arg(pluginName()).toLatin1().data(),
                               QString("The given default value \"%1\" is not in the possible values of the stateType \"%2\".")
                               .arg(stateType.defaultValue().toString()).arg(stateType.name()).toLatin1().data());

                }
                stateTypes.append(stateType);

                // create ActionType if this StateType is writable
                if (st.contains("writable") && st.value("writable").toBool()) {
                    // Note: fields already checked in StateType
                    ActionType actionType(ActionTypeId(stateType.id().toString()));
                    actionType.setName("set " + stateType.name());
                    ParamType paramType(stateType.name(), t, stateType.defaultValue());
                    paramType.setAllowedValues(stateType.possibleValues());
                    paramType.setUnit(stateType.unit());
                    paramType.setLimits(stateType.minValue(), stateType.maxValue());
                    actionType.setParamTypes(QList<ParamType>() << paramType);
                    actionTypes.append(actionType);
                }
            }
            deviceClass.setStateTypes(stateTypes);

            foreach (const QJsonValue &actionTypesJson, jo.value("actionTypes").toArray()) {
                QJsonObject at = actionTypesJson.toObject();
                QStringList missingFields = verifyFields(QStringList() << "id" << "name", at);
                if (!missingFields.isEmpty()) {
                    qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in actionTypes";
                    broken = true;
                    break;
                }

                ActionType actionType(at.value("id").toString());
                actionType.setName(at.value("name").toString());
                actionType.setParamTypes(parseParamTypes(at.value("paramTypes").toArray()));
                actionTypes.append(actionType);
            }
            deviceClass.setActionTypes(actionTypes);

            QList<EventType> eventTypes;
            foreach (const QJsonValue &eventTypesJson, jo.value("eventTypes").toArray()) {
                QJsonObject et = eventTypesJson.toObject();
                QStringList missingFields = verifyFields(QStringList() << "id" << "name", et);
                if (!missingFields.isEmpty()) {
                    qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in eventTypes";
                    broken = true;
                    break;
                }

                EventType eventType(et.value("id").toString());
                eventType.setName(et.value("name").toString());
                eventType.setParamTypes(parseParamTypes(et.value("paramTypes").toArray()));
                eventTypes.append(eventType);
            }
            deviceClass.setEventTypes(eventTypes);

            if (!broken)
                deviceClasses.append(deviceClass);

        }
    }