前の関連記事:Calc(39)コンテクストメニューをカスタマイズする: その7
セルのコンテクストメニュー
「切り取り」「コピー」「貼り付け」以外は削ることにします。
デフォルトコンテクストメニューのディスパッチコマンドはCalc(39)コンテクストメニューをカスタマイズする: その7で作成したcellを参考にします。
行ヘッダーのコンテクストメニュー
「切り取り」「コピー」「貼り付け」「上に行を挿入」「行の削除」以外は削ることにします。
デフォルトコンテクストメニューのディスパッチコマンドはrowheaderです。
列ヘッダーのコンテクストメニュー
横にセルの結合をして使う予定なので列を切り貼りするメニューは削ってしまいます。
ということでこれは全部削ってしまうことにします。
デフォルトコンテクストメニューのディスパッチコマンドはcolheaderです。
シートタブのコンテクストメニュー
「シートを移動またはコピー」以外は削ってしまいます。
デフォルトコンテクストメニューのディスパッチコマンドはsheettabです。
デフォルトのコンテクストメニューの項目を削除するマクロ
マクロを使わなくても、ツール→カスタマイズ→コンテキストメニュー、でコンテキストメニュー項目はGUIで整理できますが、今回はマクロを使ってやります。
#!/opt/libreoffice5.4/program/python
# -*- coding: utf-8 -*-
import unohelper # オートメーションには必須(必須なのはuno)。
from com.sun.star.ui import XContextMenuInterceptor
from com.sun.star.ui import ActionTriggerSeparatorType # 定数
from com.sun.star.ui.ContextMenuInterceptorAction import EXECUTE_MODIFIED # enum
def macro(documentevent=None): # 引数は文書のイベント駆動用。
doc = XSCRIPTCONTEXT.getDocument() if documentevent is None else documentevent.Source # ドキュメントのモデルを取得。
controller = doc.getCurrentController() # コントローラーを取得。
contextmenuinterceptor = ContextMenuInterceptor()
controller.registerContextMenuInterceptor(contextmenuinterceptor)
class ContextMenuInterceptor(unohelper.Base, XContextMenuInterceptor):
def notifyContextMenuExecute(self, contextmenuexecuteevent): # 右クリックで呼ばれる関数。contextmenuexecuteevent.ActionTriggerContainerを操作しないとコンテクストメニューが表示されない。
contextmenu = contextmenuexecuteevent.ActionTriggerContainer # コンテクストメニューコンテナの取得。
name = contextmenu.getName().rsplit("/")[-1] # コンテクストメニューの名前を取得。
addMenuentry = menuentryCreator(contextmenu) # 引数のActionTriggerContainerにインデックス0から項目を挿入する関数を取得。
if name=="cell": # セルのとき
del contextmenu[:] # contextmenu.clear()は不可。
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Cut"})
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Copy"})
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Paste"})
elif name=="rowheader": # 行ヘッダーのとき。
del contextmenu[:] # contextmenu.clear()は不可。
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Cut"})
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Copy"})
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Paste"})
addMenuentry("ActionTriggerSeparator", {"SeparatorType": ActionTriggerSeparatorType.LINE})
addMenuentry("ActionTrigger", {"CommandURL": ".uno:InsertRowsBefore"})
addMenuentry("ActionTrigger", {"CommandURL": ".uno:DeleteRows"})
elif name=="colheader": # 列ヘッダーの時。
pass # contextmenuを操作しないとすべての項目が表示されない。
elif name=="sheettab": # シートタブの時。
del contextmenu[:] # contextmenu.clear()は不可。
addMenuentry("ActionTrigger", {"CommandURL": ".uno:Move"})
return EXECUTE_MODIFIED
def menuentryCreator(menucontainer): # 引数のActionTriggerContainerにインデックス0から項目を挿入する関数を取得。
i = 0 # インデックスを初期化する。
def addMenuentry(menutype, props): # i: index, propsは辞書。menutypeはActionTriggerかActionTriggerSeparator。
menuentry = menucontainer.createInstance("com.sun.star.ui.{}".format(menutype)) # ActionTriggerContainerからインスタンス化する。
[menuentry.setPropertyValue(key, val) for key, val in props.items()] #setPropertyValuesでは設定できない。エラーも出ない。
menucontainer.insertByIndex(i, menuentry) # submenucontainer[i]やsubmenucontainer[i:i]は不可。挿入以降のメニューコンテナの項目のインデックスは1増える。
nonlocal i
i += 1 # インデックスを増やす。
return addMenuentry
g_exportedScripts = macro, #マクロセレクターに限定表示させる関数をタプルで指定。
ActionTriggerContainerのメニュー項目を挿入したり削除したりするにはインデックスで行う必要があります。非表示にするメニュー項目を削除しようと考えたのですが、いちいちCommandURLのディスパッチコマンドをみてインデックスを取得して削除しないといけません。
それは面倒なので、まずはdel contextmenu[:]ですべての項目を削除してから表示したい項目を追加することにしました。
同じインデックスに挿入するとすでにある項目のインデックスが増えます。
つまり、インデックスを変更しなければ、コードで書いた順に下にずれていくのですが、それはわかりにくいので、menuentryCreator()関数のクロージャーでインデックスを増やして、コードに書いた順に上になるように項目を追加しています。
contextmenuexecuteevent.ActionTriggerContainerをいじらないとすべての項目が表示されませんでした。
なので、列ヘッダーのときは何もしていません。
DeleteDefaultContextMenuEntries.ods
このマクロを埋め込んだCalcドキュメントです。




0 件のコメント:
コメントを投稿