# -*- coding: utf-8 -*-
from PyQt4.QtGui import QAction
from PyQt4.QtGui import QMenu
from PyQt4.QtCore import QObject
from collections import defaultdict
from ninja_ide.core import settings
from ninja_ide.gui.ide import IDE
SEC01 = 100
SEC02 = 200
SEC03 = 300
SEC04 = 400
SEC05 = 500
SEC06 = 600
SEC07 = 700
SEC08 = 800
SEC09 = 900
SEC10 = 1000
#WE WILL PROBABLY NEED TO SAVE THE WEIGHT WITH THE ACTIONS SO WE CAN
#DETERMINE TO LOCATE A PLUGIN LOADED AFTER INITIALIZATION AT THE PROPER PLACE
def menu_add_section(menu, section_parts):
menus = []
for each_part in section_parts:
action, weight = each_part
add = None
if isinstance(action, QAction):
add = menu.addAction
elif isinstance(action, QMenu):
add = menu.addMenu
menus.append(action)
if add:
add(action)
#FIXME: This appends a separator at the end of each menu
#FIXME: add separator between sections
menu.addSeparator()
return menus
class _MenuBar(QObject):
def __init__(self):
super(_MenuBar, self).__init__()
self._roots = {}
self._children = {}
self._submenu = {}
self._menu_refs = {}
self._toolbar_index = {}
IDE.register_service('menu_bar', self)
#TODO: Create recent file service
#menu_file_connections = (
#{'target': 'main_container',
#'signal_name': 'recentTabsModified(QStringList)',
#'slot': self._menuFile.update_recent_files},
#)
def add_root(self, root_name, root_weight=None):
"""
Add a root menu with desired weight or at end of list
"""
#If self._roots is empty this is going to explode
if root_name not in self._roots:
if root_weight is None:
root_weight = sorted(self._roots.values())[-1] + 1
self._roots[root_name] = root_weight
def get_root(self):
#Get the list of menu categories from ide: IDE.get_menu_categories
iter_items = list(self._roots.items())
iter_items.sort(key=lambda x: x[1])
return [item[0] for item in iter_items]
def add_child(self, root_name, sub_name, child, weight,
namespace="ninjaide"):
child_path = (root_name, sub_name, namespace, child)
oname = child.objectName()
if oname:
self._toolbar_index[oname] = child
if child_path not in self._children:
self.add_root(root_name)
self._children[child_path] = (child, weight)
def get_children_of(self, parent, sub_name=None, namespace=None):
children = defaultdict(lambda: [])
for each_child in self._children:
child_parent, sub_parent, child_namespace, child_name = each_child
if (parent == child_parent) and (sub_parent == sub_name) \
and ((namespace == child_namespace) or (not namespace)):
child, weight = self._children[each_child]
#Group by namespace and weight
weight_index = "%d_%s" % (weight / 100, namespace)
children[weight_index].append((child, weight))
return children
def add_toolbar_item(self, toolbar_item):
section, item, weight = toolbar_item
self._toolbar_sections[section] = (item, weight)
def load_menu(self, ide):
#menuBar is the actual QMenuBar object from IDE which is a QMainWindow
self.menubar = ide.menuBar()
# Create Root
categories = ide.get_menu_categories()
for category in categories:
self.add_root(category, categories[category])
# EACH ITEM menu should be obtained from ide.get_menuitems()
# which is going to return a dict with:
# key: QAction or QMenu
# value: (category[string], weight[int])
# QAction/QMenu, and ask something like "instanceof" for those
# objects to see if we should execute an addMenu or addAction to
# the MenuBar.
menuitems = ide.get_menuitems()
for action in menuitems:
category, weight = menuitems[action]
category, subcategory = category
#FIXME: Need cateogory and sub, which should be none
self.add_child(category, subcategory, action, weight)
#FIXME: This should add to the given methods and they to the actual adding on menu upon add
#FIXME: To support this we should have a way to add these in order after menu creation
for each_menu in self.get_root():
menu_object = self.menubar.addMenu(each_menu)
self._menu_refs[each_menu] = menu_object
all_children = self.get_children_of(each_menu)
for each_child_grp_key in sorted(all_children):
each_child_grp = all_children[each_child_grp_key]
menus = menu_add_section(menu_object,
sorted(each_child_grp, key=lambda x: x[1]))
#FIXME: Prettify the following
for menu in menus:
self._submenu[(each_menu, menu.title())] = menu
for each_parent, each_submenu in list(self._submenu.keys()):
menu = self._submenu[(each_parent, each_submenu)]
all_children = self.get_children_of(each_parent, each_submenu)
for each_child_grp_key in sorted(all_children):
each_child_grp = all_children[each_child_grp_key]
menu_add_section(menu,
sorted(each_child_grp, key=lambda x: x[1]))
#ADD A LATER CALLBACK
def load_toolbar(self, ide):
#FIXME: Do the same as above to add items to toolbar
toolbar = ide.get_service("toolbar")
toolbar.clear()
for toolbar_action in settings.TOOLBAR_ITEMS:
tool_item = self._toolbar_index.get(toolbar_action, None)
if tool_item:
toolbar.addAction(tool_item)
menu = _MenuBar()