diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py
index 7b67a7644..74c355784 100644
--- a/web/pgadmin/__init__.py
+++ b/web/pgadmin/__init__.py
@@ -17,11 +17,14 @@ from flask_security.utils import login_user
from flask_mail import Mail
from settings_model import db, Role, User
-import inspect, logging, os
+import inspect, imp, logging, os
# Configuration settings
import config
+# Global module list
+modules = [ ]
+
def create_app(app_name=config.APP_NAME):
"""Create the Flask application, startup logging and dynamically load
additional modules (blueprints) that are found in this directory."""
@@ -88,6 +91,7 @@ def create_app(app_name=config.APP_NAME):
path = os.path.dirname(os.path.realpath(__file__))
files = os.listdir(path)
+
for f in files:
d = os.path.join(path, f)
if os.path.isdir(d) and os.path.isfile(os.path.join(d, '__init__.py')):
@@ -98,10 +102,16 @@ def create_app(app_name=config.APP_NAME):
# Looks like a module, so import it, and register the blueprint if present
# We rely on the ordering of syspath to ensure we actually get the right
- # module here.
+ # module here. Note that we also try to load the 'browser' module for
+ # the browser integration hooks.
app.logger.info('Examining potential module: %s' % d)
- module = __import__(f, globals(), locals(), ['views'], -1)
- if hasattr(module.views, 'blueprint'):
+ module = __import__(f, globals(), locals(), ['browser', 'views'], -1)
+
+ # Add the module to the global module list
+ modules.append(module)
+
+ # Register the blueprint if present
+ if 'views' in dir(module) and 'blueprint' in dir(module.views):
app.logger.info('Registering blueprint module: %s' % f)
app.register_blueprint(module.views.blueprint)
diff --git a/web/pgadmin/about/__init__.py b/web/pgadmin/about/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/web/pgadmin/about/browser.py b/web/pgadmin/about/browser.py
new file mode 100644
index 000000000..5f26ea2d9
--- /dev/null
+++ b/web/pgadmin/about/browser.py
@@ -0,0 +1,18 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2014, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Browser integration functions for the About module."""
+
+from flask import url_for
+
+import config
+
+def get_help_menu_items():
+ """Return a (set) of dicts of help menu items, with name, priority and URL."""
+ return [{'name': 'About %s' % (config.APP_NAME), 'priority': 999, 'url': url_for('about.index')}]
\ No newline at end of file
diff --git a/web/pgadmin/about/templates/about/index.html b/web/pgadmin/about/templates/about/index.html
new file mode 100644
index 000000000..f23c4e2ad
--- /dev/null
+++ b/web/pgadmin/about/templates/about/index.html
@@ -0,0 +1 @@
+About {{ config.APP_NAME }}
diff --git a/web/pgadmin/about/views.py b/web/pgadmin/about/views.py
new file mode 100644
index 000000000..1e57672c7
--- /dev/null
+++ b/web/pgadmin/about/views.py
@@ -0,0 +1,27 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2014, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""A blueprint module implementing the about box."""
+MODULE_NAME = 'about'
+
+import config
+from flask import Blueprint, current_app, render_template
+from flask.ext.security import login_required
+
+# Initialise the module
+blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix='/' + MODULE_NAME)
+
+##########################################################################
+# A test page
+##########################################################################
+@blueprint.route("/")
+@login_required
+def index():
+ """Render the about box."""
+ return render_template(MODULE_NAME + '/index.html')
diff --git a/web/pgadmin/browser/templates/browser/index.html b/web/pgadmin/browser/templates/browser/index.html
index 7df1d3c57..43a12dc07 100644
--- a/web/pgadmin/browser/templates/browser/index.html
+++ b/web/pgadmin/browser/templates/browser/index.html
@@ -16,18 +16,40 @@
+
-
File
+ -
+ Edit
+
+
+
+ -
+ Tools
+
+
+
-
Help
diff --git a/web/pgadmin/browser/views.py b/web/pgadmin/browser/views.py
index b3876ed99..1c8e2b792 100644
--- a/web/pgadmin/browser/views.py
+++ b/web/pgadmin/browser/views.py
@@ -10,11 +10,15 @@
"""A blueprint module implementing the core pgAdmin browser."""
MODULE_NAME = 'browser'
-import config
from flask import Blueprint, current_app, render_template
from flaskext.gravatar import Gravatar
from flask.ext.security import login_required
from flask.ext.login import current_user
+from inspect import getmoduleinfo, getmembers
+
+from pgadmin import modules
+
+import config
# Initialise the module
blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix='/' + MODULE_NAME)
@@ -26,6 +30,7 @@ blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url
@login_required
def index():
"""Render and process the main browser window."""
+ # Get the Gravatar
gravatar = Gravatar(current_app,
size=100,
rating='g',
@@ -34,4 +39,37 @@ def index():
use_ssl=False,
base_url=None)
- return render_template(MODULE_NAME + '/index.html', username=current_user.email)
+ # Get the menu items from the module
+ file_items = [ ]
+ edit_items = [ ]
+ tools_items = [ ]
+ help_items = [ ]
+
+ for module in modules:
+ # Get the edit menu items
+ if 'browser' in dir(module) and 'get_file_menu_items' in dir(module.browser):
+ file_items.extend(module.browser.get_file_menu_items())
+
+ # Get the edit menu items
+ if 'browser' in dir(module) and 'get_edit_menu_items' in dir(module.browser):
+ edit_items.extend(module.browser.get_edit_menu_items())
+
+ # Get the tools menu items
+ if 'browser' in dir(module) and 'get_tools_menu_items' in dir(module.browser):
+ tools_items.extend(module.browser.get_tools_menu_items())
+
+ # Get the help menu items
+ if 'browser' in dir(module) and 'get_help_menu_items' in dir(module.browser):
+ help_items.extend(module.browser.get_help_menu_items())
+
+ file_items = sorted(file_items, key=lambda k: k['priority'])
+ edit_items = sorted(edit_items, key=lambda k: k['priority'])
+ tools_items = sorted(tools_items, key=lambda k: k['priority'])
+ help_items = sorted(help_items, key=lambda k: k['priority'])
+
+ return render_template(MODULE_NAME + '/index.html',
+ username=current_user.email,
+ file_items=file_items,
+ edit_items=edit_items,
+ tools_items=tools_items,
+ help_items=help_items)
diff --git a/web/pgadmin/test/__init__.py b/web/pgadmin/test/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/web/pgadmin/test/browser.py b/web/pgadmin/test/browser.py
new file mode 100644
index 000000000..0ddf4721d
--- /dev/null
+++ b/web/pgadmin/test/browser.py
@@ -0,0 +1,16 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2014, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Browser integration functions for the Test module."""
+
+from flask import url_for
+
+def get_file_menu_items():
+ """Return a (set) of dicts of file menu items, with name, priority and URL."""
+ return [{'name': 'Generated Test HTML', 'priority': 100, 'url': url_for('test.generated')}]
\ No newline at end of file
diff --git a/web/pgadmin/test/views.py b/web/pgadmin/test/views.py
new file mode 100644
index 000000000..cef736478
--- /dev/null
+++ b/web/pgadmin/test/views.py
@@ -0,0 +1,35 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2014, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""A blueprint module providing utility functions for the application."""
+MODULE_NAME = 'test'
+
+import config
+from flask import Blueprint, render_template
+from flask.ext.security import login_required
+from time import time, ctime
+
+# Initialise the module
+blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix='/' + MODULE_NAME)
+
+##########################################################################
+# A test page
+##########################################################################
+@blueprint.route("/generated")
+@login_required
+def generated():
+ """Generate a simple test page to demonstrate that output can be rendered."""
+ output = """
+Today is %s
+
+This is Flask-generated HTML.
+
+%s v%s""" % (ctime(time()), config.APP_NAME, config.APP_VERSION)
+
+ return output
diff --git a/web/pgadmin/utils/views.py b/web/pgadmin/utils/views.py
index b464e9027..4f5811d93 100644
--- a/web/pgadmin/utils/views.py
+++ b/web/pgadmin/utils/views.py
@@ -18,22 +18,6 @@ from time import time, ctime
# Initialise the module
blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix='/' + MODULE_NAME)
-##########################################################################
-# A test page
-##########################################################################
-@blueprint.route("/test")
-@login_required
-def test():
- """Generate a simple test page to demonstrate that output can be rendered."""
- output = """
-Today is %s
-
-This is Flask-generated HTML.
-
-%s v%s""" % (ctime(time()), config.APP_NAME, config.APP_VERSION)
-
- return output
-
##########################################################################
# A special URL used to "ping" the server
##########################################################################