0

私はサンダーバードのコードベースで遊んでいます。目的は、インラインの連絡先編集を実装することです。Click現在のコードはツリー上のイベントをキャッチしXUL、ダブルクリック ( events.detail == 2) の場合は、プロファイル エディターを開きます。現在の の編集を開始するように変更し、対応するドキュメントtreeCellに追加しました。更新されたコードは次のようになりますeditable=trueXUL

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_IMPLEMENTED) [nsITreeView.isEditable]" nsresult: "0x80004001 (NS_ERROR_NOT_IMPLEMENTED)" location: "JS frame :: chrome://global/content/bindings/tree.xml :: startEditing :: line 337" data: no]

私はここでかなり迷っています。XUL の経験が豊富な人が助けてくれますか? ありがとう!

4

2 に答える 2

2

私は似たようなことをしようとしていましたが、同じ問題があります。

オーバーライドされた関数と同じように設定された元の 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 を置き換えるコンポーネントとして実装されていますが、単にラッパーを作成するように変更される可能性があります。

于 2012-03-22T20:11:04.133 に答える
1

<tree>ウィジェットはnsITreeViewオブジェクトを使用して、表示する必要があるデータを取得または操作します。nsITreeViewDOM または 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()、セルの新しい値を保存する必要があります。

于 2011-10-27T15:32:50.980 に答える