Эх сурвалжийг харах

Zwischenstand zur Ansicht.

Rind 7 жил өмнө
parent
commit
d0d02944eb

+ 11 - 0
QmlTest/.gitignore

@@ -0,0 +1,11 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
+
+Debug/
+Release/
+res/
+*.user

+ 30 - 0
QmlTest/QmlTest.pro

@@ -0,0 +1,30 @@
+TEMPLATE = app
+
+QT += qml quick
+CONFIG += c++11
+
+SOURCES += main.cpp
+
+RESOURCES += qml.qrc
+
+# Additional import path used to resolve QML modules in Qt Creator's code model
+QML_IMPORT_PATH =
+
+# Additional import path used to resolve QML modules just for Qt Quick Designer
+QML_DESIGNER_IMPORT_PATH =
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which as been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target

+ 12 - 0
QmlTest/main.cpp

@@ -0,0 +1,12 @@
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+    QGuiApplication app(argc, argv);
+
+    QQmlApplicationEngine engine;
+    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+    return app.exec();
+}

+ 32 - 0
QmlTest/main.qml

@@ -0,0 +1,32 @@
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import gfa.plugins.qml.net 1.0
+
+Window {
+    visible: true
+    width: 640
+    height: 480
+    title: qsTr("Hello World")
+
+    NetInterfaces {
+        id: idItf
+    }
+
+    MouseArea {
+        anchors.fill: parent
+        onClicked: {
+            if(idItf.initialize())
+            {
+                var ifs = idItf.getInterface("eth0");
+                if(ifs.length > 0)
+                {
+                    console.log(ifs[0].ipAddress);
+                }
+                else
+                {
+                    console.log("No interface found!");
+                }
+            }
+        }
+    }
+}

+ 5 - 0
QmlTest/qml.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>main.qml</file>
+    </qresource>
+</RCC>

+ 75 - 0
libgfanet/deploy.sh

@@ -0,0 +1,75 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+COMMAND=$1
+LIB_BASE=$2
+BUILD_TYPE=$3
+KIT_NAME=$4
+SYS_ROOT=$5
+SRC_DIR=$6
+
+#echo $SRC_DIR
+#exit 0
+
+if [ "$BUILD_TYPE" == "debug" ]; then
+	LIB_NAME="lib"$LIB_BASE"d.so"
+elif [ "$BUILD_TYPE" == "release" ]; then
+	LIB_NAME="lib"$LIB_BASE".so"
+else
+	echo "Invalid Build-type: "$BUILD_TYPE
+	exit 1
+fi
+
+if [ "$KIT_NAME" == "Desktop Qt 5.7.0 GCC 64bit" ]; then
+	LIB_PREFIX=$SYS_ROOT"/usr/lib"
+	INC_PREFIX=$SYS_ROOT"/usr/include/gfa"
+elif [ "$KIT_NAME" == "GfA-Device" ]; then
+	LIB_PREFIX=$SYS_ROOT"/usr/lib"
+	INC_PREFIX=$SYS_ROOT"/usr/include/gfa"
+else
+	echo "Invalid Kit-name: "$KIT_NAME
+	exit 1
+fi
+
+LIB_TARGET=$LIB_NAME".1.0.0"
+LIB_LINK0=$LIB_NAME
+LIB_LINK1=$LIB_NAME".1"
+
+if [ "$COMMAND" == "deploy" ]; then
+	HOST=$6
+	USER=$7@$HOST
+	PASS=$8
+	pscp -pw $PASS $LIB_NAME $USER:/usr/lib/$LIB_TARGET > /dev/null
+	plink -batch -t -pw $PASS $USER ln -sfn /usr/lib/$LIB_TARGET /usr/lib/$LIB_LINK0
+	plink -batch -t -pw $PASS $USER ln -sfn /usr/lib/$LIB_TARGET /usr/lib/$LIB_LINK1
+	exit 0
+fi
+
+if [ ! -d "$INC_PREFIX" ]; then
+	sudo mkdir -p "$INC_PREFIX"
+fi
+
+if [ -f $LIB_PREFIX/$LIB_LINK0 ]; then
+	sudo rm -f $LIB_PREFIX/$LIB_LINK0
+fi
+if [ -f $LIB_PREFIX/$LIB_LINK1 ]; then
+	sudo rm -f $LIB_PREFIX/$LIB_LINK1
+fi
+if [ -f $LIB_PREFIX/$LIB_TARGET ]; then
+	sudo rm -f $LIB_PREFIX/$LIB_TARGET
+fi
+
+if [ "$COMMAND" == "clean" ]; then
+	sudo rm -f $LIB_PREFIX/$LIB_LINK0
+	sudo rm -f $LIB_PREFIX/$LIB_LINK1
+	sudo rm -f $LIB_PREFIX/$LIB_TARGET
+	sudo rm -f "$INC_PREFIX/gfanet.h" "$INC_PREFIX/interfaces.h" "$INC_PREFIX/inet4s.h" "$INC_PREFIX/inet4d.h" "$INC_PREFIX/inet4m.h"
+fi
+
+if [ "$COMMAND" == "install" ]; then
+	sudo cp $LIB_NAME $LIB_PREFIX/$LIB_TARGET
+	sudo ln -s $LIB_PREFIX/$LIB_TARGET $LIB_PREFIX/$LIB_LINK0
+	sudo ln -s $LIB_PREFIX/$LIB_TARGET $LIB_PREFIX/$LIB_LINK1
+	sudo cp -f "$SRC_DIR/gfanet.h" "$SRC_DIR/interfaces.h" "$SRC_DIR/inet4s.h" "$SRC_DIR/inet4d.h" "$SRC_DIR/inet4m.h" "$INC_PREFIX"
+fi

+ 9 - 8
libgfanet/gfanet.pro

@@ -1,14 +1,15 @@
 TEMPLATE = lib
 TARGET = gfanet
 CONFIG += plugin c++11
-
-#TARGET = $$qtLibraryTarget($$TARGET)
+CONFIG -= app_bundle
+CONFIG -= qt
 
 CONFIG(debug, debug|release) {
     QMAKE_CXXFLAGS -= -Os
     QMAKE_CFLAGS -= -Os
     QMAKE_CXXFLAGS += -D_DEBUG
     QMAKE_CFLAGS += -D_DEBUG
+	TARGET = gfanetd
 }
 
 # Input
@@ -28,9 +29,9 @@ HEADERS += \
     inet4d.h \
     inet4m.h
 
-#unix {
-#    installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
-#    qmldir.path = $$installPath
-#    target.path = $$installPath
-#    INSTALLS += target qmldir
-#}
+linux-buildroot-g++ {
+#	target.path = /usr/lib/lib$${TARGET}.so.1.0.0
+#	INSTALLS += target
+}
+
+#message($$target.path)

+ 51 - 16
libgfanet/interfaces.cpp

@@ -3,8 +3,8 @@
 #include "util.h"
 #include "interfaces.h"
 
-//#define _ETC_NETWORK_INTERFACES			"/etc/network/interfaces"
-#define _ETC_NETWORK_INTERFACES			"/home/wrk/share/gfanet/libgfanet/res/interfaces"
+#define _ETC_NETWORK_INTERFACES			"/etc/network/interfaces"
+//#define _ETC_NETWORK_INTERFACES			"/home/wrk/share/gfanet/libgfanet/res/interfaces"
 
 /////////////////////////////////////////////////////////////////////////////
 // iface block
@@ -58,27 +58,34 @@ static const char *g_pszIncludes[] =
 
 /////////////////////////////////////////////////////////////////////////////
 
-static const char *_GetIfaceProtoStr(IfaceProtos ip)
+const char *GetIfaceProtoStr(IfaceProtos ip)
 {
 	if(ip >= IFP_Inet && ip <= IFP_Can)
 		return g_pszProtos[ip];
 	return "";
 }
 
-static const char *_GetIfaceMethodStr(IfaceMethods im)
+const char *GetIfaceMethodStr(IfaceMethods im)
 {
 	if(im >= IFM_Static && im <= IFM_Auto)
 		return g_pszMethods[im];
 	return "";
 }
 
-static const char *_GetIfaceCommandsStr(IfaceCommands ic)
+const char *GetIfaceCommandsStr(IfaceCommands ic)
 {
 	if(ic >= IFC_PreUp && ic <= IFC_PostDown)
 		return g_pszCommands[ic];
 	return "";
 }
 
+const char *GetIncTypeStr(ItfInclude inc)
+{
+	if(inc >= II_File && inc <= II_Directory)
+		return g_pszIncludes[inc];
+	return "";
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
 CfgGroup ParseCfgGroup(const std::vector<std::string> &v, ITF_CONFIG_GROUP &icg)
@@ -359,7 +366,7 @@ void ProcessGroupMembers(ETC_NETWORK_INTERFACES &eni)
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
 
-int ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni)
+bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath)
 {
 	typedef enum ParseStates
 	{
@@ -373,10 +380,13 @@ int ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni)
 	static const std::regex regc(strRegExComt, std::regex_constants::ECMAScript | std::regex_constants::optimize);
 	static const std::regex regl(strRegExLine, std::regex_constants::ECMAScript | std::regex_constants::optimize);
 	std::string buf;
+
+	if(!pszPath)
+		pszPath = _ETC_NETWORK_INTERFACES;
 		
 	eni._reset();
 
-	if(ReadFile(_ETC_NETWORK_INTERFACES, buf) > 0)
+	if(ReadFile(pszPath, buf) > 0)
 	{
 		ParseStates ps = PS_Root;
 		std::string line;
@@ -446,21 +456,22 @@ int ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni)
 
 		ProcessIface(eni);
 		ProcessGroupMembers(eni);
+		return true;
 	}
 
-	return 0;
+	return false;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
 
-bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *pszFile)
+bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *pszPath)
 {
-	if(!pszFile)
-		pszFile = _ETC_NETWORK_INTERFACES;
+	if(!pszPath)
+		pszPath = _ETC_NETWORK_INTERFACES;
 
 	int line;
-	FILE *pf = fopen(pszFile, "wb");
+	FILE *pf = fopen(pszPath, "wb");
 
 	if(pf)
 	{
@@ -545,18 +556,18 @@ bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *ps
 					if(ib.proto != IFP_Unknown)
 					{
 						fputc(' ', pf);
-						fputs(_GetIfaceProtoStr(ib.proto), pf);
+						fputs(GetIfaceProtoStr(ib.proto), pf);
 					}
 					if(ib.method != IFM_Unknown)
 					{
 						fputc(' ', pf);
-						fputs(_GetIfaceMethodStr(ib.method), pf);
+						fputs(GetIfaceMethodStr(ib.method), pf);
 					}
 					fprintf(pf, " inherits %s\n", ib.inheritedFrom.c_str());
 					
 				}
 				else
-					fprintf(pf, "iface %s %s %s\n", ib.cfgName.c_str(), _GetIfaceProtoStr(ib.proto), _GetIfaceMethodStr(ib.method));
+					fprintf(pf, "iface %s %s %s\n", ib.cfgName.c_str(), GetIfaceProtoStr(ib.proto), GetIfaceMethodStr(ib.method));
 
 				if(ib.proto == IFP_Inet)
 				{
@@ -583,7 +594,7 @@ bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *ps
 					{
 						const IFACE_COMMAND &cmd = *itu;
 						fputc('\t', pf);
-						fputs(_GetIfaceCommandsStr(cmd.cmd), pf);
+						fputs(GetIfaceCommandsStr(cmd.cmd), pf);
 						fputc(' ', pf);
 						fputs(cmd.args.c_str(), pf);
 						fputc('\n', pf);
@@ -605,9 +616,33 @@ bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *ps
 			}
 		}
 
+		/////////////////////////////////////////////////////////////////////
+		// write includes
+
+		if(eni.inc.size() > 0)
+		{
+			fputs("##############################################################\n", pf);
+			fputs("# includes\n\n", pf);
+
+			for(auto iti = eni.inc.begin(); iti != eni.inc.end(); iti++)
+			{
+				const ITF_INCLUDE &inc = *iti;
+				
+				if(inc.inc == II_File || inc.inc == II_Directory)
+				{
+					fputs(GetIncTypeStr(inc.inc), pf);
+					fputc(' ', pf);
+					fputs(inc.path.c_str(), pf);
+					fputc('\n', pf);
+				}
+			}
+			fputc('\n', pf);
+		}
+
 		/////////////////////////////////////////////////////////////////////
 
 		fclose(pf);
+		return true;
 	}
 
 	return false;

+ 9 - 4
libgfanet/interfaces.h

@@ -67,6 +67,7 @@ typedef enum IfaceProtos
 }IfaceProtos;
 
 IfaceProtos GetIfaceProto(const std::string &s);
+const char *GetIfaceProtoStr(IfaceProtos ip);
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -86,6 +87,7 @@ typedef enum IfaceMethods
 }IfaceMethods;
 
 IfaceMethods GetIfaceMethod(const std::string &s);
+const char *GetIfaceMethodStr(IfaceMethods im);
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -108,6 +110,7 @@ typedef struct _IFACE_COMMAND
 typedef const IFACE_COMMAND *LPCIFACE_COMMAND;
 
 IfaceCommands GetIfaceCommand(const std::string &s);
+const char *GetIfaceCommandsStr(IfaceCommands ic);
 bool ParseIfaceCmd(const std::vector<std::string> &v, std::vector<IFACE_COMMAND> &c);
 
 /////////////////////////////////////////////////////////////////////////////
@@ -128,6 +131,7 @@ typedef const ITF_INCLUDE *LPCITF_INCLUDE;
 typedef std::vector<ITF_INCLUDE> ITF_INCLUDE_LIST;
 
 bool ParseIncludes(const std::vector<std::string> &v, ITF_INCLUDE_LIST &inc);
+const char *GetIncTypeStr(ItfInclude inc);
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -198,13 +202,14 @@ typedef struct _ETC_NETWORK_INTERFACES
 	_ETC_NETWORK_INTERFACES(void){_reset();}
 	void _reset(void)
 	{
-		cgl.clear();
 		mbl.clear();
+		cgl.clear();
 		ibl.clear();
 		inc.clear();
+		unparsed.clear();
 	}
-	ITF_CONFIG_GROUP_LIST	cgl;
 	ITF_MAPPING_BLOCK_LIST	mbl;
+	ITF_CONFIG_GROUP_LIST	cgl;
 	ITF_IFACE_BLOCK_LIST	ibl;
 	ITF_INCLUDE_LIST		inc;
 	std::vector<std::string> unparsed;
@@ -213,8 +218,8 @@ typedef const ETC_NETWORK_INTERFACES *LPCETC_NETWORK_INTERFACES;
 
 void ProcessIface(ETC_NETWORK_INTERFACES &eni);
 void ProcessGroupMembers(ETC_NETWORK_INTERFACES &eni);
-int ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni);
-bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *pszFile = NULL);
+bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath = NULL);
+bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *pszPath = NULL);
 
 /////////////////////////////////////////////////////////////////////////////
 #endif	//	!defined(AGD_INTERFACES_H__0F16A7C6_9054_4BBB_8A10_EAE00ED4EE9C__INCLUDED_)

+ 11 - 0
qtplugin/.gitignore

@@ -0,0 +1,11 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
+
+Debug/
+Release/
+res/
+*.user

+ 108 - 0
qtplugin/netinterfaces.cpp

@@ -0,0 +1,108 @@
+#include "netinterfaces.h"
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+NetInterfaces::NetInterfaces(QObject *pParent) : QObject(pParent)
+{
+	setObjectName("NetInterfaces");
+}
+
+NetInterfaces::~NetInterfaces(void)
+{
+	reset();
+}
+
+void NetInterfaces::classBegin()
+{
+}
+
+void NetInterfaces::componentComplete()
+{
+}
+
+void NetInterfaces::reset(void)
+{
+	for(auto it = m_itfList.begin(); it != m_itfList.end(); it++)
+	{
+		Interface *pi = *it;
+		delete pi;
+	}
+
+	m_itfList.clear();
+	m_eni._reset();
+}
+
+bool NetInterfaces::initialize(void)
+{
+	bool bRet = false;
+	reset();
+	if((bRet = ::ParseEtcNetworkInterfaces(m_eni)))
+	{
+		for(auto it = m_eni.ibl.begin(); it != m_eni.ibl.end(); it++)
+		{
+			ITF_IFACE_BLOCK &ibl = *it;
+			m_itfList.push_back(new Interface(ibl));
+		}
+	}
+	return bRet;
+}
+
+QVariantList NetInterfaces::getInterface(const QString &itfName)
+{
+	QVariantList list;
+    list.clear();
+
+	if(m_eni.ibl.size() > 0)
+	{
+		for(auto it = m_itfList.begin(); it != m_itfList.end(); it++)
+		{
+			Interface *pi = *it;
+			const ITF_IFACE_BLOCK &ibl = pi->getIface();
+
+			if(	itfName == ibl.cfgName.c_str() &&
+				ibl.proto == IFP_Inet &&
+				(ibl.method == IFM_Static || ibl.method == IFM_Dhcp))
+			{
+				QVariant var = QVariant::fromValue(pi);
+				list.append(var);
+			}
+		}
+	}
+
+	return list;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+Interface::Interface(ITF_IFACE_BLOCK &ifb, QObject *pParent) : QObject(pParent), m_ifb(ifb)
+{
+	setObjectName("Interface");
+}
+
+Interface::~Interface(void)
+{
+}
+
+QString Interface::name(void) const
+{
+	return QString::fromStdString(m_ifb.cfgName);
+}
+
+QString Interface::ipAddress(void) const
+{
+	if(m_ifb.proto == IFP_Inet && m_ifb.method == IFM_Static)
+		return inet_ntoa(m_ifb.inet4s.addr);
+	else
+		return "";
+}
+
+QString Interface::family(void) const
+{
+	return ::GetIfaceProtoStr(m_ifb.proto);
+}
+
+QString Interface::method(void) const
+{
+	return ::GetIfaceMethodStr(m_ifb.method);
+}

+ 67 - 0
qtplugin/netinterfaces.h

@@ -0,0 +1,67 @@
+// netinterfaces.h :
+//
+
+#if !defined(AGD_NETINTERFACES_H__54DE87BE_1F3C_4914_A062_9CCFCB496122__INCLUDED_)
+#define AGD_NETINTERFACES_H__54DE87BE_1F3C_4914_A062_9CCFCB496122__INCLUDED_
+
+#include <vector>
+#include <QObject>
+#include <QList>
+#include <QQmlListProperty>
+#include <qqmlparserstatus.h>
+#include <gfa/gfanet.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// netinterfaces.h - Declarations:
+
+class Interface : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QString name READ name)
+    Q_PROPERTY(QString family READ family)
+    Q_PROPERTY(QString ipAddress READ ipAddress)
+    Q_PROPERTY(QString method READ method)
+
+public:
+    explicit Interface(ITF_IFACE_BLOCK &ifb, QObject *pParent = 0);
+    virtual ~Interface(void);
+    
+    inline const ITF_IFACE_BLOCK & getIface(void) const {
+    	return m_ifb;}
+    
+private:
+    QString name(void) const;
+    QString ipAddress(void) const;
+    QString family(void) const;
+    QString method(void) const;
+
+private:
+	ITF_IFACE_BLOCK &m_ifb;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class NetInterfaces : public QObject, public QQmlParserStatus
+{
+    Q_OBJECT
+    Q_INTERFACES(QQmlParserStatus)
+
+public:
+    explicit NetInterfaces(QObject *pParent = 0);
+    virtual ~NetInterfaces(void);
+
+public:
+	Q_INVOKABLE void reset(void);
+	Q_INVOKABLE bool initialize(void);
+	Q_INVOKABLE QVariantList getInterface(const QString &itfName);
+
+	virtual void classBegin();
+	virtual void componentComplete();
+
+private:
+	ETC_NETWORK_INTERFACES m_eni;
+	std::vector<Interface*> m_itfList;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+#endif	//	!defined(AGD_NETINTERFACES_H__54DE87BE_1F3C_4914_A062_9CCFCB496122__INCLUDED_)

+ 50 - 0
qtplugin/netinterfaces.pro

@@ -0,0 +1,50 @@
+TEMPLATE = lib
+TARGET = NetInterfaces
+QT += sql qml
+CONFIG += qt plugin c++11
+
+CONFIG(debug, debug|release) {
+    QMAKE_CXXFLAGS -= -Os
+    QMAKE_CFLAGS -= -Os
+    QMAKE_CXXFLAGS += -D_DEBUG
+    QMAKE_CFLAGS += -D_DEBUG
+    QMAKE_LIBS += -lgfanetd
+}
+
+CONFIG(release, debug|release) {
+    QMAKE_LIBS += -lgfanet
+}
+
+#TARGET = $$qtLibraryTarget($$TARGET)
+#message($$TARGET)
+uri = gfa.plugins.qml.net
+
+# Input
+SOURCES += \
+    netinterfaces.cpp \
+    netinterfaces_plugin.cpp
+
+HEADERS += \
+    netinterfaces.h \
+    netinterfaces_plugin.h
+
+DISTFILES = qmldir
+DISTFILES += gfa.plugins.qml.net.qmltypes
+
+!equals(_PRO_FILE_PWD_, $$OUT_PWD)
+{
+    copy_qmldir.target = $$OUT_PWD/qmldir
+    copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
+    copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
+    QMAKE_EXTRA_TARGETS += copy_qmldir
+    PRE_TARGETDEPS += $$copy_qmldir.target
+}
+
+qmldir.files = qmldir
+unix {
+    installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
+    qmldir.path = $$installPath
+    target.path = $$installPath
+    INSTALLS += target qmldir
+message($${installPath})
+}

+ 12 - 0
qtplugin/netinterfaces_plugin.cpp

@@ -0,0 +1,12 @@
+#include "netinterfaces_plugin.h"
+#include "netinterfaces.h"
+#include <qqml.h>
+
+void NetInterfacesPlugin::registerTypes(const char *uri)
+{
+    // @uri gfa.plugins.qml.net
+    qmlRegisterType<NetInterfaces>(uri, 1, 0, "NetInterfaces");
+//    qmlRegisterType<Interface>(uri, 1, 0, "Interface");
+    qmlRegisterUncreatableType<Interface>(uri, 1, 0, "Interface", "return type only");
+//    qmlRegisterUncreatableType<QList<Interface*>>(uri, 1, 0, "InterfaceList", "return type only");
+}

+ 22 - 0
qtplugin/netinterfaces_plugin.h

@@ -0,0 +1,22 @@
+// netinterfaces_plugin.h :
+//
+
+#if !defined(AGD_NETINTERFACES_PLUGIN_H__1F6C7511_8182_473A_8CCE_E196D6E20F69__INCLUDED_)
+#define AGD_NETINTERFACES_PLUGIN_H__1F6C7511_8182_473A_8CCE_E196D6E20F69__INCLUDED_
+
+#include <QQmlExtensionPlugin>
+
+/////////////////////////////////////////////////////////////////////////////
+// netinterfaces_plugin.h - Declarations:
+
+class NetInterfacesPlugin : public QQmlExtensionPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+    void registerTypes(const char *uri);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+#endif	//	!defined(AGD_NETINTERFACES_PLUGIN_H__1F6C7511_8182_473A_8CCE_E196D6E20F69__INCLUDED_)

+ 8 - 0
qtplugin/pdump.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+
+PDUMP="/home/wrk/Qt5.7.0/5.7/gcc_64/bin/qmlplugindump"
+URI="gfa.plugins.qml.net"
+VERSION=1.0
+
+$PDUMP $URI $VERSION > /home/wrk/Qt5.7.0/5.7/gcc_64/qml/gfa/plugins/qml/net/net.qmltypes

+ 4 - 0
qtplugin/qmldir

@@ -0,0 +1,4 @@
+module gfa.plugins.qml.net
+plugin NetInterfaces
+classname NetInterfaces
+typeinfo net.qmltypes