精华内容
下载资源
问答
  • Linux设备树中一些标准属性介绍标准属性1、compatible 属性2、 model 属性3、 status 属性4、 #address-cells 和#size-cells 属性5、 reg 属性6、 ranges 属性7、 name 属性8、 device_type 属性 标准属性 节点是由...

    标准属性

    节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性是标准属性, Linux 下的很多外设驱动都会使用这些标准属性。

    1、compatible 属性

    compatible 属性也叫做“兼容性”属性,这是非常重要的一个属性! compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序, compatible 属性的值格式如下所示:

    "manufacturer,model"
    

    其中 manufacturer 表示厂商, model 一般是模块对应的驱动名字。比如 imx6ull-alientekemmc.dts 中 sound 节点是 I.MX6U-ALPHA 开发的音频设备节点, I.MX6U-ALPHA 开发板上的音频芯片采用的欧胜(WOLFSON)出品的 WM8960, sound 节点的 compatible 属性值如下:

    compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";
    

    属性值有两个,分别为“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”,其中“fsl”表示厂商是飞思卡尔,“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驱动模块名字。 sound这个设备首先使用第一个兼容值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值查。

    一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。比如在文件 imx-wm8960.c 中有如下内容:
    在这里插入图片描述
    第 632~635 行的数组 imx_wm8960_dt_ids 就是 imx-wm8960.c 这个驱动文件的匹配表,此匹配表只有一个匹配值“fsl,imx-audio-wm8960”。如果在设备树中有哪个节点的 compatible 属性值与此相等,那么这个节点就会使用此驱动文件。

    第 642 行, wm8960 采用了 platform_driver 驱动模式。此行设置.of_match_table 为 imx_wm8960_dt_ids,也就是设置这个 platform_driver 所使用的OF 匹配表。

    2、 model 属性

    model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,比如:

    model = "wm8960-audio";
    

    3、 status 属性

    status 属性看名字就知道是和设备状态有关的, status 属性值也是字符串,字符串是设备的状态信息,可选的状态如表下所示:

    描述
    “okay” 表明设备是可操作的。
    “disabled” 表明设备当前是不可操作的,但是在未来可以变为可操作的,比如热插拔设备插入以后。至于 disabled 的具体含义还要看设备的绑定文档。
    “fail” 表明设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可操作。
    “fail-sss” 含义和“fail”相同,后面的 sss 部分是检测到的错误内容。

    4、 #address-cells 和#size-cells 属性

    这两个属性的值都是无符号 32 位整形, #address-cells 和#size-cells 这两个属性可以用在任何拥有子节点的设备中,用于描述子节点的地址信息。 #address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位), #size-cells 属性值决定了子节点 reg 属性中长度信息所占的。字长(32 位)。 #address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度, reg 属性的格式一为:

    reg = <address1 length1 address2 length2 address3 length3……>
    

    每个“address length”组合表示一个地址范围,其中 address 是起始地址, length 是地址长度, #address-cells 表明 address 这个数据所占用的字长, #size-cells 表明 length 这个数据所占用的字长,比如:

    spi4 {
     	compatible = "spi-gpio";
    	 #address-cells = <1>;
    	 #size-cells = <0>;
    
    gpio_spi: gpio_spi@0 {
    	 compatible = "fairchild,74hc595";
    	 reg = <0>;
     	};
     };
    
     aips3: aips-bus@02200000 {
    	 compatible = "fsl,aips-bus", "simple-bus";
    	 #address-cells = <1>;
    	 #size-cells = <1>;
    
     dcp: dcp@02280000 {
    	 compatible = "fsl,imx6sl-dcp";
    	 reg = <0x02280000 0x4000>;
    	 };
     };
    

    第 3, 4 行,节点 spi4 的#address-cells = <1>, #size-cells = <0>,说明 spi4 的子节点 reg 属性中起始地址所占用的字长为 1,地址长度所占用的字长为 0。

    第 8 行,子节点 gpio_spi: gpio_spi@0 的 reg 属性值为 <0>,因为父节点设置了#addresscells = <1>, #size-cells = <0>,因此 addres=0没有 length 的值,相当于设置了起始地址,而没有设置地址长度。

    第 14, 15 行,设置 aips3: aips-bus@02200000 节点#address-cells = <1>, #size-cells = <1>,说明 aips3: aips-bus@02200000 节点起始地址长度所占用的字长为 1,地址长度所占用的字长也为 1。

    第 19 行,子节点 dcp: dcp@02280000 的 reg 属性值为<0x02280000 0x4000>,因为父节点设置了#address-cells = <1>, #size-cells = <1>, address= 0x02280000, length= 0x4000,相当于设置了起始地址为 0x02280000,地址长度为 0x40000。

    5、 reg 属性

    reg 属性前面已经提到过了, reg 属性的值一般是(address, length)对。 reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息,比如在 imx6ull.dtsi 中有如下内容:

    uart1: serial@02020000 {
    	 compatible = "fsl,imx6ul-uart",
    	 "fsl,imx6q-uart", "fsl,imx21-uart";
    	 reg = <0x02020000 0x4000>;
    	 interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
    	 clocks = <&clks IMX6UL_CLK_UART1_IPG>,
    	 <&clks IMX6UL_CLK_UART1_SERIAL>;
    	 clock-names = "ipg", "per";
    	 status = "disabled";
     };
    

    上述代码是节点 uart1, uart1 节点描述了 I.MX6ULL 的 UART1 相关信息,重点是第4行的 reg 属性。其中 uart1 的父节点 aips1: aips-bus@02000000 设置了#address-cells = <1>、 #sizecells = <1>,因此 reg 属性中 address=0x02020000, length=0x4000。查阅《I.MX6ULL 参考手册》可知, I.MX6ULL 的 UART1 寄存器首地址为 0x02020000,但是 UART1 的地址长度(范围)并没有 0x4000 这么多,这里我们重点是获取 UART1 寄存器首地址。

    6、 ranges 属性

    ranges属性值可以为空或者按照(child-bus-address,parent-bus-address,length)格式编写的数字矩阵, ranges 是一个地址映射/转换表, ranges 属性每个项目由子地址、父地址和地址空间长度这三部分组成:

    child-bus-address:子总线地址空间的物理地址,由父节点的#address-cells 确定此物理地址所占用的字长。

    parent-bus-address: 父总线地址空间的物理地址,同样由父节点的#address-cells 确定此物理地址所占用的字长。

    length: 子地址空间的长度,由父节点的#size-cells 确定此地址长度所占用的字长。

    如果 ranges 属性值为空值,说明子地址空间和父地址空间完全相同,不需要进行地址转换,对于我们所使用的 I.MX6ULL 来说,子地址空间和父地址空间完全相同,因此会在 imx6ull.dtsi中找到大量的值为空的 ranges 属性,如下所示:

    soc {
    	#address-cells = <1>;
    	#size-cells = <1>;
    	compatible = "simple-bus";
    	interrupt-parent = <&gpc>;
    	ranges;
     }
    

    第 6 行定义了 ranges 属性,但是 ranges 属性值为空。

    soc {
    	compatible = "simple-bus";
    	#address-cells = <1>;
    	#size-cells = <1>;
    	ranges = <0x0 0xe0000000 0x00100000>;
    
    serial {
    	device_type = "serial";
    	compatible = "ns16550";
    	reg = <0x4600 0x100>;
    	clock-frequency = <0>;
    	interrupts = <0xA 0x8>;
    	interrupt-parent = <&ipic>;
    	};
    };
    

    第 5 行,节点 soc 定义的 ranges 属性,值为<0x0 0xe0000000 0x00100000>,此属性值指定了一个 1024KB(0x00100000)的地址范围,子地址空间的物理起始地址为 0x0,父地址空间的物理起始地址为 0xe0000000。

    第 10 行, serial 是串口设备节点, reg 属性定义了 serial 设备寄存器的起始地址为 0x4600,寄存器长度为 0x100。经过地址转换, serial 设备可以从 0xe0004600 开始进行读写操作,0xe0004600=0x4600+0xe0000000。

    7、 name 属性

    name 属性值为字符串, name 属性用于记录节点名字, name 属性已经被弃用,不推荐使用name 属性,一些老的设备树文件可能会使用此属性。

    8、 device_type 属性

    device_type 属性值为字符串, IEEE 1275 会用到此属性,用于描述设备的 FCode,但是设备树没有 FCode,所以此属性也被抛弃了。此属性只能用于 cpu 节点或者 memory 节点。imx6ull.dtsi 的 cpu0 节点用到了此属性,内容如下所示:

    cpu0: cpu@0 {
     	compatible = "arm,cortex-a7";
     	device_type = "cpu";
    	 reg = <0>;
    ......
     };
    

    关于标准属性就讲解这么多,其他的比如中断、 IIC、 SPI 等使用的标准属性等到具体的例程再具体分析。

    展开全文
  • linux设备树笔记__自定义改造

    千次阅读 2015-11-26 16:56:24
    设备树(DTS)我们基本都是通过of_get_xxx这样的内核API来被动获取设备结点的属性值,很少会去修改它,如果要修改某个属性值,必须在各个设备驱动之前修改,一般在board级别代码修改。那为什么要去修改呢,什么需求...

    需求

    设备树(DTS)我们基本都是通过of_get_xxx这样的内核API来被动获取设备结点的属性值,很少会去修改它,如果要修改某个属性值,必须在各个设备驱动之前修改,一般在board级别代码修改。那为什么要去修改呢,什么需求才要这样做呢?我们碰到了这样的需求了。

    是这样的,我们的项目中一个产品在PCB改版时,硬件资源发生了改变(由DTS来配置的),其中一个使能脚的控制改变了,既要保持对前一个版本(内核有硬件版本号全局变量)的兼容又要对新版本兼容,这就限制你不能孤立的修改DTS引脚配置。我们以前的方法是用全局资源硬件版本号在每个需要改变驱动中进行手动判断修改,这就造成了设备驱动的纯洁性较差,且不易直观知晓历史版本修改记录。

    我们现在的做法就是这个文章说要写的,后来想到只在board级别代码中根据硬件版本号,统一修改了DTS属性,这样在后面驱动加载时,驱动获得就是对应版本的配置,并且驱动不用做任何修改。具体下面有个例子。



    自定义DTS修改函数

    在进入具体的例子之前先贴上自定义函数,基于内核基本的open firmware(of.h)函数,

    //----------------------------------------------------------------------------
    // Provide a group of functions to change the node/property values
    //----------------------------------------------------------------------------
    extern rwlock_t devtree_lock;//全局设备树链表结构的读写锁
    
    /*根据设备节点的属性名,打印所有属性值*/
    void of_print_property(const struct device_node *node,	const char *property_name)
    {
    	const __be32 *intspec;
    	int len;
    	int value;
    	int i;
    
    	if (!node || !property_name)
    		return;
    
    	intspec = of_get_property(node, property_name, &len);
    	if (intspec) {
    		for (i = 0; i < len/sizeof(*intspec); i++) {
    			value = be32_to_cpup(intspec+i);
    			printk(KERN_INFO "    [%d] = %08x\n", i, value);
    		}
    	}
    }
    
    /*根据设备节点将一个属性拷贝给另一个属性*/
    bool of_copy_property_value(const struct device_node *node,
    	const char *target_property_name, const char *src_property_name)
    {
    	unsigned long flags;
    	const void *value;
    	struct property *pp;
    
    	if (!node || !target_property_name || !src_property_name)
    		return false;
    
    	pp = of_find_property(node, target_property_name, NULL);
    	if (!pp) {
    		printk(KERN_ERR "%s: %s/%s not found\n", __FUNCTION__, node->name, target_property_name);
    		return false;
    	}
    
    	value = of_get_property(node, src_property_name, NULL);
    	if (!value) {
    		printk(KERN_ERR "%s: %s/%s not found\n", __FUNCTION__, node->name, src_property_name);
    		return false;
    	}
    
    	write_lock_irqsave(&devtree_lock, flags);
    	pp->value = (void*)value;
    	write_unlock_irqrestore(&devtree_lock, flags);
    	return true;
    }
    
    /*根据设备节点,修改属性的gpio值*/
    bool of_set_property_gpio(const struct device_node *node,
    	const char *property_name, const int gpio)
    {
    	unsigned long flags;
    	const __be32 *intspec;
    	__be32 *pgpio;
    
    	if (!node || !property_name)
    		return false;
    
    	intspec = of_get_property(node, property_name, NULL);
    	if (!intspec) {
    		printk(KERN_ERR "%s: %s/%s not found\n", __FUNCTION__, node->name, property_name);
    		return false;
    	}
    
    	pgpio = (__be32*)intspec + 1;
    	write_lock_irqsave(&devtree_lock, flags);
    	*pgpio = cpu_to_be32p(&gpio);
    	write_unlock_irqrestore(&devtree_lock, flags);
    	return true;
    }
    
    /*根据设备节点全路径,打印属性的值*/
    void print_property(const char *node_name,	const char *property_name)
    {
    	struct device_node *node = of_find_node_by_path(node_name);
    	if (!node) {
    		printk(KERN_ERR "%s: node '%s' not found\n", __FUNCTION__, node_name);
    		return;
    	}
    
    	of_print_property(node, property_name);
    	printk(KERN_INFO "%s: %s :\n", __FUNCTION__, node_name);
    	of_node_put(node);
    }
    
    /*根据设备节点全路径,将一个属性拷贝给另一个属性*/
    bool copy_property_value(const char *node_name,
    	const char *target_property_name, const char *src_property_name)
    
    {
    	bool result;
    	struct device_node *node = of_find_node_by_path(node_name);
    	if (!node) {
    		printk(KERN_ERR "%s: node '%s' not found\n", __FUNCTION__, node_name);
    		return false;
    	}
    
    	result = of_copy_property_value(node, target_property_name, src_property_name);
    	printk(KERN_INFO "%s: %s : (%s) -> (%s) %s\n", __FUNCTION__, node_name,
    		src_property_name, target_property_name, result ? "successfully" : "failed");
    	of_node_put(node);
    	return result;
    }
    
    /*根据设备节点全路径,修改一个属性的gpio值*/
    bool set_property_gpio(const char *node_name,
    	const char *property_name, const int gpio)
    {
    	bool result;
    	struct device_node *node = of_find_node_by_path(node_name);
    	if (!node) {
    		printk(KERN_ERR "%s: node '%s' not found\n", __FUNCTION__, node_name);
    		return false;
    	}
    
    	result = of_set_property_gpio(node, property_name, gpio);
    	printk(KERN_INFO "%s: %s : (%s) -> %d %s\n", __FUNCTION__, node_name,
    		property_name, gpio, result ? "successfully" : "failed");
    	of_node_put(node);
    	return result;
    }

    我们对外只要用copy_property_value()和set_property_gpio()即可,但我们后来决定推荐用copy_property_value(),为什么?在DTS文件中添加新的属性,然后拷贝给原来的属性,DTS中还能更直观看见不同版本使其修改记录。


    NFC例子

    具体是NFC的enable引脚的例子。

    以NFC为例,在PCB V5版本以前我们使用属性

    nxp-pn544,nfc-enable= <&msmgpio 82 0x02> ;

    即使用msmgpio 82脚且flag为2作为NFC的使能配置,到V6.1后使用

    nxp-pn544,nfc-enable<&pm8110_gpios 2 0x00>;

    改用pm8110_gpios 的2脚且flag为0作为新使能配置,为了保持驱动不修改,那么就要不修改属性名而修改属性,即在board级代码中修改nxp-pn544,nfc-enable 的属性。

    即需求为

          属性

          nxp-pn544,nfc-enable= <&msmgpio 82 0x02>;

          要改为

          nxp-pn544,nfc-enable= <&pm8110_gpios 2 0x00>; 


    我们使用copy_property_value函数,要修改2个地方
    1.修改board-seuic-d500.dts
    修改前:
    &soc {
    i2c@f9924000 {
    ...
    nxp_pn544@28 {
    compatible = "nxp,nfc-pn544";
    reg = <0x28>;
    interrupt-parent = <&msmgpio>;
    interrupts = <84 0x2>;
    nxp-pn544,nfc-enable = <&msmgpio 82 0x02>;
    nxp-pn544,nfc-firm-gpio = <&msmgpio 94 0x02>;
    nxp-pn544,nfc-int = <&msmgpio 84 0x02>;
    nxp-pn544,nfc-power = <&msmgpio 42 0x02>;
    };
    ...
    }
    }
    修改后:
    &soc {
    i2c@f9924000 {
    ...
    nxp_pn544@28 {
    compatible = "nxp,nfc-pn544";
    reg = <0x28>;
    interrupt-parent = <&msmgpio>;
    interrupts = <84 0x2>;
    nxp-pn544,nfc-enable-v6.1 = <&pm8110_gpios 2 0x00>;
    nxp-pn544,nfc-enable = <&msmgpio 82 0x02>;
    nxp-pn544,nfc-firm-gpio = <&msmgpio 94 0x02>;
    nxp-pn544,nfc-int = <&msmgpio 84 0x02>;
    nxp-pn544,nfc-power = <&msmgpio 42 0x02>;
    };
    ...
    }
    }
    2.修改board-8610-gpiomux.c 
    void __init msm8610_init_board_d500(void)
    {
    if (pcb_version == 6) {
    copy_property_value("/soc/i2c@f9924000/nxp_pn544@28",
    "nxp-pn544,nfc-enable",
    "nxp-pn544,nfc-enable-v6.1");
    }

    即设备D500 硬件版本为6时,将nxp-pn544,nfc-enable-v6.1属性拷贝给nxp-pn544,nfc-enable 用。

    这样不管哪个版本都能使用正确的gpio配置了。

    展开全文
  • 节点是由一堆属性组成的,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性都是标准属性 1. compatible属性 compatible属性也叫做“兼容性”属性,是一个...

    节点是由一堆属性组成的,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性都是标准属性

     

    1. compatible属性

    compatible属性也叫做“兼容性”属性,是一个字符串列表,compatible属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序,格式如下所示

                                                      “manufacturer,model”

    其中manufacturrer表示厂商,model一般是模块对应的驱动名字。比如像下面这个sound节点

        sound {
                               compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

                        . . . . . .

                   }

    属性有两个,分别是“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”,其中“fsl” 表示厂商是飞思卡尔,“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驱动模块名字,这个设备首先使用第一个兼容值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值查。

    那么怎么找?去哪里找?

    一般驱动程序文件都会有一个OF匹配表,此OF匹配表保存着一些compatible值,如果设备节点的compatible属性值和OF匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。

    比如在文件imx-wm8960.c中有如下内容

    static const struct of_device_id imx_wm8960_dt_ids[] = {
    	{ .compatible = "fsl,imx-audio-wm8960", },
    	{ /* sentinel */ }
    };
    MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids);
    
    static struct platform_driver imx_wm8960_driver = {
    	.driver = {
    		.name = "imx-wm8960",
    		.pm = &snd_soc_pm_ops,
    		.of_match_table = imx_wm8960_dt_ids,
    	},
    	.probe = imx_wm8960_probe,
    	.remove = imx_wm8960_remove,
    };

    imx_wm8960_dt_ids 就是 imx-wm8960.c 这个驱动文件的匹配表,此匹配表只有一个匹配值“fsl,imx-audio-wm8960”。如果在设备树中有哪个节点的 compatible 属性值与此相等,那么这个节点就会使用此驱动文件

     

    2. #address-cells和#size-cells属性

    这两个属性的值都是无符号32位整型,用于描述子节点的地址信息。#address-cells属性值决定了子节点reg属性中地址信息所占用的字长(32位),#size-cells属性值决定了子节点reg属性中长度信息所占的字长(32 位)(reg属性见下面)

    spi4 {
        compatible = "spi-gpio";
        #address-cells = <1>;
        #size-cells = <0>;
        gpio_spi: gpio_spi@0 {
        compatible = "fairchild,74hc595";
        reg = <0>;
        };
    }

    节点 spi4 的#address-cells = <1>, #size-cells = <0>,说明 spi4 的子节点 reg 属性中起始地址所占用的字长为 1,地址长度所占用的字长为 0。


           因为父节点设置了#address cells = <1>, #size-cells = <0>,因此 addres=0,没有 length 的值,相当于设置了起始地址而没有设置地址长度。

    3. reg属性

          #address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度, reg 属性的格式一为:

    reg = <address1 length1 address2 length2 address3 length3……>

     reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息,比如在 imx6ull.dtsi 中有如下内容:

    uart1: serial@02020000 {
        compatible = "fsl,imx6ul-uart",
        "fsl,imx6q-uart", "fsl,imx21-uart";
        reg = <0x02020000 0x4000>;
        interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clks IMX6UL_CLK_UART1_IPG>,
        <&clks IMX6UL_CLK_UART1_SERIAL>;
        clock-names = "ipg", "per";
        status = "disabled";
    };

    上述代码是节点 uart1, uart1 节点描述了 I.MX6ULL 的 UART1 相关信息,重点是第 326 行的 reg 属性。其中 uart1 的父节点 aips1: aips-bus@02000000 设置了#address-cells = <1>、 #sizecells = <1>,因此 reg 属性中 address=0x02020000, length=0x4000。查阅《I.MX6ULL 参考手册》可知, I.MX6ULL 的 UART1 寄存器首地址为 0x02020000,但是 UART1 的地址长度(范围)并没有 0x4000 这么多,这里我们重点是获取 UART1 寄存器首地址。
     

    展开全文
  • 关于ztree双击

    2012-07-05 19:55:00
    在项目中使用了ztree来做组织结构的树,我们定义的树中拥有三种节点(使用树节点中的一个自定义属性type来区分):组织结构,建筑,设备类型。要求是:双击的时候将点击的节点添加到另一棵树中。但是,双击组织结构...

    在项目中使用了ztree来做组织结构的树,我们定义的树中拥有三种节点(使用树节点中的一个自定义属性type来区分):组织结构,建筑,设备类型。要求是:双击的时候将点击的节点添加到另一棵树中。但是,双击组织结构不触发,双击建筑连同建筑及其下属设备类型一起添加,双击设备添加其父建筑节点和自己本身,目标树中拥有的不添加。

    做完之后没有觉得如何。后来被同事发现一个bug,当目标树中有一个建筑节点时,双击源树中的这个节点,虽然目标树中没有添加,而且也给出了重复提示。但是源树中的该节点下面添加了整个树。。。开始以为是判断逻辑上面有问题,但是检查多遍都没发现哪里有问题,然后又通过firefox的Firebug给每一个addNodes方法添加断点,居然发现,任何一个addNodes方法都没有调用,但是居然还是添加了。并且,如果是在源树中双击的不是建筑节点,而是设备类型节点,在相同的情况下也没有问题。原因始终是没有找到。不过问题还是解决了。

    原来的写法是,给树节点添加onDblClick事件,所有的判断是否添加到目标树的逻辑以及添加语句都在这里实现。修改后的方法是:把判断是否添加到目标树的逻辑放在了beforeDblClick事件中。只要不符合条件都返回false,这样onDblClick事件不会响应。

    总结:尽管由于事件原因,没能发现原理问题,不过能解决这个问题,还是颇费了一番功夫,写下来以备日后忘记。

    转载于:https://www.cnblogs.com/seving/archive/2012/07/05/2578352.html

    展开全文
  • 实例076 将数据库数据显示到视图 100 实例077 用TreeView控件制作导航界面 102 实例078 用TreeView控件遍历磁盘目录 102 实例079 修改TreeView控件的节点 105 实例080 将XML文件节点绑定到TreeView...
  • 2.4 要包含在项目的 C 文件..............................................................................35 2.5 emWin 的配置 ..............................................................................
  • wxPython学习手册

    热门讨论 2014-04-19 08:01:58
    15.1.2 如何将更多的项目添加到树中? 482 15.1.3 如何管理项目? 482 15.2 树控件的显示样式 483 15.3 对树形控件的元素排序 485 15.4 控制与每项相关的图像 486 15.5 使用编程的方式访问树。 488 15.6 管理树中的...
  • 11.4.2 添加自定义属性 460 11.4.3 高级属性实现 460 11.4.4 访问环境属性 461 11.5 Activex控件事件开发 461 11.5.1 添加常用事件 462 11.5.2 添加自定义事件 463 11.6 Activex控件方法开发 464 11.6.1 添加常用...
  • 11.4.2 添加自定义属性 460 11.4.3 高级属性实现 460 11.4.4 访问环境属性 461 11.5 Activex控件事件开发 461 11.5.1 添加常用事件 462 11.5.2 添加自定义事件 463 11.6 Activex控件方法开发 464 11.6.1 添加常用...
  • 11.4.2 添加自定义属性 460 11.4.3 高级属性实现 460 11.4.4 访问环境属性 461 11.5 Activex控件事件开发 461 11.5.1 添加常用事件 462 11.5.2 添加自定义事件 463 11.6 Activex控件方法开发 464 11.6.1 添加常用...
  • asp.net知识库

    2015-06-18 08:45:45
    从NUnit理解.NET自定义属性的应用(转载) 如何在.NET实现脚本引擎 (CodeDom篇) .NET的插件机制的简单实现 我对J2EE和.NET的一点理解 难分难舍的DSO(一) InternalsVisibleToAttribute,友元程序集访问属性 ...
  • 合并PDF软件.rar

    2020-06-06 22:17:54
    贴心PDF书签编辑器:带有阅读界面(具有便于阅读竖排文档的从右到左阅读方式),可批量修改PDF书签属性(颜色、样式、目标页码、缩放比例等),在书签执行查找替换(支持正则表达式及XPath匹配、可快速选择篇、章...
  • 实例215 修改继承窗体的控件属性 287 第3篇 控件应用篇 第11章 Windows常用控件的使用 290 11.1 按钮控件的使用 291 实例216 轻松打造绚丽按钮 291 实例217 给Button控件创建快捷键 292 实例218 使Button控件大小...
  •  实例135 的实现 177 6.2 常见算法的实际应用 180  实例136 计算1+22+33+44+…+nn的值 180  实例137 计算10!的值 181  实例138 求最大公约数 181  实例139 求最小公倍数 182  实例140 判断素数的算法...
  • 实例261 将数据库数据显示到视图 实例262 用树型列表动态显示菜单 实例263 用TreeView控件遍历磁盘目录 实例264 修改TreeView控件的节点文本 实例265 将XML文件节点绑定到TreeView控件 11.9 选项卡控件...
  • 实例261 将数据库数据显示到视图 实例262 用树型列表动态显示菜单 实例263 用TreeView控件遍历磁盘目录 实例264 修改TreeView控件的节点文本 实例265 将XML文件节点绑定到TreeView控件 11.9 选项卡控件...
  • 实例261 将数据库数据显示到视图 实例262 用树型列表动态显示菜单 实例263 用TreeView控件遍历磁盘目录 实例264 修改TreeView控件的节点文本 实例265 将XML文件节点绑定到TreeView控件 11.9 选项卡控件...
  • 实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134——...
  • 实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134...
  • C++范例大全(400)

    2013-06-29 21:23:07
    实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134——...
  • 实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134——...
  • VC++6.0示例程序光盘

    热门讨论 2012-03-18 13:40:03
    实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134——...
  • VC++6.0示例程序光盘.part1

    热门讨论 2011-02-21 09:17:43
    实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134——...
  • 实例129——激活使用属性表对话框的“应用”按钮 实例130——去除属性表对话框的“应用”按钮 实例131——在对话框使用属性表 实例132——创建向导对话框 实例133——设置对话框的背景颜色 实例134——...
  • A 新增 选取 android 设备上的 profile 文件进行分析 详情 A 新增 WXML 面板支持自定义组件数据查看与实时修改 A 新增 WXML 面板支持使用键盘 (上下左右) navigate the DOM tree A 新增 WXML 面板支持右键操作 ...
  • 精通Qt4编程(第二版)源代码

    热门讨论 2014-01-19 13:07:18
    较深入地分析了Qt对象模型的一些基本知识,涉及信号和槽机制、Qt元对象系统、属性系统和对象机制,以及部件类型和部件的几何布局等内容。 35 \ 第4章 程序主窗口—— QMainWindow 卢传富 Qt应用程序的主窗口是由...
  • 精通qt4编程(源代码)

    热门讨论 2010-03-17 19:10:40
    较深入地分析了Qt对象模型的一些基本知识,涉及信号和槽机制、Qt元对象系统、属性系统和对象机制,以及部件类型和部件的几何布局等内容。 35 \ 第4章 程序主窗口—— QMainWindow 卢传富 Qt应用程序的主窗口是由多...
  • 在左边的窗格,以形结构层次分明的列出了所有的用户界面 (UI) 元素,选择其中某个元素后,就可以在右边的窗格查看其说明并修改其中可以用户自定义属性。  除了可以通过“自定义用户界面”对话框修改已有的...
  • iPhone开发秘籍(第2版)--源代码

    热门讨论 2012-12-11 13:51:22
    6.2 秘诀:建立视图层次结构 163 6.3 秘诀:查询子视图 164 6.4 管理子视图 166 6.4.1 添加子视图 166 6.4.2 重新排序和删除子视图 166 6.4.3 视图回调 166 6.5 秘诀:标记和检索视图 167 6.6 秘诀:命名...
  • 修改高级表格支持库,允许“复制选定文本()”“剪切选定文本()”在“允许选择块”属性为假时复制剪切当前单元格的文本。 18. 修改扩展界面支持库三,为“高级选择夹”增加“不点燃选中子夹”属性。 19. 修改XML...

空空如也

空空如也

1 2 3 4
收藏数 79
精华内容 31
关键字:

自定义属性设备树中