XUL/Thunderbird:开始编辑返回

发布于 2024-12-12 12:35:14 字数 994 浏览 2 评论 0原文

我正在使用雷鸟代码库,目的是实现内联联系人编辑。当前代码捕获 XUL 树上的 Click 事件,如果是双击 (events.detail == 2),则会打开配置文件编辑器。我对其进行了修改,以便开始编辑当前的 treeCell,并且我确实将 editable=true 添加到相应的 XUL 文档中。更新后的代码读取

var orow = {}, ocolumn = {}, opart = {};
gAbResultsTree.treeBoxObject.getCellAt(event.clientX, event.clientY,
                                       orow, ocolumn, opart);

var row = orow.value, column = ocolumn.value.index;         
if (row == -1) 
  return;

if (event.detail == 2)
  gAbResultsTree.startEditing(row, column);

不幸的是,当代码到达 startEditing 部分时,它返回

Error: uncaught exception: [Exception..."Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLMENTED) [nsITreeView.isEditable ]" nsresult: "0x80004001 (NS_ERROR_NOT_IMPLMENTED)" 位置: "JS 框架:: chrome://global/content/bindings/tree.xml :: startEditing :: line 337" data: no]

我在这里几乎迷失了。有更多 XUL 经验的人可以帮忙吗? 谢谢!

I'm playing with the thunderbird codebase, the aim being to implement inline contact editing. The current code catches the Click event on a XUL tree, and if it's a double click (events.detail == 2), it open the profile editor. I modified it so as to start editing the current treeCell, and I did add editable=true to the corresponding XUL document. The updated code reads

var orow = {}, ocolumn = {}, opart = {};
gAbResultsTree.treeBoxObject.getCellAt(event.clientX, event.clientY,
                                       orow, ocolumn, opart);

var row = orow.value, column = ocolumn.value.index;         
if (row == -1) 
  return;

if (event.detail == 2)
  gAbResultsTree.startEditing(row, column);

Unfortunately, when the code reaches the startEditing part, it returns

Error: uncaught exception: [Exception... "Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEMENTED) [nsITreeView.isEditable]" nsresult: "0x80004001 (NS_ERROR_NOT_IMPLEMENTED)" location: "JS frame :: chrome://global/content/bindings/tree.xml :: startEditing :: line 337" data: no]

I'm pretty much lost here. Could someone with more XUL experience help?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

皓月长歌 2024-12-19 12:35:14

我试图做类似的事情,但我遇到了同样的问题。

原始abview设置为__proto__并覆盖函数的包装器工作正常,直到它被设置为abResultsTree的视图。

我终于找到了(我希望)一个优雅的解决方案。

function MyAbView() {
    this.originalAbViewInstance = this.originalAbViewFactory.createInstance(null, Ci.nsIAbView);

    if (!this.proxiesGenerated) {
        // find out which interfaces are implemented by original instance, their property proxies will be generated later
        for (var ifName in Ci) {
            if (Ci[ifName] instanceof Ci.nsIJSID && this.originalAbViewInstance instanceof Ci[ifName]) {
                MyAbView.prototype.supportedInterfaces.push(Ci[ifName]);
            }
        }

        function generatePropertyProxy(name) {
            Object.defineProperty(MyAbView.prototype, name, {
                get: function() {
                    return this.originalAbViewInstance[name];
                },
                set: function(val) {
                    this.originalAbViewInstance[name] = val;
                },
                enumerable: true
            });
        }

        for (var prop in this.originalAbViewInstance) {
            if (this[prop] == undefined) {
                generatePropertyProxy(prop);
            }
        }

        MyAbView.prototype.proxiesGenerated = true;
    } else {
        for each (var interface in this.supportedInterfaces) {
            this.originalAbViewInstance.QueryInterface(interface);
        }
    }
}

MyAbView.prototype = {
    classID: null,

    _xpcom_factory: {
        createInstance: function(outer, iid) {
            return new MyAbView().QueryInterface(iid);
        }
    },

    QueryInterface: function(aIID) {
        for each (var interface in this.supportedInterfaces) {
            if (interface.equals(aIID)) {
                return this;
            }
        }

        throw Components.results.NS_ERROR_NO_INTERFACE;
    },

    originalAbViewFactory: null,
    originalAbViewInstance: null,

    proxiesGenerated: false,
    supportedInterfaces: [],

    // any overriden functions come here
};

它被实现为一个组件来替换原始的 abview,但它可能会被修改为仅创建一个包装器。

I was trying to do something similar and I have same problem.

Wrapper with original abview set as __proto__ with functions overriden works fine until it is set as abResultsTree's view.

I've finally found (I hope) an elegant solution.

function MyAbView() {
    this.originalAbViewInstance = this.originalAbViewFactory.createInstance(null, Ci.nsIAbView);

    if (!this.proxiesGenerated) {
        // find out which interfaces are implemented by original instance, their property proxies will be generated later
        for (var ifName in Ci) {
            if (Ci[ifName] instanceof Ci.nsIJSID && this.originalAbViewInstance instanceof Ci[ifName]) {
                MyAbView.prototype.supportedInterfaces.push(Ci[ifName]);
            }
        }

        function generatePropertyProxy(name) {
            Object.defineProperty(MyAbView.prototype, name, {
                get: function() {
                    return this.originalAbViewInstance[name];
                },
                set: function(val) {
                    this.originalAbViewInstance[name] = val;
                },
                enumerable: true
            });
        }

        for (var prop in this.originalAbViewInstance) {
            if (this[prop] == undefined) {
                generatePropertyProxy(prop);
            }
        }

        MyAbView.prototype.proxiesGenerated = true;
    } else {
        for each (var interface in this.supportedInterfaces) {
            this.originalAbViewInstance.QueryInterface(interface);
        }
    }
}

MyAbView.prototype = {
    classID: null,

    _xpcom_factory: {
        createInstance: function(outer, iid) {
            return new MyAbView().QueryInterface(iid);
        }
    },

    QueryInterface: function(aIID) {
        for each (var interface in this.supportedInterfaces) {
            if (interface.equals(aIID)) {
                return this;
            }
        }

        throw Components.results.NS_ERROR_NO_INTERFACE;
    },

    originalAbViewFactory: null,
    originalAbViewInstance: null,

    proxiesGenerated: false,
    supportedInterfaces: [],

    // any overriden functions come here
};

It's implemented as a component to replace the original abview, but it might be modified to just create a wrapper.

独自唱情﹋歌 2024-12-19 12:35:14

小部件使用 nsITreeView 对象来检索或操作需要显示的数据。有预定义的 nsITreeView 实现从 DOM 或 RDF 数据源读取数据,但可以选择使用自己的树视图。 Thunderbird 的地址簿选择后者:

gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
                    .createInstance(Components.interfaces.nsIAbView);

...

gAbResultsTree.treeBoxObject.view =
  gAbView.QueryInterface(Components.interfaces.nsITreeView);

不幸的是,有问题的组件是用 C++ 实现的,位于文件 nsAbView.cpp。这意味着在不重新编译 Thunderbird 的情况下更改它是不可能的。并且现有组件未实现编辑树单元格所需的 isEditable()setCellText() 方法。

如果您还不想搞乱 C++,您可以将该组件包装在您自己的对象中。像这样的事情:

gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
                    .createInstance(Components.interfaces.nsIAbView);
gAbViewWrapper = {
  __proto__: gAbView,
  QueryInterface: function(iid)
  {
    gAbView.QueryInterface(iid);
    return this;
  },
  isEditable: function(row, col)
  {
    // Do something here
  },
  setCellText: function(row, col, value)
  {
    // Do something here
  }
};

...

gAbResultsTree.treeBoxObject.view =
  gAbViewWrapper.QueryInterface(Components.interfaces.nsITreeView);

方法 isEditable() 应再次检查此特定单元格是否可编辑 - 即使该列可编辑,单个单元格也不必如此。 setCellText() 应该存储单元格的新值。

The <tree> widget uses an nsITreeView object to retrieve or manipulate data that needs to be displayed. There are predefined nsITreeView implementations reading data from the DOM or RDF datasources but one can choose to use his own tree view. Thunderbird's address book chooses the latter:

gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
                    .createInstance(Components.interfaces.nsIAbView);

...

gAbResultsTree.treeBoxObject.view =
  gAbView.QueryInterface(Components.interfaces.nsITreeView);

Unfortunately for you, the component in question is implemented in C++, in the file nsAbView.cpp. This means that changing it without recompiling Thunderbird isn't possible. And the existing component doesn't implement isEditable() and setCellText() methods that would be required to edit tree cells.

If you don't want to mess with C++ yet, you could wrap that component in your own object. Something like this:

gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
                    .createInstance(Components.interfaces.nsIAbView);
gAbViewWrapper = {
  __proto__: gAbView,
  QueryInterface: function(iid)
  {
    gAbView.QueryInterface(iid);
    return this;
  },
  isEditable: function(row, col)
  {
    // Do something here
  },
  setCellText: function(row, col, value)
  {
    // Do something here
  }
};

...

gAbResultsTree.treeBoxObject.view =
  gAbViewWrapper.QueryInterface(Components.interfaces.nsITreeView);

Method isEditable() should check again whether this particular cell is editable - even if the column is editable, individual cells don't have to be. And setCellText() should store the new value for the cell.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文