| 1 | # ============================================================================ |
|---|
| 2 | # |
|---|
| 3 | # Copyright (C) 2007-2008 Conceptive Engineering bvba. All rights reserved. |
|---|
| 4 | # www.conceptive.be / project-camelot@conceptive.be |
|---|
| 5 | # |
|---|
| 6 | # This file is part of the Camelot Library. |
|---|
| 7 | # |
|---|
| 8 | # This file may be used under the terms of the GNU General Public |
|---|
| 9 | # License version 2.0 as published by the Free Software Foundation |
|---|
| 10 | # and appearing in the file LICENSE.GPL included in the packaging of |
|---|
| 11 | # this file. Please review the following information to ensure GNU |
|---|
| 12 | # General Public Licensing requirements will be met: |
|---|
| 13 | # http://www.trolltech.com/products/qt/opensource.html |
|---|
| 14 | # |
|---|
| 15 | # If you are unsure which license is appropriate for your use, please |
|---|
| 16 | # review the following information: |
|---|
| 17 | # http://www.trolltech.com/products/qt/licensing.html or contact |
|---|
| 18 | # project-camelot@conceptive.be. |
|---|
| 19 | # |
|---|
| 20 | # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
|---|
| 21 | # WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|---|
| 22 | # |
|---|
| 23 | # For use of this library in commercial applications, please contact |
|---|
| 24 | # project-camelot@conceptive.be |
|---|
| 25 | # |
|---|
| 26 | # ============================================================================ |
|---|
| 27 | |
|---|
| 28 | from PyQt4 import QtCore |
|---|
| 29 | |
|---|
| 30 | from camelot.view.model_thread import model_function |
|---|
| 31 | from camelot.core.utils import ugettext as _ |
|---|
| 32 | |
|---|
| 33 | _application_admin_ = [] |
|---|
| 34 | |
|---|
| 35 | def get_application_admin(): |
|---|
| 36 | if not len(_application_admin_): |
|---|
| 37 | raise Exception('No application admin class has been constructed yet') |
|---|
| 38 | return _application_admin_[0] |
|---|
| 39 | |
|---|
| 40 | class ApplicationAdmin(QtCore.QObject): |
|---|
| 41 | """The Application Admin class defines how the application should look |
|---|
| 42 | like, it also ties python classes to their associated admin classes. It's |
|---|
| 43 | behaviour can be steered by overwriting its static attributes or it's |
|---|
| 44 | methods : |
|---|
| 45 | |
|---|
| 46 | .. attribute:: name |
|---|
| 47 | |
|---|
| 48 | The name of the application, as it will appear in the title of the main |
|---|
| 49 | window. |
|---|
| 50 | |
|---|
| 51 | .. attribute:: sections |
|---|
| 52 | |
|---|
| 53 | A list containing the various sections that should appear in the left panel |
|---|
| 54 | of the mainwindow. |
|---|
| 55 | |
|---|
| 56 | .. image:: ../_static/picture2.png |
|---|
| 57 | |
|---|
| 58 | """ |
|---|
| 59 | |
|---|
| 60 | name = 'Camelot' |
|---|
| 61 | sections = ['Relations', 'Configuration'] |
|---|
| 62 | admins = {} |
|---|
| 63 | |
|---|
| 64 | sections_changed_signal = QtCore.SIGNAL('sections_changed()') |
|---|
| 65 | """This signal is emitted whenever the sections are changed, and the views |
|---|
| 66 | should be updated""" |
|---|
| 67 | |
|---|
| 68 | def __init__(self): |
|---|
| 69 | QtCore.QObject.__init__(self) |
|---|
| 70 | _application_admin_.append(self) |
|---|
| 71 | # |
|---|
| 72 | # Cache created ObjectAdmin objects |
|---|
| 73 | # |
|---|
| 74 | self._object_admin_cache = {} |
|---|
| 75 | |
|---|
| 76 | def register(self, entity, admin_class): |
|---|
| 77 | self.admins[entity] = admin_class |
|---|
| 78 | |
|---|
| 79 | @model_function |
|---|
| 80 | def get_sections(self): |
|---|
| 81 | from camelot.admin.section import structure_to_sections |
|---|
| 82 | return structure_to_sections(self.sections) |
|---|
| 83 | |
|---|
| 84 | def get_entity_admin(self, entity): |
|---|
| 85 | """Get the default entity admin for this entity, return None, if not |
|---|
| 86 | existant""" |
|---|
| 87 | |
|---|
| 88 | admin_class = None |
|---|
| 89 | try: |
|---|
| 90 | admin_class = self.admins[entity] |
|---|
| 91 | except KeyError: |
|---|
| 92 | pass |
|---|
| 93 | if not admin_class and hasattr(entity, 'Admin'): |
|---|
| 94 | admin_class = entity.Admin |
|---|
| 95 | if admin_class: |
|---|
| 96 | try: |
|---|
| 97 | return self._object_admin_cache[admin_class] |
|---|
| 98 | except KeyError: |
|---|
| 99 | admin = admin_class(self, entity) |
|---|
| 100 | self._object_admin_cache[admin_class] = admin |
|---|
| 101 | return admin |
|---|
| 102 | |
|---|
| 103 | def get_entity_query(self, entity): |
|---|
| 104 | """Get the root query for an entity""" |
|---|
| 105 | return entity.query |
|---|
| 106 | |
|---|
| 107 | def create_main_window(self): |
|---|
| 108 | """create_main_window""" |
|---|
| 109 | from camelot.view.mainwindow import MainWindow |
|---|
| 110 | mainwindow = MainWindow(self) |
|---|
| 111 | return mainwindow |
|---|
| 112 | |
|---|
| 113 | def get_entities_and_queries_in_section(self, section): |
|---|
| 114 | """:return: a list of tuples of (admin, query) instances related to |
|---|
| 115 | the entities in this section. |
|---|
| 116 | """ |
|---|
| 117 | result = [(self.get_entity_admin(e), self.get_entity_query(e)) |
|---|
| 118 | for e, a in self.admins.items() |
|---|
| 119 | if hasattr(a, 'section') |
|---|
| 120 | and a.section == section] |
|---|
| 121 | result.sort(cmp = lambda x, y: cmp(x[0].get_verbose_name_plural(), |
|---|
| 122 | y[0].get_verbose_name_plural())) |
|---|
| 123 | return result |
|---|
| 124 | |
|---|
| 125 | def get_actions(self): |
|---|
| 126 | """:return: a list of camelot.admin.application_action.ApplicationAction objects |
|---|
| 127 | that should be added to the menu and the icon bar for this application |
|---|
| 128 | """ |
|---|
| 129 | return [] |
|---|
| 130 | |
|---|
| 131 | def get_name(self): |
|---|
| 132 | """:return: the name of the application""" |
|---|
| 133 | return self.name |
|---|
| 134 | |
|---|
| 135 | def get_icon(self): |
|---|
| 136 | """:return: the QIcon that should be used for the application""" |
|---|
| 137 | from camelot.view.art import Icon |
|---|
| 138 | return Icon('tango/32x32/apps/system-users.png').getQIcon() |
|---|
| 139 | |
|---|
| 140 | def get_splashscreen(self): |
|---|
| 141 | """:return: a QtGui.QPixmap to be used as splash screen""" |
|---|
| 142 | from camelot.view.art import Pixmap |
|---|
| 143 | return Pixmap('splashscreen.png').getQPixmap() |
|---|
| 144 | |
|---|
| 145 | def get_organization_name(self): |
|---|
| 146 | return 'Conceptive Engineering' |
|---|
| 147 | |
|---|
| 148 | def get_organization_domain(self): |
|---|
| 149 | return 'conceptive.be' |
|---|
| 150 | |
|---|
| 151 | def get_help_url(self): |
|---|
| 152 | """:return: a QUrl pointing to the index page for help""" |
|---|
| 153 | from PyQt4.QtCore import QUrl |
|---|
| 154 | return QUrl('http://www.conceptive.be/projects/camelot/') |
|---|
| 155 | |
|---|
| 156 | def get_stylesheet(self): |
|---|
| 157 | """ |
|---|
| 158 | :return: the qt stylesheet to be used for this application as a string |
|---|
| 159 | or None if no stylesheet needed |
|---|
| 160 | """ |
|---|
| 161 | return None |
|---|
| 162 | |
|---|
| 163 | def get_translator(self): |
|---|
| 164 | """Reimplement this method to add application specific translations |
|---|
| 165 | to your application. |
|---|
| 166 | |
|---|
| 167 | :return: a QTranslator that should be used to translate the application |
|---|
| 168 | """ |
|---|
| 169 | return QtCore.QTranslator() |
|---|
| 170 | |
|---|
| 171 | def get_about(self): |
|---|
| 172 | """:return: the content of the About dialog, a string with html |
|---|
| 173 | syntax""" |
|---|
| 174 | return """<b>Camelot Project</b> |
|---|
| 175 | <p> |
|---|
| 176 | Copyright © 2008-2009 Conceptive Engineering. |
|---|
| 177 | All rights reserved. |
|---|
| 178 | </p> |
|---|
| 179 | <p> |
|---|
| 180 | http://www.conceptive.be/projects/camelot |
|---|
| 181 | </p> |
|---|
| 182 | """ |
|---|
| 183 | |
|---|
| 184 | def get_default_field_attributes(self, type_, field): |
|---|
| 185 | """Returns the default field attributes""" |
|---|
| 186 | from camelot.core.view.field_attributes import \ |
|---|
| 187 | _sqlalchemy_to_python_type_ |
|---|
| 188 | return _sqlalchemy_to_python_type_[type_](field) |
|---|
| 189 | |
|---|
| 190 | def update_window_menu(self, mainwin): |
|---|
| 191 | from PyQt4 import QtCore |
|---|
| 192 | |
|---|
| 193 | def add_actions(): |
|---|
| 194 | mainwin.windowMenu.clear() |
|---|
| 195 | mainwin.windowMenu.addAction(mainwin.closeAllAct) |
|---|
| 196 | mainwin.windowMenu.addAction(mainwin.cascadeAct) |
|---|
| 197 | mainwin.windowMenu.addAction(mainwin.separatorAct) |
|---|
| 198 | |
|---|
| 199 | windows = mainwin.workspace.subWindowList() |
|---|
| 200 | |
|---|
| 201 | mainwin.separatorAct.setVisible(len(windows) != 0) |
|---|
| 202 | |
|---|
| 203 | for i, child in enumerate(windows): |
|---|
| 204 | title = child.windowTitle() |
|---|
| 205 | if i < 9: |
|---|
| 206 | text = _('&%s %s' % (i+1, title)) |
|---|
| 207 | else: |
|---|
| 208 | text = _('%s %s' % (i+1, title)) |
|---|
| 209 | |
|---|
| 210 | action = mainwin.windowMenu.addAction(text) |
|---|
| 211 | action.setCheckable(True) |
|---|
| 212 | action.setChecked(child == mainwin.activeMdiChild()) |
|---|
| 213 | |
|---|
| 214 | def create_window_activator(window): |
|---|
| 215 | |
|---|
| 216 | def activate_window(): |
|---|
| 217 | mainwin.workspace.setActiveSubWindow(window) |
|---|
| 218 | |
|---|
| 219 | return activate_window |
|---|
| 220 | |
|---|
| 221 | mainwin.connect( |
|---|
| 222 | action, |
|---|
| 223 | QtCore.SIGNAL('triggered()'), |
|---|
| 224 | create_window_activator(child) |
|---|
| 225 | ) |
|---|
| 226 | |
|---|
| 227 | return add_actions |
|---|