diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e94089 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*~ + diff --git a/db_manager.py b/db_manager.py index 6935c44..5b6bdac 100644 --- a/db_manager.py +++ b/db_manager.py @@ -22,7 +22,7 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -from .ui.dbmanager_ui import Ui_DBManager +from .ui.DbManager_ui import Ui_DBManager class DBManager(QMainWindow, Ui_DBManager): @@ -37,6 +37,12 @@ def __init__(self, iface, parent=None): self.restoreGeometry( settings.value("/DB_Manager/geometry").toByteArray() ) self.restoreState( settings.value("/DB_Manager/windowState").toByteArray() ) + self.connect(self.treeView, SIGNAL("currentChanged"), self.itemChanged) + + self.connect(self.actionRunQuery, SIGNAL("triggered()"), self.runQuery) + self.connect(self.actionExit, SIGNAL("triggered()"), self.close) + + def closeEvent(self, e): # save the window state settings = QSettings() @@ -46,6 +52,21 @@ def closeEvent(self, e): QMainWindow.closeEvent(self, e) + def itemChanged(self, item): + if item: self.infoTab.showInfo(item) + + def runQuery(self): + db = self.treeView.currentDatabase() + if db == None: + QMessageBox.information(self, u"Sorry", u"No database selected or you are not connected.") + return + + from dlg_sql_window import DlgSqlWindow + dlg = DlgSqlWindow(self, db) + dlg.exec_() + self.emit( SIGNAL('reloadDatabase'), db) + + def registerAction(self, action, menu, callback): """ register an action to the manager's main menu """ invoke_callback = lambda x: self.__invokeCallback( callback, checked ) diff --git a/db_manager_plugin.py b/db_manager_plugin.py index 764e781..fbdfb7e 100644 --- a/db_manager_plugin.py +++ b/db_manager_plugin.py @@ -42,7 +42,6 @@ def unload(self): self.iface.removePluginDatabaseMenu( u"DB Manager", self.action ) if self.dlg != None: self.dlg.close() - self.dlg = None def run(self): if self.dlg == None: @@ -52,5 +51,6 @@ def run(self): self.dlg.show() def onDestroyed(self, obj): + print ">>>>>> destroyed" self.dlg = None diff --git a/db_model.py b/db_model.py index 9639f0f..9e11daa 100644 --- a/db_model.py +++ b/db_model.py @@ -24,7 +24,9 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -from . import db_plugins +from .db_plugins import supportedDbTypes, createDbPlugin +from .db_plugins.plugin import * + try: from . import resources_rc except ImportError: @@ -33,12 +35,25 @@ class TreeItem(QObject): def __init__(self, data, parent=None): QObject.__init__(self, parent) + self.populated = True self.parentItem = parent self.itemData = data self.childItems = [] if parent: parent.appendChild(self) + def __del__(self): + print "TreeItem.__del__", self, self.data(0) + self.itemData = None + + def deleteChildren(self): + for c in self.childItems: + c.parentItem = None + c.deleteChildren() + + def populate(self, index): + self.emit( SIGNAL("startToPopulate"), index ) + def getItemData(self): return self.itemData @@ -89,38 +104,40 @@ def icon(self): class ConnectionItem(TreeItem): - def __init__(self, db, parent=None): - TreeItem.__init__(self, db, parent) + def __init__(self, connection, parent=None): + TreeItem.__init__(self, connection, parent) self.populated = False + self.connect( self, SIGNAL("startToPopulate"), self.__populate) def data(self, column): if column == 0: return self.getItemData().connectionName() return None - - def populate(self): + + def __populate(self, index): if self.populated: return True - db = self.getItemData() + connection = self.getItemData() try: - if not db.connect(): + if not connection.connect(): return False - except (db_plugins.InvalidDataException, db_plugins.DbError), e: + except (InvalidDataException, ConnectionError), e: QMessageBox.warning( None, u"Unable to connect", unicode(e) ) return False - schemas = db.connector.schemas() + schemas = connection.db.schemas() if schemas != None: for s in schemas: SchemaItem(s, self) else: - tables = db.connector.tables() + tables = connection.db.tables() for t in tables: TableItem(t, self) self.populated = True + self.emit( SIGNAL("populated"), index ) return True @@ -128,6 +145,7 @@ class SchemaItem(TreeItem): def __init__(self, schema, parent): TreeItem.__init__(self, schema, parent) self.populated = False + self.connect( self, SIGNAL("startToPopulate"), self.__populate) # load (shared) icon with first instance of schema item if not hasattr(SchemaItem, 'schemaIcon'): @@ -141,15 +159,15 @@ def data(self, column): def icon(self): return self.schemaIcon - def populate(self): + def __populate(self, index): if self.populated: return True - schema = self.getItemData() - db = self.parent().getItemData() - for t in db.connector.tables( schema.name ): + for t in self.getItemData().tables(): TableItem(t, self) + self.populated = True + self.emit( SIGNAL("populated"), index ) return True @@ -172,9 +190,6 @@ def data(self, column): elif column == 1: return self.getItemData().geomType return None - - def childCount(self): - return 0 def icon(self): geom_type = self.getItemData().geomType @@ -193,16 +208,19 @@ def icon(self): class DBModel(QAbstractItemModel): - def __init__(self, parent=None): QAbstractItemModel.__init__(self, parent) - self.header = ['Table'] + self.header = ['Databases'] self.rootItem = TreeItem(None, None) - for dbtype in db_plugins.supportedDBTypes(): - dbpluginclass = db_plugins.create( dbtype ) + for dbtype in supportedDbTypes(): + dbpluginclass = createDbPlugin( dbtype ) PluginItem( dbpluginclass, self.rootItem ) + def __del__(self): + print "DBModel.__del__" + self.rootItem.deleteChildren() + self.rootItem = None def getItem(self, index): if not index.isValid(): @@ -268,20 +286,16 @@ def parent(self, index): def rowCount(self, parent): parentItem = parent.internalPointer() if parent.isValid() else self.rootItem + if not parentItem.populated: + self.connect( parentItem, SIGNAL('populated'), self._onDataChanged ) + parentItem.populate( parent ) + else: + self.disconnect( parentItem, SIGNAL('populated'), self._onDataChanged ) return parentItem.childCount() def hasChildren(self, parent): parentItem = parent.internalPointer() if parent.isValid() else self.rootItem - return parentItem.childCount() > 0 or (hasattr(parentItem, 'populated') and parentItem.populated == False) - - def canFetchMore(self, parent): - parentItem = parent.internalPointer() if parent.isValid() else self.rootItem - return hasattr(parentItem, 'populated') and parentItem.populated == False - - def fetchMore(self, parent): - parentItem = parent.internalPointer() if parent.isValid() else self.rootItem - if hasattr(parentItem, 'populate'): - parentItem.populate() + return parentItem.childCount() > 0 or not parentItem.populated def setData(self, index, value, role): @@ -297,11 +311,16 @@ def setData(self, index, value, role): # rename schema or table or view try: item.getItemData().rename(new_name) - self.emit(SIGNAL('dataChanged(const QModelIndex &, const QModelIndex &)'), index, index) + self._onDataChanged(index) return True - except db_plugins.DbError, e: + except DbError, e: DlgDbError.showError(e, None) return False return False + + def _onDataChanged(self, indexFrom, indexTo=None): + if indexTo == None: indexTo = indexFrom + self.emit( SIGNAL('dataChanged(const QModelIndex &, const QModelIndex &)'), indexFrom, indexTo) + diff --git a/db_plugins/__init__.py b/db_plugins/__init__.py index 8d031f7..bcbd5d0 100644 --- a/db_plugins/__init__.py +++ b/db_plugins/__init__.py @@ -23,7 +23,7 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -class NotSupportedDBType(Exception): +class NotSupportedDbType(Exception): def __init__(self, dbtype): self.msg = u"%s is not supported yet" % dbtype Exception(self, self.msg) @@ -31,115 +31,32 @@ def __init__(self, dbtype): def __str__(self): return self.msg.encode('utf-8') -class InvalidDataException(Exception): - def __init__(self, msg): - self.msg = unicode( msg ) - Exception(self, self.msg) - - def __str__(self): - return self.msg.encode('utf-8') - -class DbError(Exception): - def __init__(self, errormsg, query=None): - self.msg = unicode( errormsg ) - self.query = unicode( query ) if query else None - Exception(self, self.msg) - - def __str__(self): - msg = self.msg - if self.query != None: - msg += u"\nQuery:\n%s" % self.query - return msg.encode('utf-8') - - -class DBConnector: - def __init__(self, uri): - self.uri = uri - - def quoteId(self, identifier): - if hasattr(identifier, '__iter__'): - ids = list() - for i in identifier: - if i == None: - continue - ids.append( self.quoteId(i) ) - return u'.'.join( ids ) - - identifier = unicode(identifier) # make sure it's python unicode string - return u'"%s"' % identifier.replace('"', '""') - - def quoteString(self, txt): - """ make the string safe - replace ' with '' """ - txt = unicode(txt) # make sure it's python unicode string - return txt.replace("'", "''") - - -class DBPlugin: - def __init__(self, conn_name): - self.connName = conn_name - - def connectionName(self): - return self.connName - - def connect(self): - return False - - @classmethod - def icon(self): - return None - - @classmethod - def typeName(self): - # return the db typename (e.g. 'postgis') - pass - - @classmethod - def typeNameString(self): - # return the db typename string (e.g. 'PostGIS') - pass - - @classmethod - def connectionSettingsKey(self): - # return the key used to store the connections in settings - pass - - @classmethod - def connections(self): - # get the list of connections - conn_list = [] - settings = QSettings() - settings.beginGroup( self.connectionSettingsKey() ) - for name in settings.childGroups(): - conn_list.append( create(self.typeName(), name) ) - settings.endGroup() - return conn_list - - -def init(): +def initDbPluginList(): import os current_dir = os.path.dirname(__file__) for name in os.listdir(current_dir): if not os.path.isdir( os.path.join( current_dir, name ) ): continue try: - exec( u"from %s import plugin as mod" % name ) - except : + exec( u"from .%s import plugin as mod" % name ) + except ImportError, e: continue - plugin_class = mod.classFactory() - SUPPORTED_DBTYPES[ plugin_class.typeName() ] = plugin_class + pluginclass = mod.classFactory() + SUPPORTED_DBTYPES[ pluginclass.typeName() ] = pluginclass return len(SUPPORTED_DBTYPES) > 0 -def supportedDBTypes(): +def supportedDbTypes(): return sorted(SUPPORTED_DBTYPES.keys()) -def create(dbtype, conn_name=None): +def createDbPlugin(dbtype, conn_name=None): if not SUPPORTED_DBTYPES.has_key( dbtype ): - raise NotSupportedDBType( dbtype ) + raise NotSupportedDbType( dbtype ) dbplugin = SUPPORTED_DBTYPES[ dbtype ] return dbplugin if conn_name is None else dbplugin(conn_name) # initialize the plugin list SUPPORTED_DBTYPES = {} -init() +initDbPluginList() + diff --git a/db_plugins/connector.py b/db_plugins/connector.py new file mode 100644 index 0000000..83f4c49 --- /dev/null +++ b/db_plugins/connector.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- + +""" +/*************************************************************************** +Name : DB Manager +Description : Database manager plugin for QuantumGIS +Date : May 23, 2011 +copyright : (C) 2011 by Giuseppe Sucameli +email : brush.tyler@gmail.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +class DBConnector: + def __init__(self, uri): + self.connection = None + self.uri = uri + + def __del__(self): + print "DBConnector.__del__", self.uri.uri() + if self.connection != None: + self.connection.close() + self.connection = None + + def quoteId(self, identifier): + if hasattr(identifier, '__iter__'): + ids = list() + for i in identifier: + if i == None: + continue + ids.append( self.quoteId(i) ) + return u'.'.join( ids ) + + identifier = unicode(identifier) # make sure it's python unicode string + return u'"%s"' % identifier.replace('"', '""') + + def quoteString(self, txt): + """ make the string safe - replace ' with '' """ + txt = unicode(txt) # make sure it's python unicode string + return u"'%s'" % txt.replace("'", "''") + + +class SqlTableModel(QAbstractTableModel): + def __init__(self, parent=None): + QAbstractTableModel.__init__(self, parent) + self.header = [] + self.resdata = [] + + def rowCount(self, parent): + return len(self.resdata) + + def columnCount(self, parent): + return len(self.header) + + def data(self, index, role): + if role != Qt.DisplayRole: + return QVariant() + + val = self.resdata[ index.row() ][ index.column() ] + if val == None: + return QVariant("NULL") + else: + return QVariant(val) + + def headerData(self, section, orientation, role): + if role != Qt.DisplayRole: + return QVariant() + + if orientation == Qt.Vertical: + # header for a row + return QVariant(section+1) + else: + # header for a column + return QVariant(self.header[section]) diff --git a/db_plugins/plugin.py b/db_plugins/plugin.py new file mode 100644 index 0000000..9d21cf2 --- /dev/null +++ b/db_plugins/plugin.py @@ -0,0 +1,253 @@ +# -*- coding: utf-8 -*- + +""" +/*************************************************************************** +Name : DB Manager +Description : Database manager plugin for QuantumGIS +Date : May 23, 2011 +copyright : (C) 2011 by Giuseppe Sucameli +email : brush.tyler@gmail.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from ..db_plugins import createDbPlugin + +class InvalidDataException(Exception): + def __init__(self, msg): + self.msg = unicode( msg ) + Exception(self, self.msg) + + def __str__(self): + return self.msg.encode('utf-8') + +class ConnectionError(Exception): + def __init__(self, msg): + self.msg = unicode( msg ) + Exception(self, self.msg) + + def __str__(self): + return self.msg.encode('utf-8') + +class DbError(Exception): + def __init__(self, errormsg, query=None): + self.msg = unicode( errormsg ) + self.query = unicode( query ) if query else None + Exception(self, self.msg) + + def __str__(self): + msg = self.msg + if self.query: + msg += u"\nQuery:\n%s" % self.query + return msg.encode('utf-8') + + +class DBPlugin: + def __init__(self, conn_name): + self.connName = conn_name + self.db = None + + def __del__(self): + print "DBPlugin.__del__", self.connName + self.db = None + + def connectionName(self): + return self.connName + + def database(self): + return self.db + + def connect(self): + return False + + @classmethod + def icon(self): + return None + + @classmethod + def typeName(self): + # return the db typename (e.g. 'postgis') + pass + + @classmethod + def typeNameString(self): + # return the db typename string (e.g. 'PostGIS') + pass + + @classmethod + def connectionSettingsKey(self): + # return the key used to store the connections in settings + pass + + @classmethod + def connections(self): + # get the list of connections + conn_list = [] + settings = QSettings() + settings.beginGroup( self.connectionSettingsKey() ) + for name in settings.childGroups(): + conn_list.append( createDbPlugin(self.typeName(), name) ) + settings.endGroup() + return conn_list + + +class Item: + def database(self): + return None + + def generalInfo(self): + return [] + + def privilegesDetails(self): + return None + + def spatialInfo(self): + return None + + def runAction(self): + pass + +class Database(Item): + def __init__(self, connection, connector): + self.connection = connection + self.connector = connector + + def __del__(self): + print "Database.__del__", self.connection.connectionName() + self.connection = None + self.connector = None + + def connectionDetails(self): + return [] + + def database(self): + return self + + def schemas(self): + return None + + def tables(self, schema=None): + return None + + + +class DatabaseSubItem(Item): + def __init__(self, db): + self._db = db + + def __del__(self): + print "DatabaseSubItem.__del__", self + self._db = None + + def database(self): + return self._db + + +class Schema(DatabaseSubItem): + def __init__(self, db): + DatabaseSubItem.__init__(self, db) + self.oid = self.name = self.owner = self.perms = None + self.tableCount = 0 + + def __del__(self): + print "Schema.__del__", self.name + + def tables(self): + return self._db.tables(self) + + +class SchemaSubItem(Item): + def __init__(self, schema): + self._schema = schema + + def __del__(self): + print "SchemaSubItem.__del__", self + self._schema = None + + def schema(self): + return self._schema + + +class Table(DatabaseSubItem, SchemaSubItem): + def __init__(self, db, schema=None): + DatabaseSubItem.__init__(self, db) + SchemaSubItem.__init__(self, schema) + self.name = self.isView = self.owner = self.pages = self.geomCol = self.geomType = self.geomDim = self.srid = None + self.rowCount = None + + self._fields = self._indexes = self._triggers = None + + def __del__(self): + print "Table.__del__", self.name + self._db = None + self._schema = None + + def fields(self): + return self._fields + + def indexes(self): + return self._indexes + + def triggers(self): + return self._triggers + + + def runAction(self, action): + if action == "rows/count": + try: + self.rowCount = self._db.connector.getTableRowCount(self.name, self._schema.name if self._schema else None) + self.rowCount = int(self.rowCount) if self.rowCount != None else None + except: + self.rowCount = "Unknown" + + +class TableSubItem: + def __init__(self, table): + self._table = table + + def __del__(self): + print "TableSubItem.__del__", self + self._table = None + + def table(self): + return self._table + + +class TableField(TableSubItem): + def __init__(self, table): + TableSubItem.__init__(self, table) + self.num = self.name = self.dataType = self.notNull = self.default = self.hasDefault = self.primaryKey = None + + +class TableConstraint(TableSubItem): + """ class that represents a constraint of a table (relation) """ + + TypeCheck, TypeForeignKey, TypePrimaryKey, TypeUnique = range(4) + types = { "c" : TypeCheck, "f" : TypeForeignKey, "p" : TypePrimaryKey, "u" : TypeUnique } + + onAction = { "a" : "NO ACTION", "r" : "RESTRICT", "c" : "CASCADE", "n" : "SET NULL", "d" : "SET DEFAULT" } + matchTypes = { "u" : "UNSPECIFIED", "f" : "FULL", "p" : "PARTIAL" } + + def __init__(self, table): + TableSubItem.__init__(self, table) + self._table = table + self.name = self.type = self.columns = None + + +class TableIndex(TableSubItem): + def __init__(self, table): + TableSubItem.__init__(self, table) + self.name = self.columns = self.isUnique = None + diff --git a/db_plugins/postgis/connector.py b/db_plugins/postgis/connector.py index 7058661..619fa3b 100644 --- a/db_plugins/postgis/connector.py +++ b/db_plugins/postgis/connector.py @@ -23,7 +23,9 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -from ...db_plugins import DBConnector, DbError +from ..connector import DBConnector, SqlTableModel +from ..plugin import ConnectionError, DbError + import psycopg2 class PostGisDBConnector(DBConnector): @@ -40,11 +42,11 @@ def __init__(self, uri): self.dbname = self.user try: - self.con = psycopg2.connect( self.__connectionInfo() ) + self.connection = psycopg2.connect( self.__connectionInfo() ) except psycopg2.OperationalError, e: - raise DbError(e) + raise ConnectionError(e) - self.has_spatial = self.__checkSpatial() + self.__checkSpatial() self.__checkGeometryColumnsTable() # a counter to ensure that the cursor will be unique @@ -62,24 +64,27 @@ def __connectionInfo(self): def __checkSpatial(self): """ check whether postgis_version is present in catalog """ - c = self.con.cursor() - self._exec_sql(c, "SELECT COUNT(*) FROM pg_proc WHERE proname = 'postgis_version'") - return (c.fetchone()[0] > 0) + c = self.connection.cursor() + self._exec_sql(c, u"SELECT COUNT(*) FROM pg_proc WHERE proname = 'postgis_version'") + self.has_spatial = c.fetchone()[0] > 0 + return self.has_spatial def __checkGeometryColumnsTable(self): - c = self.con.cursor() - self._exec_sql(c, "SELECT relname FROM pg_class WHERE relname = 'geometry_columns' AND pg_class.relkind IN ('v', 'r')") + c = self.connection.cursor() + self._exec_sql(c, u"SELECT relname FROM pg_class WHERE relname = 'geometry_columns' AND pg_class.relkind IN ('v', 'r')") self.has_geometry_columns = (len(c.fetchall()) != 0) if not self.has_geometry_columns: self.has_geometry_columns_access = False - return - - # find out whether has privileges to access geometry_columns table - self.has_geometry_columns_access = self.getTablePrivileges('geometry_columns')[0] + else: + # find out whether has privileges to access geometry_columns table + self.has_geometry_columns_access = self.getTablePrivileges('geometry_columns')[0] + return self.has_geometry_columns def getInfo(self): - return "" + c = self.connection.cursor() + self._exec_sql(c, u"SELECT version()") + return c.fetchone() def getSpatialInfo(self): """ returns tuple about postgis support: @@ -90,45 +95,43 @@ def getSpatialInfo(self): - proj version - whether uses stats """ - c = self.con.cursor() - self._exec_sql(c, "SELECT postgis_lib_version(), postgis_scripts_installed(), postgis_scripts_released(), postgis_geos_version(), postgis_proj_version(), postgis_uses_stats()") + c = self.connection.cursor() + self._exec_sql(c, u"SELECT postgis_lib_version(), postgis_scripts_installed(), postgis_scripts_released(), postgis_geos_version(), postgis_proj_version(), postgis_uses_stats()") return c.fetchone() def getDatabasePrivileges(self): """ db privileges: (can create schemas, can create temp. tables) """ - sql = "SELECT has_database_privilege('%(d)s', 'CREATE'), has_database_privilege('%(d)s', 'TEMP')" % { 'd' : self.quoteString(self.dbname) } - c = self.con.cursor() + sql = u"SELECT has_database_privilege(%(d)s, 'CREATE'), has_database_privilege(%(d)s, 'TEMP')" % { 'd' : self.quoteString(self.dbname) } + c = self.connection.cursor() self._exec_sql(c, sql) return c.fetchone() def getSchemaPrivileges(self, schema): """ schema privileges: (can create new objects, can access objects in schema) """ - sql = "SELECT has_schema_privilege('%(s)s', 'CREATE'), has_schema_privilege('%(s)s', 'USAGE')" % { 's' : self.quoteString(schema) } - c = self.con.cursor() + sql = u"SELECT has_schema_privilege(%(s)s, 'CREATE'), has_schema_privilege(%(s)s, 'USAGE')" % { 's' : self.quoteString(schema) } + c = self.connection.cursor() self._exec_sql(c, sql) return c.fetchone() def getTablePrivileges(self, table, schema=None): """ table privileges: (select, insert, update, delete) """ t = self.quoteId( (schema,table) ) - sql = """SELECT has_table_privilege('%(t)s', 'SELECT'), has_table_privilege('%(t)s', 'INSERT'), - has_table_privilege('%(t)s', 'UPDATE'), has_table_privilege('%(t)s', 'DELETE')""" % { 't': self.quoteString(t) } - c = self.con.cursor() + sql = u"""SELECT has_table_privilege(%(t)s, 'SELECT'), has_table_privilege(%(t)s, 'INSERT'), + has_table_privilege(%(t)s, 'UPDATE'), has_table_privilege(%(t)s, 'DELETE')""" % { 't': self.quoteString(t) } + c = self.connection.cursor() self._exec_sql(c, sql) return c.fetchone() - def schemas(self): + def getSchemas(self): """ get list of schemas in tuples: (oid, name, owner, perms) """ - c = self.con.cursor() - sql = "SELECT oid, nspname, pg_get_userbyid(nspowner), nspacl FROM pg_namespace WHERE nspname !~ '^pg_' AND nspname != 'information_schema'" + c = self.connection.cursor() + sql = u"SELECT oid, nspname, pg_get_userbyid(nspowner), nspacl FROM pg_namespace WHERE nspname !~ '^pg_' AND nspname != 'information_schema' ORDER BY nspname" self._exec_sql(c, sql) + return c.fetchall() - schema_cmp = lambda x,y: cmp(unicode(x[1]).lower(), unicode(y[1]).lower()) - return map(lambda x: Schema(x), sorted(c.fetchall(), cmp=schema_cmp)) - - def tables(self, schema=None): + def getTables(self, schema=None): """ get list of tables with schemas, whether user has privileges, whether table has geometry column(s) etc. @@ -140,25 +143,25 @@ def tables(self, schema=None): - srid - type """ - c = self.con.cursor() + c = self.connection.cursor() if schema: - schema_where = " AND nspname = '%s' " % self.quoteString(schema) + schema_where = u" AND nspname = %s " % self.quoteString(schema) else: - schema_where = " AND (nspname != 'information_schema' AND nspname !~ 'pg_') " + schema_where = u" AND (nspname != 'information_schema' AND nspname !~ 'pg_') " # LEFT OUTER JOIN: like LEFT JOIN but if there are more matches, for join, all are used (not only one) # first find out whether postgis is enabled if not self.has_spatial: # get all tables and views - sql = """SELECT pg_class.relname, pg_namespace.nspname, pg_class.relkind = 'v', pg_get_userbyid(relowner), reltuples, relpages, NULL, NULL, NULL, NULL + sql = u"""SELECT pg_class.relname, pg_namespace.nspname, pg_class.relkind = 'v', pg_get_userbyid(relowner), reltuples, relpages, NULL, NULL, NULL, NULL FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace WHERE pg_class.relkind IN ('v', 'r')""" + schema_where + "ORDER BY nspname, relname" else: # discovery of all tables and whether they contain a geometry column - sql = """SELECT pg_class.relname, pg_namespace.nspname, pg_class.relkind, pg_get_userbyid(relowner), reltuples, relpages, pg_attribute.attname, pg_attribute.atttypid::regtype, NULL, NULL + sql = u"""SELECT pg_class.relname, pg_namespace.nspname, pg_class.relkind = 'v', pg_get_userbyid(relowner), reltuples, relpages, pg_attribute.attname, pg_attribute.atttypid::regtype, NULL, NULL FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace LEFT OUTER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid AND @@ -171,7 +174,7 @@ def tables(self, schema=None): # get geometry info from geometry_columns if exists if self.has_spatial and self.has_geometry_columns and self.has_geometry_columns_access: - sql = """SELECT relname, nspname, relkind, pg_get_userbyid(relowner), reltuples, relpages, + sql = u"""SELECT relname, nspname, relkind = 'v', pg_get_userbyid(relowner), reltuples, relpages, geometry_columns.f_geometry_column, geometry_columns.type, geometry_columns.coord_dimension, geometry_columns.srid FROM pg_class JOIN pg_namespace ON relnamespace=pg_namespace.oid @@ -184,29 +187,174 @@ def tables(self, schema=None): if geo_item[7]: items[i] = geo_item - return map(lambda x: Table(x), items) + return items + + def getTableRowCount(self, table, schema=None): + c = self.connection.cursor() + table_name = self.quoteId( (schema, table) ) if schema != None else self.quoteId( table ) + self._exec_sql( c, u"SELECT COUNT(*) FROM %s" % table_name ) + return c.fetchone()[0] + + def getTableFields(self, table, schema=None): + """ return list of columns in table """ + c = self.connection.cursor() + schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema != None else "" + sql = u"""SELECT a.attnum AS ordinal_position, + a.attname AS column_name, + t.typname AS data_type, + a.attlen AS char_max_len, + a.atttypmod AS modifier, + a.attnotnull AS notnull, + a.atthasdef AS hasdefault, + adef.adsrc AS default_value + FROM pg_class c + JOIN pg_attribute a ON a.attrelid = c.oid + JOIN pg_type t ON a.atttypid = t.oid + JOIN pg_namespace nsp ON c.relnamespace = nsp.oid + LEFT JOIN pg_attrdef adef ON adef.adrelid = a.attrelid AND adef.adnum = a.attnum + WHERE + a.attnum > 0 AND c.relname=%s %s + ORDER BY a.attnum""" % (self.quoteString(table), schema_where) + + self._exec_sql(c, sql) + return c.fetchall() + + def getTableIndexes(self, table, schema=None): + """ get info about table's indexes. ignore primary key constraint index, they get listed in constaints """ + schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else "" + sql = u"""SELECT relname, indkey, indisunique = 't' + FROM pg_index JOIN pg_class ON pg_index.indrelid=pg_class.oid + JOIN pg_namespace nsp ON pg_class.relnamespace = nsp.oid + WHERE pg_class.relname=%s %s + AND indisprimary != 't' """ % (self.quoteString(table), schema_where) + c = self.connection.cursor() + self._exec_sql(c, sql) + return c.fetchall() + + + def getTableConstraints(self, table, schema=None): + c = self.connection.cursor() + + schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else "" + sql = u"""SELECT c.conname, c.contype, c.condeferrable, c.condeferred, array_to_string(c.conkey, ' '), c.consrc, + t2.relname, c.confupdtype, c.confdeltype, c.confmatchtype, array_to_string(c.confkey, ' ') FROM pg_constraint c + LEFT JOIN pg_class t ON c.conrelid = t.oid + LEFT JOIN pg_class t2 ON c.confrelid = t2.oid + JOIN pg_namespace nsp ON t.relnamespace = nsp.oid + WHERE t.relname = %s %s """ % (self.quoteString(table), schema_where) + + self._exec_sql(c, sql) + return c.fetchall() + + + def getTableTriggers(self, table, schema=None): + c = self.connection.cursor() + + schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else "" + sql = u"""SELECT tgname, proname, tgtype, tgenabled FROM pg_trigger trig + LEFT JOIN pg_class t ON trig.tgrelid = t.oid + LEFT JOIN pg_proc p ON trig.tgfoid = p.oid + JOIN pg_namespace nsp ON t.relnamespace = nsp.oid + WHERE t.relname = %s %s """ % (self.quoteString(table), schema_where) + + self._exec_sql(c, sql) + + triggers = [] + for row in c.fetchall(): + triggers.append(TableTrigger(row)) + return triggers + + + def getTableRules(self, table, schema=None): + c = self.connection.cursor() + + schema_where = u" AND schemaname=%s " % self.quoteString(schema) if schema is not None else "" + sql = u"""SELECT rulename, definition FROM pg_rules + WHERE tablename=%s %s """ % (self.quoteString(table), schema_where) + + self._exec_sql(c, sql) + return c.fetchall() + + + def getTableEstimatedExtent(self, geom, table, schema=None): + """ find out estimated extent (from the statistics) """ + try: + c = self.connection.cursor() + extent = u"estimated_extent(%s,%s,%s)" % (self.quoteString(schema), self.quoteString(table), self.quoteString(geom)) + sql = u"""SELECT xmin(%(ext)s), ymin(%(ext)s), xmax(%(ext)s), ymax(%(ext)s) """ % { 'ext' : extent } + self._exec_sql(c, sql) + return c.fetchone() + except DbError, e: + return + + def getViewDefinition(self, view, schema=None): + """ returns definition of the view """ + schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else "" + sql = u"""SELECT pg_get_viewdef(c.oid) FROM pg_class c + JOIN pg_namespace nsp ON c.relnamespace = nsp.oid + WHERE relname=%s %s AND relkind='v' """ % (self.quoteString(view), schema_where) + c = self.connection.cursor() + self._exec_sql(c, sql) + return c.fetchone()[0] + + def getSpatialRefInfo(self, srid): + if not self.has_spatial: + return + + try: + c = self.connection.cursor() + self._exec_sql(c, "SELECT srtext FROM spatial_ref_sys WHERE srid = '%d'" % srid) + sr = c.fetchone() + if sr != None: + return + srtext = sr[0] + # try to extract just SR name (should be quoted in double quotes) + regex = QRegExp( '"([^"]+)"' ) + if regex.indexIn( srtext ) > -1: + srtext = regex.cap(1) + return srtext + except DbError, e: + return def _exec_sql(self, cursor, sql): try: - cursor.execute(sql) + cursor.execute(unicode(sql)) except psycopg2.Error, e: # do the rollback to avoid a "current transaction aborted, commands ignored" errors - self.con.rollback() + self.connection.rollback() raise DbError(e) def _exec_sql_and_commit(self, sql): """ tries to execute and commit some action, on error it rolls back the change """ - c = self.con.cursor() + c = self.connection.cursor() self._exec_sql(c, sql) - self.con.commit() - + self.connection.commit() -class Schema: - def __init__(self, row): - self.oid, self.name, self.owner, self.perms = row + def getSqlTableModel(self, sql, parent): + try: + c = self.connection.cursor() + t = QTime() + t.start() + self._exec_sql(c, sql) + secs = t.elapsed() / 1000.0 + model = PGSqlTableModel(c, parent) + rowcount = c.rowcount + + # commit before closing the cursor to make sure that the changes are stored + self.connection.commit() + c.close() + except: + raise + return (model, secs, rowcount) -class Table: - def __init__(self, row): - self.name, self.schema, self.isView, self.owner, self.tuples, self.pages, self.geomCol, self.geomType, self.geomDim, self.srid = row +class PGSqlTableModel(SqlTableModel): + def __init__(self, cursor, parent=None): + SqlTableModel.__init__(self, parent) + try: + resdata = cursor.fetchall() + self.header = map(lambda x: x[0], cursor.description) + self.resdata = resdata + except psycopg2.Error, e: + pass # nothing to fetch! diff --git a/db_plugins/postgis/plugin.py b/db_plugins/postgis/plugin.py index 64a4812..721f8f1 100644 --- a/db_plugins/postgis/plugin.py +++ b/db_plugins/postgis/plugin.py @@ -23,7 +23,7 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -from ...db_plugins import * +from ..plugin import * try: from . import resources_rc except ImportError: @@ -75,5 +75,230 @@ def connect(self, parent=None): from .connector import PostGisDBConnector uri = qgis.core.QgsDataSourceURI() uri.setConnection(host, port, database, username, password) - self.connector = PostGisDBConnector(uri) + self.db = PGDatabase( self, PostGisDBConnector(uri) ) return True + + +class PGDatabase(Database): + def __init__(self, connection, connector): + Database.__init__(self, connection, connector) + + def generalInfo(self): + info = self.connector.getInfo() + return [ + ("Server version: ", info[0]) + ] + + def connectionDetails(self): + return [ + ("Host:", self.connector.host), + ("User:", self.connector.user) + ] + + def spatialInfo(self): + info = self.connector.getSpatialInfo() + ret = [ + ("Library:", info[0]), + ("Scripts:", info[1]), + ("GEOS:", info[3]), + ("Proj:", info[4]), + ("Use stats:", info[5]) + ] + + if info[1] != None and info[1] != info[2]: + ret.append( u"\n Version of installed scripts doesn't match version of released scripts!\n" \ + "This is probably a result of incorrect PostGIS upgrade." ) + + if not self.connector.has_geometry_columns: + ret.append( u"\n geometry_columns table doesn't exist!\n" \ + "This table is essential for many GIS applications for enumeration of tables." ) + elif not self.connector.has_geometry_columns_access: + ret.append( u"\n This user doesn't have privileges to read contents of geometry_columns table!\n" \ + "This table is essential for many GIS applications for enumeration of tables." ) + + return ret + + def privilegesDetails(self): + details = self.connector.getDatabasePrivileges() + ret = [] + if details[0]: ret.append("create new schemas") + if details[1]: ret.append("create temporary tables") + return ret + + + def schemas(self): + return map(lambda x: PGSchema(x, self), self.connector.getSchemas()) + + def tables(self, schema=None): + return map(lambda x: PGTable(x, self, schema), self.connector.getTables(schema.name)) + + +class PGSchema(Schema): + def __init__(self, row, db): + Schema.__init__(self, db) + self.oid, self.name, self.owner, self.perms = row + self.tableCount = len(self.tables()) + + def generalInfo(self): + info = [ + ("Tables:", self.tableCount) + ] + if self.owner: info.append( ("Owner", self.owner) ) + return info + + def privilegesDetails(self): + details = self._db.connector.getSchemaPrivileges(self.name) + ret = [] + if details[0]: ret.append("create new objects") + if details[1]: ret.append("access objects") + return ret + +class PGTable(Table): + def __init__(self, row, db, schema=None): + Table.__init__(self, db, schema) + self.name, schema_name, self.isView, self.owner, self.estimatedRowCount, self.pages, self.geomColumn, self.geomType, self.geomDim, self.srid = row + self.estimatedRowCount = int(self.estimatedRowCount) + self._constraints = self._rules = None + + def generalInfo(self): + # if the estimation is less than 100 rows, try to count them - it shouldn't take long time + if self.rowCount == None and self.estimatedRowCount < 100: + self.runAction("rows/count") + + ret = [ + ("Relation type:", "View" if self.isView else "Table"), + ("Owner:", self.owner), + ("Pages:", self.pages), + ("Rows (estimation):", self.estimatedRowCount ) + ] + + if self.rowCount == None or (isinstance(self.rowCount, int) and self.rowCount >= 0): + ret.append( ("Rows (counted):", self.rowCount if self.rowCount != None else 'Unknown (find out)') ) + + # privileges + schema_priv = self._schema.privilegesDetails() if self._schema else None + # has the user access to this schema? + if schema_priv == None: + pass + elif len(schema_priv) <= 0: + priv_string += " This user doesn't have usage privileges for this schema!" + else: + table_priv = self._db.connector.getTablePrivileges(self.name, self._schema.name if self._schema else None) + privileges = [] + if table_priv[0]: privileges.append("select") + if table_priv[1]: privileges.append("insert") + if table_priv[2]: privileges.append("update") + if table_priv[3]: privileges.append("delete") + priv_string = u", ".join(privileges) if len(privileges) > 0 else u' This user has no privileges!' + ret.append( ("Privileges:", priv_string ) ) + + if table_priv[0] and not table_priv[1] and not table_priv[2] and not table_priv[3]: + ret.append( (u'\n This user has read-only privileges.') ) + + + if not self.isView: + if self.rowCount != None and (self.estimatedRowCount > 2 * self.rowCount or self.estimatedRowCount * 2 < self.rowCount): + ret.append( (u"\n There's a significant difference between estimated and real row count. \n" \ + "Consider running VACUUM ANALYZE.") ) + + if len( filter(lambda fld: fld.primaryKey, self.fields()) ) <= 0: + ret.append( (u"\n No primary key defined for this table!") ) + + return ret + + def spatialInfo(self): + if self.geomType == None: + return [] + + ret = [ + ("Column:", self.geomColumn), + ("Geometry:", self.geomType) + ] + + if self.geomDim: # only if we have info from geometry_columns + ret.append( ("Dimension:", self.geomDim) ) + sr_info = self._db.connector.getSpatialRefInfo(self.srid) if self.srid != -1 else "Undefined" + if sr_info: ret.append( ("Spatial ref:", "%s (%d)" % (sr_info, self.srid)) ) + + if not self.isView: + # estimated extent + extent = self._db.connector.getTableEstimatedExtent(self.geomColumn, self.name, self.schema().name if self.schema() else None) + if extent != None and extent[0] != None: + extent = '%.5f, %.5f - %.5f, %.5f' % extent + else: + extent = '(unknown)' + ret.append( ("Extent:", extent) ) + + if self.geomType.lower() == 'geometry': + ret.append( u"\nThere isn't entry in geometry_columns!" ) + + if not self.isView: + # find out whether the geometry column has spatial index on it + has_spatial_index = False + for fld in self.fields(): + if fld.name == self.geomColumn: + for idx in self.indexes(): + if fld.num in idx.columns: + has_spatial_index = True + break + break + + if not has_spatial_index: + ret.append( u'\nNo spatial index defined.' ) + + return ret + + def fieldsDetails(self): + pass + + + def fields(self): + if self._fields == None: + self._fields = map(lambda x: PGTableField(x, self), self._db.connector.getTableFields(self.name, self.schema().name if self.schema() else None)) + return self._fields + + def constraints(self): + if self._constraints == None: + self._constraints = map(lambda x: PGTableConstraint(x, self), self._db.connector.getTableConstraints(self.name, self.schema().name if self.schema() else None)) + return self._constraints + + def indexes(self): + if self._indexes == None: + self._indexes = map(lambda x: PGTableIndex(x, self), self._db.connector.getTableIndexes(self.name, self.schema().name if self.schema() else None)) + return self._indexes + + +class PGTableField(TableField): + def __init__(self, row, table): + TableField.__init__(self, table) + self.num, self.name, self.dataType, self.charMaxLen, self.modifier, self.notNull, self.hasDefault, self.default = row + self.primaryKey = False + + # find out whether fields are part of primary key + for con in self._table.constraints(): + if con.type == PGTableConstraint.TypePrimaryKey and self.num in con.columns: + self.primaryKey = True + break + +class PGTableConstraint(TableConstraint): + def __init__(self, row, table): + TableConstraint.__init__(self, table) + self.name, constr_type, self.isDefferable, self.isDeffered, columns = row[:5] + self.columns = map(int, columns.split(' ')) + self.type = TableConstraint.types[constr_type] # convert to enum + + if self.type == TableConstraint.TypeCheck: + self.checkSource = row[5] + elif self.type == TableConstraint.TypeForeignKey: + self.foreignTable = row[6] + self.foreignOnUpdate = TableConstraint.onAction[row[7]] + self.foreignOnDelete = TableConstraint.onAction[row[8]] + self.foreignMatchType = TableConstraint.matchTypes[row[9]] + self.foreignKeys = row[10] + +class PGTableIndex(TableIndex): + def __init__(self, row, table): + TableIndex.__init__(self, table) + self.name, columns, self.isUnique = row + self.columns = map(int, columns.split(' ')) + diff --git a/db_plugins/spatialite/connector.py b/db_plugins/spatialite/connector.py index 7e20bd1..6d7d8c0 100644 --- a/db_plugins/spatialite/connector.py +++ b/db_plugins/spatialite/connector.py @@ -23,20 +23,26 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -from ...db_plugins import DBConnector, DbError +from ..connector import DBConnector, SqlTableModel +from ..plugin import ConnectionError, DbError + from pyspatialite import dbapi2 as sqlite +def classFactory(): + return SpatiaLiteDBConnector + class SpatiaLiteDBConnector(DBConnector): def __init__(self, uri): DBConnector.__init__(self, uri) self.dbname = uri.database() try: - self.con = sqlite.connect( self.__connectionInfo() ) + self.connection = sqlite.connect( self.__connectionInfo() ) except sqlite.OperationalError, e: - raise DbError(e) - - self.has_spatial = self.__checkSpatial() + raise ConnectionError(e) + + self.__checkSpatial() + self.__checkGeometryColumnsTable() # a counter to ensure that the cursor will be unique self.last_cursor_id = 0 @@ -46,9 +52,13 @@ def __connectionInfo(self): def __checkSpatial(self): """ check if is a valid spatialite db """ + self.has_spatial = self.__checkGeometryColumnsTable() + return self.has_spatial + + def __checkGeometryColumnsTable(self): try: - c = self.con.cursor() - self._exec_sql(c, "SELECT CheckSpatialMetaData()") + c = self.connection.cursor() + self._exec_sql(c, u"SELECT CheckSpatialMetaData()") self.has_geometry_columns = c.fetchone()[0] == 1 except Exception, e: self.has_geometry_columns = False @@ -57,9 +67,9 @@ def __checkSpatial(self): return self.has_geometry_columns def getInfo(self): - c = self.con.cursor() - self._exec_sql(c, "SELECT sqlite_version()") - return c.fetchone()[0] + c = self.connection.cursor() + self._exec_sql(c, u"SELECT sqlite_version()") + return c.fetchone() def getSpatialInfo(self): """ returns tuple about spatialite support: @@ -67,15 +77,15 @@ def getSpatialInfo(self): - geos version - proj version """ - c = self.con.cursor() - self._exec_sql(c, "SELECT spatialite_version(), NULL, NULL, geos_version(), proj4_version(), NULL") + c = self.connection.cursor() + self._exec_sql(c, u"SELECT spatialite_version(), geos_version(), proj4_version()") return c.fetchone() - def schemas(self): + def getSchemas(self): return None - def tables(self, schema=None): + def getTables(self, schema=None): """ get list of tables, whether table has geometry column(s) etc. @@ -86,11 +96,11 @@ def tables(self, schema=None): - srid - type """ - c = self.con.cursor() + c = self.connection.cursor() sys_tables = ['sqlite_stat1'] # get the R*Tree tables - sql = "SELECT f_table_name, f_geometry_column FROM geometry_columns WHERE spatial_index_enabled = 1" + sql = u"SELECT f_table_name, f_geometry_column FROM geometry_columns WHERE spatial_index_enabled = 1" self._exec_sql(c, sql) for idx_item in c.fetchall(): sys_tables.append( 'idx_%s_%s' % idx_item ) @@ -101,12 +111,12 @@ def tables(self, schema=None): items = [] # get geometry info from geometry_columns if exists if self.has_geometry_columns: - sql = """SELECT m.name, m.type = 'view', g.f_geometry_column, g.type, g.coord_dimension, g.srid + sql = u"""SELECT m.name, m.type = 'view', g.f_geometry_column, g.type, g.coord_dimension, g.srid FROM sqlite_master AS m LEFT JOIN geometry_columns AS g ON lower(m.name) = lower(g.f_table_name) WHERE m.type in ('table', 'view') ORDER BY m.name, g.f_geometry_column""" else: - sql = "SELECT name, type, NULL, NULL, NULL, NULL FROM sqlite_master WHERE type IN ('table', 'view')" + sql = u"SELECT name, type, NULL, NULL, NULL, NULL FROM sqlite_master WHERE type IN ('table', 'view')" self._exec_sql(c, sql) @@ -115,25 +125,111 @@ def tables(self, schema=None): item.append( item[0] in sys_tables ) items.append( item ) - return map(lambda x: Table(x), items) + return items + + + def getTableRowCount(self, table, schema=None): + c = self.connection.cursor() + self._exec_sql(c, u"SELECT COUNT(*) FROM %s" % self.quoteId(table) ) + return c.fetchone()[0] + + def getTableFields(self, table, schema=None): + """ return list of columns in table """ + c = self.connection.cursor() + sql = u"PRAGMA table_info(%s)" % (self.quoteId(table)) + self._exec_sql(c, sql) + return c.fetchall() + + + def getTableIndexes(self, table, schema=None): + """ get info about table's indexes """ + c = self.connection.cursor() + sql = u"PRAGMA index_list(%s)" % (self.quoteId(table)) + self._exec_sql(c, sql) + indexes = c.fetchall() + + for i, idx in enumerate(indexes): + num, name, unique = idx + sql = u"PRAGMA index_info(%s)" % (self.quoteId(name)) + self._exec_sql(c, sql) + + idx = [num, name, unique] + cols = [] + for seq, cid, cname in c.fetchall(): + cols.append(cid) + idx.append(cols) + indexes[i] = idx + + return indexes + + + def getTableTriggers(self, table, schema=None): + c = self.connection.cursor() + sql = u"SELECT name, sql FROM sqlite_master WHERE tbl_name = %s AND type = 'trigger'" % (self.quoteString(table)) + self._exec_sql(c, sql) + return c.fetchall() + + def getTableEstimatedExtent(self, geom, table, schema=None): + """ find out estimated extent (from the statistics) """ + c = self.connection.cursor() + sql = u"""SELECT Min(MbrMinX(%(geom)s)), Min(MbrMinY(%(geom)s)), Max(MbrMaxX(%(geom)s)), Max(MbrMaxY(%(geom)s)) + FROM %(table)s """ % { 'geom' : self.quoteId(geom), 'table' : self.quoteId(table) } + self._exec_sql(c, sql) + return c.fetchone() + + def getViewDefinition(self, view, schema=None): + """ returns definition of the view """ + sql = u"SELECT sql FROM sqlite_master WHERE type = 'view' AND name = %s" % (self.quoteString(view)) + c = self.connection.cursor() + self._exec_sql(c, sql) + return c.fetchone()[0] + + def getSpatialRefInfo(self, srid): + c = self.connection.cursor() + self._exec_sql(c, u"SELECT ref_sys_name FROM spatial_ref_sys WHERE srid = %s" % self.quoteString(srid)) + return c.fetchone()[0] def _exec_sql(self, cursor, sql): try: - cursor.execute(sql) + cursor.execute(unicode(sql)) except sqlite.Error, e: # do the rollback to avoid a "current transaction aborted, commands ignored" errors - self.con.rollback() + self.connection.rollback() raise DbError(e) def _exec_sql_and_commit(self, sql): """ tries to execute and commit some action, on error it rolls back the change """ - c = self.con.cursor() + c = self.connection.cursor() self._exec_sql(c, sql) - self.con.commit() + self.connection.commit() + -class Table: - def __init__(self, row): - self.name, self.isView, self.geomCol, self.geomType, self.geomDim, self.srid, self.sysTable = row - self.schema = self.owner = self.tuples = self.pages = None + def getSqlTableModel(self, sql, parent): + try: + c = self.connection.cursor() + t = QTime() + t.start() + self._exec_sql(c, sql) + secs = t.elapsed() / 1000.0 + model = SLSqlTableModel(c, parent) + rowcount = c.rowcount + + # commit before closing the cursor to make sure that the changes are stored + self.connection.commit() + c.close() + except: + raise + return (model, secs, rowcount) + +class SLSqlTableModel(SqlTableModel): + def __init__(self, cursor, parent=None): + SqlTableModel.__init__(self, parent) + try: + resdata = cursor.fetchall() + if cursor.description != None: + self.header = map(lambda x: x[0], cursor.description) + self.resdata = resdata + except sqlite.OperationalError, e: + pass # nothing to fetch! diff --git a/db_plugins/spatialite/plugin.py b/db_plugins/spatialite/plugin.py index 020d0af..e838956 100644 --- a/db_plugins/spatialite/plugin.py +++ b/db_plugins/spatialite/plugin.py @@ -23,7 +23,7 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * -from ...db_plugins import * +from ..plugin import * try: from . import resources_rc except ImportError: @@ -66,6 +66,123 @@ def connect(self, parent=None): from .connector import SpatiaLiteDBConnector uri = qgis.core.QgsDataSourceURI() uri.setDatabase(database) - self.connector = SpatiaLiteDBConnector(uri) + self.db = SLDatabase( self, SpatiaLiteDBConnector(uri) ) return True + +class SLDatabase(Database): + def __init__(self, connection, connector): + Database.__init__(self, connection, connector) + + def connectionDetails(self): + return [ + ("Filename:", self.connector.dbname) + ] + + def spatialInfo(self): + info = self.connector.getSpatialInfo() + ret = [ + ("Library:", info[0]), + ("GEOS:", info[1]), + ("Proj:", info[2]) + ] + + if not self.connector.has_geometry_columns: + ret.append( u"\n geometry_columns table doesn't exist! " \ + "This table is essential for many GIS applications for enumeration of tables." ) + + return ret + + def privilegesDetails(self): + return None + + def generalInfo(self): + info = self.connector.getInfo() + return [ + ("SQLite version", info[0]) + ] + + def tables(self, schema=None): + return map(lambda x: SLTable(x, self), self.connector.getTables()) + + +class SLTable(Table): + def __init__(self, row, db, schema=None): + Table.__init__(self, db, None) + self.name, self.isView, self.geomColumn, self.geomType, self.geomDim, self.srid, self.isSysTable = row + + def generalInfo(self): + if self.rowCount == None: + self.runAction("rows/count") + + return [ + ("Relation type:", "View" if self.isView else "Table"), + ("Rows:", self.rowCount) + ] + + def spatialInfo(self): + if self.geomType == None: + return [] + + ret = [ + ("Column:", self.geomColumn), + ("Geometry:", self.geomType) + ] + + if self.geomDim: # only if we have info from geometry_columns + ret.append( ("Dimension:", self.geomDim) ) + sr_info = self._db.connector.getSpatialRefInfo(self.srid) if self.srid != -1 else "Undefined" + if sr_info: ret.append( ("Spatial ref:", "%s (%d)" % (sr_info, self.srid)) ) + + if not self.isView: + # estimated extent + extent = self._db.connector.getTableEstimatedExtent(self.geomColumn, self.name, self.schema().name if self.schema() else None) + if extent != None and extent[0] != None: + extent = '%.5f, %.5f - %.5f, %.5f' % extent + else: + extent = '(unknown)' + ret.append( ("Extent:", extent) ) + + if self.geomType.lower() == 'geometry': + ret.append( u"\nThere isn't entry in geometry_columns!" ) + + if not self.isView: + # find out whether the geometry column has spatial index on it + has_spatial_index = False + for fld in self.fields(): + if fld.name == self.geomColumn: + for idx in self.indexes(): + if fld.num in idx.columns: + has_spatial_index = True + break + break + + if not has_spatial_index: + ret.append( u'\nNo spatial index defined.' ) + + return ret + + def fieldsDetails(self): + pass + + + def fields(self): + return map(lambda x: SLTableField(x, self), self._db.connector.getTableFields(self.name)) + + def indexes(self): + if self._indexes == None: + self._indexes = map(lambda x: SLTableIndex(x, self), self._db.connector.getTableIndexes(self.name)) + return self._indexes + + +class SLTableField(TableField): + def __init__(self, row, table): + TableField.__init__(self, table) + self.num, self.name, self.dataType, self.notNull, self.default, self.primaryKey = row + self.hasDefault = self.default != None + +class SLTableIndex(TableIndex): + def __init__(self, row, table): + TableIndex.__init__(self, table) + self.num, self.name, self.isUnique, self.columns = row + diff --git a/db_tree.py b/db_tree.py index b74cf45..3bf45d9 100644 --- a/db_tree.py +++ b/db_tree.py @@ -28,11 +28,12 @@ class DBTree(QTreeView): def __init__(self, parent=None): QTreeView.__init__(self, parent) - self.setAttribute(Qt.WA_DeleteOnClose) - self.setModel( DBModel() ) + self.setModel( DBModel(self) ) - def refresh(self, selectedItemOnly=False): - self.model().refresh(selectedItemOnly) + self.connect(self.selectionModel(), SIGNAL("currentChanged(const QModelIndex&, const QModelIndex&)"), self.itemChanged) + self.connect(self, SIGNAL("expanded(const QModelIndex&)"), self.itemChanged) + self.connect(self, SIGNAL("collapsed(const QModelIndex&)"), self.itemChanged) + self.connect(self.model(), SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), self.itemChanged) def currentItem(self): indexes = self.selectedIndexes() @@ -40,3 +41,15 @@ def currentItem(self): return return self.model().getItem(indexes[0]) + def currentDatabase(self): + item = self.currentItem() + if item == None: return + try: + return item.database() + except TypeError: + return None + + def itemChanged(self, indexFrom, indexTo=None): + self.setCurrentIndex(indexFrom) + self.emit( SIGNAL('currentChanged'), self.currentItem() ) + diff --git a/dlg_db_error.py b/dlg_db_error.py new file mode 100644 index 0000000..eccec1a --- /dev/null +++ b/dlg_db_error.py @@ -0,0 +1,22 @@ +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from ui.DlgDbError_ui import Ui_DlgDbError + +class DlgDbError(QDialog, Ui_DlgDbError): + + def __init__(self, e, parent=None): + QDialog.__init__(self, parent) + + self.setupUi(self) + + msg = "
" + e.msg.replace('<','<') + "
" + self.txtMessage.setHtml(msg) + if e.query != None: + query = "
" + e.query.replace('<','<') + "
" + self.txtQuery.setHtml(query) + + @staticmethod + def showError(e, parent=None): + dlg = DlgDbError(e, parent) + dlg.exec_() diff --git a/dlg_sql_window.py b/dlg_sql_window.py new file mode 100644 index 0000000..048f997 --- /dev/null +++ b/dlg_sql_window.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from .ui.DlgSqlWindow_ui import Ui_DlgSqlWindow + +from .db_plugins.plugin import DbError +from .dlg_db_error import DlgDbError + +class DlgSqlWindow(QDialog, Ui_DlgSqlWindow): + + def __init__(self, parent=None, db=None): + QDialog.__init__(self, parent) + self.db = db.connector + self.setupUi(self) + + settings = QSettings() + self.restoreGeometry(settings.value("/PostGIS_Manager/sql_geometry").toByteArray()) + + self.connect(self.btnExecute, SIGNAL("clicked()"), self.executeSql) + self.connect(self.btnClear, SIGNAL("clicked()"), self.clearSql) + self.connect(self.buttonBox.button(QDialogButtonBox.Close), SIGNAL("clicked()"), self.close) + + + def closeEvent(self, e): + """ save window state """ + settings = QSettings() + settings.setValue("/PostGIS_Manager/sql_geometry", QVariant(self.saveGeometry())) + + QDialog.closeEvent(self, e) + + def clearSql(self): + self.editSql.setPlainText(QString()) + + def executeSql(self): + sql = self.editSql.toPlainText() + if sql.isEmpty(): + return + + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + try: + model, secs, rowcount = self.db.getSqlTableModel( sql, self ) + self.viewResult.setModel( model ) + self.update() + self.lblResult.setText("%d rows, %.1f seconds" % (rowcount, secs)) + QApplication.restoreOverrideCursor() + + except DbError, e: + QApplication.restoreOverrideCursor() + DlgDbError.showError(e, self) + diff --git a/icons/layer_line.png b/icons/layer_line.png new file mode 100644 index 0000000..34139c7 Binary files /dev/null and b/icons/layer_line.png differ diff --git a/icons/layer_point.png b/icons/layer_point.png new file mode 100644 index 0000000..b400bc2 Binary files /dev/null and b/icons/layer_point.png differ diff --git a/icons/layer_polygon.png b/icons/layer_polygon.png new file mode 100644 index 0000000..6757d24 Binary files /dev/null and b/icons/layer_polygon.png differ diff --git a/icons/layer_unknown.png b/icons/layer_unknown.png new file mode 100644 index 0000000..cdf52fb Binary files /dev/null and b/icons/layer_unknown.png differ diff --git a/icons/namespace.png b/icons/namespace.png new file mode 100644 index 0000000..4a94238 Binary files /dev/null and b/icons/namespace.png differ diff --git a/icons/namespaces.xpm b/icons/namespaces.xpm new file mode 100644 index 0000000..65a34b4 --- /dev/null +++ b/icons/namespaces.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static char * namespaces_xpm[] = { +"16 16 15 1", +" c None", +". c #D89494", +"+ c #BD4949", +"@ c #FF8D8D", +"# c #FF8888", +"$ c #FF8383", +"% c #FFFFFF", +"& c #C86868", +"* c #FF7D7D", +"= c #D85E5E", +"- c #FF7676", +"; c #FF6F6F", +"> c #FF6868", +", c #FF6060", +"' c #FF5C5C", +" .+. ", +" .+@+. ", +" .+#+#+. ", +" .+$+%+$+&+. ", +".+*+%+%+=+@+. ", +"+-+%+++%+#+#+. ", +".+;++@++$+%+$+. ", +" .++#++*+%+%+*+.", +" .+$++-+%+-+%+-+", +".+*+%++;+%+%+;+.", +"+-+%+-++>+%+>+. ", +".+;+%+%++,+,+. ", +" .+>+%+>++'+. ", +" .+,+,+..+. ", +" .+'+. ", +" .+. "}; diff --git a/icons/rt_sql-layer.png b/icons/rt_sql-layer.png new file mode 100644 index 0000000..1d6170e Binary files /dev/null and b/icons/rt_sql-layer.png differ diff --git a/icons/table.png b/icons/table.png new file mode 100644 index 0000000..cdde7bf Binary files /dev/null and b/icons/table.png differ diff --git a/icons/tables.xpm b/icons/tables.xpm new file mode 100644 index 0000000..cfb4e29 --- /dev/null +++ b/icons/tables.xpm @@ -0,0 +1,82 @@ +/* XPM */ +static char * tables_xpm[] = { +"16 16 63 1", +" c None", +". c #2195E7", +"+ c #8ACEFE", +"@ c #94CFF9", +"# c #ADD5F2", +"$ c #CADCEA", +"% c #DEE3E7", +"& c #E6E7E7", +"* c #E6E6E6", +"= c #C5D8E6", +"- c #76B9E8", +"; c #309CE8", +"> c #88CDFE", +", c #52B0F2", +"' c #B3D5ED", +") c #DDDDDD", +"! c #83CBFE", +"~ c #7AC6FB", +"{ c #6FC0F9", +"] c #63B9F6", +"^ c #56B2F3", +"/ c #49ABF0", +"( c #3DA5ED", +"_ c #319EEB", +": c #2799E9", +"< c #DEDEDE", +"[ c #83CBFD", +"} c #4AABF0", +"| c #3DA4ED", +"1 c #2899E9", +"2 c #DFDFDF", +"3 c #E2E2E2", +"4 c #E3E3E3", +"5 c #E5E5E5", +"6 c #87C0E7", +"7 c #E0E0E0", +"8 c #A7A7A7", +"9 c #ACACAC", +"0 c #ECECEC", +"a c #EEEEEE", +"b c #E9E9E9", +"c c #E1E1E1", +"d c #A6A6A6", +"e c #A8A8A8", +"f c #ADADAD", +"g c #AFAFAF", +"h c #EAEAEA", +"i c #90CAF3", +"j c #E7E7E7", +"k c #EBEBEB", +"l c #E8E8E8", +"m c #A9A9A9", +"n c #EFEFEF", +"o c #F1F1F1", +"p c #EDEDED", +"q c #AAAAAA", +"r c #B0B0B0", +"s c #B2B2B2", +"t c #E4E4E4", +"u c #F0F0F0", +"v c #7BC6FB", +"w c #6FC0F8", +"x c #2899E8", +"........... ", +".+@#$%&**=-; ", +".>,.......... ", +".>.+@#$%&**=-; ", +".'.>,.......... ", +".).>.+@#$%&**=-;", +".).'.>!~{]^/(_:.", +".<.).>[~{]^}|_1.", +".2.).'))<2345*6.", +".7.<.)**87490ab.", +".c.2.)d8ec59fgh.", +"ii.7.<27c3*jbhk.", +" .c.2lbm4jgnop.", +" ii.7mmq5bgrsa.", +" .c3t5*k0pau.", +" i>!vw]^}|_x."}; diff --git a/icons/toolbar/action_del_table.png b/icons/toolbar/action_del_table.png new file mode 100644 index 0000000..9191a21 Binary files /dev/null and b/icons/toolbar/action_del_table.png differ diff --git a/icons/toolbar/action_edit_table.png b/icons/toolbar/action_edit_table.png new file mode 100644 index 0000000..77032b0 Binary files /dev/null and b/icons/toolbar/action_edit_table.png differ diff --git a/icons/toolbar/action_export.png b/icons/toolbar/action_export.png new file mode 100644 index 0000000..2299cbb Binary files /dev/null and b/icons/toolbar/action_export.png differ diff --git a/icons/toolbar/action_import.png b/icons/toolbar/action_import.png new file mode 100644 index 0000000..1eeaf74 Binary files /dev/null and b/icons/toolbar/action_import.png differ diff --git a/icons/toolbar/action_new_table.png b/icons/toolbar/action_new_table.png new file mode 100644 index 0000000..04f8367 Binary files /dev/null and b/icons/toolbar/action_new_table.png differ diff --git a/icons/toolbar/action_refresh.png b/icons/toolbar/action_refresh.png new file mode 100644 index 0000000..cab4d02 Binary files /dev/null and b/icons/toolbar/action_refresh.png differ diff --git a/icons/toolbar/action_sql_window.png b/icons/toolbar/action_sql_window.png new file mode 100644 index 0000000..a5ad728 Binary files /dev/null and b/icons/toolbar/action_sql_window.png differ diff --git a/icons/user.xpm b/icons/user.xpm new file mode 100644 index 0000000..a9cae23 --- /dev/null +++ b/icons/user.xpm @@ -0,0 +1,88 @@ +/* XPM */ +static char * user_xpm[] = { +"16 16 69 1", +" c None", +". c #999999", +"+ c #6A6A6A", +"@ c #BDBDBD", +"# c #7E7A77", +"$ c #B7AEA7", +"% c #E4D8CE", +"& c #E4D8D0", +"* c #B6AEAA", +"= c #7E7A79", +"- c #D7CCC3", +"; c #F8EADF", +"> c #F8EAE1", +", c #F7EAE2", +"' c #F7EAE4", +") c #D7CCC9", +"! c #7E7A7A", +"~ c #F7EAE6", +"{ c #F7EAE8", +"] c #B6AEAE", +"^ c #F7EAEA", +"/ c #E3D8DA", +"( c #F7EAEC", +"_ c #E3D8DB", +": c #F7EAEE", +"< c #B6AEB1", +"[ c #D6CCD0", +"} c #7D7A7C", +"| c #5B5C5C", +"1 c #5A5C5C", +"2 c #6A6D6D", +"3 c #A6B4B7", +"4 c #B4C5C9", +"5 c #879093", +"6 c #646768", +"7 c #636768", +"8 c #838E93", +"9 c #A8BFCA", +"0 c #99ADB7", +"a c #656B6D", +"b c #5A5A5A", +"c c #A3B0B3", +"d c #D4EAF0", +"e c #D1E9F0", +"f c #CEE7F0", +"g c #CBE6F1", +"h c #C7E4F1", +"i c #C4E3F1", +"j c #C1E1F1", +"k c #BDE0F1", +"l c #92A8B4", +"m c #585A5B", +"n c #838A8C", +"o c #BADEF2", +"p c #B7DDF2", +"q c #77858C", +"r c #949494", +"s c #A5B3B7", +"t c #B4DCF2", +"u c #90AAB8", +"v c #6E6E6E", +"w c #BFD3D9", +"x c #B2DBF2", +"y c #A3C6DB", +"z c #585858", +"A c #CCE5EE", +"B c #B1DAF2", +"C c #B0D8F0", +"D c #555555", +" .++. ", +" @#$%&*=@ ", +" #-;>,')! ", +" .$;>,'~{]. ", +" +%>,'~{^/+ ", +" +&,'~{^(_+ ", +" .*'~{^(:<. ", +" =){^(:[} ", +" |!]/_<}1 ", +" 234567890a ", +" bcdefghijklm ", +" ndefghijkopq ", +" rsefghijkoptur ", +" vwfghijkoptxyv ", +" zAghijkoptxBCz ", +" DzDDDDDDDDDDzD "}; diff --git a/icons/users.xpm b/icons/users.xpm new file mode 100644 index 0000000..d398175 --- /dev/null +++ b/icons/users.xpm @@ -0,0 +1,64 @@ +/* XPM */ +static char * users_xpm[] = { +"16 16 45 1", +" c None", +". c #C5C5C5", +"+ c #7F7F7F", +"@ c #8B8782", +"# c #D0C5BC", +"$ c #D0C5BE", +"% c #8B8785", +"& c #F8EAE1", +"* c #F7EAE4", +"= c #CFC5C4", +"- c #F7EAE8", +"; c #CFC5C7", +"> c #BFBFBF", +", c #8B8788", +"' c #5B5C5C", +") c #7D8384", +"! c #6F7374", +"~ c #6E7374", +"{ c #798184", +"] c #5A5C5C", +"^ c #B7B7B7", +"/ c #8C9597", +"( c #D4EAF0", +"_ c #D0E8F0", +": c #CAE6F1", +"< c #C4E3F1", +"[ c #727C80", +"} c #6D6D6D", +"| c #9B9B9B", +"1 c #808080", +"2 c #B4C4C8", +"3 c #9AB1BC", +"4 c #5B5B5B", +"5 c #CCE3EB", +"6 c #BEE0F1", +"7 c #6D777C", +"8 c #747A7B", +"9 c #819097", +"0 c #A1A1A1", +"a c #555555", +"b c #73797B", +"c c #9FBBCA", +"d c #9EB0B7", +"e c #B8DEF2", +"f c #B1D7EC", +" .++. ", +" .@#$%. ", +" +#&*=+ .++. ", +" +$*-;+ .@#$%. ", +" >%=;,> +#&*=+ ", +" ')!~{] +$*-;+ ", +"^/(_:<[}+|%=;,> ", +"12_:<3@#$%!!~{] ", +"45:<67#&*=8_:<9^", +"04aaaa$*-;b:<6c1", +" >%=;,d<6ef4", +" ')!~{]aaa40", +" ^/(_:<9^ ", +" 12_:<6c1 ", +" 45:<6ef4 ", +" 04aaaa40 "}; diff --git a/icons/view.png b/icons/view.png new file mode 100644 index 0000000..bb53117 Binary files /dev/null and b/icons/view.png differ diff --git a/icons/warning-20px.png b/icons/warning-20px.png new file mode 100644 index 0000000..6af93aa Binary files /dev/null and b/icons/warning-20px.png differ diff --git a/info_viewer.py b/info_viewer.py new file mode 100644 index 0000000..b9caa7b --- /dev/null +++ b/info_viewer.py @@ -0,0 +1,454 @@ +# -*- coding: utf-8 -*- + +""" +/*************************************************************************** +Name : DB Manager +Description : Database manager plugin for QuantumGIS +Date : May 23, 2011 +copyright : (C) 2011 by Giuseppe Sucameli +email : brush.tyler@gmail.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from .db_plugins.plugin import * + +class InfoViewer(QTextBrowser): + + def __init__(self, parent=None): + QTextBrowser.__init__(self, parent) + self.connect(self, SIGNAL("anchorClicked(const QUrl&)"), self.__linkClicked) + self.__clear() + + def __del__(self): + print "InfoViewer.__del__" + self.item = None + + def __linkClicked(self, url): + if self.item == None: + return + + if url.scheme() == "action": + self.item.runAction( url.path() ) + self.refresh() + + def refresh(self): + return self.showInfo( self.item ) + + def showInfo(self, item): + self.item = item + if isinstance(item, DBPlugin): + return self.__showDatabaseInfo(item) + elif isinstance(item, Schema): + return self.__showSchemaInfo(item) + elif isinstance(item, Table): + return self.__showTableInfo(item) + return self.__clear() + + def __clear(self): + self.item = None + self.setHtml("") + + def __showDatabaseInfo(self, connection): + html = u'

 %s

' % connection.connectionName() + html += '
' + + db = connection.database() + if db == None: + html += '

Not connected

' + self.setHtml(html) + return + + conn_details = db.connectionDetails() + if conn_details == None or len(conn_details) <= 0: + pass + else: + html += '

Connection details

' + html += '
' + html += self.__convert2Html( conn_details ) + html += '
' + + general_info = db.generalInfo() + if general_info == None or len(general_info) <= 0: + pass + else: + html += '

General info

' + html += '
' + html += self.__convert2Html( general_info ) + html += '
' + + spatial_info = db.spatialInfo() + if spatial_info == None: + pass + else: + html += u'

%s

' % connection.typeNameString() + html += '
' + if len(spatial_info) <= 0: + html += '%s support not enabled!' % connection.typeNameString() + else: + html += self.__convert2Html( spatial_info ) + html += '
' + + priv_details = db.privilegesDetails() + if priv_details == None: + pass + else: + html += '

Privileges

' + html += '
' + if len(priv_details) <= 0: + html += 'This user has no privileges!' + else: + html += "User has privileges:
    " + for row in priv_details: + html += u'
  • %s' % (row) + html += "
" + html += "
" + + self.setHtml(html) + + + def __showSchemaInfo(self, schema): + html = u'

 %s

' % schema.name + html += '
' + + general_info = schema.generalInfo() + if general_info == None or len(general_info) <= 0: + pass + else: + html += '

Schema details

' + html += '
' + html += self.__convert2Html( general_info ) + html += '
' + + priv_details = schema.privilegesDetails() + if priv_details == None: + pass + else: + html += '

Privileges

' + html += '
' + if len(priv_details) <= 0: + html += 'This user has no privileges to access this schema!' + else: + html += "User has privileges:
    " + for row in priv_details: + html += u'
  • %s' % (row) + html += "
" + html += "
" + + self.setHtml(html) + + + def __showTableInfo(self, table): + html = '

 %s

' % table.name + html += '
' + + general_info = table.generalInfo() + if general_info == None or len(general_info) <= 0: + pass + else: + html += '

General info

' + html += '
' + html += self.__convert2Html( general_info ) + html += '
' + + + # permissions + priv_details = table.privilegesDetails() + if priv_details == None: + pass + else: + html += '

Privileges

' + html += '
' + + # has the user access to this schema? + schema_priv = table.schema().privilegesDetails() if table.schema() else None + if schema_priv == None: + pass + else: + if len(schema_priv) <= 0: + html += '
This user doesn\'t have usage privileges for this schema!
' + + if len(priv_details) <= 0: + html += 'This user has no privileges!' + else: + html += "User has privileges:" + html += '
    ' + for row in priv_details: + html += u"
  • %s" % (row) + html += "
" + html += "
" + + # spatial info + spatial_info = table.spatialInfo() + if spatial_info == None: + pass + else: + html += u'

%s

' % table.database().connection.typeNameString() + html += '
' + if len(spatial_info) <= 0: + html += u'This is not a spatial table.' + else: + html += self.__convert2Html( spatial_info ) + html += '
' + + # fields + fields_details = table.fieldsDetails() + if fields_details == None: + pass + else: + if len(fields_details) <= 0: + pass + html += '

Fields

' + html += '
' + html += self.__convert2Html( fields_details ) + html += '
' + + self.setHtml(html) + return + + + html += '' + html += '
# Name Type ' + if self.db.getTypeName() == 'postgis': + html += 'Length' + html += 'Null Default ' + for fld in fields: + is_null_txt = "N" if fld.notnull else "Y" + default = fld.default if fld.hasdefault else "" + if not hasattr(fld, 'modifier') or fld.modifier == -1: + fldtype = fld.data_type + else: fldtype = "%s (%d)" % (fld.data_type, fld.modifier) + + # find out whether it's part of primary key + pk_style = '' + if self.db.getTypeName() == 'postgis': + for con in constraints: + if con.con_type == DbConnection.TableConstraint.TypePrimaryKey and fld.num in con.keys: + pk_style = ' style="text-decoration:underline;"' + break + + elif self.db.getTypeName() == 'spatialite': + if fld.primary_key: + pk_style = ' style="text-decoration:underline;"' + + html += '
%s%s%s' % (fld.num, pk_style, fld.name, fldtype) + if self.db.getTypeName() == 'postgis': + html += '%d' % fld.char_max_len + html += '%s%s' % (is_null_txt, default) + html += " 
" + + + # constraints + constraints_details = table.constraintsDetails() + if constraints_details == None or len(constraints_details) <= 0: + pass + else: + html += '

Constraints

' + html += '
' + html += self.__convert2Html( constraints_details ) + html += '
' + + if self.db.getTypeName() == 'postgis': + if len(constraints) != 0: + html += '
NameTypeColumn(s)' + for con in constraints: + if con.con_type == DbConnection.TableConstraint.TypeCheck: con_type = "Check" + elif con.con_type == DbConnection.TableConstraint.TypePrimaryKey: con_type = "Primary key" + elif con.con_type == DbConnection.TableConstraint.TypeForeignKey: con_type = "Foreign key" + elif con.con_type == DbConnection.TableConstraint.TypeUnique: con_type = "Unique" + keys = "" + for key in con.keys: + if len(keys) != 0: keys += "
" + keys += self._field_name_by_number(key, fields) + html += "%s%s%s" % (con.name, con_type, keys) + html += " 
" + + + # indexes + indexes_details = table.indexesDetails() + if indexes_details == None or len(indexes_details) <= 0: + pass + else: + html += '

Indexes

' + html += '
' + html += self.__convert2Html( indexes_details ) + html += '
' + + if len(indexes) != 0: + html += '

Indexes

' + html += '
NameColumn(s)' + for fld in indexes: + keys = "" + for key in fld.columns: + if len(keys) != 0: keys += "
" + keys += self._field_name_by_number(key, fields) + html += "
%s%s" % (fld.name, keys) + html += " 
" + + + # triggers + triggers_details = table.indexesDetails() + if triggers_details == None or len(triggers_details) <= 0: + pass + else: + html += '

Triggers

' + html += '
' + html += self.__convert2Html( triggers_info ) + html += '
' + + if len(triggers) != 0: + html += '

Triggers

' + html += '
NameFunction' + if self.db.getTypeName() == 'postgis': + html += 'TypeEnabled' + + for trig in triggers: + if self.db.getTypeName() == 'postgis': + trig_type = "Before " if trig.type & DbConnection.TableTrigger.TypeBefore else "After " + if trig.type & DbConnection.TableTrigger.TypeInsert: trig_type += "INSERT " + if trig.type & DbConnection.TableTrigger.TypeUpdate: trig_type += "UPDATE " + if trig.type & DbConnection.TableTrigger.TypeDelete: trig_type += "DELETE " + if trig.type & DbConnection.TableTrigger.TypeTruncate: trig_type += "TRUNCATE " + trig_type += "
for each " + trig_type += "row" if trig.type & DbConnection.TableTrigger.TypeRow else "statement" + if trig.enabled: + txt_enabled = 'Yes (disable)' % trig.name + else: + txt_enabled = 'No (enable)' % trig.name + html += '
%s (delete)%s%s%s' % (trig.name, trig.name, trig.function, trig_type, txt_enabled) + + elif self.db.getTypeName() == 'spatialite': + html += '
%s%s' % (trig.name, trig.function) + + html += " 
" + if self.db.getTypeName() == 'postgis': + html += "Enable all triggers / Disable all triggers" + html += "
" + + + # rules + rules_details = table.rulesDetails() + if rules_details == None or len(rules_details) <= 0: + pass + else: + html += '
' + html += '

Rules

' + html += '
' + html += self.__convert2Html( rules_info ) + html += '
' + + html += '
NameDefinition' + for rule in rules: + html += '
%s (delete)%s' % (rule.name, rule.name, rule.definition) + html += " 
" + + + if table.isView: + html += '
' + html += '

View definition

' + html += '

%s

' % table.getViewDefinition() + html += '
' + + + self.setHtml(html) + #return priv[0] # ability to SELECT? + return True + + + + def setHtml(self, html): + html = unicode(html).replace( '', '   ' ) + html = unicode(html).replace( '', '   ' ) + html = u""" + + + + + + %s + +""" % html + #print ">>>>>\n", html, "\n<<<<<<" + return QTextBrowser.setHtml(self, html) + + + def _field_name_by_number(self, num, fields): + """ return field specified by its number or None if doesn't exist """ + for fld in fields: + if fld.num == num: + return fld.name + return "??? (#%d)" % num + + + def __convertTxt2Html(self, t): + return u"%s" % unicode(t).replace("\n", "
") + + def __convertTable2Html(self, t): + if self.__isString(t) or self.__isNumber(t): + t = [t] + + rows = [] + maxcols = 0 + props = {} + for i, row in enumerate(t): + if i == 0 and isinstance(row, dict): + props = row + else: + rows.append( row ) + maxcols = max(maxcols, len(row)) + + html = u'' + if maxcols == 1: + for row in rows: + html += u'

' % props['p.class'] if props.has_key('p.class') else '

' + html += u'%s

' % self.__convertTxt2Html(row) + + else: + html += u'' % props['table.class'] if props.has_key('table.class') else '
' + for row in rows: + if self.__isString(row) or self.__isNumber(row): + row = [row] + + html += u'' % props['tr.class'] if props.has_key('tr.class') else '' + for i, col in enumerate(row): + if i >= maxcols: + break + elif len(row) > 1 and i == 0: + html += u'
= len(row)-1 and i < maxcols-1: + html += u'' % props['td.class'] if props.has_key('td.class') else '>' + html += u'%s' % self.__convertTxt2Html(col) + + html += '
' + return html + + def __convert2Html(self, t): + if self.__isString(t) or self.__isNumber(t): + return self.__convertTxt2Html(t) + return self.__convertTable2Html(t) + + + def __isString(self, t): + return isinstance(t, str) or isinstance(t, unicode) or isinstance(t, QString) + + def __isNumber(self, t): + return isinstance(t, int) or isinstance(t, float) or isinstance(t, bool) + diff --git a/resources.qrc b/resources.qrc index c4cab16..e66184c 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,5 +1,24 @@ - icons/loading.gif + icons/layer_line.png + icons/layer_point.png + icons/layer_polygon.png + icons/layer_unknown.png + icons/namespace.png + icons/namespaces.xpm + icons/rt_sql-layer.png + icons/table.png + icons/tables.xpm + icons/user.xpm + icons/users.xpm + icons/view.png + icons/warning-20px.png + icons/toolbar/action_del_table.png + icons/toolbar/action_edit_table.png + icons/toolbar/action_export.png + icons/toolbar/action_import.png + icons/toolbar/action_new_table.png + icons/toolbar/action_refresh.png + icons/toolbar/action_sql_window.png diff --git a/resources_rc.py b/resources_rc.py new file mode 100644 index 0000000..1cf3110 --- /dev/null +++ b/resources_rc.py @@ -0,0 +1,1355 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created: Tue Jun 21 01:17:39 2011 +# by: The Resource Compiler for PyQt (Qt v4.7.2) +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore + +qt_resource_data = "\ +\x00\x00\x06\x52\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\ +\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x03\x7e\x00\x00\x03\x7e\ +\x01\x59\x5f\x8a\xa9\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ +\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x05\xcf\x49\x44\ +\x41\x54\x58\x85\xc5\x97\x5d\x6c\x5c\x47\x15\xc7\xff\x67\xe6\x7e\ +\xed\x5d\xef\xae\xed\x6c\xd6\x89\xbd\xac\xdb\x34\x6e\x82\x9b\xd0\ +\x0a\xd2\x1a\x24\x22\x1a\x15\x09\x02\xb4\x11\x79\xa8\x5a\x48\x23\ +\x95\xa8\x42\xf0\xd2\x14\x08\x54\x6a\x11\x12\x15\x88\x37\x10\x50\ +\xa4\x4a\x41\xcd\x43\x1f\x28\x42\x54\xaa\x14\x21\x55\x15\x8a\x22\ +\x82\x9b\x52\x10\x92\x6b\x87\xb4\x6e\x6b\xd7\xae\xbf\xbd\xf6\x7e\ +\xdf\xbd\x73\x67\x0e\x2f\x89\xeb\xb5\x1d\xef\x6e\x22\xc4\x91\xee\ +\xc3\x9d\x8f\xf3\xff\xdd\x33\xe7\xce\x9c\x21\x66\xc6\xff\xd3\xac\ +\x9b\x99\x44\x44\x83\x00\x06\x01\x8c\x31\xf3\xd8\xba\xf6\x2c\x84\ +\x38\x29\x24\xfa\x8c\x36\xcb\x30\x98\x06\x30\xc2\xcc\xc3\x37\xf4\ +\xd5\x2c\x02\x44\xe4\x03\xc8\x01\xe8\x04\x30\x02\xe0\x90\x70\xc4\ +\x79\x7f\xb0\xb3\x52\xbd\x5a\xe8\x10\x52\x4c\x32\x61\x81\x18\x19\ +\x1d\xea\xdb\x53\x9f\xcf\x54\x62\xfd\xbe\xd4\x55\x8d\x70\x3e\x50\ +\xe5\x91\x15\x9b\x6b\xe6\xef\x51\x45\x7d\xb5\x2d\x00\x22\xb2\x2c\ +\x21\x9e\x66\xe6\x1f\x27\xa5\xac\xc6\x84\xd0\x0b\x4a\x75\x20\x26\ +\x2a\x3d\xa7\xf6\xd2\x8e\x87\xb2\x65\x0e\x35\x55\xaf\x14\x9d\xa8\ +\x14\x0a\x2b\x61\x9b\xd8\x40\x32\x14\xbe\xd5\xe0\x90\x23\x43\x57\ +\xbe\x71\x29\x15\xad\x84\x5f\x63\xe6\x8b\x1b\x75\x36\x2d\x01\x11\ +\xdd\xef\x08\x71\xd2\x15\xe2\xc1\x3d\x9e\x27\x7e\x94\xcb\x2d\xf7\ +\x39\x4e\x04\x00\x45\xad\x83\xef\x7e\x30\x9e\x2e\x5e\x5a\xa4\x1d\ +\x0f\x65\xcb\xe4\x48\x8e\xdf\xdd\x55\xdf\x36\x82\x96\xe0\xce\xfb\ +\x7b\xf4\xd2\x2b\x53\x47\x01\x6c\x02\x68\x88\x80\x45\xf4\xb0\x2f\ +\xe5\xd9\xe3\x3b\x77\x46\x43\xc9\x64\x7d\xc0\xf3\xd4\xc6\x09\x55\ +\x63\xc4\xb1\xb1\xd1\xbe\xbb\xfe\x74\x78\x46\x26\x6c\xbd\x9d\xf8\ +\x75\x0b\xde\x2b\xd9\xe3\x4f\xbe\x95\x30\x75\xf3\x00\x33\x5f\x5e\ +\xdf\x27\xd6\xbf\xc4\x84\xf8\xe9\x33\xfd\xfd\xb5\x13\x99\x4c\x79\ +\x2b\x71\x00\xf8\x77\xa5\xe2\x0a\x57\x40\x76\x58\xa6\x15\x71\x00\ +\xf0\xee\x48\xa8\xec\x0f\x3e\x59\x13\x31\xf9\x87\x8d\x7d\x6b\x00\ +\x44\x14\xab\x31\xef\xb9\x27\x1e\xdf\x36\xa4\x67\x17\x66\x13\xe9\ +\x07\xb3\x75\x10\xb5\xf5\xff\x76\x7e\x61\x57\x8d\x15\xf7\x12\x51\ +\x72\x4b\x00\x09\x3c\xb6\xcf\xf7\x4b\x92\x68\x5b\x47\xb3\x5a\x39\ +\x9d\x47\x7a\xca\xed\x88\x03\x00\x08\x88\x1f\x48\x95\x84\x2b\x7f\ +\xb6\x25\x80\x27\xc4\xe9\x6f\x66\x32\x4d\xd7\x34\x26\x44\xb4\xf2\ +\xda\xac\xdf\x36\x00\x80\xfe\x67\x0f\x06\x90\xf4\x38\x11\xdd\xbd\ +\x09\x80\x89\xa6\xdf\x28\x14\xb6\xff\x7c\x00\x3f\xef\xed\xcf\xe7\ +\xcf\x7f\xe4\x2d\xbe\x3c\x91\x6e\x17\x40\xa6\x6c\xe3\x0f\x74\xd4\ +\x00\xec\xdf\x04\x60\x98\x27\x97\xa3\xa8\xa9\x93\xfd\xbe\x1f\xfe\ +\x3a\xb7\x67\x7e\xf9\xa5\x09\xf7\xea\xb7\x86\x77\x87\x73\x35\x4b\ +\xaf\x2a\x11\xce\x54\x25\x9a\x65\x05\x03\x6a\x39\x74\x00\xac\x09\ +\x11\x33\x83\x88\x2c\x49\x54\x7e\x79\x70\x70\x29\x25\x65\x4b\xd9\ +\xad\x01\x9c\x7a\xf7\x9d\xf4\xa2\xaa\xc7\x22\x0d\x08\x02\xec\xb8\ +\x15\x25\x8e\x65\x2b\x76\xa7\x63\xaa\x63\xab\x4e\xf8\x61\xd5\xa2\ +\xba\x81\xcc\xc6\x0c\x2b\x66\x35\x5a\x70\x55\x5d\x0b\x22\xfa\x7d\ +\x18\xe9\x27\xd6\x03\xd8\x36\xd1\xfc\x99\x5c\x2e\x3a\x92\x4a\x05\ +\xad\x00\x00\x40\x60\x0c\x1d\x1b\x7d\x3b\xfb\xca\xb7\xef\x9a\xf1\ +\x2c\x69\x5e\x7a\x73\xbe\xfb\xc2\x78\xc1\xa9\x2b\x43\xb9\x6e\x57\ +\xef\xef\xf1\x4d\xcc\x16\x3c\xb5\x5a\xb7\x8a\x35\xad\x3e\xfd\x89\ +\x78\x74\x67\x8f\x5f\x3b\xf3\xe7\xf7\xe3\xf5\xc8\x0c\x31\xf3\x98\ +\x05\x00\xcc\xac\x24\xd1\x2f\x5f\xcf\xe7\x9f\x3c\x92\x4a\xb5\xaa\ +\x0f\x4f\x08\x76\xa4\xe0\xd9\x82\x72\xef\x48\xcb\xea\xc9\xa1\x9e\ +\xe5\x93\x43\x3d\x4d\xe7\x1d\xde\x9b\x74\x5e\xff\xcf\xea\x03\x00\ +\xc6\x04\x00\x10\x91\x27\x89\x7e\xf8\x44\x6f\xef\x96\x9b\xcf\x76\ +\x16\x13\x22\x1c\xf9\xa8\xec\xb4\x33\xa7\x58\xd3\x0a\xc0\x22\xf0\ +\x71\x12\x7e\x36\x69\x59\xfa\x36\xd7\x6d\x1b\xc0\x16\x44\x9e\x2d\ +\x9a\x0f\x5c\x67\x4b\x95\x88\x36\x02\x5c\x2a\x6b\xbd\xf4\xab\xe9\ +\xe9\x78\xcb\xfb\xeb\x35\x4b\x48\x8b\xaf\xcc\x55\x63\x06\x68\xfa\ +\x0b\x03\xc0\x42\x59\xc9\xa9\x95\xc0\x07\x30\xbc\x06\xc0\xcc\xaa\ +\x6e\xcc\x7d\x7f\x2d\x14\xde\x7e\x6e\x72\x32\xde\x0e\xc0\xb3\xd9\ +\x5c\x7e\x78\xbc\x48\x5f\x7f\x61\xb4\xef\x17\xaf\x4d\xa5\x17\x4b\ +\xca\xde\x6e\xfc\x1f\xff\xb9\xe0\x0a\xd0\x8b\xcc\x5c\x05\x36\x9c\ +\x86\x44\xe4\x79\x42\x8c\x7d\xa7\xb7\x37\xf1\x95\xee\xee\x5a\x3b\ +\x20\xff\x28\x95\xdc\x17\xe6\x66\x92\xb3\x4a\xb9\xa7\x3e\xb7\xab\ +\x7c\xfc\x9e\xf4\xea\x56\xe3\x4e\x9c\xbb\xd2\x31\x5f\x52\x47\xaf\ +\x9f\x8a\x0d\x8b\xc7\xcc\x41\x60\xcc\xa3\xe7\xe6\xe6\xda\x4a\x2a\ +\x00\xb8\x37\x91\xa8\x9f\x1d\xd8\xb7\xf8\xd4\xee\xbe\xfc\xb9\x37\ +\xe6\xe2\x3f\x39\x3f\xb9\xc3\x6c\xd8\x98\x26\xf2\x75\xbb\x50\xd3\ +\x0c\xe0\xad\xeb\x6d\x9b\xb2\x87\x99\x2f\x57\xb4\xe6\xd9\x30\xbc\ +\xa9\x7a\xf1\x8b\x5d\x5d\xd5\xdf\xec\x19\x58\xf8\xd7\x87\x25\xef\ +\x2f\xa3\xf9\xc4\xfa\xbe\x91\xe9\xb2\x63\x09\xba\xc0\xcc\x6b\x67\ +\xce\x26\x00\x47\xca\xd3\xb6\x10\x76\x97\x65\xb5\x54\x6c\x6c\x65\ +\xfd\xae\xab\x32\xb6\xad\x6a\x4a\x37\x44\x32\x62\x26\x03\x34\xe4\ +\x79\x03\x00\x11\x7d\xc6\x06\x9e\x7b\x7e\x60\xa0\xe0\x09\x71\x4b\ +\xf5\x7a\x1d\x2c\x53\xb1\xc6\xfa\xf0\xf6\x1d\x9e\x12\xc4\x07\x6f\ +\x08\x60\x03\x8f\x1d\xed\xee\x8e\xae\xd7\x80\xb7\x62\x2b\x61\x24\ +\x0f\xf4\x36\x16\x37\x49\xcf\x32\x86\xd1\x71\x43\x00\x05\x5c\x18\ +\x2e\x16\x79\x3e\x0c\xe5\xad\x88\x0f\x17\x8b\x5e\x64\x0c\x75\xc5\ +\xac\x46\x80\x98\x34\x4a\x73\x8a\xe8\xe3\xaa\x67\x63\xa2\xbd\xba\ +\x14\x45\xbf\x7b\xfc\xea\xd5\xa7\x0e\x76\x74\x54\x0e\xf8\xbe\x33\ +\xe0\xfb\xe1\x7d\x89\x44\xd0\xca\x5e\x17\x30\xd3\xf7\xde\x1f\x4f\ +\x4f\xd5\xeb\xee\x23\x87\x32\x15\xcf\x16\x0d\x91\x4c\xc7\x6d\x4d\ +\x04\x0b\x40\x0f\x80\x39\xe0\x06\xf7\x02\x22\xea\x04\xf0\xb0\x2d\ +\xc4\xa7\x5c\xe0\xb0\x06\xf6\x7e\xb9\xab\x2b\x38\xbe\x73\x67\xb0\ +\xcb\x71\x36\x25\x67\xc5\x18\xf1\xb7\xd5\x55\xef\xb7\x73\x33\x5d\ +\x83\xbd\xbe\x7e\xe6\x4b\xb9\xa5\xa4\x67\x35\x88\xe7\xab\x4a\x3e\ +\x7f\x71\xc6\x7b\x73\xa2\xb4\x10\x28\x33\xc8\xd7\x84\x9b\xde\x8c\ +\xae\x01\xdd\xe9\x0a\xf1\x7d\xcd\x7c\x42\x12\x51\xa7\x94\x81\x20\ +\xe2\xc0\x18\x51\xd1\xda\xd3\x80\xb4\x89\x3e\x80\xc4\x6d\xa7\x8f\ +\xf4\x95\x0e\xf5\x27\x83\xa4\x2b\xcd\xd4\x6a\xdd\x7a\x6f\xb1\x66\ +\x5f\x9e\x28\x8a\x8b\xe3\x05\xdf\x12\xf4\x62\x4d\x99\xa7\x99\xb9\ +\xb8\xe6\x9c\x99\xdb\x7a\x00\x64\x00\xdc\x0b\x60\x08\xc0\x3e\x00\ +\xdd\xeb\x3e\xe4\x58\xdc\x91\x97\x2d\x41\x81\x20\x8a\x3c\x4b\x2c\ +\x25\x3c\x79\xc1\x12\xe2\x0c\x80\xdd\x5b\xf9\x6b\x29\x02\x37\x63\ +\x44\xe4\x31\x73\xd3\xe2\xe6\x7f\x06\xd0\xaa\xfd\x17\xba\xbf\xbe\ +\x5a\x06\x69\x1b\xa1\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ +\x82\ +\x00\x00\x01\xb4\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\ +\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\ +\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd9\x07\x02\ +\x0a\x27\x08\x38\x45\x4c\x5d\x00\x00\x01\x34\x49\x44\x41\x54\x38\ +\xcb\x95\x53\x3b\xae\xc2\x30\x10\x1c\x3f\x71\x00\x1a\x44\x11\x0a\ +\x8a\x48\x8f\x2a\x0d\x25\x05\x22\xa2\x31\x3e\x0a\x39\x04\x87\x70\ +\x8e\x62\x2a\xb2\x88\x92\x36\x85\x15\x3a\x0a\x28\x10\x0d\x07\x40\ +\x32\x45\x88\x65\x13\xe7\x7d\x5c\x59\xbb\x33\xb3\x2b\xcf\x98\xa1\ +\xe3\x54\x52\x9a\xab\x52\x00\x80\x48\x08\x4c\xb2\x8c\x85\x70\xec\ +\x27\x72\xba\x5c\x02\x00\x68\xb7\xeb\x14\x61\x9d\xe4\xc5\x02\xb4\ +\xdf\x03\x80\xbd\x87\x44\x58\x90\x3c\x9f\x83\x0e\x07\x44\x42\x00\ +\x00\x3e\x6b\xae\x48\xaf\x45\x9e\xcd\x2c\xf0\x7b\xbd\xb6\xe2\xd4\ +\xf4\x94\x42\x25\xa5\xf1\x36\xa9\xa4\x34\x05\xe7\xc6\x6c\x36\xa6\ +\xe0\xdc\x54\x52\x9a\xcf\x13\xc2\x00\x40\xcf\x4e\x9e\x4e\x41\xc7\ +\xa3\x9d\x7c\xca\x73\xb8\x2e\x34\xdb\x50\x83\x7d\x6f\xc2\x0a\xce\ +\x4d\x9a\x24\xa0\xb2\xf4\x81\xab\x15\xd2\x24\xa9\xef\x65\x89\x74\ +\xbb\x05\x00\x2b\xdc\x70\xea\x37\x78\x3e\xc3\x61\xe8\xaa\x3b\xbd\ +\xaf\x48\x08\x90\xd6\x48\xe3\x18\x57\xa5\x70\xca\x73\xbb\x36\x69\ +\x0d\xd2\xda\xba\x61\xa7\xc7\xb1\xad\x33\xcf\x81\xf1\x18\x74\x3e\ +\xb7\x1c\xf0\xc8\x0e\x66\x92\x65\x8c\xb5\x6c\x1c\x8d\x40\x97\x8b\ +\x27\x62\xc9\x4e\xaf\xb1\x31\x1c\xa4\xe1\x10\x74\xbb\xf9\x41\x72\ +\x6a\x6e\x06\xba\xa3\x3c\x18\x80\xee\xf7\x3a\xca\xef\xfb\xaf\x51\ +\x6e\x89\xf4\xfb\xb5\x8d\x8f\xc7\xdf\x3f\xd3\x7f\xbf\xf3\x0b\x02\ +\x44\x08\x8a\x41\x5c\x33\x46\x00\x00\x00\x00\x49\x45\x4e\x44\xae\ +\x42\x60\x82\ +\x00\x00\x03\xcb\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\ +\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x03\x7e\x00\x00\x03\x7e\ +\x01\x59\x5f\x8a\xa9\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ +\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x03\x48\x49\x44\ +\x41\x54\x58\x85\xc5\x96\x4d\x68\x5c\x55\x14\xc7\x7f\xf7\x7f\x27\ +\xd2\xcc\x9c\xd7\xa4\xda\x68\x45\xeb\x42\x43\x5b\xa1\x48\x5d\xf9\ +\x11\xd1\xa2\x04\x85\x54\x91\xba\x71\x21\x2e\x84\xd6\xe2\x56\xb3\ +\x10\x11\x3f\x16\x0a\xae\x8c\xb8\x32\x4a\x76\x82\xe8\xc2\x8d\x88\ +\x08\x82\x16\x5b\x35\x45\xa2\x56\x37\x2d\x68\x8b\xa2\xa4\x1f\x89\ +\x7d\x31\x56\xed\x7d\xc7\x45\xc7\x38\x9d\x99\x17\x26\x9d\x74\x72\ +\xe0\x6e\xfe\xf7\xbd\x7b\x7e\x9c\xff\xb9\xe7\xbd\xe0\xee\xfc\x17\ +\x31\x8b\x37\x01\xc7\x53\x9e\xe6\xe9\x51\xa8\x21\xf9\x08\x70\x08\ +\x78\xb8\x57\xc9\x2f\x00\x00\xf6\x01\xc7\x81\xa9\xb5\x02\xd8\x0c\ +\x1c\x4e\x79\xfa\x6b\xad\x00\x7e\x05\x76\xc4\x2c\x56\xd7\x0a\xe0\ +\x65\xe0\x6a\xe0\xa5\x5e\x02\xe0\xee\x4b\x4b\xa6\xe7\x65\x4a\x32\ +\xdd\xdb\xa8\x97\x2d\x6a\x6c\xea\xe4\xb9\x65\xcf\x68\x02\xe8\x93\ +\x69\xbf\x4c\x27\x65\x1a\x2c\x7d\x69\x08\x93\xe9\x9d\x68\xf1\x60\ +\xb7\x00\x8d\x16\x90\xf2\xf4\x0f\xf0\x18\x70\x05\x30\xd6\xae\x62\ +\xa1\x1a\x36\xeb\x4f\x4d\x3b\xbe\x21\x85\xb4\xab\x5b\x07\xd4\x2c\ +\xa4\x3c\x1d\x01\x8e\x00\xf7\xb4\x05\x88\xe1\x75\x02\x87\x7c\xc1\ +\xef\xf3\x33\x7e\xaa\x5b\x80\x4a\x89\x1e\x81\xb3\xcd\x62\x9f\xf5\ +\x8d\x86\x10\x6e\x2d\x54\x6c\x73\xf7\xa2\xdb\xe4\xcb\x01\x0c\x01\ +\xb3\xcd\x62\x41\x31\x0a\xbc\xeb\xf3\x3e\xd7\xee\xa5\xb0\x29\xd4\ +\xb4\xa8\x27\x70\xaa\x29\x4f\x2f\x74\x02\xd0\x62\x41\x3d\x7e\x07\ +\xac\x35\xc3\xff\x5a\x08\xa1\x1a\x06\xc2\x70\x08\x61\xdd\xd2\x61\ +\x7f\x68\x2a\x14\xe1\x21\xb9\x3e\xef\x24\x39\x94\x57\xe0\x34\xb0\ +\xb1\x59\x2c\xbc\x78\x43\x41\x9f\xc6\xf5\xf1\xa4\x4c\xe3\x14\x44\ +\x8c\x33\x31\x8b\x6f\xe3\x1c\x23\xb0\x2b\x15\x69\x8b\x2f\xfa\xcf\ +\x9d\x02\x94\x55\x60\x1a\x18\x8b\x59\xbc\xbc\x51\xf4\x05\x9f\x71\ +\xfc\x37\x9c\xf1\x42\xc5\xdd\x29\x4f\xeb\x8a\x50\x3c\x08\x04\x97\ +\x8f\x02\xe3\x2b\x49\x7e\xfe\xd0\x76\x77\xd3\x74\xad\x4c\xb9\x4c\ +\x93\xcd\x7b\xd1\xe2\x6e\x99\xe6\x18\xc2\xba\x9d\x01\x2d\x83\xa8\ +\x09\xe2\x49\x99\x0a\x99\x46\x5a\x20\x6a\xf1\x4b\x99\x1e\x5f\x0d\ +\x80\x32\x0b\x00\x26\x80\xef\x81\xc9\x98\xc5\xcb\x2e\xa8\x5a\xf0\ +\x0f\x81\x9b\x57\x54\xea\x92\x28\x05\x48\x79\x3a\x07\xec\x05\xb6\ +\x02\x5f\xc5\x2c\x4e\xc5\x2c\xde\x58\xdf\x3e\x87\x97\x36\xf0\xc5\ +\x01\x84\x6a\xb8\xa6\x62\x95\x47\xc2\x40\x58\x6a\xbc\x94\xa7\x83\ +\xc0\xd3\xc0\x4f\xc0\xfd\xc0\x4c\xcc\xe2\x3e\x77\xbf\x05\xf8\x61\ +\x35\x00\x96\xbc\xa8\x58\x65\x67\xb4\x78\x40\xa6\xf9\xb8\x3e\x8e\ +\xb5\xe9\x89\x4c\xa6\x49\x99\x5c\xa6\x39\xfa\xb9\xee\x92\x34\x61\ +\xac\xc5\x47\x65\x3a\x81\x71\x65\x49\x73\x3e\x55\x87\xd8\xb3\x1a\ +\x00\xc1\xdd\x5b\xaa\xa2\x4c\xef\x07\xc2\x6c\xca\xd3\xde\x76\x55\ +\x8b\x59\x3c\x00\xdc\x06\x1c\x06\x8e\xd6\xed\xf8\x0c\xf8\x38\xe5\ +\x69\x45\xdf\x88\xb6\x00\x61\x30\x5c\xaf\xa4\xef\x70\x9e\x29\xfa\ +\x8b\xb7\xfc\x84\xe7\x4d\x00\x33\xc0\x37\xc0\xdf\xc0\x30\xb0\x03\ +\x18\xe4\x7c\xaf\x4c\x00\x6f\xa6\x3c\x2d\x74\x44\x50\xea\x4d\xc6\ +\x48\xcc\xe2\xb4\x4c\x8b\x32\x4d\x70\x15\x35\x77\x07\xe3\x2e\x99\ +\x4e\x01\xd5\x06\x5b\x82\x4c\x77\xca\xf4\x5e\xfd\x8f\xea\x17\x99\ +\x76\x76\x35\x88\x1a\x40\xb6\x06\x0b\x9f\xc8\xf4\x35\xc6\x76\x99\ +\xbe\x95\xe9\xd9\x65\x06\xd8\x36\x99\xbe\x90\xe9\xb4\x4c\x37\x74\ +\x0d\x50\xb7\xa8\x22\xd3\x6b\x32\x79\xb4\xb8\x1f\x88\xcb\x4e\x37\ +\xd3\x46\x99\x8e\xd5\x2b\xf1\xa2\x4c\x0f\xc8\xd4\x76\x74\xaf\xec\ +\xca\x6c\x60\xa0\xd3\x67\x65\x1a\x96\xe9\x23\x99\xce\xd6\x6f\xcd\ +\xac\x4c\xbb\xbb\x02\xb8\x98\x25\x53\x94\x69\xbb\x4c\x1f\xd4\xbf\ +\x2d\xaf\xca\x74\x7b\xcf\x00\x1a\x40\x24\xd3\x2b\x75\x08\x97\xe9\ +\x39\xf7\x92\x39\x70\x29\x23\x66\xb1\x1f\xb8\x03\x38\x9a\xf2\xf4\ +\x63\xcf\x01\x9a\xe3\x5f\xe8\x59\x5d\x85\xd2\x6b\xbb\xf2\x00\x00\ +\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x01\xe8\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\ +\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\ +\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd9\x07\x02\ +\x0a\x22\x29\x09\x5b\xa8\x46\x00\x00\x01\x68\x49\x44\x41\x54\x38\ +\xcb\x9d\x93\xbd\x6a\xe3\x40\x14\x85\xbf\x7b\x33\xe3\x19\x35\x4b\ +\xba\x64\xcb\x2d\x93\x07\x08\x18\x0b\xd9\xcf\x92\x36\xfb\x3a\x69\ +\xd2\x6d\x9b\x17\xd8\xd6\x32\xd8\x58\xa4\x4b\x60\x61\xab\x2d\xb6\ +\x58\x08\x09\x29\xf2\xe3\xb5\x25\x4b\x29\x44\x26\x52\xa4\x40\xc8\ +\xc0\x81\x99\x61\xee\xb9\xe7\xe3\x32\x02\xf0\xed\xf4\x5f\xc5\x27\ +\xd6\x9f\x93\xaf\x62\x5e\x0e\xdf\x47\xfb\xd8\xaa\x60\xd7\x6c\xd8\ +\xb7\xff\xd9\x73\x05\x5f\x4c\xc9\x60\x07\x84\xda\xff\x21\xaf\xb8\ +\xbc\x55\x7e\xfe\x15\x2e\xae\xeb\xba\x60\x50\x56\x70\xbf\xdd\xe1\ +\x66\xed\xb8\xca\x2d\xab\xbc\xe4\x71\x53\xf2\xb8\xd9\xd6\xca\x4b\ +\x56\xeb\x92\xa7\xa2\x64\x5d\x54\xe4\xdb\x12\x00\x6d\x87\xaa\x7a\ +\x76\xf5\x92\x0a\x2a\x01\x79\x73\x1f\x12\x1c\xb8\x3b\x0e\xdc\x5d\ +\xfd\x58\xa4\x57\xaa\x8a\x88\xf0\xe3\xb7\x70\xf6\x8b\x76\x82\x8f\ +\x16\xab\x2a\xc7\x87\xaf\xc1\x5b\x08\x51\x14\x05\x65\x59\x16\x0a\ +\xb2\x2c\xc3\x39\x17\x24\x22\x5d\x04\x11\x21\x4d\xd3\xd0\xb1\x99\ +\x06\x20\x4d\x53\x54\xeb\x7e\x71\x1c\xf7\x1b\x0c\x87\xc3\xde\xd8\ +\xa3\xd1\xa8\x85\xd0\x4c\xa0\x4d\x83\x28\x8a\xf0\xde\xe3\xbd\x0f\ +\x08\x22\xc2\x72\xb9\x64\x30\x18\x04\xbd\x8b\x30\x9d\x4e\x5b\x1d\ +\x5e\xf6\x22\xc2\x6c\x36\x0b\xf7\x49\x92\x74\x0d\xac\xb5\x24\x49\ +\x82\xaa\xb6\x0a\x45\x84\xc9\x64\xd2\x41\x83\x55\x17\xc1\x7b\x8f\ +\x73\x0e\x6b\x2d\x8b\xc5\x22\x3c\x9e\xcf\xe7\x18\x63\x30\xc6\x60\ +\xad\xed\x47\x50\xd5\xce\x14\x9a\x38\xcd\x29\x8c\xc7\xe3\x7e\x83\ +\x38\x8e\x3b\x13\x10\x91\x80\xd6\x34\xef\x18\x1c\x9d\x17\x9f\xf9\ +\xd1\x3c\x03\xdf\x1d\x68\xb5\x32\x71\x66\x6a\x00\x00\x00\x00\x49\ +\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x03\xb8\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\ +\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x03\x7e\x00\x00\x03\x7e\ +\x01\x59\x5f\x8a\xa9\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ +\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x03\x35\x49\x44\ +\x41\x54\x58\x85\xed\x97\x4f\x68\x54\x57\x14\xc6\xbf\xef\xdc\xf7\ +\x66\x26\x93\x26\x46\x23\x98\x58\x9b\x5a\xb4\x25\x90\xd8\x58\xff\ +\xa1\x82\xa5\x14\x0a\xc5\x6e\xba\x29\x42\xab\x48\x4b\xa1\xbb\xae\ +\x44\x77\x81\xae\xb2\xb7\x14\xc4\x95\xe2\xb6\x85\xae\xda\xae\x84\ +\xda\x46\x5c\xb4\x88\xc6\xfa\x07\x6a\xd4\x46\x52\xa8\x66\x2c\x26\ +\x9a\x3f\x33\xf7\x7c\x5d\x8c\x8b\x34\x64\xde\x4c\xc9\x43\x17\xf5\ +\x6c\xdf\x77\xee\xf9\x71\xde\xf9\x0e\xf7\x52\x12\x9e\x65\xd8\x33\ +\xad\xfe\x1c\xa0\x15\x00\x92\xb6\x9e\x1c\xd9\x6a\x36\xfa\x22\x79\ +\x9c\x64\x29\x4f\x00\x66\x0d\x21\xc9\xce\xdd\x49\x32\xb1\x3b\x84\ +\x8e\x4d\x31\x12\xee\xfa\xd6\xfd\xd1\x28\x30\x34\x2b\x8d\xe7\x01\ +\x90\xd9\x81\xb7\x43\xf8\x6e\x57\x08\x9d\x20\xf9\xd0\x0c\x05\x33\ +\x1e\x32\x7b\x61\x07\xf0\x4d\x1e\xc5\x9b\x02\xbc\x42\x6e\x2f\x3f\ +\x11\xdd\x37\xc3\x43\x12\x91\xc4\x46\xb2\x3f\x2f\x80\x24\xeb\x63\ +\x87\x3b\xdb\x48\xc8\x0c\x55\x12\x53\x21\x20\x95\x00\xd6\x43\x39\ +\x2c\x91\xcc\x0e\x54\xa4\xab\x25\x09\x45\x09\x01\xc0\x1c\x80\x7b\ +\x21\x60\x02\x18\xcf\xa3\x78\x53\x80\xaf\xa5\xf7\xfe\x88\x71\xbe\ +\x20\x21\x75\x87\x4b\xf8\x49\xaa\x5e\x76\x3f\xb0\x9c\x9e\x64\x27\ +\xc9\x7d\x24\x43\xab\x00\x99\x2e\x78\x72\x68\x71\x1b\x70\xa2\xdb\ +\x6c\xe7\x24\x70\xe5\x37\xf7\x4f\x25\xcd\x2c\xd1\xb4\x0f\x86\x70\ +\x79\x90\xec\xeb\x93\x78\xc7\xbd\x76\x51\xfa\xe1\x86\xf4\xfe\x8a\ +\x01\x5a\x89\x3d\x49\x32\xba\x3d\x4d\xf7\xb6\x03\xe8\x89\x11\x6b\ +\xdc\x71\xc7\xdd\x4f\x49\x9f\x8f\x4b\x5f\x65\xe5\xae\x78\x13\x92\ +\x4c\xb7\x98\xed\x2c\x4b\xa8\x02\xa8\x98\x61\x9a\xc4\xcb\xa4\x6d\ +\x06\x8e\x35\xcb\xcf\x74\x41\x8b\xd1\xb3\x4e\x4a\x00\x40\x00\x66\ +\x48\x14\xcd\x90\x02\x28\x4b\x5d\x4f\x03\xe0\xee\xbc\xfb\x7c\x17\ +\x59\x8a\x66\x70\x12\x53\x66\xa0\x84\x0a\x70\xab\x59\xf2\x8a\x7f\ +\x81\x24\x5d\x70\x3f\x11\xdc\x51\x72\x47\x41\x02\x01\xfc\x4c\xfa\ +\x75\xe9\x70\xb3\xfc\x5c\x86\x10\x00\xb6\x91\xc3\x03\x66\x47\xdc\ +\xac\xed\xae\x74\x6f\x2c\xc6\x0f\x2a\xd2\x68\x2e\x00\x24\x7b\x01\ +\xbc\x01\xe0\xac\xa4\xb9\x1c\x78\x5b\x03\x20\xb9\x66\x6b\x08\x63\ +\x5b\xcc\xd6\xbd\xe4\xce\xdb\xee\xb5\x5f\xa5\xef\xaf\xb7\xe0\xef\ +\x5c\x00\xde\x4a\xd3\xb1\xd7\x93\x64\xb0\x0d\x40\x6f\x8c\x58\xed\ +\x8e\x9b\xee\x7e\x46\xfa\xe4\x96\x74\x3a\x0f\x80\x86\x43\x48\xb2\ +\x63\x80\xec\x6f\x5b\xe4\xef\x19\x12\x9b\xeb\xfe\x1e\xce\xa3\x78\ +\x26\x40\x01\xd8\xb8\x56\x0a\x05\x09\x41\xc2\x34\x89\xbf\xcd\x30\ +\x6b\x86\x32\xd9\xdd\xec\xe0\x57\x43\x38\xb3\x3f\x49\x66\x0e\x86\ +\x30\xfb\x8e\x59\xa5\x97\xfc\x78\x39\x5d\xc3\x3d\xb0\x00\x5c\xab\ +\xba\x2f\xb4\x93\x45\x27\x21\xd4\xef\x04\xaa\xfb\x7b\x2c\xab\xf8\ +\x50\x08\xa7\xde\x2c\x14\x3e\xea\x91\xd8\x13\x23\x56\xb9\x97\xce\ +\x03\x27\xbb\xc9\x1b\x53\xd2\xf9\xc5\xda\x86\x1d\x90\x54\xbb\xe0\ +\x7e\x3a\x75\x47\xd1\xbd\x7e\x0f\x00\xf0\x23\x59\xbb\x2a\x7d\xd8\ +\x28\x8f\x24\x87\x42\x38\xb0\x1a\xe0\x63\x12\x0f\x42\xc0\x23\x33\ +\xec\x25\x93\x01\xe0\x64\xcb\x1d\x00\x80\xb3\xd2\x67\x3b\xc8\xdb\ +\xfd\xd2\xd1\x9a\x54\x9e\x94\x26\x2f\xc6\xb8\x7f\x5a\x9a\xc8\x48\ +\xdb\xb0\x41\x2a\x9a\x3b\xe6\xcc\xf0\x80\x44\xc1\x0c\xa9\x84\xb5\ +\x64\xdf\x7f\x02\x00\x80\x5f\xa4\x11\x00\x23\xcd\x74\x8b\xe2\x4f\ +\xb8\xc7\x12\x99\xb8\x84\x79\x12\xf7\xcd\xea\x73\x24\xfd\xb5\x54\ +\x9c\xfb\xbb\x40\x52\xed\x8a\xfb\xb9\xa2\x3b\x8a\x12\x12\x09\x0e\ +\xe0\x12\xa9\x9b\xee\x5f\x2c\xd5\xe7\xb6\x8a\xff\x75\x28\x99\xbe\ +\x0b\x9c\x7b\x2d\x84\x5d\x55\x33\x9b\x00\x16\xae\xc5\xf8\xe5\xef\ +\x31\x1e\x79\x2a\x00\x8b\x40\x0c\x40\x97\xa4\x4a\x43\xcd\xff\xfe\ +\x75\xfc\x0f\x8f\xfa\x84\x70\x59\x1c\x44\x67\x00\x00\x00\x00\x49\ +\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x04\x0c\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x14\x00\x00\x00\x12\x08\x06\x00\x00\x00\x5b\xd0\xfe\x10\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\ +\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\ +\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x0b\x08\ +\x0f\x20\x02\xf0\x0b\x2f\xaf\x00\x00\x03\x8c\x49\x44\x41\x54\x38\ +\xcb\x6d\x92\x4d\x68\x5c\x55\x14\xc7\x7f\xf7\xbd\x37\x93\x99\xcc\ +\x4c\x26\x93\x99\x7c\x99\x2f\x67\x5e\x62\x9a\x98\x76\x32\x69\x42\ +\x46\x63\x0d\x93\x40\xbb\xb0\xd1\x56\x28\x2d\x0a\xc6\x18\x54\xba\ +\x30\xc1\x45\x04\x75\x63\x17\x0a\x22\x42\x2b\x88\x3b\xbf\xc8\x26\ +\x20\x45\x41\x74\xd3\x55\x77\x41\xb1\xa0\x71\xd3\x08\x49\x13\x0c\ +\x12\x0d\xd2\x66\x32\x2f\xf3\xe6\xdd\x7b\x5d\x4c\x3a\x4c\x62\x0e\ +\x1c\xee\xe1\xf0\xff\x9f\x7b\xfe\xe7\x1c\x00\x71\xc4\xa9\x7a\x59\ +\x82\xf1\x1f\xda\x5b\xd7\x6f\x26\x1a\x7e\xbb\x06\xe9\x23\x98\x63\ +\x79\x47\x01\x15\xfb\x0a\x7c\xdf\x37\xc6\x7f\xbe\xbf\xb4\xa8\xb7\ +\x3e\x7c\x5f\x7f\x16\xa8\xf9\xd1\x07\xd6\x31\xc5\x2a\x6e\x00\xfa\ +\x80\xaf\xab\x62\x3e\x00\x6a\x60\xc6\xbe\x30\x75\x3a\x62\xf7\xd2\ +\x9c\x19\xa6\x7f\x64\xe8\xec\x9b\x30\x65\x54\xe1\xaa\x78\x1a\xd0\ +\xc6\x31\x6d\x03\x88\x24\x3c\x52\xd7\xde\xfa\x96\x7d\xe9\x32\x62\ +\xaf\x80\xb1\x5f\x24\x7d\x7e\xca\xe8\x0a\x06\xde\xbd\x08\x0d\xd5\ +\xd8\x6a\x95\xc6\x31\xdd\x09\x1b\x30\x7c\xd6\x5c\xdf\x0b\x57\x52\ +\x3e\x7f\x10\xa9\x14\xd2\xf3\xa8\xab\x8b\x91\xc9\x8e\x64\x4e\x08\ +\xf1\x32\xff\x37\x01\x68\xf3\xe8\x12\x00\xf1\x09\x74\xb7\x9c\xea\ +\xff\xe2\xe4\x2b\xaf\xfa\x31\x4c\xdc\xc1\x41\x54\x43\x03\xd6\xca\ +\x0a\xb1\x40\x40\x6c\xfe\xb1\x9a\xd1\x05\x67\xf1\x2e\xe4\x0f\x1a\ +\xa9\xf0\xcd\xa3\x4b\xf9\x14\xac\x5a\xcb\xbc\x9e\x9d\x7f\x63\x28\ +\x9c\x68\x41\x27\x93\xdc\xd9\xda\x22\xaf\x35\x8d\x4a\xe1\x5f\x5b\ +\xc3\xd4\x32\xb4\xbd\xbe\x61\xde\x83\x5b\x0f\x0e\xcf\xb3\x22\xb9\ +\x32\xe0\x08\x4c\x3c\x3a\x96\x7d\x3e\x71\x62\x00\x4c\x93\x7c\x53\ +\x13\xd3\xd3\xd3\xcc\xcd\xcf\x43\x2e\x87\xf0\x24\x03\xf1\x26\xba\ +\x9b\xe2\x33\x93\x30\xcc\xe1\x82\x18\xd5\x1b\xfa\x12\x7c\xb5\xb1\ +\xe8\x7b\x7d\xcf\x5d\x08\x88\x82\x03\x7d\x7d\x04\x43\x21\xc2\xe1\ +\x30\xf1\x78\x1c\xa3\xbe\x1e\x9d\xcb\x61\x3e\xd8\xe5\xa9\xb6\xb6\ +\x68\x8b\x65\xbd\x1d\x29\xab\x3c\x54\x10\x40\x8c\x97\x25\xbf\x64\ +\x8f\x8d\x66\xa3\xf1\x04\x3a\x16\x83\x8e\x0e\xfc\x7e\x3f\x9d\x9d\ +\x9d\xf4\xf4\xf4\x94\x91\xe7\xce\x41\x63\x23\x49\xd7\x63\x20\x11\ +\x3b\xff\x2c\x3c\x53\xad\xf0\xe1\xd9\xf0\x22\x34\x47\x9a\xe2\x0b\ +\x6d\xfe\x5d\xfe\x5d\xba\x81\x77\x72\x00\x8c\xf2\x7f\xc9\x64\x92\ +\x54\x2a\x55\xa6\x84\xc3\x38\x57\x2e\xf3\xfb\xce\x1a\x76\x43\xd8\ +\x68\xb5\xac\x77\x9e\x86\xfa\x43\x92\x5f\x03\xed\xf7\x59\x73\x8f\ +\x9d\xee\xeb\x95\x77\x7f\xa1\x94\x1e\xa1\x14\x8b\xa1\x94\x42\x6b\ +\x4d\x2a\x95\xc2\xb6\x6d\xb4\xd6\x28\xa5\x60\x62\x12\x6f\x68\x04\ +\xe7\x9f\xbf\x18\x6c\x8e\x8f\x74\xc1\xf4\xc3\x59\x9a\x80\x78\x1d\ +\xec\xe6\x64\xfb\xe7\xdd\x11\xb7\xc6\x33\x0c\xc4\xc2\x47\x98\x75\ +\x31\x84\x10\x08\x21\xb0\x6d\x9b\xae\xae\x2e\x4c\xd3\xa4\x54\x2a\ +\xe1\xba\x2e\xba\xa5\x8d\xed\xef\x6e\x12\xf5\x59\x62\xc7\x95\x69\ +\xd7\x93\x8b\x7f\x42\xc1\xfc\x18\xac\x90\x65\xdd\x18\x7a\xa2\x7f\ +\xd8\xdc\x58\xc1\xb9\x74\x15\x35\x7c\x06\x21\xca\xd7\x94\xcf\xe7\ +\x99\x9d\x9d\x65\x79\x79\x99\x5c\x2e\x87\xeb\xba\x14\x8b\x45\xbc\ +\x68\x94\xbd\x7b\x1b\xec\xfe\x7a\x87\x78\x38\x12\xf9\x7b\xcf\x31\ +\xb6\xe1\x96\x11\x86\xf1\x8e\xfe\xee\x8b\xb5\x3b\x6b\x94\x3c\x4d\ +\x7e\x74\x12\x67\x7f\x9f\x82\xe3\x50\x28\x14\x28\x79\x1e\xa3\xd9\ +\x2c\xa7\xd2\x69\x1c\xe7\x20\xef\x38\x38\x45\x17\xff\xc4\x59\x1c\ +\xd7\x23\x52\x72\x49\xd5\xd4\xcc\xa4\x21\x23\xbe\x8e\x84\x6e\x3f\ +\x39\xf6\xf8\x19\x73\xf5\x27\x3c\xa9\x29\x26\xfb\x91\x75\x09\xb4\ +\x30\xd0\x18\x28\x04\x4a\x0b\xa4\x06\x4f\x6a\x4a\x4a\xe3\x49\x85\ +\xeb\x49\x9c\xcd\x4d\x9c\xf5\x75\xa4\x12\x04\x42\x21\xbe\xdd\xdd\ +\xfb\xc6\x32\x83\x81\x5e\x21\x3d\x64\x6b\x0f\xca\xd3\x88\x7c\x11\ +\x71\x7f\x13\xe5\x49\xa4\xd4\x48\xa9\x90\x52\xe1\x79\xaa\x12\x2b\ +\xa9\x10\x9e\xc2\x2f\x15\x66\x20\x54\xce\x7b\x12\x4b\x88\x8c\xb8\ +\x66\x18\x57\x83\xa1\xda\x05\x65\x88\xa0\xd2\x1a\xa9\x35\x52\x83\ +\xd2\x1a\x49\x55\xac\x35\x0a\xca\xef\x01\x46\x52\x8e\xb5\x86\x7d\ +\xad\x8b\xab\x4a\x5d\xff\x0f\xa0\x90\x7c\x2f\xa9\x78\xa9\xd8\x00\ +\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x05\x78\ +\x2f\ +\x2a\x20\x58\x50\x4d\x20\x2a\x2f\x0d\x0a\x73\x74\x61\x74\x69\x63\ +\x20\x63\x68\x61\x72\x20\x2a\x20\x74\x61\x62\x6c\x65\x73\x5f\x78\ +\x70\x6d\x5b\x5d\x20\x3d\x20\x7b\x0d\x0a\x22\x31\x36\x20\x31\x36\ +\x20\x36\x33\x20\x31\x22\x2c\x0d\x0a\x22\x20\x09\x63\x20\x4e\x6f\ +\x6e\x65\x22\x2c\x0d\x0a\x22\x2e\x09\x63\x20\x23\x32\x31\x39\x35\ +\x45\x37\x22\x2c\x0d\x0a\x22\x2b\x09\x63\x20\x23\x38\x41\x43\x45\ +\x46\x45\x22\x2c\x0d\x0a\x22\x40\x09\x63\x20\x23\x39\x34\x43\x46\ +\x46\x39\x22\x2c\x0d\x0a\x22\x23\x09\x63\x20\x23\x41\x44\x44\x35\ +\x46\x32\x22\x2c\x0d\x0a\x22\x24\x09\x63\x20\x23\x43\x41\x44\x43\ +\x45\x41\x22\x2c\x0d\x0a\x22\x25\x09\x63\x20\x23\x44\x45\x45\x33\ +\x45\x37\x22\x2c\x0d\x0a\x22\x26\x09\x63\x20\x23\x45\x36\x45\x37\ +\x45\x37\x22\x2c\x0d\x0a\x22\x2a\x09\x63\x20\x23\x45\x36\x45\x36\ +\x45\x36\x22\x2c\x0d\x0a\x22\x3d\x09\x63\x20\x23\x43\x35\x44\x38\ +\x45\x36\x22\x2c\x0d\x0a\x22\x2d\x09\x63\x20\x23\x37\x36\x42\x39\ +\x45\x38\x22\x2c\x0d\x0a\x22\x3b\x09\x63\x20\x23\x33\x30\x39\x43\ +\x45\x38\x22\x2c\x0d\x0a\x22\x3e\x09\x63\x20\x23\x38\x38\x43\x44\ +\x46\x45\x22\x2c\x0d\x0a\x22\x2c\x09\x63\x20\x23\x35\x32\x42\x30\ +\x46\x32\x22\x2c\x0d\x0a\x22\x27\x09\x63\x20\x23\x42\x33\x44\x35\ +\x45\x44\x22\x2c\x0d\x0a\x22\x29\x09\x63\x20\x23\x44\x44\x44\x44\ +\x44\x44\x22\x2c\x0d\x0a\x22\x21\x09\x63\x20\x23\x38\x33\x43\x42\ +\x46\x45\x22\x2c\x0d\x0a\x22\x7e\x09\x63\x20\x23\x37\x41\x43\x36\ +\x46\x42\x22\x2c\x0d\x0a\x22\x7b\x09\x63\x20\x23\x36\x46\x43\x30\ +\x46\x39\x22\x2c\x0d\x0a\x22\x5d\x09\x63\x20\x23\x36\x33\x42\x39\ +\x46\x36\x22\x2c\x0d\x0a\x22\x5e\x09\x63\x20\x23\x35\x36\x42\x32\ +\x46\x33\x22\x2c\x0d\x0a\x22\x2f\x09\x63\x20\x23\x34\x39\x41\x42\ +\x46\x30\x22\x2c\x0d\x0a\x22\x28\x09\x63\x20\x23\x33\x44\x41\x35\ +\x45\x44\x22\x2c\x0d\x0a\x22\x5f\x09\x63\x20\x23\x33\x31\x39\x45\ +\x45\x42\x22\x2c\x0d\x0a\x22\x3a\x09\x63\x20\x23\x32\x37\x39\x39\ +\x45\x39\x22\x2c\x0d\x0a\x22\x3c\x09\x63\x20\x23\x44\x45\x44\x45\ +\x44\x45\x22\x2c\x0d\x0a\x22\x5b\x09\x63\x20\x23\x38\x33\x43\x42\ +\x46\x44\x22\x2c\x0d\x0a\x22\x7d\x09\x63\x20\x23\x34\x41\x41\x42\ +\x46\x30\x22\x2c\x0d\x0a\x22\x7c\x09\x63\x20\x23\x33\x44\x41\x34\ +\x45\x44\x22\x2c\x0d\x0a\x22\x31\x09\x63\x20\x23\x32\x38\x39\x39\ +\x45\x39\x22\x2c\x0d\x0a\x22\x32\x09\x63\x20\x23\x44\x46\x44\x46\ +\x44\x46\x22\x2c\x0d\x0a\x22\x33\x09\x63\x20\x23\x45\x32\x45\x32\ +\x45\x32\x22\x2c\x0d\x0a\x22\x34\x09\x63\x20\x23\x45\x33\x45\x33\ +\x45\x33\x22\x2c\x0d\x0a\x22\x35\x09\x63\x20\x23\x45\x35\x45\x35\ +\x45\x35\x22\x2c\x0d\x0a\x22\x36\x09\x63\x20\x23\x38\x37\x43\x30\ +\x45\x37\x22\x2c\x0d\x0a\x22\x37\x09\x63\x20\x23\x45\x30\x45\x30\ +\x45\x30\x22\x2c\x0d\x0a\x22\x38\x09\x63\x20\x23\x41\x37\x41\x37\ +\x41\x37\x22\x2c\x0d\x0a\x22\x39\x09\x63\x20\x23\x41\x43\x41\x43\ +\x41\x43\x22\x2c\x0d\x0a\x22\x30\x09\x63\x20\x23\x45\x43\x45\x43\ +\x45\x43\x22\x2c\x0d\x0a\x22\x61\x09\x63\x20\x23\x45\x45\x45\x45\ +\x45\x45\x22\x2c\x0d\x0a\x22\x62\x09\x63\x20\x23\x45\x39\x45\x39\ +\x45\x39\x22\x2c\x0d\x0a\x22\x63\x09\x63\x20\x23\x45\x31\x45\x31\ +\x45\x31\x22\x2c\x0d\x0a\x22\x64\x09\x63\x20\x23\x41\x36\x41\x36\ +\x41\x36\x22\x2c\x0d\x0a\x22\x65\x09\x63\x20\x23\x41\x38\x41\x38\ +\x41\x38\x22\x2c\x0d\x0a\x22\x66\x09\x63\x20\x23\x41\x44\x41\x44\ +\x41\x44\x22\x2c\x0d\x0a\x22\x67\x09\x63\x20\x23\x41\x46\x41\x46\ +\x41\x46\x22\x2c\x0d\x0a\x22\x68\x09\x63\x20\x23\x45\x41\x45\x41\ +\x45\x41\x22\x2c\x0d\x0a\x22\x69\x09\x63\x20\x23\x39\x30\x43\x41\ +\x46\x33\x22\x2c\x0d\x0a\x22\x6a\x09\x63\x20\x23\x45\x37\x45\x37\ +\x45\x37\x22\x2c\x0d\x0a\x22\x6b\x09\x63\x20\x23\x45\x42\x45\x42\ +\x45\x42\x22\x2c\x0d\x0a\x22\x6c\x09\x63\x20\x23\x45\x38\x45\x38\ +\x45\x38\x22\x2c\x0d\x0a\x22\x6d\x09\x63\x20\x23\x41\x39\x41\x39\ +\x41\x39\x22\x2c\x0d\x0a\x22\x6e\x09\x63\x20\x23\x45\x46\x45\x46\ +\x45\x46\x22\x2c\x0d\x0a\x22\x6f\x09\x63\x20\x23\x46\x31\x46\x31\ +\x46\x31\x22\x2c\x0d\x0a\x22\x70\x09\x63\x20\x23\x45\x44\x45\x44\ +\x45\x44\x22\x2c\x0d\x0a\x22\x71\x09\x63\x20\x23\x41\x41\x41\x41\ +\x41\x41\x22\x2c\x0d\x0a\x22\x72\x09\x63\x20\x23\x42\x30\x42\x30\ +\x42\x30\x22\x2c\x0d\x0a\x22\x73\x09\x63\x20\x23\x42\x32\x42\x32\ +\x42\x32\x22\x2c\x0d\x0a\x22\x74\x09\x63\x20\x23\x45\x34\x45\x34\ +\x45\x34\x22\x2c\x0d\x0a\x22\x75\x09\x63\x20\x23\x46\x30\x46\x30\ +\x46\x30\x22\x2c\x0d\x0a\x22\x76\x09\x63\x20\x23\x37\x42\x43\x36\ +\x46\x42\x22\x2c\x0d\x0a\x22\x77\x09\x63\x20\x23\x36\x46\x43\x30\ +\x46\x38\x22\x2c\x0d\x0a\x22\x78\x09\x63\x20\x23\x32\x38\x39\x39\ +\x45\x38\x22\x2c\x0d\x0a\x22\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\ +\x2e\x2e\x20\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\x2e\x2b\x40\x23\ +\x24\x25\x26\x2a\x2a\x3d\x2d\x3b\x20\x20\x20\x20\x22\x2c\x0d\x0a\ +\x22\x2e\x3e\x2c\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x20\x20\ +\x20\x22\x2c\x0d\x0a\x22\x2e\x3e\x2e\x2b\x40\x23\x24\x25\x26\x2a\ +\x2a\x3d\x2d\x3b\x20\x20\x22\x2c\x0d\x0a\x22\x2e\x27\x2e\x3e\x2c\ +\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x20\x22\x2c\x0d\x0a\x22\ +\x2e\x29\x2e\x3e\x2e\x2b\x40\x23\x24\x25\x26\x2a\x2a\x3d\x2d\x3b\ +\x22\x2c\x0d\x0a\x22\x2e\x29\x2e\x27\x2e\x3e\x21\x7e\x7b\x5d\x5e\ +\x2f\x28\x5f\x3a\x2e\x22\x2c\x0d\x0a\x22\x2e\x3c\x2e\x29\x2e\x3e\ +\x5b\x7e\x7b\x5d\x5e\x7d\x7c\x5f\x31\x2e\x22\x2c\x0d\x0a\x22\x2e\ +\x32\x2e\x29\x2e\x27\x29\x29\x3c\x32\x33\x34\x35\x2a\x36\x2e\x22\ +\x2c\x0d\x0a\x22\x2e\x37\x2e\x3c\x2e\x29\x2a\x2a\x38\x37\x34\x39\ +\x30\x61\x62\x2e\x22\x2c\x0d\x0a\x22\x2e\x63\x2e\x32\x2e\x29\x64\ +\x38\x65\x63\x35\x39\x66\x67\x68\x2e\x22\x2c\x0d\x0a\x22\x69\x69\ +\x2e\x37\x2e\x3c\x32\x37\x63\x33\x2a\x6a\x62\x68\x6b\x2e\x22\x2c\ +\x0d\x0a\x22\x20\x20\x2e\x63\x2e\x32\x6c\x62\x6d\x34\x6a\x67\x6e\ +\x6f\x70\x2e\x22\x2c\x0d\x0a\x22\x20\x20\x69\x69\x2e\x37\x6d\x6d\ +\x71\x35\x62\x67\x72\x73\x61\x2e\x22\x2c\x0d\x0a\x22\x20\x20\x20\ +\x20\x2e\x63\x33\x74\x35\x2a\x6b\x30\x70\x61\x75\x2e\x22\x2c\x0d\ +\x0a\x22\x20\x20\x20\x20\x69\x3e\x21\x76\x77\x5d\x5e\x7d\x7c\x5f\ +\x78\x2e\x22\x7d\x3b\x0d\x0a\ +\x00\x00\x01\x98\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\ +\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\ +\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd9\x07\x02\ +\x0a\x23\x2d\x17\x2d\x5d\x1e\x00\x00\x01\x18\x49\x44\x41\x54\x38\ +\xcb\xa5\x93\xb1\x4a\x03\x41\x10\x86\xbf\xdd\x5c\x04\x05\x83\x9d\ +\x82\x67\x63\x6d\x93\x46\x63\x65\x13\xf0\x31\x2c\xb4\x92\x34\x87\ +\x8d\xcf\x20\x88\x2f\xa0\xef\x60\x27\x68\x65\xa3\x87\x18\x14\x1b\ +\x05\xc1\xc2\xa4\xb6\x72\xcf\xd3\xdd\xdb\xb5\xb9\x04\xef\x74\xcd\ +\x85\x0c\x2c\xcb\xf2\xcf\x7c\x33\xb3\xb3\x0b\x13\x9a\x00\xe8\xf6\ +\x0e\xdd\x5d\xff\x68\xac\xc0\x9d\xf5\xbe\x18\x02\x8e\xaf\x43\xb7\ +\xd9\x8a\xb0\xa6\x8e\xfb\x9a\x83\x74\x81\x9a\x99\x47\xda\x06\x92\ +\x29\x9c\x13\x00\x64\xee\x1d\x25\x1f\x78\x13\x67\x3c\xbf\x5e\xb1\ +\xb5\xfa\x28\x82\x01\xd1\x61\xb9\xb8\x3d\xa8\x94\x7d\x71\x79\x06\ +\x9d\x25\x00\x04\x65\x71\xbb\xd5\xfb\x37\xf8\x24\x5e\x2a\x9c\x83\ +\x2a\x4e\xbf\xe0\x79\x4b\x5e\x00\xc0\xc6\xca\x3e\xd3\xaa\x8d\xb4\ +\x0d\x54\xed\x86\xcb\x97\xce\x9f\x7e\x5e\xc0\x67\xfd\x09\x35\xdb\ +\x45\x5b\x85\xb6\xca\xdb\x92\xf4\x2a\x6e\x30\xa3\xe1\x56\x12\x4b\ +\x00\xe7\x83\x78\xc5\x52\x0b\xe5\x2c\xf1\xfd\xe9\xa8\xf7\xe7\xbf\ +\x83\x51\xa3\xfc\x59\x52\x50\x75\x84\x9e\x02\x8a\x80\xf6\xda\x2e\ +\xc6\xa6\x64\xf6\x03\x63\x13\x74\x96\xa0\xad\xc2\xe4\x4b\x67\x49\ +\xae\xa7\x45\x40\x33\x8c\x38\x8f\xc7\xfb\x4c\xcd\x30\x02\xf6\x98\ +\xd8\xbe\x01\xab\x3d\x6a\x80\x67\x7f\xc2\xcf\x00\x00\x00\x00\x49\ +\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x02\xcb\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x12\x00\x00\x00\x12\x08\x06\x00\x00\x00\x56\xce\x8e\x57\ +\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\ +\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x10\x00\x00\ +\x0b\x10\x01\xad\x23\xbd\x75\x00\x00\x00\x07\x74\x49\x4d\x45\x07\ +\xd6\x03\x0b\x09\x2c\x1f\x23\xfa\xf5\x97\x00\x00\x02\x58\x49\x44\ +\x41\x54\x38\xcb\x65\x94\x4d\x88\x8e\x51\x14\xc7\x7f\xe7\x79\xef\ +\xfb\xbc\xcd\x68\xec\x95\x8d\x8f\x99\x86\x61\xa1\xc8\xc2\x14\x4d\ +\x19\x25\x29\x91\xb2\xf0\x51\x12\x0b\x9a\xf2\x51\x34\x1b\x8a\x64\ +\x4b\x16\x6a\xec\x94\x94\x7c\x64\x44\x29\x24\x64\x6f\x61\xc1\x1e\ +\x0b\xf9\x5a\x3d\xf7\xeb\x58\xdc\xfb\x7c\xbc\xb9\x75\x9f\xee\xbd\ +\xe7\xdc\x73\xce\xff\x7f\xff\xe7\x91\x3b\x6f\x3e\x6b\xbf\x57\x50\ +\x9a\x82\xb2\x5f\x30\x30\x3d\x4a\xd3\x4b\x7b\x53\xef\x0b\xfa\xa6\ +\x47\xd9\xef\x31\xe8\x15\x94\xfd\xd6\x5e\x0f\x53\xb9\x00\xaa\x20\ +\x8a\x00\xa2\xd2\x18\x25\x7f\x55\x40\x05\x44\x40\xd0\x6c\x50\x80\ +\x26\x98\x71\x3e\xa4\x73\x01\xc9\x57\x9b\x03\xb4\x09\x40\x7b\xf7\ +\xbf\x51\x9a\x02\x53\x79\x45\x09\x4d\x0d\x31\x46\x5e\x3d\x7b\xc0\ +\xab\xc5\xfb\x7c\xf9\xf4\x11\x6b\x2b\x56\x8d\x4f\x72\x7c\xee\x1c\ +\x3b\x76\xee\x6a\x83\x0e\x55\x0d\x85\xf3\x01\xeb\x23\xd6\x07\x2a\ +\x17\xf8\xfe\xed\x2b\xd7\x2f\x9d\x65\x30\xb2\x84\x23\xa7\xce\x73\ +\x74\xee\x02\x7f\x7e\xff\xe2\xcc\x89\xc3\xbc\x7f\xfb\x26\xfb\x46\ +\xac\xcb\xd3\x47\x9c\x0f\x98\xca\xc7\x21\x3e\xcc\x60\x94\xcb\x0b\ +\x8f\x99\x98\x9c\xa2\xec\x27\x92\xb7\x6c\x9b\xe5\xd0\xae\x69\x16\ +\x1f\xde\x67\xe3\xe6\xe9\x16\xa2\xa4\xa9\x80\xb1\x3e\xb4\xf0\x05\ +\xca\x72\x94\x65\x2b\x26\xa8\x7c\xcc\xfe\x42\x6f\x30\x02\x40\x54\ +\xc5\xfa\xd0\xe2\x41\x6b\x72\x31\xd6\xc5\x6e\xf0\xc6\x56\x3b\xc6\ +\x18\xb8\x71\x65\x1e\x11\x61\xfb\xee\xfd\xd8\x8c\xa0\x85\x11\x00\ +\xc5\x38\x1f\x11\x34\xdf\xd5\x8e\x8f\x12\x43\x64\xe1\xea\x39\x3e\ +\xbc\x7e\xce\xb1\x33\x17\x19\x9f\xda\xd0\x06\x6a\x58\x4f\x6f\x6d\ +\xaa\x10\x50\x29\x5a\x83\x34\x22\xe0\xc5\xbd\x5b\x7c\x78\xf9\x94\ +\x83\x27\xe7\x99\xdd\x7b\x30\x05\x11\x10\xc9\x09\x55\x73\x72\x93\ +\x74\x44\x53\x51\x23\x1f\x14\x78\xfd\xe4\x2e\xe3\xeb\x37\x32\xb3\ +\xe7\xd0\x30\xa4\x54\x6f\x12\xa8\x08\x10\x30\x95\x8b\x59\xd8\x1d\ +\x45\x67\x9e\xfe\xfe\xfc\xc1\xca\xb5\x1b\xa8\x42\x18\x52\x73\x77\ +\xd4\x27\xc6\x86\x5c\x51\xd2\x7f\x43\xb4\x0a\xac\xd9\xb4\x95\xe5\ +\xab\xd7\xe1\x5c\xfd\xb2\x1d\x0a\x72\x5d\x68\x42\x63\x9c\x8b\x99\ +\xb0\xf0\x5f\x9a\x99\x03\xa7\x58\x3a\x36\x46\xe5\x63\xc3\x5d\xdb\ +\x46\x9d\x8c\x12\x28\xac\x0f\x58\x17\xb0\x21\xa9\xdb\xfa\x76\x7d\ +\xf3\xf4\x3e\x1e\x2d\x5c\xc3\x85\x40\x55\xdb\x7c\xc0\xba\x88\x73\ +\xb5\x6f\xea\x8c\x56\xd9\xd2\xa5\x40\x9a\x75\x12\x61\x4c\x99\x91\ +\xac\x9b\x4c\x64\x6e\x6e\x55\xc5\x00\x58\xaf\xa8\xc4\x61\x9d\x09\ +\xcc\xdd\x7e\x47\xdf\x14\x43\x2f\x26\x14\x0d\xc0\xfa\x81\x84\x22\ +\x05\x52\x14\xeb\x22\xd2\xe9\x21\x95\x94\x74\x48\xe8\xcd\xef\xa6\ +\x43\xa4\x28\x8a\xf0\x0f\x23\x2d\x32\x96\x8b\x20\x4b\x56\x00\x00\ +\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x02\x7c\ +\x2f\ +\x2a\x20\x58\x50\x4d\x20\x2a\x2f\x0d\x0a\x73\x74\x61\x74\x69\x63\ +\x20\x63\x68\x61\x72\x20\x2a\x20\x6e\x61\x6d\x65\x73\x70\x61\x63\ +\x65\x73\x5f\x78\x70\x6d\x5b\x5d\x20\x3d\x20\x7b\x0d\x0a\x22\x31\ +\x36\x20\x31\x36\x20\x31\x35\x20\x31\x22\x2c\x0d\x0a\x22\x20\x09\ +\x63\x20\x4e\x6f\x6e\x65\x22\x2c\x0d\x0a\x22\x2e\x09\x63\x20\x23\ +\x44\x38\x39\x34\x39\x34\x22\x2c\x0d\x0a\x22\x2b\x09\x63\x20\x23\ +\x42\x44\x34\x39\x34\x39\x22\x2c\x0d\x0a\x22\x40\x09\x63\x20\x23\ +\x46\x46\x38\x44\x38\x44\x22\x2c\x0d\x0a\x22\x23\x09\x63\x20\x23\ +\x46\x46\x38\x38\x38\x38\x22\x2c\x0d\x0a\x22\x24\x09\x63\x20\x23\ +\x46\x46\x38\x33\x38\x33\x22\x2c\x0d\x0a\x22\x25\x09\x63\x20\x23\ +\x46\x46\x46\x46\x46\x46\x22\x2c\x0d\x0a\x22\x26\x09\x63\x20\x23\ +\x43\x38\x36\x38\x36\x38\x22\x2c\x0d\x0a\x22\x2a\x09\x63\x20\x23\ +\x46\x46\x37\x44\x37\x44\x22\x2c\x0d\x0a\x22\x3d\x09\x63\x20\x23\ +\x44\x38\x35\x45\x35\x45\x22\x2c\x0d\x0a\x22\x2d\x09\x63\x20\x23\ +\x46\x46\x37\x36\x37\x36\x22\x2c\x0d\x0a\x22\x3b\x09\x63\x20\x23\ +\x46\x46\x36\x46\x36\x46\x22\x2c\x0d\x0a\x22\x3e\x09\x63\x20\x23\ +\x46\x46\x36\x38\x36\x38\x22\x2c\x0d\x0a\x22\x2c\x09\x63\x20\x23\ +\x46\x46\x36\x30\x36\x30\x22\x2c\x0d\x0a\x22\x27\x09\x63\x20\x23\ +\x46\x46\x35\x43\x35\x43\x22\x2c\x0d\x0a\x22\x20\x20\x20\x20\x2e\ +\x2b\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\ +\x20\x20\x20\x2e\x2b\x40\x2b\x2e\x20\x20\x20\x20\x20\x20\x20\x20\ +\x22\x2c\x0d\x0a\x22\x20\x20\x2e\x2b\x23\x2b\x23\x2b\x2e\x20\x20\ +\x20\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\x20\x2e\x2b\x24\x2b\x25\ +\x2b\x24\x2b\x26\x2b\x2e\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\x2e\ +\x2b\x2a\x2b\x25\x2b\x25\x2b\x3d\x2b\x40\x2b\x2e\x20\x20\x20\x22\ +\x2c\x0d\x0a\x22\x2b\x2d\x2b\x25\x2b\x2b\x2b\x25\x2b\x23\x2b\x23\ +\x2b\x2e\x20\x20\x22\x2c\x0d\x0a\x22\x2e\x2b\x3b\x2b\x2b\x40\x2b\ +\x2b\x24\x2b\x25\x2b\x24\x2b\x2e\x20\x22\x2c\x0d\x0a\x22\x20\x2e\ +\x2b\x2b\x23\x2b\x2b\x2a\x2b\x25\x2b\x25\x2b\x2a\x2b\x2e\x22\x2c\ +\x0d\x0a\x22\x20\x2e\x2b\x24\x2b\x2b\x2d\x2b\x25\x2b\x2d\x2b\x25\ +\x2b\x2d\x2b\x22\x2c\x0d\x0a\x22\x2e\x2b\x2a\x2b\x25\x2b\x2b\x3b\ +\x2b\x25\x2b\x25\x2b\x3b\x2b\x2e\x22\x2c\x0d\x0a\x22\x2b\x2d\x2b\ +\x25\x2b\x2d\x2b\x2b\x3e\x2b\x25\x2b\x3e\x2b\x2e\x20\x22\x2c\x0d\ +\x0a\x22\x2e\x2b\x3b\x2b\x25\x2b\x25\x2b\x2b\x2c\x2b\x2c\x2b\x2e\ +\x20\x20\x22\x2c\x0d\x0a\x22\x20\x2e\x2b\x3e\x2b\x25\x2b\x3e\x2b\ +\x2b\x27\x2b\x2e\x20\x20\x20\x22\x2c\x0d\x0a\x22\x20\x20\x2e\x2b\ +\x2c\x2b\x2c\x2b\x2e\x2e\x2b\x2e\x20\x20\x20\x20\x22\x2c\x0d\x0a\ +\x22\x20\x20\x20\x2e\x2b\x27\x2b\x2e\x20\x20\x20\x20\x20\x20\x20\ +\x20\x22\x2c\x0d\x0a\x22\x20\x20\x20\x20\x2e\x2b\x2e\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x22\x7d\x3b\x0d\x0a\ +\x00\x00\x05\x7e\ +\x2f\ +\x2a\x20\x58\x50\x4d\x20\x2a\x2f\x0a\x73\x74\x61\x74\x69\x63\x20\ +\x63\x68\x61\x72\x20\x2a\x20\x75\x73\x65\x72\x5f\x78\x70\x6d\x5b\ +\x5d\x20\x3d\x20\x7b\x0a\x22\x31\x36\x20\x31\x36\x20\x36\x39\x20\ +\x31\x22\x2c\x0a\x22\x20\x09\x63\x20\x4e\x6f\x6e\x65\x22\x2c\x0a\ +\x22\x2e\x09\x63\x20\x23\x39\x39\x39\x39\x39\x39\x22\x2c\x0a\x22\ +\x2b\x09\x63\x20\x23\x36\x41\x36\x41\x36\x41\x22\x2c\x0a\x22\x40\ +\x09\x63\x20\x23\x42\x44\x42\x44\x42\x44\x22\x2c\x0a\x22\x23\x09\ +\x63\x20\x23\x37\x45\x37\x41\x37\x37\x22\x2c\x0a\x22\x24\x09\x63\ +\x20\x23\x42\x37\x41\x45\x41\x37\x22\x2c\x0a\x22\x25\x09\x63\x20\ +\x23\x45\x34\x44\x38\x43\x45\x22\x2c\x0a\x22\x26\x09\x63\x20\x23\ +\x45\x34\x44\x38\x44\x30\x22\x2c\x0a\x22\x2a\x09\x63\x20\x23\x42\ +\x36\x41\x45\x41\x41\x22\x2c\x0a\x22\x3d\x09\x63\x20\x23\x37\x45\ +\x37\x41\x37\x39\x22\x2c\x0a\x22\x2d\x09\x63\x20\x23\x44\x37\x43\ +\x43\x43\x33\x22\x2c\x0a\x22\x3b\x09\x63\x20\x23\x46\x38\x45\x41\ +\x44\x46\x22\x2c\x0a\x22\x3e\x09\x63\x20\x23\x46\x38\x45\x41\x45\ +\x31\x22\x2c\x0a\x22\x2c\x09\x63\x20\x23\x46\x37\x45\x41\x45\x32\ +\x22\x2c\x0a\x22\x27\x09\x63\x20\x23\x46\x37\x45\x41\x45\x34\x22\ +\x2c\x0a\x22\x29\x09\x63\x20\x23\x44\x37\x43\x43\x43\x39\x22\x2c\ +\x0a\x22\x21\x09\x63\x20\x23\x37\x45\x37\x41\x37\x41\x22\x2c\x0a\ +\x22\x7e\x09\x63\x20\x23\x46\x37\x45\x41\x45\x36\x22\x2c\x0a\x22\ +\x7b\x09\x63\x20\x23\x46\x37\x45\x41\x45\x38\x22\x2c\x0a\x22\x5d\ +\x09\x63\x20\x23\x42\x36\x41\x45\x41\x45\x22\x2c\x0a\x22\x5e\x09\ +\x63\x20\x23\x46\x37\x45\x41\x45\x41\x22\x2c\x0a\x22\x2f\x09\x63\ +\x20\x23\x45\x33\x44\x38\x44\x41\x22\x2c\x0a\x22\x28\x09\x63\x20\ +\x23\x46\x37\x45\x41\x45\x43\x22\x2c\x0a\x22\x5f\x09\x63\x20\x23\ +\x45\x33\x44\x38\x44\x42\x22\x2c\x0a\x22\x3a\x09\x63\x20\x23\x46\ +\x37\x45\x41\x45\x45\x22\x2c\x0a\x22\x3c\x09\x63\x20\x23\x42\x36\ +\x41\x45\x42\x31\x22\x2c\x0a\x22\x5b\x09\x63\x20\x23\x44\x36\x43\ +\x43\x44\x30\x22\x2c\x0a\x22\x7d\x09\x63\x20\x23\x37\x44\x37\x41\ +\x37\x43\x22\x2c\x0a\x22\x7c\x09\x63\x20\x23\x35\x42\x35\x43\x35\ +\x43\x22\x2c\x0a\x22\x31\x09\x63\x20\x23\x35\x41\x35\x43\x35\x43\ +\x22\x2c\x0a\x22\x32\x09\x63\x20\x23\x36\x41\x36\x44\x36\x44\x22\ +\x2c\x0a\x22\x33\x09\x63\x20\x23\x41\x36\x42\x34\x42\x37\x22\x2c\ +\x0a\x22\x34\x09\x63\x20\x23\x42\x34\x43\x35\x43\x39\x22\x2c\x0a\ +\x22\x35\x09\x63\x20\x23\x38\x37\x39\x30\x39\x33\x22\x2c\x0a\x22\ +\x36\x09\x63\x20\x23\x36\x34\x36\x37\x36\x38\x22\x2c\x0a\x22\x37\ +\x09\x63\x20\x23\x36\x33\x36\x37\x36\x38\x22\x2c\x0a\x22\x38\x09\ +\x63\x20\x23\x38\x33\x38\x45\x39\x33\x22\x2c\x0a\x22\x39\x09\x63\ +\x20\x23\x41\x38\x42\x46\x43\x41\x22\x2c\x0a\x22\x30\x09\x63\x20\ +\x23\x39\x39\x41\x44\x42\x37\x22\x2c\x0a\x22\x61\x09\x63\x20\x23\ +\x36\x35\x36\x42\x36\x44\x22\x2c\x0a\x22\x62\x09\x63\x20\x23\x35\ +\x41\x35\x41\x35\x41\x22\x2c\x0a\x22\x63\x09\x63\x20\x23\x41\x33\ +\x42\x30\x42\x33\x22\x2c\x0a\x22\x64\x09\x63\x20\x23\x44\x34\x45\ +\x41\x46\x30\x22\x2c\x0a\x22\x65\x09\x63\x20\x23\x44\x31\x45\x39\ +\x46\x30\x22\x2c\x0a\x22\x66\x09\x63\x20\x23\x43\x45\x45\x37\x46\ +\x30\x22\x2c\x0a\x22\x67\x09\x63\x20\x23\x43\x42\x45\x36\x46\x31\ +\x22\x2c\x0a\x22\x68\x09\x63\x20\x23\x43\x37\x45\x34\x46\x31\x22\ +\x2c\x0a\x22\x69\x09\x63\x20\x23\x43\x34\x45\x33\x46\x31\x22\x2c\ +\x0a\x22\x6a\x09\x63\x20\x23\x43\x31\x45\x31\x46\x31\x22\x2c\x0a\ +\x22\x6b\x09\x63\x20\x23\x42\x44\x45\x30\x46\x31\x22\x2c\x0a\x22\ +\x6c\x09\x63\x20\x23\x39\x32\x41\x38\x42\x34\x22\x2c\x0a\x22\x6d\ +\x09\x63\x20\x23\x35\x38\x35\x41\x35\x42\x22\x2c\x0a\x22\x6e\x09\ +\x63\x20\x23\x38\x33\x38\x41\x38\x43\x22\x2c\x0a\x22\x6f\x09\x63\ +\x20\x23\x42\x41\x44\x45\x46\x32\x22\x2c\x0a\x22\x70\x09\x63\x20\ +\x23\x42\x37\x44\x44\x46\x32\x22\x2c\x0a\x22\x71\x09\x63\x20\x23\ +\x37\x37\x38\x35\x38\x43\x22\x2c\x0a\x22\x72\x09\x63\x20\x23\x39\ +\x34\x39\x34\x39\x34\x22\x2c\x0a\x22\x73\x09\x63\x20\x23\x41\x35\ +\x42\x33\x42\x37\x22\x2c\x0a\x22\x74\x09\x63\x20\x23\x42\x34\x44\ +\x43\x46\x32\x22\x2c\x0a\x22\x75\x09\x63\x20\x23\x39\x30\x41\x41\ +\x42\x38\x22\x2c\x0a\x22\x76\x09\x63\x20\x23\x36\x45\x36\x45\x36\ +\x45\x22\x2c\x0a\x22\x77\x09\x63\x20\x23\x42\x46\x44\x33\x44\x39\ +\x22\x2c\x0a\x22\x78\x09\x63\x20\x23\x42\x32\x44\x42\x46\x32\x22\ +\x2c\x0a\x22\x79\x09\x63\x20\x23\x41\x33\x43\x36\x44\x42\x22\x2c\ +\x0a\x22\x7a\x09\x63\x20\x23\x35\x38\x35\x38\x35\x38\x22\x2c\x0a\ +\x22\x41\x09\x63\x20\x23\x43\x43\x45\x35\x45\x45\x22\x2c\x0a\x22\ +\x42\x09\x63\x20\x23\x42\x31\x44\x41\x46\x32\x22\x2c\x0a\x22\x43\ +\x09\x63\x20\x23\x42\x30\x44\x38\x46\x30\x22\x2c\x0a\x22\x44\x09\ +\x63\x20\x23\x35\x35\x35\x35\x35\x35\x22\x2c\x0a\x22\x20\x20\x20\ +\x20\x20\x20\x2e\x2b\x2b\x2e\x20\x20\x20\x20\x20\x20\x22\x2c\x0a\ +\x22\x20\x20\x20\x20\x40\x23\x24\x25\x26\x2a\x3d\x40\x20\x20\x20\ +\x20\x22\x2c\x0a\x22\x20\x20\x20\x20\x23\x2d\x3b\x3e\x2c\x27\x29\ +\x21\x20\x20\x20\x20\x22\x2c\x0a\x22\x20\x20\x20\x2e\x24\x3b\x3e\ +\x2c\x27\x7e\x7b\x5d\x2e\x20\x20\x20\x22\x2c\x0a\x22\x20\x20\x20\ +\x2b\x25\x3e\x2c\x27\x7e\x7b\x5e\x2f\x2b\x20\x20\x20\x22\x2c\x0a\ +\x22\x20\x20\x20\x2b\x26\x2c\x27\x7e\x7b\x5e\x28\x5f\x2b\x20\x20\ +\x20\x22\x2c\x0a\x22\x20\x20\x20\x2e\x2a\x27\x7e\x7b\x5e\x28\x3a\ +\x3c\x2e\x20\x20\x20\x22\x2c\x0a\x22\x20\x20\x20\x20\x3d\x29\x7b\ +\x5e\x28\x3a\x5b\x7d\x20\x20\x20\x20\x22\x2c\x0a\x22\x20\x20\x20\ +\x20\x7c\x21\x5d\x2f\x5f\x3c\x7d\x31\x20\x20\x20\x20\x22\x2c\x0a\ +\x22\x20\x20\x20\x32\x33\x34\x35\x36\x37\x38\x39\x30\x61\x20\x20\ +\x20\x22\x2c\x0a\x22\x20\x20\x62\x63\x64\x65\x66\x67\x68\x69\x6a\ +\x6b\x6c\x6d\x20\x20\x22\x2c\x0a\x22\x20\x20\x6e\x64\x65\x66\x67\ +\x68\x69\x6a\x6b\x6f\x70\x71\x20\x20\x22\x2c\x0a\x22\x20\x72\x73\ +\x65\x66\x67\x68\x69\x6a\x6b\x6f\x70\x74\x75\x72\x20\x22\x2c\x0a\ +\x22\x20\x76\x77\x66\x67\x68\x69\x6a\x6b\x6f\x70\x74\x78\x79\x76\ +\x20\x22\x2c\x0a\x22\x20\x7a\x41\x67\x68\x69\x6a\x6b\x6f\x70\x74\ +\x78\x42\x43\x7a\x20\x22\x2c\x0a\x22\x20\x44\x7a\x44\x44\x44\x44\ +\x44\x44\x44\x44\x44\x44\x7a\x44\x20\x22\x7d\x3b\x0a\ +\x00\x00\x04\x57\ +\x2f\ +\x2a\x20\x58\x50\x4d\x20\x2a\x2f\x0d\x0a\x73\x74\x61\x74\x69\x63\ +\x20\x63\x68\x61\x72\x20\x2a\x20\x75\x73\x65\x72\x73\x5f\x78\x70\ +\x6d\x5b\x5d\x20\x3d\x20\x7b\x0d\x0a\x22\x31\x36\x20\x31\x36\x20\ +\x34\x35\x20\x31\x22\x2c\x0d\x0a\x22\x20\x09\x63\x20\x4e\x6f\x6e\ +\x65\x22\x2c\x0d\x0a\x22\x2e\x09\x63\x20\x23\x43\x35\x43\x35\x43\ +\x35\x22\x2c\x0d\x0a\x22\x2b\x09\x63\x20\x23\x37\x46\x37\x46\x37\ +\x46\x22\x2c\x0d\x0a\x22\x40\x09\x63\x20\x23\x38\x42\x38\x37\x38\ +\x32\x22\x2c\x0d\x0a\x22\x23\x09\x63\x20\x23\x44\x30\x43\x35\x42\ +\x43\x22\x2c\x0d\x0a\x22\x24\x09\x63\x20\x23\x44\x30\x43\x35\x42\ +\x45\x22\x2c\x0d\x0a\x22\x25\x09\x63\x20\x23\x38\x42\x38\x37\x38\ +\x35\x22\x2c\x0d\x0a\x22\x26\x09\x63\x20\x23\x46\x38\x45\x41\x45\ +\x31\x22\x2c\x0d\x0a\x22\x2a\x09\x63\x20\x23\x46\x37\x45\x41\x45\ +\x34\x22\x2c\x0d\x0a\x22\x3d\x09\x63\x20\x23\x43\x46\x43\x35\x43\ +\x34\x22\x2c\x0d\x0a\x22\x2d\x09\x63\x20\x23\x46\x37\x45\x41\x45\ +\x38\x22\x2c\x0d\x0a\x22\x3b\x09\x63\x20\x23\x43\x46\x43\x35\x43\ +\x37\x22\x2c\x0d\x0a\x22\x3e\x09\x63\x20\x23\x42\x46\x42\x46\x42\ +\x46\x22\x2c\x0d\x0a\x22\x2c\x09\x63\x20\x23\x38\x42\x38\x37\x38\ +\x38\x22\x2c\x0d\x0a\x22\x27\x09\x63\x20\x23\x35\x42\x35\x43\x35\ +\x43\x22\x2c\x0d\x0a\x22\x29\x09\x63\x20\x23\x37\x44\x38\x33\x38\ +\x34\x22\x2c\x0d\x0a\x22\x21\x09\x63\x20\x23\x36\x46\x37\x33\x37\ +\x34\x22\x2c\x0d\x0a\x22\x7e\x09\x63\x20\x23\x36\x45\x37\x33\x37\ +\x34\x22\x2c\x0d\x0a\x22\x7b\x09\x63\x20\x23\x37\x39\x38\x31\x38\ +\x34\x22\x2c\x0d\x0a\x22\x5d\x09\x63\x20\x23\x35\x41\x35\x43\x35\ +\x43\x22\x2c\x0d\x0a\x22\x5e\x09\x63\x20\x23\x42\x37\x42\x37\x42\ +\x37\x22\x2c\x0d\x0a\x22\x2f\x09\x63\x20\x23\x38\x43\x39\x35\x39\ +\x37\x22\x2c\x0d\x0a\x22\x28\x09\x63\x20\x23\x44\x34\x45\x41\x46\ +\x30\x22\x2c\x0d\x0a\x22\x5f\x09\x63\x20\x23\x44\x30\x45\x38\x46\ +\x30\x22\x2c\x0d\x0a\x22\x3a\x09\x63\x20\x23\x43\x41\x45\x36\x46\ +\x31\x22\x2c\x0d\x0a\x22\x3c\x09\x63\x20\x23\x43\x34\x45\x33\x46\ +\x31\x22\x2c\x0d\x0a\x22\x5b\x09\x63\x20\x23\x37\x32\x37\x43\x38\ +\x30\x22\x2c\x0d\x0a\x22\x7d\x09\x63\x20\x23\x36\x44\x36\x44\x36\ +\x44\x22\x2c\x0d\x0a\x22\x7c\x09\x63\x20\x23\x39\x42\x39\x42\x39\ +\x42\x22\x2c\x0d\x0a\x22\x31\x09\x63\x20\x23\x38\x30\x38\x30\x38\ +\x30\x22\x2c\x0d\x0a\x22\x32\x09\x63\x20\x23\x42\x34\x43\x34\x43\ +\x38\x22\x2c\x0d\x0a\x22\x33\x09\x63\x20\x23\x39\x41\x42\x31\x42\ +\x43\x22\x2c\x0d\x0a\x22\x34\x09\x63\x20\x23\x35\x42\x35\x42\x35\ +\x42\x22\x2c\x0d\x0a\x22\x35\x09\x63\x20\x23\x43\x43\x45\x33\x45\ +\x42\x22\x2c\x0d\x0a\x22\x36\x09\x63\x20\x23\x42\x45\x45\x30\x46\ +\x31\x22\x2c\x0d\x0a\x22\x37\x09\x63\x20\x23\x36\x44\x37\x37\x37\ +\x43\x22\x2c\x0d\x0a\x22\x38\x09\x63\x20\x23\x37\x34\x37\x41\x37\ +\x42\x22\x2c\x0d\x0a\x22\x39\x09\x63\x20\x23\x38\x31\x39\x30\x39\ +\x37\x22\x2c\x0d\x0a\x22\x30\x09\x63\x20\x23\x41\x31\x41\x31\x41\ +\x31\x22\x2c\x0d\x0a\x22\x61\x09\x63\x20\x23\x35\x35\x35\x35\x35\ +\x35\x22\x2c\x0d\x0a\x22\x62\x09\x63\x20\x23\x37\x33\x37\x39\x37\ +\x42\x22\x2c\x0d\x0a\x22\x63\x09\x63\x20\x23\x39\x46\x42\x42\x43\ +\x41\x22\x2c\x0d\x0a\x22\x64\x09\x63\x20\x23\x39\x45\x42\x30\x42\ +\x37\x22\x2c\x0d\x0a\x22\x65\x09\x63\x20\x23\x42\x38\x44\x45\x46\ +\x32\x22\x2c\x0d\x0a\x22\x66\x09\x63\x20\x23\x42\x31\x44\x37\x45\ +\x43\x22\x2c\x0d\x0a\x22\x20\x20\x2e\x2b\x2b\x2e\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\x20\x2e\x40\x23\x24\ +\x25\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\ +\x20\x2b\x23\x26\x2a\x3d\x2b\x20\x20\x20\x2e\x2b\x2b\x2e\x20\x20\ +\x22\x2c\x0d\x0a\x22\x20\x2b\x24\x2a\x2d\x3b\x2b\x20\x20\x2e\x40\ +\x23\x24\x25\x2e\x20\x22\x2c\x0d\x0a\x22\x20\x3e\x25\x3d\x3b\x2c\ +\x3e\x20\x20\x2b\x23\x26\x2a\x3d\x2b\x20\x22\x2c\x0d\x0a\x22\x20\ +\x27\x29\x21\x7e\x7b\x5d\x20\x20\x2b\x24\x2a\x2d\x3b\x2b\x20\x22\ +\x2c\x0d\x0a\x22\x5e\x2f\x28\x5f\x3a\x3c\x5b\x7d\x2b\x7c\x25\x3d\ +\x3b\x2c\x3e\x20\x22\x2c\x0d\x0a\x22\x31\x32\x5f\x3a\x3c\x33\x40\ +\x23\x24\x25\x21\x21\x7e\x7b\x5d\x20\x22\x2c\x0d\x0a\x22\x34\x35\ +\x3a\x3c\x36\x37\x23\x26\x2a\x3d\x38\x5f\x3a\x3c\x39\x5e\x22\x2c\ +\x0d\x0a\x22\x30\x34\x61\x61\x61\x61\x24\x2a\x2d\x3b\x62\x3a\x3c\ +\x36\x63\x31\x22\x2c\x0d\x0a\x22\x20\x20\x20\x20\x20\x3e\x25\x3d\ +\x3b\x2c\x64\x3c\x36\x65\x66\x34\x22\x2c\x0d\x0a\x22\x20\x20\x20\ +\x20\x20\x27\x29\x21\x7e\x7b\x5d\x61\x61\x61\x34\x30\x22\x2c\x0d\ +\x0a\x22\x20\x20\x20\x20\x5e\x2f\x28\x5f\x3a\x3c\x39\x5e\x20\x20\ +\x20\x20\x22\x2c\x0d\x0a\x22\x20\x20\x20\x20\x31\x32\x5f\x3a\x3c\ +\x36\x63\x31\x20\x20\x20\x20\x22\x2c\x0d\x0a\x22\x20\x20\x20\x20\ +\x34\x35\x3a\x3c\x36\x65\x66\x34\x20\x20\x20\x20\x22\x2c\x0d\x0a\ +\x22\x20\x20\x20\x20\x30\x34\x61\x61\x61\x61\x34\x30\x20\x20\x20\ +\x20\x22\x7d\x3b\x0d\x0a\ +\x00\x00\x05\x7f\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ +\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\ +\x01\x42\x28\x9b\x78\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ +\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x00\x18\x74\x45\ +\x58\x74\x54\x69\x74\x6c\x65\x00\x47\x49\x53\x20\x69\x63\x6f\x6e\ +\x20\x74\x68\x65\x6d\x65\x20\x30\x2e\x31\x77\x5a\xf1\x1a\x00\x00\ +\x00\x18\x74\x45\x58\x74\x41\x75\x74\x68\x6f\x72\x00\x52\x6f\x62\ +\x65\x72\x74\x20\x53\x7a\x63\x7a\x65\x70\x61\x6e\x65\x6b\x5f\x56\ +\xb1\x08\x00\x00\x00\x27\x74\x45\x58\x74\x44\x65\x73\x63\x72\x69\ +\x70\x74\x69\x6f\x6e\x00\x68\x74\x74\x70\x3a\x2f\x2f\x72\x6f\x62\ +\x65\x72\x74\x2e\x73\x7a\x63\x7a\x65\x70\x61\x6e\x65\x6b\x2e\x70\ +\x6c\x90\x59\x48\x60\x00\x00\x00\x18\x74\x45\x58\x74\x43\x72\x65\ +\x61\x74\x69\x6f\x6e\x20\x54\x69\x6d\x65\x00\x32\x30\x30\x38\x2d\ +\x31\x32\x2d\x31\x32\x58\x2e\x3b\xbf\x00\x00\x00\x52\x74\x45\x58\ +\x74\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x00\x43\x43\x20\x41\x74\ +\x74\x72\x69\x62\x75\x74\x69\x6f\x6e\x2d\x53\x68\x61\x72\x65\x41\ +\x6c\x69\x6b\x65\x20\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\ +\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\ +\x6c\x69\x63\x65\x6e\x73\x65\x73\x2f\x62\x79\x2d\x73\x61\x2f\x33\ +\x2e\x30\x2f\x5e\x83\x5a\xbc\x00\x00\x03\xff\x49\x44\x41\x54\x48\ +\x89\xa5\x96\x5f\x6c\x53\x55\x1c\xc7\x3f\xf7\xf4\x76\x6b\x7b\xe9\ +\x56\xba\x92\xd1\xb9\xb2\x96\x07\x65\x26\x8c\x0d\x90\x17\x30\x84\ +\x81\x84\x37\xc7\xeb\x20\x88\x33\x31\xf4\x85\xa8\xf0\x44\x62\x22\ +\x26\x46\x1f\x58\x0c\x8a\x59\x0c\x91\x85\x44\x89\x0f\xc4\x00\x25\ +\xc8\xaa\x0c\x54\xcc\x28\xb0\x11\x45\x63\x62\xc1\xfd\x69\xa4\x8e\ +\x66\x6b\xd7\x76\xed\xc6\x7a\xcf\xf1\x61\x71\x61\xdb\x5d\x15\xfc\ +\x3e\xdd\x73\x7f\xe7\xfc\x3e\xbf\xef\x3d\xbf\x73\x72\x35\xa5\x14\ +\xe5\xb4\xed\xd5\x37\x3d\xe6\x8c\x3a\xa8\xdb\x6c\x9b\xa5\x52\x41\ +\x29\x65\x1d\x80\x10\xe2\x81\xd0\xb4\xa1\x92\x69\xfe\x68\xb3\x6b\ +\x1f\x5d\xed\xfe\x30\x63\xb5\x5e\x2b\x07\x68\x7d\xe5\xad\x23\x52\ +\xf1\xb6\xc7\xe3\xd1\xdd\x6e\xb7\x72\xb9\x9c\x25\xa7\xcb\x30\x01\ +\x8a\x85\x49\x5b\xa1\x50\xd4\x73\xb9\x9c\x96\xc9\x64\x4a\x52\x9a\ +\xef\x7e\xff\xf9\xf1\xf7\x17\xe6\xd0\xcb\x55\x1f\xf0\xd7\x1e\x75\ +\xba\xab\x54\x5d\x5d\x40\xd7\x84\x06\x60\x9f\x0b\x7a\xbd\x00\x28\ +\xa9\x88\xc7\xe3\x6a\x68\x78\xe8\x28\xb0\x18\x50\x82\xa8\x00\xaf\ +\x15\xe0\x9d\x83\xfb\x75\x21\x04\x52\xca\x59\xbb\x9a\x40\x13\x1a\ +\xa6\x29\xc9\x4e\x16\x39\xfa\xf1\x69\x72\xf9\x3c\x0e\x47\xa5\x00\ +\x6c\x56\x39\x74\x01\xde\x8b\x91\x48\x4d\x2c\x16\xf3\x56\x55\x55\ +\xcd\xec\xdd\xb7\xef\x81\x7f\xe5\xca\x47\xd1\x68\xd4\xdb\x77\x23\ +\x86\x61\x18\x6a\xeb\xb6\xed\xda\x33\x81\x00\xa7\x3f\x3b\xc9\xde\ +\xfd\xaf\x61\x9a\x26\xcb\x5c\x0e\x96\x7b\xbd\xac\x0a\x06\x59\x51\ +\xe3\xcb\xf7\x44\x7b\xaa\xad\x00\x22\x97\xcf\xdb\x2e\x9c\x3f\xef\ +\x7f\x69\xe7\xce\x2a\xc3\x30\x6a\x3e\xed\xea\x5a\xdb\xdb\xdb\xbb\ +\xe1\xd2\xc5\x8b\xa1\x75\xcd\x2d\x34\x04\x83\xda\xe9\x53\x27\x99\ +\x9e\x9e\x66\x78\xf0\x0f\x9c\x4e\x07\x2e\x97\x0b\xa7\xc3\x41\x28\ +\x14\xc2\x57\x53\x83\x86\xb4\x4c\x0e\x20\x5c\x2e\x97\x34\x0c\xa3\ +\xd4\x73\xf9\x32\x3e\x9f\x8f\x70\x38\xcc\xfd\x7b\xf7\x68\x59\xbf\ +\x9e\x96\x8d\x2f\xb0\xb5\x75\x07\x7e\x7f\x1d\x03\xb7\x6f\x2d\x95\ +\x83\x4c\x66\x62\xc9\x98\x9e\xc9\x64\xf4\xf6\x3d\x7b\xfe\xfc\x6b\ +\x74\xf4\xd9\x7b\xf1\x38\x9f\x9c\x38\x41\x7d\x20\x80\x10\x02\x80\ +\x62\xb1\x48\x3e\x9f\x63\x7a\x6a\x0a\x14\x98\xa6\x49\xa9\x54\x42\ +\x49\x49\x3c\x1e\x27\x97\xcd\x92\xcd\x65\x97\x04\x88\x87\xa3\xa3\ +\xf6\xee\xee\xee\x55\x4e\x87\x83\xe7\xd6\xac\xa1\x50\x28\xd0\xd4\ +\xd4\x44\x7f\x7f\x3f\xdf\xf6\x7c\x4d\xe7\x07\xef\x91\x1e\x4f\xd3\ +\xb2\x61\x23\xa6\x94\xdc\xba\xd1\xc7\xed\xd8\x0d\x52\xa9\x14\x93\ +\x93\x93\x54\x2f\x5f\xce\x8b\x5b\x36\x2f\xed\xa0\xb1\xb1\xb1\xd0\ +\xb6\x7b\x77\xb2\xaf\xaf\x2f\x64\x18\x06\xaf\x1f\x38\x40\x28\x14\ +\x42\x4a\x49\xef\xd5\x6b\x34\x04\x43\xa4\xd3\x69\x7e\xfb\xf5\x17\ +\x42\xab\x57\x73\xe7\xf6\x2d\xa4\x52\x54\x3a\x1c\x34\x37\x37\xcf\ +\x56\xc9\xd2\x67\x49\x1b\x4a\x24\x54\xa0\xbe\xbe\x3f\x95\x4a\x6d\ +\xf0\x78\x3c\xf3\x82\x0f\x52\xe3\x18\x86\xb1\x68\xd1\x4c\xc9\xa4\ +\x30\x3d\xc3\x97\xdf\xc4\x66\xc7\x8f\x1e\x71\xf5\xda\x35\x7e\xf8\ +\xe2\xb8\xb6\xc8\xc1\xa5\x48\x84\x70\x38\xbc\xf1\xab\xb3\x67\x55\ +\x5b\x5b\xdb\xbc\xe0\x99\x0b\x57\x48\x8c\x8e\x51\x5b\x5b\x8b\xdb\ +\xbd\x0c\x47\x65\x25\x15\x15\x15\x24\xc7\x26\x28\x16\x8b\x4c\x4f\ +\x4d\x31\x31\x31\xc1\xd0\xd0\x30\x9a\x10\xe7\x2c\x3f\xd1\x92\xde\ +\x80\x8e\x97\xb7\x33\x9c\x4c\x71\x25\xf6\x13\xc9\x44\x82\x6c\xa1\ +\x80\x94\x8a\xdf\x07\x13\x08\xa1\xe1\x71\xbb\x59\x5d\x5f\xcb\x8e\ +\xb5\x01\x8e\x1c\x7e\x63\xf7\x13\x03\x00\x1a\xfc\x2b\xe8\x68\xdb\ +\x01\x80\x54\x8a\xf1\x6c\x0e\x25\x15\x35\xd5\xee\xb9\x4e\x3b\x77\ +\xce\xb2\xf8\xff\x06\x78\x5c\x42\xd3\xf0\x55\x57\x01\x30\x98\x1a\ +\x24\x32\x10\x61\x64\x6c\x04\x80\xeb\x9d\xd7\x17\xee\xf4\x4d\x85\ +\x3a\xf4\x44\x80\xc7\x15\x19\x88\x30\x23\x67\x58\x53\xdf\x88\x6e\ +\xd3\xd9\xb5\x6e\x17\x52\x49\xa2\x3f\x47\x29\x99\x25\x26\x26\x33\ +\x9b\x92\xe9\x64\xe7\x53\x03\x46\xc6\x46\x68\x0a\xad\xc3\x26\x66\ +\xef\xb8\x06\x5f\x03\x00\x76\xdd\x8e\x5d\xb7\x53\x61\xaf\x20\x99\ +\x4e\x6e\x12\x4f\x0b\x00\xe6\x92\x97\x8b\x3d\xb5\x03\x80\xd6\xe7\ +\x5b\x09\xae\x08\xce\x7b\xd7\xb1\xb5\x03\x98\x75\x78\xe7\xfe\xc0\ +\xff\x03\xa4\xb3\xe3\xf8\xdd\x2b\x2d\x63\x0f\xc7\x47\x81\x05\x0e\ +\xca\xb5\x9b\x95\x4e\x7d\x77\x6a\xee\xf9\x58\xfb\x31\x00\x0e\x9f\ +\x39\x3c\x6f\xce\x1c\x20\x1c\x0e\x2f\x3a\xe6\xe5\x64\xd1\x96\x96\ +\xd2\x01\xba\xba\xba\x2c\x27\xff\x0b\xf4\x26\xb0\xe9\x9f\xc1\xdd\ +\xc4\x5d\xab\x4d\xbf\x59\xf6\xaf\xa2\x9c\xda\x3b\xdb\xb7\x68\x68\ +\x9d\x8f\x43\x16\x26\x57\xa8\x43\x7f\x03\x64\x65\x9c\xa6\xc8\x81\ +\xc5\x52\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x02\x82\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01\x42\x28\ +\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x0b\x1b\x0c\x2b\ +\x00\xbd\x1b\xd1\x60\x00\x00\x02\x14\x49\x44\x41\x54\x48\xc7\xd5\ +\x96\x3d\x48\x1b\x61\x18\xc7\x7f\xb9\xbc\xa7\x98\x10\x52\x88\x34\ +\xd5\x4e\x66\xf2\x04\x09\x08\xcd\x10\xeb\x50\xc8\x70\x4b\xa1\x74\ +\xd0\xa9\x14\x6c\x4c\xd7\xb6\x1e\x6d\xa7\xac\x0d\x25\xb6\x9d\xb2\ +\x14\x2c\xa1\x93\x9d\xea\x12\x1c\x84\x82\x42\x41\x51\x68\x89\x9a\ +\x4e\x16\x87\x40\xd3\x28\x2d\x35\x21\xc1\xcb\x47\x07\xb9\xcb\x97\ +\x5a\x4d\xd2\xc1\x67\x79\xef\xfd\x3f\x77\xff\xff\xf3\xf5\xf2\x1e\ +\x5c\x76\xb3\x18\x0f\xb7\xee\x3f\xf9\xa1\xeb\x25\x77\x37\x48\x65\ +\x59\x64\x3e\xc5\x5f\x5d\x03\x10\x06\xa8\xeb\x25\x77\x34\x1a\xed\ +\x4a\xd4\x9a\xa6\x99\x81\x8a\x7a\xc7\xee\xf7\x5d\xe6\xe7\xdf\x51\ +\x2c\x14\x8e\x9d\x42\x26\xf4\x70\x06\xcf\x90\x87\x78\x3c\x4e\x32\ +\x99\x3c\x93\x58\x19\x19\xe1\xc1\xf4\x74\x03\x26\x35\xbf\x54\xd2\ +\x4b\xb5\x54\x45\x4d\xbf\x54\x2e\xff\x33\x72\x61\xb5\xb6\x62\xf5\ +\x1b\xcf\x90\x87\x48\xe4\xc5\x89\x1f\x37\x47\x76\x5e\x13\x75\x8d\ +\xa9\x68\x9a\x26\x75\xa9\xc9\x95\x16\x01\x5d\x2f\x49\x1f\xa2\xcf\ +\xbb\xd2\xe4\x49\x2d\x22\x9d\x58\x22\x80\xc7\x2f\xdf\x92\xfe\x79\ +\x00\xc0\xf5\xab\x2e\x5e\x3f\x9d\x01\xe0\xf3\xd7\x6f\xbc\x79\xff\ +\xf1\x4c\xe2\x47\xf7\xee\xe0\xf7\x0e\x9f\xde\x03\xc0\x24\x6c\x36\ +\xbf\x77\x18\xbf\xf7\xe2\x19\x4a\xff\xfb\x24\x5f\xfe\x12\x89\x76\ +\x53\x3f\xda\xdb\xa3\xb0\xb4\x84\x9e\x4e\xb7\xf8\x62\x36\xb0\x04\ +\x83\x6b\x65\x49\x9a\x6d\xbb\x44\xcf\x7a\x8b\xdc\xb8\x7b\x1b\x59\ +\x55\xc9\x6d\x6d\x61\x91\x65\x00\xaa\xba\x8e\x63\x74\x94\xa3\x6c\ +\xd6\x97\x5d\x5c\x9c\x6b\xbb\x44\xfb\xe1\x30\xbd\x83\x83\x38\xc6\ +\xc6\x10\x4e\x27\x7f\x36\x36\x00\x70\x8e\x8f\x63\x57\x14\x0e\x37\ +\x37\xa9\x82\x4f\x74\x32\x21\xb9\xed\x6d\xa4\xbe\x3e\xec\x8a\x62\ +\x62\x76\x45\x21\x9f\x4a\x91\xdb\xd9\xe9\x6c\x8a\x62\xb6\xe3\xd5\ +\x88\xdc\x10\xc9\xa7\x52\x26\xd6\xd1\x14\xed\x87\xc3\xfc\x5a\x59\ +\x01\xa0\x67\x60\xc0\x14\x28\xa6\xd3\x26\xde\xd1\x14\x19\xe6\x9e\ +\x9a\xc2\x15\x08\x70\xb0\xbc\x0c\x80\x2b\x10\x00\x20\xb3\xb0\xd0\ +\x28\xd0\x23\x8b\xcc\xa4\x16\x39\xf7\x95\x19\xb3\x41\xbf\xaa\x9a\ +\xe4\x06\xa1\x21\x52\x39\x3c\x24\x9b\x48\xd4\xee\xe4\x8b\x5a\x32\ +\x18\x5c\xbb\x32\x31\xe1\x13\x0e\x07\xd9\x44\xa2\xc1\xd7\xaf\xaa\ +\x94\xf3\x79\x7e\xaf\xae\xae\xb7\x2d\xf0\x25\x14\xba\x69\xad\x54\ +\xe6\xaa\xe0\x3b\xe5\x6f\x62\xbd\x2c\x49\xb3\x7f\x01\x9d\xe6\xd1\ +\x58\x93\x42\x94\x4e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ +\x82\ +\x00\x00\x05\x54\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x16\x00\x00\x00\x16\x08\x06\x00\x00\x00\xc4\xb4\x6c\x3b\ +\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ +\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\ +\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\ +\x67\x9b\xee\x3c\x1a\x00\x00\x04\xe6\x49\x44\x41\x54\x38\x8d\xb5\ +\x95\x69\x4c\x14\x67\x18\xc7\xff\xef\x3b\x33\x3b\xbb\xb3\x4b\x39\ +\x96\x5b\xe4\x10\x6b\x91\xa0\x16\x45\xa8\x68\x1b\x8f\x9a\x26\xad\ +\x31\x69\xda\x10\x82\x9a\x98\xa6\x02\xd6\x4f\xb6\x4d\x13\x93\x26\ +\xfd\xd2\x34\x31\x35\x69\xd2\x5a\x14\x24\x35\xb6\x80\xa4\x34\x69\ +\xb5\xb1\x47\x62\x3c\x4a\xad\x0a\x04\x41\x5b\x05\x42\x3d\x10\x16\ +\x01\x71\x81\xbd\xe7\x78\x9f\x7e\x60\x21\x1c\x7e\xf0\x4b\x27\xf9\ +\x67\x92\x99\x67\x7e\xf3\x9b\x67\x9e\x99\x97\x11\x11\xfe\x8f\x8d\ +\x3f\x4b\x51\x59\x59\x8b\xf4\x2c\x75\x1b\xf6\x37\x67\x97\xbe\xdb\ +\x92\x00\x00\xec\x69\xc6\x25\x95\xdf\xae\x50\x14\xf5\x23\x30\x6c\ +\x35\x4d\x2b\x4d\x10\x14\x89\x33\x3f\xe7\x6c\xd4\x12\x74\x41\x90\ +\x68\x11\x14\xf8\xa3\xa3\xb6\xd2\x98\xb9\xe6\xa5\x7d\xa7\x53\x04\ +\xa7\xbf\x4c\x0b\x5b\x3b\xeb\x2b\x1e\xcc\x03\x33\x06\x56\xfa\x5e\ +\x73\x3d\xc0\xca\x5f\x7e\x71\xa9\x6d\x65\x4e\xb2\xec\x72\xaa\xe0\ +\x9c\x41\xd7\x0d\x04\x42\x06\x1e\x3c\x9a\xb4\x6e\xf4\x7a\x02\x23\ +\xe3\x01\x89\x31\x1c\xf6\x73\xe5\x0b\x97\xa4\x73\xe8\xbc\xdd\x12\ +\x62\x05\x31\x91\xd5\x51\xbb\x67\x60\x1e\x78\xe3\x81\xe6\x93\xd9\ +\x69\x71\x65\x7b\x5e\x5f\xad\x45\x0c\x0b\x13\xfe\x30\x62\x34\x15\ +\x9a\xaa\x40\xe2\x00\xe3\x0c\xa0\x69\x03\x7f\x30\x82\x4b\x9d\xf7\ +\xc3\xd7\xff\x1e\xd2\x49\xc0\xb3\xa9\x30\x6b\xd9\xad\xfe\x11\x63\ +\x72\x22\x98\x77\xed\xc4\xae\x41\x79\x06\x5a\x54\xf5\x5d\x49\x82\ +\x4b\x7b\x7b\x7b\xf1\x32\xed\xeb\x96\x76\x31\xe6\x0d\x72\xce\x01\ +\x61\x11\x11\x83\x99\xea\x76\x85\x4a\x0a\x32\x9c\x85\x2f\xa4\x4a\ +\x44\x40\xc8\x20\x6c\x5d\x9f\x6b\x2f\xca\xcf\xb0\xf7\x3f\x7c\x12\ +\xf3\x6a\x51\x16\xeb\xea\x1d\x36\x75\x21\x89\x79\x2f\xcf\x2e\x2b\ +\xd5\xcf\xb9\x54\x67\xfd\x99\x4e\x9a\x0a\x18\xcc\x61\x57\xc2\x96\ +\x10\xdf\x5f\xab\xad\xe0\x21\x8e\x14\xcf\x88\x7f\xfb\xb9\xd6\xbe\ +\x1f\x3e\xfd\xa6\x35\xd8\xd6\x33\x4c\x4e\x55\xc2\xd0\x78\x08\x4f\ +\x02\x26\xd6\xe7\xa7\x33\x45\xe6\xb0\x2c\x01\xd9\x1e\x9e\x0f\x06\ +\xc3\x6b\x03\xc3\x93\xcc\x1d\x17\xe3\x5d\x9e\x9d\x7a\x43\xd7\x4d\ +\x2f\x20\x3e\x07\x80\x9b\x35\x15\xde\xf6\xfa\x8a\xb6\x2b\x35\xe5\ +\xe5\x86\x6e\x6d\xfc\xfd\x4a\x5f\xfb\x89\x1f\x3b\x82\xf1\x0e\x8e\ +\xcc\x24\x0d\x97\x6e\x8d\x42\x91\x38\x2c\x21\x58\x64\xa1\x31\x09\ +\xa8\x9a\x43\x1d\xca\xcc\x48\xae\x8d\xd5\xec\x0d\x60\xbc\xcf\x22\ +\x9b\x77\xe1\xc4\xb4\xd5\x55\x74\xe9\x86\x79\x68\x2a\xa0\x4b\x31\ +\x0e\x05\x43\xe3\x21\x08\x00\x76\x85\xc3\xb2\x88\x29\x42\x16\x00\ +\x30\xdb\x63\x4b\x88\x60\xa2\xcb\xf1\x65\x8c\xc3\xfe\xb3\xae\xab\ +\x8f\x29\xc2\x4e\xc5\x2c\x4d\x9e\x5a\x08\x2e\xaa\x6a\x5c\xa5\xc8\ +\xd2\xd9\xea\xb7\x8a\xd4\xa4\x78\x0d\x69\x89\x4e\x6c\x2e\x48\x86\ +\xaa\x48\x30\x05\x31\x9b\xb5\x00\xec\x48\x4b\xcf\x39\x8b\xcb\xe2\ +\xcc\xde\x37\x04\x00\xa0\x72\xc5\xa2\xf9\x2e\xaa\x6a\x48\x63\xc4\ +\x7f\xb3\x2c\xd2\x8e\xb6\xb4\x47\x48\x10\x88\x00\xc2\xf4\x5e\x08\ +\xb2\xe9\x56\x40\x00\x73\x3e\x90\xe2\xaa\xa6\x31\x06\xb8\x16\xd1\ +\x00\x10\xc1\xc7\xb8\xd8\xfe\xc4\xe6\xee\x71\xf9\x46\x1c\x4f\xab\ +\x01\x00\x85\xa0\xb6\x9f\xda\x3b\x4a\x04\x92\xe7\x1c\x8f\x6b\xf8\ +\x64\x87\x6c\x93\x39\x00\x06\xc6\x80\xb0\x6e\xe2\xe3\xba\xd6\xc8\ +\xfd\x91\xc9\xf7\xaf\x1f\xdf\xdd\x1d\xad\x8b\x4c\xdb\xd7\x29\x40\ +\xbc\x56\x5a\x50\x18\x76\xc7\xe8\xf1\xdd\xff\x3e\x2c\x1d\x1c\x7d\ +\x5c\x47\x84\xc4\x79\xad\x00\x11\xb3\xdb\x64\x5c\xb8\x35\x02\x06\ +\x42\x69\x5e\x12\x9a\xce\xdf\x89\x0c\x8c\xfa\x8e\xb6\x1d\xdf\xd5\ +\xb0\xd0\x4e\x16\xce\x14\x49\x15\xc7\x54\x87\xef\xa7\xc9\xb0\x48\ +\x9a\xf0\xfb\xab\x6c\xb2\x6c\xcd\x9c\x9f\x33\x6e\xd3\x96\x86\x29\ +\x90\x91\xe8\x04\x03\xd0\xdd\x3f\x46\x9c\xb1\x55\xc5\xef\x34\x2f\ +\x5d\xf4\xdc\x12\x9e\xb3\x2c\xb1\x61\xd2\x17\xdc\x7d\xfb\xde\xe0\ +\x87\xbe\x40\x38\x9b\x71\xdc\x9d\xbd\xf1\xac\x30\x88\x31\x00\x6b\ +\x72\xe2\x30\x38\x1e\xc4\x90\x97\xe3\xc8\x81\x2d\xf6\xa6\xf3\x3d\ +\xdb\xce\x5d\xe9\xef\x29\xa9\x6e\xfa\x4a\x58\xd4\x01\x62\x03\x5c\ +\xb1\x64\x22\xe9\x88\x43\x55\xe2\x7a\xee\x0e\x6d\xb6\x29\x12\xb9\ +\x63\x35\xc3\x3b\x11\xaa\x5f\x04\x9e\x96\x66\x08\x86\x74\xe4\x2f\ +\x89\x45\xc4\xb4\xd0\x79\xcf\x8b\x57\x0a\x33\xa5\xe2\xfc\x74\xad\ +\xe3\xce\xf0\x07\x9e\xc7\xbe\xb0\x67\xcc\xc7\xc6\x27\x82\x4e\xc9\ +\xc6\x90\xe2\xd6\x90\x97\x93\x8c\xc4\x38\x27\x6b\xfc\xa5\x2b\xac\ +\x99\x7a\xe3\x22\x30\x67\x8c\xdd\x7f\x34\x85\x43\x35\x97\x26\x38\ +\x03\xdf\xb1\x69\xb9\x6d\xcb\xba\x2c\xbb\x37\x60\xc2\x22\xa0\x30\ +\x2f\x4d\x2e\xb0\x52\x5d\x8c\x4d\xf7\xcf\x10\x04\xd3\x14\x98\xf0\ +\x47\xd0\xf8\xeb\x0d\xbf\x65\x18\x07\x2f\x9e\xdc\x1b\x9e\x95\x24\ +\x22\x30\xc6\xa4\xf5\x95\x0d\x46\xac\xd3\x16\xe8\xef\xba\xb8\xc3\ +\xd3\x71\xe6\x51\xee\x96\xca\x9d\xee\x25\xb9\xd5\xab\x9f\x4f\xcb\ +\xc8\xcf\x4d\x51\x32\x53\x63\x99\xd3\x61\x43\xc4\x10\x30\x4c\x0b\ +\x93\x01\x1d\x5d\xbd\x1e\x71\xf5\xe6\x43\x3d\x38\x31\x72\xb8\xfb\ +\xf4\xc1\x1a\x00\x61\x00\x61\x22\xd2\x67\xc0\xf6\x75\xfb\x1a\xbc\ +\x7e\xcf\xed\xb2\xde\x73\x9f\xfd\x03\xc0\x11\x8d\x3d\x7d\xed\xce\ +\x35\x29\x2b\xb7\x95\x2b\x5a\xfc\x5a\x70\xa6\x3a\x55\xc5\x08\x46\ +\x4c\x89\x08\x10\x11\xdf\x9f\xa3\x7d\xad\xc7\x06\xae\x36\x75\x03\ +\x08\x45\x13\x24\xa2\xe0\x0c\x98\xad\xde\x7d\xec\xcd\x9b\x0d\xfb\ +\x2f\x03\xb0\x03\x50\xe7\x44\x89\x46\x92\x9c\x6e\x25\x21\xa3\x20\ +\x21\xe8\x1d\xf6\x06\x46\xfb\xbc\x00\xf4\xe8\x5c\x47\xa2\x50\x1f\ +\x80\x08\x11\xd1\xa2\xa5\x89\x31\x26\xcd\x81\xcd\x44\x06\x20\x61\ +\xfa\x37\x6f\x45\x63\x44\xa3\x03\x30\x89\xc8\x9a\xcb\xf9\x0f\x29\ +\x69\x5c\x9a\x72\xdc\xdf\x60\x00\x00\x00\x00\x49\x45\x4e\x44\xae\ +\x42\x60\x82\ +\x00\x00\x03\x27\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01\x42\x28\ +\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x0b\x1b\x0c\x31\ +\x10\x10\x81\x3b\xdf\x00\x00\x02\xb9\x49\x44\x41\x54\x48\xc7\xed\ +\x55\x5f\x48\x53\x61\x14\x3f\x77\xdf\xfd\xe7\x74\xde\x3b\xff\xd4\ +\xc5\x82\x42\xb0\xe9\xba\xea\xdc\x42\x18\x28\x62\x2f\x59\x44\xb0\ +\x41\x83\xfe\xbc\x04\xbe\x64\x41\x83\x1e\x84\xa0\x17\x21\xf2\x25\ +\x9a\x42\x44\xa0\x42\xa4\x0f\x51\x3e\x84\x8b\x72\x90\x38\xa5\x37\ +\xaf\x2d\x1f\x62\x3e\x94\x1a\x0b\x51\xcb\xae\x39\xef\xdd\x75\xbb\ +\xf7\xeb\x21\xa6\x4e\xf7\xe0\x32\x89\xa0\xef\xed\x7c\xe7\x9c\xdf\ +\x8f\x73\x7e\xdf\x39\x1f\x81\x31\x86\xfd\x3c\x26\xd8\xe7\xf3\xef\ +\x13\x90\x5b\x0d\x8f\xc7\xe3\xc0\x18\xb7\xd9\xed\xf6\x9a\x92\x92\ +\x92\x59\x59\x96\x6f\x75\x74\x74\x7c\xda\x0b\x01\x91\x16\xd9\xe3\ +\xf1\xd4\x53\x14\x35\xdc\xdc\xdc\xfc\xd5\x66\xb3\xb1\xdf\x65\x39\ +\xae\xa8\xea\xe1\x6f\x4b\x4b\x2d\x7e\xbf\xff\x6d\x3a\xa1\xf1\xa2\ +\xbf\x01\x51\xe8\xf6\xe8\xe3\x7b\xa7\x76\x5d\x81\xcf\xe7\x43\x34\ +\x4d\xbf\x6c\x6d\x6d\xe5\x44\x51\xe4\xd3\xce\x48\x24\x32\xa5\x25\ +\x12\x7d\x00\x60\xdb\x00\x27\x4d\xaf\xf4\x54\xaa\x20\x27\x0d\x78\ +\x9e\x3f\x2b\x08\x82\x55\x14\x45\x62\x8b\x0f\x57\x57\x57\xd7\x94\ +\x97\x97\xaf\x6f\x01\x7f\x7d\xfd\xca\x85\x82\x9c\x45\x66\x18\xe6\ +\xa6\xdb\xed\x46\xdb\xdb\x87\x10\x02\x7b\x55\xd5\x4c\x1a\xdc\xe9\ +\x74\xe6\x9b\xcd\x79\xbf\x25\xb2\x5d\x10\x84\xac\x01\x1f\x3e\x7e\ +\x6e\x41\xa4\xe9\x64\x5d\x5d\x5d\xbe\xd5\x6a\x05\x29\x3a\x07\x0c\ +\xc3\x24\x1a\x2f\xdd\xc8\x3a\xa1\xc8\x64\x5a\x18\x7d\x72\x5f\xc8\ +\x20\x50\x55\xb5\xa0\xb0\xb0\x70\x47\x70\x74\x26\x06\x9d\x7d\xcf\ +\x29\x87\xc3\x41\x15\x15\x15\x6d\xdc\x37\x35\x35\xb1\x00\x00\xae\ +\xca\x23\x60\x66\xe8\x8d\xfb\x44\x32\x05\x77\x02\x8f\x0e\xee\xa8\ +\x40\x55\x55\xda\x62\xb1\x64\x80\xcf\x7c\x59\x80\xbb\xbd\xcf\xc0\ +\x7e\x5c\x84\xe2\xe2\xe2\xac\xd5\x49\xd1\xb9\x0c\xbb\xb1\xb6\x22\ +\x7b\x8b\x38\x8e\x83\xe5\xe5\x65\x88\xc7\xe3\x80\x10\x82\xd2\xd2\ +\x52\x58\x53\x54\xc0\x00\x40\x51\xd4\xde\x27\x99\x65\x59\x5d\x51\ +\x94\x0c\x87\x58\x71\x14\xae\x9e\x3f\x0d\xef\x23\x11\x58\x59\x59\ +\xd9\x15\x98\xa2\xad\x67\xaf\x80\xa2\x28\x55\x51\x14\x0b\xcf\xf3\ +\x80\xd0\xe6\x63\x72\xd7\x56\x02\x42\x26\x23\xd0\xff\x42\x73\xb9\ +\x4e\xe4\x71\x1c\x07\x00\x00\xe1\x70\x38\xa1\x69\x1a\xbb\x1d\x2c\ +\x14\xfa\x25\xf2\x0e\x02\x8c\xf1\x9c\x2c\xcb\x62\x59\x59\x19\xd0\ +\x34\x9d\x91\x54\x2f\x1e\x0b\xa5\x74\xe3\xc1\x84\x34\xf1\xd4\xe5\ +\x74\x99\x79\x9e\x07\x4d\xd3\xd8\xf1\x81\x2e\x62\xd7\x2d\x4a\x26\ +\x93\x0f\xa7\xa7\xa7\x31\x41\x10\x40\x92\x9b\xeb\x49\xd3\x34\x68\ +\x6f\x6f\xaf\x18\xef\x0f\x04\x8d\x94\xe1\x95\x26\x25\x45\x96\xe5\ +\xdc\x35\xd0\x75\xbd\x77\x71\x71\x51\x89\xc5\x62\x19\x04\x23\x23\ +\x23\x53\xab\xab\xab\xb3\x00\x00\x63\x03\x81\x61\x43\xd7\xcf\x4d\ +\x4a\xd2\x5a\xce\x04\xdd\xdd\xdd\x9a\xaa\xaa\x97\x87\x86\x86\x94\ +\x70\x38\x3c\x1f\x8d\x46\x7f\xf4\xf4\xf4\x4c\x06\x83\xc1\x03\x04\ +\x41\xb4\xa5\x83\xc7\xfa\xbb\xde\x18\xba\x71\x06\x91\x64\x28\xe7\ +\x6d\x0a\x00\xe0\xf5\x7a\x1b\x0c\xc3\xb8\x46\x10\xc4\x21\x8c\xf1\ +\x3b\x84\x50\xe7\xe0\xe0\xe0\xfc\x1f\x59\xd7\xff\xbf\xcc\xbf\x46\ +\xf0\x13\x03\x47\x07\x80\x99\x55\x29\xcd\x00\x00\x00\x00\x49\x45\ +\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x02\xcf\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01\x42\x28\ +\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x0b\x1b\x0c\x29\ +\x0d\xf1\x9c\xcf\x5f\x00\x00\x02\x61\x49\x44\x41\x54\x48\xc7\xd5\ +\x95\x4b\x48\x54\x51\x18\xc7\x7f\xf7\xa1\x08\xea\xb4\x30\xbb\x8e\ +\xad\x9c\x45\x38\x43\xe0\x26\x46\x11\x11\x34\x9a\x75\xab\x10\x21\ +\x04\x43\x6b\x11\x92\x7a\x91\xb6\xae\x1a\x62\x7a\x60\x04\x41\x60\ +\x0c\x41\x44\xab\x36\x42\x1a\x99\x4a\x84\xba\x32\x5c\x38\x20\x8c\ +\x10\x4e\xcd\x84\xa2\x5e\x0b\x6f\x73\x5f\x2d\x46\x67\xc6\xf1\xd1\ +\x34\x8e\x8b\xbe\xd5\xb9\xdf\xf9\xee\xf7\xf8\xff\xcf\xff\x1c\xf8\ +\xdf\x4d\xd8\x5b\xb4\x75\x0d\xc4\x0d\xc3\x54\x8a\x91\xb4\xa4\x44\ +\x4e\x7c\x0c\x3f\xac\x01\x90\xf7\x9c\x86\x61\x2a\xa1\x50\xa8\x28\ +\x5d\xab\xaa\x9a\x6e\x54\xce\xde\x88\xae\x44\x19\x1d\x7d\x81\xbe\ +\xb3\x93\xda\x94\x4b\xe8\xbd\xd9\x83\xa7\xce\x43\x38\x1c\x66\x71\ +\x71\xf1\xd8\xc4\x5e\x9f\x8f\x1b\xdd\xdd\xfb\x7c\x62\x6e\x90\x69\ +\x98\x99\x51\xe5\x4c\x7d\xd3\xb2\xfe\xda\xb9\x2c\x49\x07\x7d\xd9\ +\x1f\x9e\x3a\x0f\xc1\xe0\xbd\x43\x7f\xce\xed\x2c\x5f\x93\xb3\x88\ +\xb1\x55\x55\x15\x8b\x44\xb2\x7d\xa0\x80\x61\x98\xe2\x9b\xd0\xdd\ +\xa2\x90\x7c\x4d\x0d\x8a\x87\x42\x04\xd0\x7f\xff\x39\xb1\x1f\xeb\ +\x00\x9c\x3f\x57\xc5\xa3\xa1\x1e\x00\x3e\x7f\x89\xf0\xf8\xe5\xdb\ +\x63\x13\xdf\xb9\x7e\x95\xe6\x86\xfa\xa3\x39\x00\xd2\x09\x73\xad\ +\xb9\xa1\x9e\xe6\x86\x7f\x9f\x50\x3c\x6d\x25\x9f\x3a\x44\xe9\xab\ +\xa2\xa5\xb3\xcf\xc9\x97\x64\x7d\x73\x8e\xb5\xc8\x30\x49\x6d\xe1\ +\xc8\x18\x07\xe6\x05\x91\x41\xb9\x90\xb1\xd7\x22\xc3\x58\xfa\x0a\ +\x15\x55\x97\x10\xa4\x32\x44\xa9\x0c\x6f\xe0\x3d\x4b\x13\x57\xb0\ +\x2d\x1d\xc7\xd2\xd9\xd9\x5e\xf6\x9b\xc9\xad\x07\x05\x41\x14\x0c\ +\x2c\xe0\x72\xb7\x23\xc9\xe5\xe0\x38\x19\x42\x77\x8b\x21\x08\x88\ +\xa5\x2e\xb4\xef\x93\xfe\x82\x20\x8a\x4e\xd4\xe2\x69\x7a\x86\xab\ +\xf6\x32\xeb\x2b\xaf\x71\x29\xad\x54\x2a\xad\x6c\x27\x66\xd0\x12\ +\x33\x54\xd5\x75\xa0\x7d\xfb\x40\x74\xf6\x16\x72\xa1\xa7\x63\x63\ +\x75\x0c\xcb\xfc\x89\xfb\xe2\x10\x8e\x9d\x64\x33\xf6\x8e\x4a\xa5\ +\x85\xf2\xea\x26\x12\x4b\x4f\xd0\xe2\xd3\x85\x9f\xa2\x60\x20\x45\ +\xa3\x16\x9f\x42\xa9\xbf\xcd\x76\xe2\x13\x89\xc8\x53\x00\x5c\x35\ +\x6d\x68\xf1\xa9\x93\x09\x2d\x3a\x31\xc2\xc6\xea\x18\x67\x3d\x9d\ +\x80\x43\x45\x75\x23\xbf\x7f\x7d\xa5\xa2\xba\x11\x70\x90\x4a\xcf\ +\xb0\x16\x7d\x75\x32\xa1\xb9\xbd\x7d\xb8\x7d\xfd\x2c\x4f\x77\xb0\ +\x15\x1b\x47\xb9\xd0\xcb\x56\x6c\x9c\xe5\xe9\x0e\xdc\xbe\x7e\xdc\ +\xde\xbe\xfd\x3a\x68\xef\x1a\x88\x27\xf3\x7c\x32\x83\x81\x11\x44\ +\xa9\x0c\xdb\x4e\x82\x93\xba\x38\x9b\xba\x1c\x66\xc3\xbb\xe9\x04\ +\x11\x51\x2c\xc5\xb6\xf4\x0c\x44\x93\xbb\x6f\x68\x3e\xe6\x04\x98\ +\xb3\x2d\xdd\x7f\x74\x80\x9d\xd2\x03\xcc\x17\x04\x91\x20\x32\xe8\ +\xc0\x7c\xb6\x2f\xdd\x7d\x8e\x92\xff\x00\x43\xf6\xfd\xa2\x9a\x94\ +\xbb\xe6\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x02\xb0\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x16\x00\x00\x00\x16\x08\x06\x00\x00\x00\xc4\xb4\x6c\x3b\ +\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\ +\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\ +\x0d\xd7\x01\x42\x28\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\ +\xd5\x0b\x04\x0a\x14\x28\x60\x19\x7b\x03\x00\x00\x02\x3d\x49\x44\ +\x41\x54\x38\xcb\xb5\x95\xbf\x6b\xdb\x50\x10\x80\xbf\xf7\x94\x4c\ +\xb5\x34\x08\x23\x27\x78\xca\xa6\xc4\x01\x27\x71\x8a\xed\x8c\x06\ +\x93\x39\x7f\x43\xf7\xac\xa5\x10\x77\x68\xeb\x92\xba\x7b\x16\x4f\ +\x5e\xf3\x37\x78\x09\x24\xb8\x3f\x30\x84\x40\xec\xe0\x25\xd0\x76\ +\x10\x96\x44\xa1\x49\xe9\x50\x94\xd7\xa1\x96\x2a\x47\x71\xec\x92\ +\xf6\xe0\xd0\xdd\x7b\xe2\xbb\xbb\x77\x27\x3d\xf8\x4f\x22\x42\x63\ +\xbf\x51\x7f\x01\xd4\x1e\x02\x53\x4a\xbd\x7c\xf6\x74\xef\xf9\xd8\ +\xe2\x7e\xa3\xae\x1e\x2a\xfb\x8d\xba\x0a\x79\x73\xb7\xa3\x5e\x5e\ +\x5e\xa2\x69\x1a\x4a\x29\x84\x10\x08\xf1\xbb\xa8\xb8\x1d\xfa\xb1\ +\x4c\xc9\x66\xb3\x63\x9c\x04\x38\x0e\x38\x3f\x3f\x4f\x40\x6e\xcb\ +\xda\xda\x1a\x4a\xa9\xc4\xfa\xbd\xe0\xd5\xd5\x55\xe6\xe6\xfe\xbc\ +\x12\x04\xc1\x98\x7f\x57\xf6\x53\xc1\x42\x08\xce\xce\xce\xa6\x36\ +\x6c\x7d\x7d\x1d\x29\xe5\x6c\x60\x29\x25\x4a\x29\xf2\xf9\x3c\x00\ +\xf3\xf3\xf3\x7f\x3d\x21\x09\xf0\xc7\xee\x07\xca\xc5\x2d\x84\x10\ +\x9c\x9e\x9e\x8e\xed\x35\x9b\xcd\xc8\xde\xd9\xd9\x21\x9d\x4e\x53\ +\x2e\x97\x09\x82\x20\x01\x4e\xd4\x50\x7c\x5c\x62\x71\x71\x11\x21\ +\x04\x1b\x1b\x1b\x63\x5a\xab\xd5\xb0\x2c\x8b\x85\x85\x05\x3a\x9d\ +\x0e\xc5\x62\x71\xe2\x19\xcb\xbb\x8e\xc2\x71\x1c\x84\x10\x0c\x06\ +\x03\x06\x83\x01\xbb\xbb\xbb\x1c\x1f\x1f\x73\x7d\x7d\x4d\xb5\x5a\ +\xc5\xf7\x7d\x7c\xdf\x8f\xa6\xe6\xae\x33\x96\xf7\x35\xcf\xb6\x6d\ +\x6c\xdb\xc6\x34\x4d\xda\xed\x36\x86\x61\xd0\x6e\xb7\x49\xa7\xd3\ +\x91\x4a\x29\x67\xcb\x38\x5e\x5a\xd8\xc8\x50\x9b\xcd\x26\x9a\xa6\ +\x45\xfe\xc1\xc1\x01\x8e\xe3\xcc\x96\xf1\xbb\xf7\x9d\x08\xda\xef\ +\xf7\xe9\xf5\x7a\x54\x2a\x15\x3c\xcf\xc3\x75\x5d\x5c\xd7\x65\x38\ +\x1c\x32\x1c\x0e\xb9\xba\xba\xe2\xf0\xf0\x10\xcf\xf3\xa6\x4f\x45\ +\xb9\xb4\x85\x65\x59\x78\x9e\x87\x6d\xdb\x00\xac\xac\xac\x50\xa9\ +\x54\xa2\x4a\x1c\xc7\xa1\xd5\x6a\xa1\xeb\x3a\x86\x61\x70\x74\x74\ +\xc4\xd2\xd2\xd2\xf4\x39\x76\x5d\x17\x21\x04\x17\x17\x17\x13\xe7\ +\xb4\x54\x2a\x71\x72\x72\x42\x36\x9b\x45\xd7\xf5\xe9\x19\xc7\x65\ +\x79\x79\x39\xf1\x71\x84\x8d\x95\x52\xb2\xb9\xb9\x49\xb7\xdb\x25\ +\x95\x4a\xcd\x06\x0e\x4b\xee\xf7\xfb\x13\x83\x16\x0a\x05\x4c\xd3\ +\x64\x7b\x7b\x7b\xb6\x9f\x50\x5c\x72\xb9\xdc\xd8\x64\x84\x76\xfc\ +\xa9\x94\x9a\x0d\x9c\xc9\x64\xfe\xc9\xd5\x14\x81\x6f\x6e\x6e\x5e\ +\xbd\x79\xfb\x7a\xef\x21\xb0\xcf\x9f\xbe\x3c\x49\xdc\x79\xb7\x82\ +\xa5\x00\x7d\xa4\x29\xe0\xd1\x68\xe6\x35\x40\x01\x3f\x81\x1f\xc0\ +\x57\xe0\x1b\xf0\x7d\xe4\x07\xa3\x7d\x7e\x01\x0e\xb4\xf5\xda\x0b\ +\x7d\x14\xc6\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x03\x29\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01\x42\x28\ +\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x0b\x1b\x0c\x2e\ +\x22\x15\x0c\x64\xc1\x00\x00\x02\xbb\x49\x44\x41\x54\x48\xc7\xd5\ +\x55\x5d\x48\x53\x61\x18\x7e\xb6\x9d\x4d\xd7\xdc\x9c\xce\x9f\x69\ +\x8a\x6d\xf3\x77\x66\xa3\x8b\x4a\x86\x11\xde\x04\x15\x5d\x08\xe2\ +\x45\x48\xa1\xe1\xba\x13\x94\x43\x78\xd3\x75\x23\x46\x06\x19\x04\ +\x0d\x63\x08\x51\xd1\x85\x61\x91\x37\x32\x10\xf2\x22\x0c\x26\x1b\ +\x6c\x44\x53\x37\x9b\x6e\xba\x79\x4e\xfe\x6c\xb3\x73\x8e\xa7\x8b\ +\x32\xa7\x9b\x6e\xea\x6e\x7a\xae\xce\xf7\x7e\xe7\x7d\xde\xf7\x7d\ +\xde\xef\x7b\x3f\xe0\x7f\x87\x60\xe7\xa3\xf5\x4e\x7f\x90\x61\xd8\ +\xd2\x6c\x90\x8a\xc5\x44\xc8\x6e\x7b\xac\x06\x00\x62\xc7\xc8\x30\ +\x6c\xa9\xc5\x62\xc9\x4a\xd6\x24\x49\xfe\x4b\x94\x48\xdc\x98\x9d\ +\x9b\xc5\xf0\xf0\x4b\xc4\x63\xb1\x3f\x9b\x84\x18\xa6\x7b\x3d\xd0\ +\x6a\xb4\xb0\xd9\x6c\x70\x3a\x9d\x87\x12\x37\xe8\xf5\xb8\xdb\xdd\ +\xbd\xc7\x26\xdc\xff\x13\xcb\xb0\xbb\xa5\x12\xbb\xf1\x59\x8e\x4b\ +\x9b\x39\x21\x12\x25\xdb\x12\x17\x5a\x8d\x16\x66\xf3\xc3\x94\xce\ +\xfb\x33\xcb\x14\x44\x42\x63\xb6\x49\x92\x14\x66\xa9\xc9\xdb\x49\ +\x01\x18\x86\x15\xbe\xb5\x0c\x64\xa5\xc9\x1d\xa4\x59\x98\x52\x22\ +\x00\xe8\x7b\xf4\x02\x81\xe5\x08\x00\xe0\x74\x89\x0a\x83\xf7\x7b\ +\x00\x00\x53\x33\x1e\x3c\x19\x19\x4d\x49\x28\x95\x08\x71\xbd\xb9\ +\x09\x75\x3a\x0d\xaa\xab\x2a\x52\xdf\x83\x96\x5b\xbd\xfc\x71\x2b\ +\x08\x2d\xba\x41\xad\x2e\xa2\x4a\x67\x44\x34\xba\x89\xa1\x57\x63\ +\x68\xae\x2d\x97\x77\x75\x75\x6d\x9c\x58\x73\x8e\xdd\x02\xbd\xf0\ +\x0c\x65\xf2\x31\xac\x53\x93\x60\xb7\x96\x60\x6a\xbf\x0a\x65\xbe\ +\xac\x33\x2b\x12\x69\x14\x7e\xf4\x77\xfc\x44\x61\xe9\x15\xd0\xb4\ +\x0b\x73\xde\x51\xcc\x87\x9b\x20\xcb\x91\x7f\x3e\xb1\x44\xeb\xf4\ +\x3c\xc2\x73\x83\xa8\xac\x52\x41\xa1\x3a\x8b\x29\xfb\x08\x38\x96\ +\x83\x6d\x52\x87\x77\xd6\x37\x82\x94\x17\xed\x28\x58\x5d\x9c\x80\ +\xfc\x14\x85\x3c\x65\x03\x7c\x5e\x07\xc0\xf3\x10\xe5\xea\x11\x8c\ +\x16\xe3\xc4\xa7\x28\x5f\xb2\x86\xbe\x1b\x1e\x54\x36\x36\x23\x1e\ +\x5b\x43\x30\xe0\x46\x9c\x91\xa1\xae\xb1\x13\xc0\x87\x83\x03\xec\ +\x10\xee\x87\xd1\x50\x0f\xa3\x61\xe0\xef\x38\x89\xe3\xbb\x63\x08\ +\xda\xca\x0a\xc8\x0b\xaa\xe1\x72\x4c\x40\x00\x16\x8a\x82\x16\x28\ +\x54\x75\x7b\x02\x1c\x4b\xa2\x95\x1f\x93\x28\x52\xcc\x40\x2c\xd3\ +\x83\xa6\x96\x40\x85\xfd\xd8\x8c\xe6\xa1\xc6\xd0\x03\x91\x48\x7c\ +\xf0\x2c\xca\x4c\x22\x1e\xb7\x2f\x4e\xe3\xf2\xa5\x72\xc8\xe4\x25\ +\x98\x99\xfe\x04\x8e\x17\x60\xdc\x21\x05\xa7\xf6\xc3\x68\xa8\x3f\ +\x3c\x40\x3a\x89\x9c\x5f\xdf\x43\x29\x09\xa0\xb0\xb8\x06\x01\xbf\ +\x0b\xb1\x68\x18\x39\xb9\xe7\x30\xd0\x4b\x22\x47\xaa\x4c\xf2\x3b\ +\xb2\x44\xd4\xba\x14\x79\x6a\x13\x3c\x1e\x0a\xd4\xb2\x0b\xdb\x1c\ +\x0f\xf5\x99\x9b\x29\xc9\xf7\x54\x20\x11\x13\xa1\x0e\xd2\x7c\xf8\ +\x93\xc9\xf3\xb8\x76\xa1\x1e\xd5\xb5\x45\xf0\x04\xce\x63\x63\x55\ +\x84\xc0\xca\x37\x7c\xf9\x68\x07\x60\x47\x22\x57\xd2\x2c\xca\x04\ +\x6d\x6d\x6d\x25\x26\x93\xe9\x35\x4d\xd3\xad\x3e\x9f\x8f\xf3\xcd\ +\x7b\x9f\xf2\xbf\x16\x06\x9f\x0f\x8f\xfb\xd3\xbe\x07\x99\x80\xe7\ +\xf9\x32\xb7\xdb\xad\x8e\x44\x22\xae\x50\x28\xf4\xc0\x6a\xb5\x8e\ +\xa6\xf3\xf9\x0d\x0a\x43\x1c\x87\x59\x88\x82\x2a\x00\x00\x00\x00\ +\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x03\x5d\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x18\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0\x77\x3d\xf8\ +\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01\x42\x28\ +\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x0b\x1b\x0c\x30\ +\x27\xb1\x27\xaf\x91\x00\x00\x02\xef\x49\x44\x41\x54\x48\xc7\xed\ +\x95\x5f\x48\x53\x51\x1c\xc7\x7f\x67\xff\xee\x9d\xbb\x73\x7f\x60\ +\xd6\x66\xc4\x08\x05\xe9\xc1\x26\xc1\x48\x9a\xae\x50\x96\x3d\xd8\ +\xdc\x20\xd2\x2c\x7a\x49\xc8\x97\x49\x31\xed\x51\xc8\xf7\x52\x23\ +\x10\x22\x18\x14\xce\xc0\x97\x3d\x89\x92\x91\xff\x2a\x5f\xbc\xec\ +\xc9\x07\x53\x50\x84\xa5\xb9\x8d\xfd\xb9\xbb\xbb\xdd\xdd\x73\x7a\ +\xd0\x62\x1b\x33\xa6\x24\x11\xf4\x83\xf3\x72\x38\xdf\xf3\xe1\xf7\ +\xe7\x7c\x0f\x22\x84\xc0\x49\x86\x0c\x4e\x38\xfe\x7d\x80\xa2\x78\ +\xc3\xe3\xf1\xb4\x00\x40\xaf\xad\xa1\xe1\x9c\x86\x61\x56\xb9\x54\ +\xea\xf1\xe0\xe0\xe0\xf6\x71\x01\x28\xbf\xc9\x5e\xaf\xf7\x26\x45\ +\x51\x63\x6e\xb7\x3b\x6d\xb1\x58\x64\x3b\xbb\xbb\xe9\x0c\xcf\x9b\ +\x77\x22\x91\xc6\x81\x81\x81\xd5\x7c\xe1\x95\x7b\x8f\xa6\xb1\x24\ +\x3e\x99\x7f\xf3\x7c\xa9\xac\x12\x79\x3c\x1e\xbd\x5c\x2e\x0f\xf8\ +\xfd\x7e\xa3\xd3\xe9\x3c\x5b\x5b\x5b\x7b\xc6\x71\xf9\x72\x9d\xa6\ +\xa2\x62\x53\x67\x30\xbc\x2c\x16\x4a\x39\xc9\xa5\x65\x2a\xa7\x1d\ +\x77\x7c\x97\xca\x02\x98\x4c\xa6\x5e\x9b\xcd\xa6\xb6\x58\x2c\xf9\ +\x73\x4b\x2e\xd4\xd7\xd7\xd7\xd4\xd4\x88\xc5\x42\x4d\x05\x0d\x3d\ +\xb7\xbd\x9a\xea\xaa\xaa\x77\xcd\xdd\x3e\x7b\x39\x4d\xee\xb1\xdb\ +\xed\x08\x00\x50\x7e\x09\x19\x86\x81\xf3\x75\x75\x5f\x8a\x85\x5c\ +\x26\x0b\x9b\xbb\x09\xe8\x74\xb7\x69\xcc\xa7\x4c\xef\x9b\xba\xfb\ +\x2e\xfe\xb6\xc9\x82\x20\x54\x9b\xcd\x66\x90\x24\x09\x78\x9e\x07\ +\x86\x61\xe0\xc1\xd0\x0b\x88\x25\x52\x00\x00\xf7\x0f\xd6\xaf\xa0\ +\x28\x2a\x9b\xe4\x78\x7a\x0b\x00\x3a\xdd\xd7\x35\x13\xa1\xa9\x0f\ +\xce\x2e\x5f\xf3\x5c\x70\x94\x2d\x09\xc8\x64\x32\x2a\xad\x56\x0b\ +\xb1\x58\x0c\x30\xc6\xc0\x30\x0c\xc4\x12\x29\x70\xb9\x5c\x87\x65\ +\x4f\x03\x00\x24\x39\x1e\x0e\x20\xcc\x44\x68\x6a\xbe\xe9\xae\xcf\ +\xb1\xf0\x7a\x34\x5c\x50\xa2\x40\x20\x70\x5a\x2e\x97\x43\x26\x93\ +\x01\x8c\x31\x1c\xd5\x3e\x92\x1c\x0f\x5b\xdf\x92\x70\xeb\x46\x1b\ +\x53\xc9\x68\xe7\xaf\x76\x3d\xb4\x16\x64\x80\x31\x96\xa9\xd5\x6a\ +\x10\x04\x01\x8e\xeb\x4d\x49\x8e\x87\xe5\xc8\x57\xe0\x38\x5e\x4e\ +\x64\x58\x59\x00\x48\x24\x12\x71\x9a\xa6\x89\x28\x8a\x48\xa1\xd8\ +\xaf\xda\x51\x41\x7b\x7b\x7b\x10\x0e\x87\x39\x49\xc4\x2d\x0b\xc1\ +\x91\xb5\x02\x40\x32\x99\x14\x69\x9a\x96\x38\x8e\x53\xe8\x74\x3a\ +\x40\x68\x7f\x90\x8c\x3a\x2d\xcc\xcc\xcc\x94\xbc\x90\xa2\xa8\xac\ +\xd3\xe9\xa4\x01\x00\xa2\xd1\x28\x84\xc3\x61\x2e\x87\x73\xad\x8b\ +\xc1\xd1\xe5\x92\x2f\xd9\xef\xf7\x6f\x3b\x1c\x8e\x6a\xab\xd5\x0a\ +\x4a\xa5\x12\x8c\x46\x63\xfe\xb9\x57\x66\xb3\xb9\x60\x8a\x9a\xba\ +\xfb\x88\xcb\xe5\x82\x58\x2c\x06\x2c\xcb\xa6\xc5\x1c\x71\x2d\x8d\ +\x3f\xfb\x74\xe8\x3b\x20\x84\xbc\x5d\x5f\x5f\x27\x08\x21\xa2\xd7\ +\xeb\xf7\xe9\x08\x91\x68\x34\x0a\xfd\xfd\xfd\xb6\x52\x59\xc4\xe3\ +\x71\x60\x59\x36\x4d\x44\xe9\x5a\xa9\xcb\x0b\x00\xd9\x6c\x76\x78\ +\x6d\x6d\xed\xbb\x20\x08\x48\x26\x93\xfd\x84\xa2\xc9\xc9\xc9\x15\ +\x8e\xe3\xc2\xa5\xc4\x2b\x2c\x9b\xc2\x58\x6c\x9b\x0b\x8e\x7c\x2c\ +\xd7\xec\x3a\x55\x2a\xd5\x58\x7b\x7b\x3b\x6f\x30\x18\x60\x76\x76\ +\x36\xb2\xb1\xb1\xa1\xc7\x18\x37\x86\x42\xa1\x9d\x62\xb3\x93\x44\ +\x3c\xb4\x30\x3e\xbc\x58\xb6\x9b\x02\x00\x74\x74\x74\xb4\x22\x84\ +\x7a\x08\x21\x95\x08\xa1\xcf\x18\xe3\xa7\xa1\x50\x28\xf5\x47\xec\ +\xfa\xff\x97\xf9\x57\x00\x3f\x00\xc4\xab\x4c\x95\xcb\x13\xf6\xb2\ +\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +" + +qt_resource_name = "\ +\x00\x0a\ +\x03\x89\x2d\x02\ +\x00\x64\ +\x00\x62\x00\x5f\x00\x6d\x00\x61\x00\x6e\x00\x61\x00\x67\x00\x65\x00\x72\ +\x00\x05\ +\x00\x6f\xa6\x53\ +\x00\x69\ +\x00\x63\x00\x6f\x00\x6e\x00\x73\ +\x00\x11\ +\x0f\x65\xaf\x87\ +\x00\x6c\ +\x00\x61\x00\x79\x00\x65\x00\x72\x00\x5f\x00\x70\x00\x6f\x00\x6c\x00\x79\x00\x67\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\ +\x00\x0d\ +\x0e\x93\xc2\x47\ +\x00\x6e\ +\x00\x61\x00\x6d\x00\x65\x00\x73\x00\x70\x00\x61\x00\x63\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x0e\ +\x01\xc1\x4e\x47\ +\x00\x6c\ +\x00\x61\x00\x79\x00\x65\x00\x72\x00\x5f\x00\x6c\x00\x69\x00\x6e\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x09\ +\x09\x28\xa3\xa7\ +\x00\x74\ +\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x0f\ +\x03\xc6\x53\xc7\ +\x00\x6c\ +\x00\x61\x00\x79\x00\x65\x00\x72\x00\x5f\x00\x70\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x10\ +\x0d\x6d\xf5\xa7\ +\x00\x77\ +\x00\x61\x00\x72\x00\x6e\x00\x69\x00\x6e\x00\x67\x00\x2d\x00\x32\x00\x30\x00\x70\x00\x78\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x0a\ +\x02\xcd\x10\x4d\ +\x00\x74\ +\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x73\x00\x2e\x00\x78\x00\x70\x00\x6d\ +\x00\x08\ +\x0f\xca\x58\xc7\ +\x00\x76\ +\x00\x69\x00\x65\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x11\ +\x08\x03\xf4\xc7\ +\x00\x6c\ +\x00\x61\x00\x79\x00\x65\x00\x72\x00\x5f\x00\x75\x00\x6e\x00\x6b\x00\x6e\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\ +\x00\x0e\ +\x09\xbf\x0e\xad\ +\x00\x6e\ +\x00\x61\x00\x6d\x00\x65\x00\x73\x00\x70\x00\x61\x00\x63\x00\x65\x00\x73\x00\x2e\x00\x78\x00\x70\x00\x6d\ +\x00\x08\ +\x09\xc5\x50\xed\ +\x00\x75\ +\x00\x73\x00\x65\x00\x72\x00\x2e\x00\x78\x00\x70\x00\x6d\ +\x00\x07\ +\x0b\x66\x28\x62\ +\x00\x74\ +\x00\x6f\x00\x6f\x00\x6c\x00\x62\x00\x61\x00\x72\ +\x00\x09\ +\x0c\x96\xa6\x4d\ +\x00\x75\ +\x00\x73\x00\x65\x00\x72\x00\x73\x00\x2e\x00\x78\x00\x70\x00\x6d\ +\x00\x10\ +\x0b\x25\x3b\xe7\ +\x00\x72\ +\x00\x74\x00\x5f\x00\x73\x00\x71\x00\x6c\x00\x2d\x00\x6c\x00\x61\x00\x79\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x14\ +\x06\xe5\x41\x07\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x64\x00\x65\x00\x6c\x00\x5f\x00\x74\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x2e\ +\x00\x70\x00\x6e\x00\x67\ +\x00\x12\ +\x0d\xa0\xed\x87\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x72\x00\x65\x00\x66\x00\x72\x00\x65\x00\x73\x00\x68\x00\x2e\x00\x70\x00\x6e\ +\x00\x67\ +\x00\x11\ +\x08\x82\xf3\xa7\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x69\x00\x6d\x00\x70\x00\x6f\x00\x72\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\ +\x00\x14\ +\x0a\x7f\x40\xe7\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x6e\x00\x65\x00\x77\x00\x5f\x00\x74\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x2e\ +\x00\x70\x00\x6e\x00\x67\ +\x00\x15\ +\x0f\x3b\xc8\x07\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x73\x00\x71\x00\x6c\x00\x5f\x00\x77\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\ +\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x15\ +\x03\x38\xa8\x07\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x65\x00\x64\x00\x69\x00\x74\x00\x5f\x00\x74\x00\x61\x00\x62\x00\x6c\x00\x65\ +\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x11\ +\x08\x82\x65\xa7\ +\x00\x61\ +\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x5f\x00\x65\x00\x78\x00\x70\x00\x6f\x00\x72\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\ +" + +qt_resource_struct = "\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x0e\x00\x00\x00\x03\ +\x00\x00\x00\x72\x00\x00\x00\x00\x00\x01\x00\x00\x08\x0e\ +\x00\x00\x00\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x15\x95\ +\x00\x00\x00\xac\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xc9\ +\x00\x00\x01\x26\x00\x00\x00\x00\x00\x01\x00\x00\x1c\xad\ +\x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00\x0b\xdd\ +\x00\x00\x01\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x7c\ +\x00\x00\x01\x70\x00\x00\x00\x00\x00\x01\x00\x00\x21\xfc\ +\x00\x00\x01\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x2b\xd9\ +\x00\x00\x01\x86\x00\x02\x00\x00\x00\x07\x00\x00\x00\x11\ +\x00\x00\x01\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x27\x7e\ +\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x11\x85\ +\x00\x00\x00\x52\x00\x00\x00\x00\x00\x01\x00\x00\x06\x56\ +\x00\x00\x00\x2a\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x11\ +\x00\x00\x02\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x41\xec\ +\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x31\x5c\ +\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x45\x19\ +\x00\x00\x02\x30\x00\x00\x00\x00\x00\x01\x00\x00\x39\x3a\ +\x00\x00\x02\x58\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x65\ +\x00\x00\x02\x06\x00\x00\x00\x00\x00\x01\x00\x00\x33\xe2\ +\x00\x00\x02\x86\x00\x00\x00\x00\x00\x01\x00\x00\x3f\x38\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/ui/dbmanager.ui b/ui/DbManager.ui similarity index 57% rename from ui/dbmanager.ui rename to ui/DbManager.ui index 259766d..c32fcde 100644 --- a/ui/dbmanager.ui +++ b/ui/DbManager.ui @@ -53,7 +53,7 @@ 0 - + true @@ -94,8 +94,73 @@ 25 + + + File + + + + + + + + + + toolBar + + + Qt::ToolButtonTextUnderIcon + + + TopToolBarArea + + + false + + + + + + + + + :/db_manager/icons/toolbar/action_refresh.png:/db_manager/icons/toolbar/action_refresh.png + + + &Refresh + + + Refresh + + + F5 + + + + + &Exit + + + Ctrl+Q + + + + + + :/db_manager/icons/toolbar/action_sql_window.png:/db_manager/icons/toolbar/action_sql_window.png + + + &SQL window... + + + Run queries on the selected database + + + F2 + + @@ -103,7 +168,15 @@ QTreeView
..db_tree
+ + InfoViewer + QWidget +
..info_viewer
+ 1 +
- + + + diff --git a/ui/DbManager_ui.py b/ui/DbManager_ui.py new file mode 100644 index 0000000..b38b9a2 --- /dev/null +++ b/ui/DbManager_ui.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/DbManager.ui' +# +# Created: Tue Jun 21 04:30:06 2011 +# by: PyQt4 UI code generator 4.8.3 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_DBManager(object): + def setupUi(self, DBManager): + DBManager.setObjectName(_fromUtf8("DBManager")) + DBManager.resize(800, 535) + self.centralwidget = QtGui.QWidget(DBManager) + self.centralwidget.setObjectName(_fromUtf8("centralwidget")) + self.gridLayout_3 = QtGui.QGridLayout(self.centralwidget) + self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) + self.splitter = QtGui.QSplitter(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth()) + self.splitter.setSizePolicy(sizePolicy) + self.splitter.setMinimumSize(QtCore.QSize(696, 0)) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName(_fromUtf8("splitter")) + self.treeView = DBTree(self.splitter) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.treeView.sizePolicy().hasHeightForWidth()) + self.treeView.setSizePolicy(sizePolicy) + self.treeView.setObjectName(_fromUtf8("treeView")) + self.tabWidget = QtGui.QTabWidget(self.splitter) + self.tabWidget.setEnabled(True) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(3) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) + self.tabWidget.setSizePolicy(sizePolicy) + self.tabWidget.setObjectName(_fromUtf8("tabWidget")) + self.infoTab = InfoViewer() + self.infoTab.setEnabled(True) + self.infoTab.setObjectName(_fromUtf8("infoTab")) + self.infoTabLayout = QtGui.QGridLayout(self.infoTab) + self.infoTabLayout.setObjectName(_fromUtf8("infoTabLayout")) + self.tabWidget.addTab(self.infoTab, _fromUtf8("")) + self.tableTab = QtGui.QWidget() + self.tableTab.setEnabled(True) + self.tableTab.setObjectName(_fromUtf8("tableTab")) + self.tableTabLayout = QtGui.QGridLayout(self.tableTab) + self.tableTabLayout.setObjectName(_fromUtf8("tableTabLayout")) + self.tabWidget.addTab(self.tableTab, _fromUtf8("")) + self.previewTab = QtGui.QWidget() + self.previewTab.setEnabled(True) + self.previewTab.setObjectName(_fromUtf8("previewTab")) + self.previewTabLayout = QtGui.QGridLayout(self.previewTab) + self.previewTabLayout.setObjectName(_fromUtf8("previewTabLayout")) + self.tabWidget.addTab(self.previewTab, _fromUtf8("")) + self.gridLayout_3.addWidget(self.splitter, 0, 0, 1, 1) + DBManager.setCentralWidget(self.centralwidget) + self.menubar = QtGui.QMenuBar(DBManager) + self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 25)) + self.menubar.setObjectName(_fromUtf8("menubar")) + self.menuFile = QtGui.QMenu(self.menubar) + self.menuFile.setObjectName(_fromUtf8("menuFile")) + DBManager.setMenuBar(self.menubar) + self.statusbar = QtGui.QStatusBar(DBManager) + self.statusbar.setObjectName(_fromUtf8("statusbar")) + DBManager.setStatusBar(self.statusbar) + self.toolBar = QtGui.QToolBar(DBManager) + self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) + self.toolBar.setObjectName(_fromUtf8("toolBar")) + DBManager.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) + self.actionRefresh = QtGui.QAction(DBManager) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/db_manager/icons/toolbar/action_refresh.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionRefresh.setIcon(icon) + self.actionRefresh.setObjectName(_fromUtf8("actionRefresh")) + self.actionExit = QtGui.QAction(DBManager) + self.actionExit.setObjectName(_fromUtf8("actionExit")) + self.actionRunQuery = QtGui.QAction(DBManager) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/db_manager/icons/toolbar/action_sql_window.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionRunQuery.setIcon(icon1) + self.actionRunQuery.setObjectName(_fromUtf8("actionRunQuery")) + self.menuFile.addAction(self.actionRefresh) + self.menuFile.addAction(self.actionRunQuery) + self.menuFile.addSeparator() + self.menuFile.addAction(self.actionExit) + self.menubar.addAction(self.menuFile.menuAction()) + self.toolBar.addAction(self.actionRefresh) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionRunQuery) + + self.retranslateUi(DBManager) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(DBManager) + + def retranslateUi(self, DBManager): + DBManager.setWindowTitle(QtGui.QApplication.translate("DBManager", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.infoTab), QtGui.QApplication.translate("DBManager", "Info", None, QtGui.QApplication.UnicodeUTF8)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tableTab), QtGui.QApplication.translate("DBManager", "Table", None, QtGui.QApplication.UnicodeUTF8)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.previewTab), QtGui.QApplication.translate("DBManager", "Preview", None, QtGui.QApplication.UnicodeUTF8)) + self.menuFile.setTitle(QtGui.QApplication.translate("DBManager", "File", None, QtGui.QApplication.UnicodeUTF8)) + self.toolBar.setWindowTitle(QtGui.QApplication.translate("DBManager", "toolBar", None, QtGui.QApplication.UnicodeUTF8)) + self.actionRefresh.setText(QtGui.QApplication.translate("DBManager", "&Refresh", None, QtGui.QApplication.UnicodeUTF8)) + self.actionRefresh.setToolTip(QtGui.QApplication.translate("DBManager", "Refresh", None, QtGui.QApplication.UnicodeUTF8)) + self.actionRefresh.setShortcut(QtGui.QApplication.translate("DBManager", "F5", None, QtGui.QApplication.UnicodeUTF8)) + self.actionExit.setText(QtGui.QApplication.translate("DBManager", "&Exit", None, QtGui.QApplication.UnicodeUTF8)) + self.actionExit.setShortcut(QtGui.QApplication.translate("DBManager", "Ctrl+Q", None, QtGui.QApplication.UnicodeUTF8)) + self.actionRunQuery.setText(QtGui.QApplication.translate("DBManager", "&SQL window...", None, QtGui.QApplication.UnicodeUTF8)) + self.actionRunQuery.setToolTip(QtGui.QApplication.translate("DBManager", "Run queries on the selected database", None, QtGui.QApplication.UnicodeUTF8)) + self.actionRunQuery.setShortcut(QtGui.QApplication.translate("DBManager", "F2", None, QtGui.QApplication.UnicodeUTF8)) + +from ..info_viewer import InfoViewer +from ..db_tree import DBTree +from .. import resources_rc diff --git a/ui/DlgDbError.ui b/ui/DlgDbError.ui new file mode 100644 index 0000000..9fc0eb9 --- /dev/null +++ b/ui/DlgDbError.ui @@ -0,0 +1,97 @@ + + DlgDbError + + + + 0 + 0 + 400 + 369 + + + + Database Error + + + + + + An error occured when executing a query: + + + + + + + + 0 + 1 + + + + + + + + Query: + + + + + + + + 0 + 3 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + DlgDbError + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DlgDbError + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ui/DlgDbError_ui.py b/ui/DlgDbError_ui.py new file mode 100644 index 0000000..11f0c43 --- /dev/null +++ b/ui/DlgDbError_ui.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/DlgDbError.ui' +# +# Created: Mon Jun 20 20:07:37 2011 +# by: PyQt4 UI code generator 4.8.3 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_DlgDbError(object): + def setupUi(self, DlgDbError): + DlgDbError.setObjectName(_fromUtf8("DlgDbError")) + DlgDbError.resize(400, 369) + self.vboxlayout = QtGui.QVBoxLayout(DlgDbError) + self.vboxlayout.setObjectName(_fromUtf8("vboxlayout")) + self.label = QtGui.QLabel(DlgDbError) + self.label.setObjectName(_fromUtf8("label")) + self.vboxlayout.addWidget(self.label) + self.txtMessage = QtGui.QTextBrowser(DlgDbError) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.txtMessage.sizePolicy().hasHeightForWidth()) + self.txtMessage.setSizePolicy(sizePolicy) + self.txtMessage.setObjectName(_fromUtf8("txtMessage")) + self.vboxlayout.addWidget(self.txtMessage) + self.label_2 = QtGui.QLabel(DlgDbError) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.vboxlayout.addWidget(self.label_2) + self.txtQuery = QtGui.QTextBrowser(DlgDbError) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(3) + sizePolicy.setHeightForWidth(self.txtQuery.sizePolicy().hasHeightForWidth()) + self.txtQuery.setSizePolicy(sizePolicy) + self.txtQuery.setObjectName(_fromUtf8("txtQuery")) + self.vboxlayout.addWidget(self.txtQuery) + self.buttonBox = QtGui.QDialogButtonBox(DlgDbError) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close) + self.buttonBox.setObjectName(_fromUtf8("buttonBox")) + self.vboxlayout.addWidget(self.buttonBox) + + self.retranslateUi(DlgDbError) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), DlgDbError.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), DlgDbError.reject) + QtCore.QMetaObject.connectSlotsByName(DlgDbError) + + def retranslateUi(self, DlgDbError): + DlgDbError.setWindowTitle(QtGui.QApplication.translate("DlgDbError", "Database Error", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("DlgDbError", "An error occured when executing a query:", None, QtGui.QApplication.UnicodeUTF8)) + self.label_2.setText(QtGui.QApplication.translate("DlgDbError", "Query:", None, QtGui.QApplication.UnicodeUTF8)) + diff --git a/ui/DlgSqlWindow.ui b/ui/DlgSqlWindow.ui new file mode 100644 index 0000000..395c923 --- /dev/null +++ b/ui/DlgSqlWindow.ui @@ -0,0 +1,116 @@ + + + DlgSqlWindow + + + + 0 + 0 + 385 + 471 + + + + SQL window + + + + + + SQL query: + + + + + + + + 0 + 1 + + + + + + + + + + &Execute (F5) + + + F5 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Clear + + + + + + + + + Result: + + + + + + + + 0 + 3 + + + + QAbstractItemView::SelectRows + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + editSql + btnExecute + btnClear + viewResult + buttonBox + + + + diff --git a/ui/DlgSqlWindow_ui.py b/ui/DlgSqlWindow_ui.py new file mode 100644 index 0000000..884bccd --- /dev/null +++ b/ui/DlgSqlWindow_ui.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/DlgSqlWindow.ui' +# +# Created: Mon Jun 20 20:07:37 2011 +# by: PyQt4 UI code generator 4.8.3 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_DlgSqlWindow(object): + def setupUi(self, DlgSqlWindow): + DlgSqlWindow.setObjectName(_fromUtf8("DlgSqlWindow")) + DlgSqlWindow.resize(385, 471) + self.vboxlayout = QtGui.QVBoxLayout(DlgSqlWindow) + self.vboxlayout.setObjectName(_fromUtf8("vboxlayout")) + self.label = QtGui.QLabel(DlgSqlWindow) + self.label.setObjectName(_fromUtf8("label")) + self.vboxlayout.addWidget(self.label) + self.editSql = QtGui.QTextEdit(DlgSqlWindow) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.editSql.sizePolicy().hasHeightForWidth()) + self.editSql.setSizePolicy(sizePolicy) + self.editSql.setObjectName(_fromUtf8("editSql")) + self.vboxlayout.addWidget(self.editSql) + self.hboxlayout = QtGui.QHBoxLayout() + self.hboxlayout.setObjectName(_fromUtf8("hboxlayout")) + self.btnExecute = QtGui.QPushButton(DlgSqlWindow) + self.btnExecute.setObjectName(_fromUtf8("btnExecute")) + self.hboxlayout.addWidget(self.btnExecute) + self.lblResult = QtGui.QLabel(DlgSqlWindow) + self.lblResult.setText(_fromUtf8("")) + self.lblResult.setObjectName(_fromUtf8("lblResult")) + self.hboxlayout.addWidget(self.lblResult) + spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.hboxlayout.addItem(spacerItem) + self.btnClear = QtGui.QPushButton(DlgSqlWindow) + self.btnClear.setObjectName(_fromUtf8("btnClear")) + self.hboxlayout.addWidget(self.btnClear) + self.vboxlayout.addLayout(self.hboxlayout) + self.label_2 = QtGui.QLabel(DlgSqlWindow) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.vboxlayout.addWidget(self.label_2) + self.viewResult = QtGui.QTableView(DlgSqlWindow) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(3) + sizePolicy.setHeightForWidth(self.viewResult.sizePolicy().hasHeightForWidth()) + self.viewResult.setSizePolicy(sizePolicy) + self.viewResult.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.viewResult.setObjectName(_fromUtf8("viewResult")) + self.vboxlayout.addWidget(self.viewResult) + self.buttonBox = QtGui.QDialogButtonBox(DlgSqlWindow) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close) + self.buttonBox.setObjectName(_fromUtf8("buttonBox")) + self.vboxlayout.addWidget(self.buttonBox) + + self.retranslateUi(DlgSqlWindow) + QtCore.QMetaObject.connectSlotsByName(DlgSqlWindow) + DlgSqlWindow.setTabOrder(self.editSql, self.btnExecute) + DlgSqlWindow.setTabOrder(self.btnExecute, self.btnClear) + DlgSqlWindow.setTabOrder(self.btnClear, self.viewResult) + DlgSqlWindow.setTabOrder(self.viewResult, self.buttonBox) + + def retranslateUi(self, DlgSqlWindow): + DlgSqlWindow.setWindowTitle(QtGui.QApplication.translate("DlgSqlWindow", "SQL window", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("DlgSqlWindow", "SQL query:", None, QtGui.QApplication.UnicodeUTF8)) + self.btnExecute.setText(QtGui.QApplication.translate("DlgSqlWindow", "&Execute (F5)", None, QtGui.QApplication.UnicodeUTF8)) + self.btnExecute.setShortcut(QtGui.QApplication.translate("DlgSqlWindow", "F5", None, QtGui.QApplication.UnicodeUTF8)) + self.btnClear.setText(QtGui.QApplication.translate("DlgSqlWindow", "&Clear", None, QtGui.QApplication.UnicodeUTF8)) + self.label_2.setText(QtGui.QApplication.translate("DlgSqlWindow", "Result:", None, QtGui.QApplication.UnicodeUTF8)) +