diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0e0061c..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -tmp/ -.idea -*.qgs -ui_*.py -resources.py -*.qm - diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 8e54354..0000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "qgiscombomanager"] - path = qgiscombomanager - url = git@github.com:3nids/qgiscombomanager.git -[submodule "qgissettingmanager"] - path = qgissettingmanager - url = git@github.com:3nids/qgissettingmanager.git diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index aff4d3c..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,41 +0,0 @@ - -### Version 1.0.1 26.06.2013 - -* Fix add layer action - -### Version 1.0 20.06.2013 - -* Stable release -* Updated for new API - -### Version 0.7 27.05.2013 _experimental_ - -* fix #5 exclude 'logged actions table' from 'search history' layers - -### Version 0.6 22.05.2013 _experimental_ - -* fix #4 fix search after/before date - -### Version 0.5 22.05.2013 _experimental_ - -* fix #1 multiple insert/update -* fix #2 distinct NULL values from empty value -* fix last field recognition - -### Version 0.4 22.05.2013 _experimental_ - -* replace 'layer' by 'table' in logged actions chooser -* only display no geometry tables in the combo box in the chooser - -### Version 0.3 12.05.2013 _experimental_ - -* Preselect current layer when opening dialog -* Fix help icon and unload - -### Version 0.2 07.05.2013 _experimental_ - -* Do not display geometry column if layer has no geometry -* Fix columns display -* Add help menu item linking to github page - -### Version 0.1 07.05.2013 _experimental_ diff --git a/Makefile b/Makefile deleted file mode 100644 index c37be35..0000000 --- a/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -#/*************************************************************************** -# * * -# * 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. * -# * * -# ***************************************************************************/ - - - -# Makefile for a PyQGIS plugin - -# global -PLUGINNAME = postgres91plusauditor -PY_FILES = __init__.py $(PLUGINNAME).py -EXTRAS = metadata.txt resources.qrc -TOOL_DIR = gui core ui qgiscombomanager qgissettingmanager -ICONS_DIR = icons - -UI_SOURCES=$(wildcard ui/*.ui) -UI_FILES=$(join $(dir $(UI_SOURCES)), $(notdir $(UI_SOURCES:%.ui=%.py))) -RC_SOURCES=$(wildcard *.qrc) -RC_FILES=$(patsubst %.qrc,%.py,$(RC_SOURCES)) -LN_SOURCES=$(wildcard i18n/*.ts) -LN_FILES=$(join $(dir $(LN_SOURCES)), $(notdir $(LN_SOURCES:%.ts=%.qm))) - -GEN_FILES = ${UI_FILES} ${RC_FILES} - -all: $(GEN_FILES) -ui: $(UI_FILES) -resources: $(RC_FILES) - -$(UI_FILES): ui/%.py: ui/%.ui - pyuic4 -o $@ $< - -$(RC_FILES): %.py: %.qrc - pyrcc4 -o $@ $< - -$(LN_FILES): i18n/%.qm: i18n/%.ts - lrelease-qt4 $< - -clean: - rm -f $(GEN_FILES) *.pyc - -compile: $(UI_FILES) $(RC_FILES) $(LN_FILES) - -transup: - pylupdate4 -noobsolete $(UI_SOURCES) $(PLUGINNAME).py gui/*.py core/*.py -ts i18n/$(PLUGINNAME)_fr.ts - -deploy: - mkdir -p $(HOME)/.qgis2/python/plugins/$(PLUGINNAME) - cp -rvf * $(HOME)/.qgis2/python/plugins/$(PLUGINNAME)/ diff --git a/README.md b/README.md deleted file mode 100644 index 622c3b1..0000000 --- a/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# About - -Postgres 91 plus Auditor is [QGIS](http://www.qgis.org) plugin providing an interface to rollback on postgis layers using the [Audit Trigger 91 plus](http://wiki.postgresql.org/wiki/Audit_trigger_91plus) - - -# The Audit Trigger 91 plus - -The [Audit Trigger 91 plus](http://wiki.postgresql.org/wiki/Audit_trigger_91plus) is a generic trigger function used for recording changes to tables into an audit log table. It records quite a bit more detail than the [older](http://wiki.postgresql.org/wiki/Audit_trigger) Audit trigger and does so in a more structured manner. - -The trigger should be up-to-date on Postgres website but the trigger code lives on [github](https://github.com/2ndQuadrant/audit-trigger). - -Follow the setps described on Postgres wiki to install and use the trigger. - -# Rolling-back - -The plugin allows you to rollback individual features. It is more aimed at correcting editing errors than viewing a whole dataset at a previous state. -You can restore or recreate a feature from any logged action. The rollback will not erase the logged actions but rather create a new state. In other words, the rollbacks is considered as an update and a new row will therefore be added to the logged actions table. -Hence, even a rollback can be rollbacked. - -# Plugin setup - -Once ou have enabled the trigger, just add the *logged_actions* table as a no geometry layer. Then, _define the logged actions layer_ from the plugin menu. - -The option **Redefine layer subset to increase performance** is recommended. While looking for actions, instead of looping over all rows it will redefine a SQL layer subset which is drastically faster. - -# Use the plugin - -You can start looking for any changes by clicking the plugin icon ![icon](https://raw.github.com/3nids/postgres91plusauditor/master/icons/qaudit-20.png). Choose a layer and eventually specify a feature ID. -Restrictions can be set to search insert/update/delete action, only geometry changes or by date. - -You can also search for a specific feature changes, by right-clicking on the feature edit form and choosing _History audit_. - -Once logged actions have been found, click on a row to see the differences with current feature if it exists. - -If the corresponding layer is in editing mode, the feature can be reset. - -# Screenshots - -![screenshot 1](https://raw.github.com/3nids/postgres91plusauditor/master/doc/screenshot-1.png) -![screenshot 2](https://raw.github.com/3nids/postgres91plusauditor/master/doc/screenshot-2.png) - - - - - diff --git a/__init__.py b/__init__.py deleted file mode 100644 index f643668..0000000 --- a/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Qaudit 91 plus -Denis Rouzaud -denis.rouzaud@gmail.com -April. 2013 -""" - - -def classFactory(iface): - from postgres91plusauditor import Postgres91plusAuditor - return Postgres91plusAuditor(iface) - - - - - diff --git a/core/__init__.py b/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/core/featurelayer.py b/core/featurelayer.py deleted file mode 100644 index 5118f3a..0000000 --- a/core/featurelayer.py +++ /dev/null @@ -1,14 +0,0 @@ - - -def primaryKey(layer): - """ - Returns the layer primary key - :param layer: qgis vector layer - :return: return the field name of the primary key - """ - if layer is None: - return None - pkeyIdx = layer.dataProvider().pkAttributeIndexes() - if len(pkeyIdx) == 0: - return None - return layer.pendingFields()[pkeyIdx[0]].name() \ No newline at end of file diff --git a/core/geometrytools.py b/core/geometrytools.py deleted file mode 100644 index 42e44a9..0000000 --- a/core/geometrytools.py +++ /dev/null @@ -1,30 +0,0 @@ -from qgis.core import QgsGeometry - -import binascii - -SRID_FLAG = 0x20000000 - - -class GeometryTools(): - def ewkb2gqgis(self, ewkb): - geom = QgsGeometry() - - geomType = int("0x" + self.decodeBinary(ewkb[2:10]), 0) - if geomType & SRID_FLAG: - ewkb = ewkb[:2] + self.encodeBinary(geomType ^ SRID_FLAG) + ewkb[18:] - geom.fromWkb(binascii.a2b_hex(ewkb)) - return geom - - def encodeBinary(self, value): - # https://github.com/elpaso/quickwkt/blob/master/QuickWKT.py#L132 - wkb = binascii.a2b_hex("%08x" % value) - wkb = wkb[::-1] - wkb = binascii.b2a_hex(wkb) - return wkb - - def decodeBinary(self, wkb): - """Decode the binary wkb and return as a hex string""" - value = binascii.a2b_hex(wkb) - value = value[::-1] - value = binascii.b2a_hex(value) - return value \ No newline at end of file diff --git a/core/loglayer.py b/core/loglayer.py deleted file mode 100644 index 84c919b..0000000 --- a/core/loglayer.py +++ /dev/null @@ -1,115 +0,0 @@ -from PyQt4.QtCore import QCoreApplication, pyqtSignal, QObject, QDateTime, Qt -from qgis.core import QgsMapLayerRegistry, QgsFeature, QgsFeatureRequest, QgsDataSourceURI - - -from mysettings import MySettings -from logresultrow import LogResultRow - -# tuplets for settings, display name, and row-data property -columnVarSetting = ("Date" , "User", "Action", "Changed geometry" , "Changed fields", "Application", "Client IP", "Client Port") -columnFancyName = ("Date" , "User", "Action", "G" , "Fields" , "Application", "Client IP", "Client port") -columnRowName = ("dateStr", "user", "action", "changedGeometryStr", "changedFields" , "application", "clientIP" , "clientPort") - - -class LogLayer(QObject): - setProgressMax = pyqtSignal(int) - setProgressMin = pyqtSignal(int) - setProgressValue = pyqtSignal(int) - - def __init__(self): - QObject.__init__(self) - self.settings = MySettings() - self.continueSearch = True - self.layer = None - - def isValid(self): - self.layer = QgsMapLayerRegistry.instance().mapLayer(self.settings.value("logLayer")) - return self.checkLayer(self.layer) - - def checkLayer(self, layer): - if layer is None: - return False - # TODO check validity - return True - - def interrupt(self): - self.continueSearch = False - - def performSearch(self, featureLayer, featureId, pkeyName, searchInserts, searchUpdates, searchDeletes, - searchOnlyGeometry, searchAfterDate, searchBeforeDate): - results = dict() - if not self.isValid(): - return - - dataUri = QgsDataSourceURI(featureLayer.dataProvider().dataSourceUri()) - if featureLayer.hasGeometryType(): - geomColumn = dataUri.geometryColumn() - else: - geomColumn = None - - # initiate the layer feature (feature at given ID, or an empty feature otherwise) - layerFeature = QgsFeature() - if featureId != 0: - featReq = QgsFeatureRequest().setFilterFid(featureId) - if not featureLayer.hasGeometryType(): - featReq.setFlags(QgsFeatureRequest.NoGeometry) - if featureLayer.getFeatures(featReq).nextFeature(layerFeature) is False: - fields = featureLayer.dataProvider().fields() - layerFeature.setFields(fields) - else: - fields = featureLayer.dataProvider().fields() - layerFeature.setFields(fields) - - # set query subset for layer to drastically improve search speed - # todo: if a subset already exists, should give a warning - if self.settings.value("redefineSubset"): - subset = "schema_name = '%s' and table_name = '%s'" % (dataUri.schema(), dataUri.table()) - if not searchInserts or not searchUpdates or not searchDeletes: - subset += "and (" - if searchInserts: - subset += " action = 'I' or" - if searchUpdates: - subset += " action = 'U' or" - if searchDeletes: - subset += " action = 'D' or" - subset = subset[:-3] + ")" - if not searchAfterDate.isNull(): - subset += " and action_tstamp_clk >= '%s'" % searchAfterDate.toString("yyyy-MM-dd hh:mm:ss") - if not searchBeforeDate.isNull(): - subset += " and action_tstamp_clk <= '%s'" % searchBeforeDate.toString("yyyy-MM-dd hh:mm:ss") - - if not self.layer.setSubsetString(subset): - raise NameError("Subset could not be set.") - - self.continueSearch = True - logFeature = QgsFeature() - featReq = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry) - iterator = self.layer.getFeatures(featReq) - self.setProgressMin.emit(0) - self.setProgressMax.emit(self.layer.featureCount()) - k = 0 - while iterator.nextFeature(logFeature): - self.setProgressValue.emit(k) - QCoreApplication.processEvents() - if not self.continueSearch: - break - # this condition is redundant if layer subset string is used - dateAction = QDateTime().fromString(logFeature["action_tstamp_clk"], Qt.ISODate) - if logFeature["schema_name"] == dataUri.schema() and \ - logFeature["table_name"] == dataUri.table() and \ - (searchInserts and logFeature["action"] == 'I' or - searchUpdates and logFeature["action"] == 'U' or - searchDeletes and logFeature["action"] == 'D') and \ - (searchAfterDate.isNull() or dateAction >= searchAfterDate) and \ - (searchBeforeDate.isNull() or dateAction <= searchBeforeDate): - row = LogResultRow(logFeature, featureLayer, pkeyName, geomColumn) - if featureId != 0 and row.layerFeatureId != featureId: - continue - if searchOnlyGeometry and not row.changedGeometry(): - continue - - results[row.dateMs] = row - k += 1 - if self.settings.value("redefineSubset"): - self.layer.setSubsetString("") - return results diff --git a/core/logresultrow.py b/core/logresultrow.py deleted file mode 100644 index 7602de1..0000000 --- a/core/logresultrow.py +++ /dev/null @@ -1,143 +0,0 @@ - -from PyQt4.QtCore import QDateTime, Qt -from qgis.core import QgsFeature, QgsGeometry, QgsFeatureRequest - -import re - -from geometrytools import GeometryTools - -# regexp to parse data from hstore -fieldRe = lambda(fieldName): re.compile('("%s"|%s)\s*=\>\s*' % (fieldName, fieldName)) -dataReWithQuote = re.compile('\s*".*?[^\\\\]*?"') -dataReWithoutQuote = re.compile('.*?,') -dataReWithoutQuoteEndOfString = re.compile('.*?$') - -geometryTools = GeometryTools() - - -class LogResultRow(): - def __init__(self, logFeature, featureLayer, pkeyName, geomColumn): - self.featureLayer = featureLayer - self.fields = featureLayer.dataProvider().fields() - self.logFeature = QgsFeature(logFeature) - self.geomColumn = geomColumn - self.date = QDateTime().fromString(logFeature["action_tstamp_clk"], Qt.ISODate) - print logFeature["action_tstamp_clk"], self.date, self.date.toMSecsSinceEpoch() - self.dateMs = self.date.toMSecsSinceEpoch() - self.logData = self.logFeature["row_data"] - self.layerFeatureId = int(self.getFieldValue(self.logData, pkeyName)) - - def getFieldValue(self, data, fieldName): - if data is None: - return None - p = fieldRe(fieldName).search(data) - if p: - value = "" - data = data[p.end():] - p = dataReWithQuote.match(data) - if p: - value = data[p.start()+1:p.end()-1] - else: - p = dataReWithoutQuote.match(data) - if p: - value = data[p.start():p.end()-1] - else: - p = dataReWithoutQuoteEndOfString.match(data) - if p: - value = data[p.start():p.end()] - return value - return None - - def dateStr(self): - return self.date.toString("ddd dd MMM yyyy hh:mm") - - def user(self): - return self.logFeature["session_user_name"] - - def action(self): - action = self.logFeature["action"] - if action == "I": - #return u"\u002B" # plus sign - return "insert" - if action == "U": - #return u"\u2713" # check sign - return "update" - if action == "D": - #return u"\u2A2F" # cross sign - return "delete" - raise NameError("Invalid action %s" % action) - - def application(self): - return self.logFeature["application_name"] - - def clientIP(self): - return self.logFeature["client_addr"] - - def clientPort(self): - return self.logFeature["client_port"] - - def changedFields(self): - data = self.logFeature["changed_fields"] - columns = "" - for field in self.fields: - if self.getFieldValue(data, field.name()) is not None: - columns += field.name() + ", " - return columns[:-2] - - def changedGeometry(self): - data = self.logFeature["changed_fields"] - geometry = self.getFieldValue(data, self.geomColumn) - return geometry is not None - - def changedGeometryStr(self): - if self.changedGeometry(): - return u"\u2713" # i.e. check sign - else: - return "" - - def geometry(self): - if self.geomColumn is None: - return QgsGeometry() - ewkb = "%s" % self.getFieldValue(self.logData, self.geomColumn) - return geometryTools.ewkb2gqgis(ewkb) - - def data(self): - out = dict() - for field in self.fields: - out[field.name()] = self.getFieldValue(self.logData, field.name()) - return out - - def getLayerFeature(self): - layerFeature = QgsFeature() - featReq = QgsFeatureRequest().setFilterFid(self.layerFeatureId) - if not self.featureLayer.hasGeometryType(): - featReq.setFlags(QgsFeatureRequest.NoGeometry) - if self.featureLayer.getFeatures(featReq).nextFeature(layerFeature): - return layerFeature - else: - return None - - def restoreFeature(self): - if not self.featureLayer.isEditable(): - return False - - currentFeature = self.getLayerFeature() - editBuffer = self.featureLayer.editBuffer() - if currentFeature is not None: - fid = currentFeature.id() - for idx, field in enumerate(self.fields): - value = self.getFieldValue(self.logData, field.name()) - editBuffer.changeAttributeValue(fid, idx, value) - if self.featureLayer.hasGeometryType(): - editBuffer.changeGeometry(fid, self.geometry()) - else: - newFeature = QgsFeature() - newFeature.setFields(self.fields) - newFeature.initAttributes(self.fields.size()) - for field in self.fields: - value = self.getFieldValue(self.logData, field.name()) - newFeature[field.name()] = QVariant(value) - if self.featureLayer.hasGeometryType(): - newFeature.setGeometry(self.geometry()) - editBuffer.addFeature(newFeature) - diff --git a/core/mysettings.py b/core/mysettings.py deleted file mode 100644 index f50e1be..0000000 --- a/core/mysettings.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -Postgres Auditor 91 plus -QGIS plugin - -Denis Rouzaud -denis.rouzaud@gmail.com -""" - -from ..qgissettingmanager import * - -pluginName = "postgres91plusauditor" - - -class MySettings(SettingManager): - def __init__(self): - SettingManager.__init__(self, pluginName) - self.addSetting("panShowGeometry", "bool", "global", True) - self.addSetting("columns", "stringlist", "global", - ("Date", "User", "Action", "Changed geometry", "Changed fields")) - - # project - self.addSetting("redefineSubset", "bool", "project", True) - self.addSetting("logLayer", "string", "project", "") diff --git a/doc/screenshot-1.png b/doc/screenshot-1.png deleted file mode 100644 index bc198ae..0000000 Binary files a/doc/screenshot-1.png and /dev/null differ diff --git a/doc/screenshot-2.png b/doc/screenshot-2.png deleted file mode 100644 index 010f5c3..0000000 Binary files a/doc/screenshot-2.png and /dev/null differ diff --git a/fonts/copse-regular-webfont.eot b/fonts/copse-regular-webfont.eot new file mode 100644 index 0000000..af1f5e6 Binary files /dev/null and b/fonts/copse-regular-webfont.eot differ diff --git a/fonts/copse-regular-webfont.svg b/fonts/copse-regular-webfont.svg new file mode 100644 index 0000000..1e920b5 --- /dev/null +++ b/fonts/copse-regular-webfont.svg @@ -0,0 +1,247 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Copyright c 2010 Daniel Rhatigansparkyultrasparkyorg with Reserved Font Name Copse +Designer : Daniel Rhatigan +Foundry : Daniel Rhatigan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/copse-regular-webfont.ttf b/fonts/copse-regular-webfont.ttf new file mode 100644 index 0000000..434b208 Binary files /dev/null and b/fonts/copse-regular-webfont.ttf differ diff --git a/fonts/copse-regular-webfont.woff b/fonts/copse-regular-webfont.woff new file mode 100644 index 0000000..a9a0450 Binary files /dev/null and b/fonts/copse-regular-webfont.woff differ diff --git a/fonts/quattrocentosans-bold-webfont.eot b/fonts/quattrocentosans-bold-webfont.eot new file mode 100644 index 0000000..c041ed9 Binary files /dev/null and b/fonts/quattrocentosans-bold-webfont.eot differ diff --git a/fonts/quattrocentosans-bold-webfont.svg b/fonts/quattrocentosans-bold-webfont.svg new file mode 100644 index 0000000..fb162e9 --- /dev/null +++ b/fonts/quattrocentosans-bold-webfont.svg @@ -0,0 +1,247 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Copyright c 2011 Pablo Impallari wwwimpallaricomimpallarigmailcomCopyright c 2011 Igino Marini wwwikerncommailiginomarinicomCopyright c 2011 Brenda Gallo gbrenda1987gmailcomwith Reserved Font Name Quattrocento Sans +Designer : Pablo Impallari +Foundry : Pablo Impallari Igino Marini Brenda Gallo +Foundry URL : wwwimpallaricom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/quattrocentosans-bold-webfont.ttf b/fonts/quattrocentosans-bold-webfont.ttf new file mode 100644 index 0000000..7389c87 Binary files /dev/null and b/fonts/quattrocentosans-bold-webfont.ttf differ diff --git a/fonts/quattrocentosans-bold-webfont.woff b/fonts/quattrocentosans-bold-webfont.woff new file mode 100644 index 0000000..fc14168 Binary files /dev/null and b/fonts/quattrocentosans-bold-webfont.woff differ diff --git a/fonts/quattrocentosans-bolditalic-webfont.eot b/fonts/quattrocentosans-bolditalic-webfont.eot new file mode 100644 index 0000000..7c1aa7a Binary files /dev/null and b/fonts/quattrocentosans-bolditalic-webfont.eot differ diff --git a/fonts/quattrocentosans-bolditalic-webfont.svg b/fonts/quattrocentosans-bolditalic-webfont.svg new file mode 100644 index 0000000..9070a8b --- /dev/null +++ b/fonts/quattrocentosans-bolditalic-webfont.svg @@ -0,0 +1,248 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Copyright c 2011 Pablo Impallari wwwimpallaricomimpallarigmailcomCopyright c 2011 Igino Marini wwwikerncommailiginomarinicomCopyright c 2011 Brenda Gallo gbrenda1987gmailcomwith Reserved Font Name Quattrocento Sans +Designer : Pablo Impallari +Foundry : Pablo Impallari Igino Marini Brenda Gallo +Foundry URL : wwwimpallaricom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/quattrocentosans-bolditalic-webfont.ttf b/fonts/quattrocentosans-bolditalic-webfont.ttf new file mode 100644 index 0000000..9766a17 Binary files /dev/null and b/fonts/quattrocentosans-bolditalic-webfont.ttf differ diff --git a/fonts/quattrocentosans-bolditalic-webfont.woff b/fonts/quattrocentosans-bolditalic-webfont.woff new file mode 100644 index 0000000..c436da0 Binary files /dev/null and b/fonts/quattrocentosans-bolditalic-webfont.woff differ diff --git a/fonts/quattrocentosans-italic-webfont.eot b/fonts/quattrocentosans-italic-webfont.eot new file mode 100644 index 0000000..379b383 Binary files /dev/null and b/fonts/quattrocentosans-italic-webfont.eot differ diff --git a/fonts/quattrocentosans-italic-webfont.svg b/fonts/quattrocentosans-italic-webfont.svg new file mode 100644 index 0000000..b613779 --- /dev/null +++ b/fonts/quattrocentosans-italic-webfont.svg @@ -0,0 +1,247 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Copyright c 2011 Pablo Impallari wwwimpallaricomimpallarigmailcomCopyright c 2011 Igino Marini wwwikerncommailiginomarinicomCopyright c 2011 Brenda Gallo gbrenda1987gmailcomwith Reserved Font Name Quattrocento Sans +Designer : Pablo Impallari +Foundry : Pablo Impallari Igino Marini Brenda Gallo +Foundry URL : wwwimpallaricom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/quattrocentosans-italic-webfont.ttf b/fonts/quattrocentosans-italic-webfont.ttf new file mode 100644 index 0000000..c7ba47a Binary files /dev/null and b/fonts/quattrocentosans-italic-webfont.ttf differ diff --git a/fonts/quattrocentosans-italic-webfont.woff b/fonts/quattrocentosans-italic-webfont.woff new file mode 100644 index 0000000..3798881 Binary files /dev/null and b/fonts/quattrocentosans-italic-webfont.woff differ diff --git a/fonts/quattrocentosans-regular-webfont.eot b/fonts/quattrocentosans-regular-webfont.eot new file mode 100644 index 0000000..346db6f Binary files /dev/null and b/fonts/quattrocentosans-regular-webfont.eot differ diff --git a/fonts/quattrocentosans-regular-webfont.svg b/fonts/quattrocentosans-regular-webfont.svg new file mode 100644 index 0000000..3470924 --- /dev/null +++ b/fonts/quattrocentosans-regular-webfont.svg @@ -0,0 +1,247 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Copyright c 2011 Pablo Impallari wwwimpallaricomimpallarigmailcomCopyright c 2011 Igino Marini wwwikerncommailiginomarinicomCopyright c 2011 Brenda Gallo gbrenda1987gmailcomwith Reserved Font Name Quattrocento Sans +Designer : Pablo Impallari +Foundry : Pablo Impallari Igino Marini Brenda Gallo +Foundry URL : wwwimpallaricom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/quattrocentosans-regular-webfont.ttf b/fonts/quattrocentosans-regular-webfont.ttf new file mode 100644 index 0000000..e414670 Binary files /dev/null and b/fonts/quattrocentosans-regular-webfont.ttf differ diff --git a/fonts/quattrocentosans-regular-webfont.woff b/fonts/quattrocentosans-regular-webfont.woff new file mode 100644 index 0000000..09ed324 Binary files /dev/null and b/fonts/quattrocentosans-regular-webfont.woff differ diff --git a/gui/__init__.py b/gui/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gui/auditdialog.py b/gui/auditdialog.py deleted file mode 100644 index 790d421..0000000 --- a/gui/auditdialog.py +++ /dev/null @@ -1,202 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal, pyqtSignature, QDateTime -from PyQt4.QtGui import QDialog, QGridLayout -from qgis.core import QgsFeature, QgsFeatureRequest -from qgis.gui import QgsRubberBand - -from ..qgiscombomanager import VectorLayerCombo -from ..qgissettingmanager import SettingDialog - -from ..core.mysettings import MySettings -from ..core.loglayer import LogLayer -from ..core.featurelayer import primaryKey - -from ..ui.ui_audit import Ui_audit - -from loggedactionstablechooserdialog import LoggedActionsTableChooserDialog -from columnchooserdialog import ColumnChooserDialog -from differenceviewer import DifferenceViewer -from loggedactionstable import LoggedActionsTable - - -class AuditDialog(QDialog, Ui_audit, SettingDialog): - rejectShowEvent = pyqtSignal() - performSearchAtShowEvent = pyqtSignal() - - def __init__(self, iface, layerId=None, featureId=None): - QDialog.__init__(self) - self.setupUi(self) - self.settings = MySettings() - SettingDialog.__init__(self, self.settings, False, True) # column chooser, advanced search options - - #init variables - self.layerId = layerId - self.featureId = featureId - self.layer = None - self.rubber = QgsRubberBand(iface.mapCanvas()) - self.mapCanvas = iface.mapCanvas() - self.resuts = dict() - - # connect "pan and show geometry" check box to draw in rubber band - self.panShowGeometry.clicked.connect(self.displayGeomDifference) - - # reject properly showEvent if checking fails - self.rejectShowEvent.connect(self.reject, Qt.QueuedConnection) - # start search directly at the end of showEvent if enough params - self.performSearchAtShowEvent.connect(self.on_searchButton_clicked, Qt.QueuedConnection) - - # setup layer - field combo, with primary key selector as field - self.layerComboManager = VectorLayerCombo(self.layerCombo, layerId, - {"dataProvider": "postgres", "finishInit": False, - "skipLayers": [lambda: self.settings.value("logLayer")]}) - self.layerComboManager.finishInit() - - # log layer - self.logLayer = LogLayer() - self.logLayer.setProgressMax.connect(self.progressBar.setMaximum) - self.logLayer.setProgressMin.connect(self.progressBar.setMinimum) - self.logLayer.setProgressValue.connect(self.progressBar.setValue) - - # logged actions table - self.loggedActionsLayout = QGridLayout(self.loggedActionsWidget) - self.loggedActionsTable = LoggedActionsTable(self.loggedActionsWidget) - self.loggedActionsLayout.addWidget(self.loggedActionsTable, 0, 0, 1, 1) - self.loggedActionsTable.itemSelectionChanged.connect(self.displayDifference) - - # difference viewer - self.differenceLayout = QGridLayout(self.differenceViewerWidget) - self.differenceViewer = DifferenceViewer(self.differenceViewerWidget) - self.differenceLayout.addWidget(self.differenceViewer, 0, 0, 1, 1) - - # set dates - now = QDateTime.currentDateTime() - self.searchBeforeDate.setDateTime(now) - self.searchAfterDate.setDateTime(now.addDays(-7)) - - # finish ui - self.buttonDisplayMode(False) - self.restoreButton.setEnabled(False) - if featureId is not None: - self.featureEdit.setText("%s" % featureId) - self.adjustSize() - - def closeEvent(self, e): - self.rubber.reset() - - def showEvent(self, e): - SettingDialog.showEvent(self, e) - while not self.logLayer.isValid(): - if not LoggedActionsTableChooserDialog().exec_(): - self.rejectShowEvent.emit() - return - if self.layerId is not None: - self.layerCombo.setEnabled(False) - layer = self.layerComboManager.getLayer() - if layer is None: - self.rejectShowEvent.emit() - return - if self.featureId is not None: - self.featureEdit.setEnabled(False) - f = QgsFeature() - featReq = QgsFeatureRequest().setFilterFid(self.featureId).setFlags(QgsFeatureRequest.NoGeometry) - if layer.getFeatures(featReq).nextFeature(f) is False: - self.rejectShowEvent.emit() - return - self.performSearchAtShowEvent.emit() - else: - layer = self.mapCanvas.currentLayer() - self.layerComboManager.setLayer(layer) - - - @pyqtSignature("on_layerCombo_currentIndexChanged(int)") - def on_layerCombo_currentIndexChanged(self, i): - self.layer = self.layerComboManager.getLayer() - self.panShowGeometry.setEnabled(self.layer is not None and self.layer.hasGeometryType()) - - @pyqtSignature("on_stopButton_clicked()") - def on_stopButton_clicked(self): - self.logLayer.interrupt() - - @pyqtSignature("on_searchButton_clicked()") - def on_searchButton_clicked(self): - self.layer = self.layerComboManager.getLayer() - pkeyName = primaryKey(self.layer) - if self.layer is None or pkeyName is None: - return - self.loggedActionsTable.geomColumn = self.layer.hasGeometryType() - featureId = int(self.featureEdit.text() or 0) - searchBeforeDate = QDateTime() - if self.searchBefore.isChecked(): - searchBeforeDate = self.searchAfterDate.dateTime() - searchAfterDate = QDateTime() - if self.searchAfter.isChecked(): - searchAfterDate = self.searchAfterDate.dateTime() - self.buttonDisplayMode(True) - self.results = self.logLayer.performSearch(self.layer, featureId, pkeyName, - self.searchInserts.isChecked(), self.searchUpdates.isChecked(), - self.searchDeletes.isChecked(), self.searchOnlyGeometry.isChecked(), - searchAfterDate, searchBeforeDate) - self.buttonDisplayMode(False) - self.panShowGeometry.setEnabled(self.layer.hasGeometryType()) - self.displayLoggedActions() - - def buttonDisplayMode(self, searchOn): - self.searchButton.setVisible(not searchOn) - self.stopButton.setVisible(searchOn) - self.progressBar.setVisible(searchOn) - - def displayLoggedActions(self): - self.differenceViewer.clearRows() - self.loggedActionsTable.displayColumns() - self.loggedActionsTable.displayRows(self.results) - - def displayDifference(self): - self.differenceViewer.clearRows() - self.restoreButton.setEnabled(False) - item = self.loggedActionsTable.selectedItems() - if len(item) == 0: - return - rowId = item[0].data(Qt.UserRole) - logRow = self.results[rowId] - if logRow.featureLayer.isEditable(): - self.restoreButton.setEnabled(True) - self.differenceViewer.display(logRow) - self.displayGeomDifference() - - def displayGeomDifference(self): - self.rubber.reset() - item = self.loggedActionsTable.selectedItems() - if len(item) == 0: - return - rowId = item[0].data(Qt.UserRole) - logRow = self.results[rowId] - - if self.layer.hasGeometryType() and self.panShowGeometry.isChecked(): - geom = logRow.geometry() - self.rubber.setToGeometry(geom, self.layer) - panTo = self.mapCanvas.mapRenderer().layerExtentToOutputExtent(self.layer, geom.boundingBox()) - panTo.scale(1.5) - self.mapCanvas.setExtent(panTo) - self.mapCanvas.refresh() - - @pyqtSignature("on_columnChooserButton_clicked()") - def on_columnChooserButton_clicked(self): - ColumnChooserDialog().exec_() - self.loggedActionsTable.displayColumns() - self.loggedActionsTable.displayRows(self.results) - - @pyqtSignature("on_restoreButton_clicked()") - def on_restoreButton_clicked(self): - item = self.loggedActionsTable.selectedItems() - if len(item) == 0: - return - rowId = item[0].data(Qt.UserRole) - logRow = self.results[rowId] - if not logRow.featureLayer.isEditable(): - return - logRow.restoreFeature() - self.mapCanvas.refresh() - - - - - diff --git a/gui/columnchooserdialog.py b/gui/columnchooserdialog.py deleted file mode 100644 index c72d1e4..0000000 --- a/gui/columnchooserdialog.py +++ /dev/null @@ -1,18 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal, pyqtSignature, QDateTime -from PyQt4.QtGui import QDialog, QGridLayout -from qgis.core import QgsFeature, QgsFeatureRequest -from qgis.gui import QgsRubberBand - -from ..qgissettingmanager import SettingDialog - -from ..core.mysettings import MySettings - -from ..ui.ui_columnchooser import Ui_columnChooser - - -class ColumnChooserDialog(QDialog, Ui_columnChooser, SettingDialog): - def __init__(self): - QDialog.__init__(self) - self.setupUi(self) - self.settings = MySettings() - SettingDialog.__init__(self, self.settings) # column chooser, advanced search options diff --git a/gui/differenceviewer.py b/gui/differenceviewer.py deleted file mode 100644 index df879a4..0000000 --- a/gui/differenceviewer.py +++ /dev/null @@ -1,74 +0,0 @@ -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QTableWidget, QTableWidgetItem, QAbstractItemView, QBrush, QColor - - -class DifferenceViewer(QTableWidget): - def __init__(self, parent): - QTableWidget.__init__(self, parent) - self.setSelectionMode(QAbstractItemView.NoSelection) - self.setColumnCount(0) - self.setRowCount(0) - self.horizontalHeader().setMinimumSectionSize(15) - self.verticalHeader().setVisible(False) - self.verticalHeader().setDefaultSectionSize(25) - #self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) - self.columns() - - def columns(self, nc=2, dateTitle=""): - while self.columnCount() > 0: - self.removeColumn(0) - if nc == 2: - headers = ("Field", dateTitle) - else: - headers = ("Field", "Current", dateTitle) - for c, header in enumerate(headers): - self.insertColumn(c) - self.setHorizontalHeaderItem(c, QTableWidgetItem(header)) - self.adjustSize() - - def display(self, logRow): - self.clearRows() - - layerFeature = logRow.getLayerFeature() - # if a feature exists (it has been modified but not deleted), display difference - if layerFeature is None: - nc = 2 - else: - nc = 3 - self.columns(nc, logRow.dateStr()) - items = [0, 0, 0] - items = items[:nc] - currentValue = None - for r, field in enumerate(logRow.fields): - self.insertRow(r) - - logValue = logRow.getFieldValue(logRow.logData, field.name()) - - items[0] = QTableWidgetItem(field.name()) - if layerFeature is not None: - currentValue = layerFeature[field.name()] - if currentValue is None: - currentValue = "NULL" - items[1] = QTableWidgetItem(currentValue) - items[nc-1] = QTableWidgetItem(logValue) - - for c, item in enumerate(items): - self.reduceFontSize(item) - item.setFlags(Qt.ItemIsEnabled) - if layerFeature is not None and currentValue != logValue: - item.setBackground(QBrush(QColor(250, 250, 210))) - self.setItem(r, c, item) - - self.resizeColumnsToContents() - self.adjustSize() - - def clearRows(self): - self.clearContents() - while self.rowCount() > 0: - self.removeRow(0) - - def reduceFontSize(self, item): - font = item.font() - font.setPointSize(font.pointSize() - 2) - item.setFont(font) - return item diff --git a/gui/loggedactionstable.py b/gui/loggedactionstable.py deleted file mode 100644 index e65000a..0000000 --- a/gui/loggedactionstable.py +++ /dev/null @@ -1,94 +0,0 @@ -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QTableWidget, QTableWidgetItem, QAbstractItemView - -from ..core.mysettings import MySettings -from ..core.loglayer import columnVarSetting, columnFancyName, columnRowName - - -class LoggedActionsTable(QTableWidget): - def __init__(self, parent): - QTableWidget.__init__(self, parent) - self.settings = MySettings() - - self.geomColumn = True - - self.setSortingEnabled(True) - self.setSelectionMode(QAbstractItemView.SingleSelection) - self.setSelectionBehavior(QAbstractItemView.SelectRows) - self.setColumnCount(0) - self.setRowCount(0) - self.horizontalHeader().setMinimumSectionSize(15) - self.verticalHeader().setVisible(False) - self.verticalHeader().setDefaultSectionSize(25) - #self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) - - self.displayColumns() - - self.adjustSize() - - def displayColumns(self): - self.clear() - for c in range(self.columnCount() - 1, -1, -1): - self.removeColumn(c) - for r in range(self.rowCount() - 1, -1, -1): - self.removeRow(r) - columns = self.settings.value("columns") - c = 0 - for i, col in enumerate(columnVarSetting): - if col in columns: - if columnRowName[i] == "changedGeometryStr" and not self.geomColumn: - continue - self.insertColumn(c) - item = QTableWidgetItem(columnFancyName[i]) - item.setData(Qt.UserRole, columnRowName[i]) - font = item.font() - font.setPointSize(font.pointSize() - 2) - item.setFont(font) - self.setHorizontalHeaderItem(c, item) - c += 1 - self.horizontalHeader().setMinimumSectionSize(15) - - def displayRows(self, data): - self.clearContents() - for r in range(self.rowCount() - 1, -1, -1): - self.removeRow(r) - for row in data.values(): - r = self.rowCount() - self.insertRow(r) - - for c in range(self.columnCount()): - crn = self.horizontalHeaderItem(c).data(Qt.UserRole) - dataStr = eval("row.%s()" % crn) - if crn == "dateStr": - item = LoggedActiontItem(dataStr) - else: - item = QTableWidgetItem(dataStr) - item.setData(Qt.UserRole, row.dateMs) - item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) - if crn in ("user", "action", "changedGeometryStr"): - item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) - else: - item.setTextAlignment(Qt.AlignVCenter) - font = item.font() - font.setPointSize(font.pointSize() - 2) - item.setFont(font) - self.setItem(r, c, item) - - self.resizeColumnsToContents() - self.sortByColumn(0, Qt.DescendingOrder) - - -class LoggedActiontItem(QTableWidgetItem): - def __init__(self, text): - QTableWidgetItem.__init__(self, text) - - def __gt__(self, other): - return long(self.data(Qt.UserRole)) > long(other.data(Qt.UserRole)) - - def __lt__(self, other): - return long(self.data(Qt.UserRole)) < long(other.data(Qt.UserRole)) - - def __eq__(self, other): - return long(self.data(Qt.UserRole)) == long(other.data(Qt.UserRole)) - - diff --git a/gui/loggedactionstablechooserdialog.py b/gui/loggedactionstablechooserdialog.py deleted file mode 100644 index 4ce9276..0000000 --- a/gui/loggedactionstablechooserdialog.py +++ /dev/null @@ -1,29 +0,0 @@ -from PyQt4.QtGui import QDialog - -from ..qgissettingmanager import SettingDialog -from ..qgiscombomanager import VectorLayerCombo - -from ..core.mysettings import MySettings -from ..core.loglayer import LogLayer - -from ..ui.ui_loggedactionstablechooser import Ui_LoggedActionsTableChooser - - -class LoggedActionsTableChooserDialog(QDialog, Ui_LoggedActionsTableChooser, SettingDialog): - - def __init__(self): - QDialog.__init__(self) - self.setupUi(self) - self.settings = MySettings() - SettingDialog.__init__(self, self.settings) - - self.layerComboManager = VectorLayerCombo(self.logLayer, - lambda: self.settings.value("logLayer"), - {"dataProvider": "postgres", "hasGeometry": False}) - - def accept(self): - layer = self.layerComboManager.getLayer() - if LogLayer().checkLayer(layer): - QDialog.accept(self) - else: - self.logLayer.setCurrentIndex(0) diff --git a/icons/connect.png b/icons/connect.png deleted file mode 100644 index f696c00..0000000 Binary files a/icons/connect.png and /dev/null differ diff --git a/icons/help.png b/icons/help.png deleted file mode 100644 index 440695a..0000000 Binary files a/icons/help.png and /dev/null differ diff --git a/icons/qaudit-20.png b/icons/qaudit-20.png deleted file mode 100644 index 3bf401a..0000000 Binary files a/icons/qaudit-20.png and /dev/null differ diff --git a/icons/qaudit-64.png b/icons/qaudit-64.png deleted file mode 100644 index 0fd2ecd..0000000 Binary files a/icons/qaudit-64.png and /dev/null differ diff --git a/images/background.png b/images/background.png new file mode 100644 index 0000000..b63b420 Binary files /dev/null and b/images/background.png differ diff --git a/images/body-background.png b/images/body-background.png new file mode 100644 index 0000000..d6a152f Binary files /dev/null and b/images/body-background.png differ diff --git a/images/bullet.png b/images/bullet.png new file mode 100644 index 0000000..2b7dc9a Binary files /dev/null and b/images/bullet.png differ diff --git a/images/hr.gif b/images/hr.gif new file mode 100644 index 0000000..a64b56c Binary files /dev/null and b/images/hr.gif differ diff --git a/images/octocat-logo.png b/images/octocat-logo.png new file mode 100644 index 0000000..28a3ad1 Binary files /dev/null and b/images/octocat-logo.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..95d7b34 --- /dev/null +++ b/index.html @@ -0,0 +1,89 @@ + + + + + + Postgres91plusauditor by 3nids + + + + + + + + + + +
+

Postgres91plusauditor

+

Postgres 91 plus Auditor is a QGIS plugin providing an interface to rollback changes on postgis layers using the Audit Trigger 91 plus

+
+ + + +
+ +
+

About

+ +

Postgres 91 plus Auditor is QGIS plugin providing an interface to rollback on postgis layers using the Audit Trigger 91 plus

+ +

The Audit Trigger 91 plus

+ +

The Audit Trigger 91 plus is a generic trigger function used for recording changes to tables into an audit log table. It records quite a bit more detail than the older Audit trigger and does so in a more structured manner.

+ +

The trigger should be up-to-date on Postgres website but the trigger code lives on github.

+ +

Follow the setps described on Postgres wiki to install and use the trigger.

+ +

Rolling-back

+ +

The plugin allows you to rollback individual features. It is more aimed at correcting editing errors than viewing a whole dataset at a previous state. +You can restore or recreate a feature from any logged action. The rollback will not erase the logged actions but rather create a new state. In other words, the rollbacks is considered as an update and a new row will therefore be added to the logged actions table. +Hence, even a rollback can be rollbacked.

+ +

Plugin setup

+ +

Once ou have enabled the trigger, just add the logged_actions table as a no geometry layer. Then, define the logged actions layer from the plugin menu.

+ +

The option Redefine layer subset to increase performance is recommended. While looking for actions, instead of looping over all rows it will redefine a SQL layer subset which is drastically faster.

+ +

Use the plugin

+ +

You can start looking for any changes by clicking the plugin icon icon. Choose a layer and eventually specify a feature ID. +Restrictions can be set to search insert/update/delete action, only geometry changes or by date.

+ +

You can also search for a specific feature changes, by right-clicking on the feature edit form and choosing History audit.

+ +

Once logged actions have been found, click on a row to see the differences with current feature if it exists.

+ +

If the corresponding layer is in editing mode, the feature can be reset.

+ +

Screenshots

+ +

screenshot 1screenshot 2

+
+ +
+ + + + \ No newline at end of file diff --git a/javascripts/main.js b/javascripts/main.js new file mode 100644 index 0000000..c57e54c --- /dev/null +++ b/javascripts/main.js @@ -0,0 +1,53 @@ +var sectionHeight = function() { + var total = $(window).height(), + $section = $('section').css('height','auto'); + + if ($section.outerHeight(true) < total) { + var margin = $section.outerHeight(true) - $section.height(); + $section.height(total - margin - 20); + } else { + $section.css('height','auto'); + } +} + +$(window).resize(sectionHeight); + +$(document).ready(function(){ + $("section h1, section h2").each(function(){ + $("nav ul").append("
  • " + $(this).text() + "
  • "); + $(this).attr("id",$(this).text().toLowerCase().replace(/ /g, '-').replace(/[^\w-]+/g,'')); + $("nav ul li:first-child a").parent().addClass("active"); + }); + + $("nav ul li").on("click", "a", function(event) { + var position = $($(this).attr("href")).offset().top - 190; + $("html, body").animate({scrollTop: position}, 400); + $("nav ul li a").parent().removeClass("active"); + $(this).parent().addClass("active"); + event.preventDefault(); + }); + + sectionHeight(); + + $('img').load(sectionHeight); +}); + +fixScale = function(doc) { + + var addEvent = 'addEventListener', + type = 'gesturestart', + qsa = 'querySelectorAll', + scales = [1, 1], + meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : []; + + function fix() { + meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1]; + doc.removeEventListener(type, fix, true); + } + + if ((meta = meta[meta.length - 1]) && addEvent in doc) { + fix(); + scales = [.25, 1.6]; + doc[addEvent](type, fix, true); + } +}; \ No newline at end of file diff --git a/metadata.txt b/metadata.txt deleted file mode 100644 index 00a9744..0000000 --- a/metadata.txt +++ /dev/null @@ -1,17 +0,0 @@ -[general] -name=Postgres 91 plus Auditor -description=Postgres 91 plus Auditor is a QGIS plugin providing an interface to rollback changes on postgis layers using the Audit Trigger 91 plus -version=1.0.1 -qgisMinimumVersion=2.0 - - -author=Denis Rouzaud -email=denis.rouzaud@gmail.com - -experimental=False - -icon=icons/qaudit-64.png -tags=history,audit,log,undo,rollback -homepage=http://3nids.github.io/postgres91plusauditor/ -tracker=https://github.com/3nids/postgres91plusauditor/issues -repository=https://github.com/3nids/postgres91plusauditor/ diff --git a/params.json b/params.json new file mode 100644 index 0000000..2192b39 --- /dev/null +++ b/params.json @@ -0,0 +1 @@ +{"name":"Postgres91plusauditor","tagline":"Postgres 91 plus Auditor is a QGIS plugin providing an interface to rollback changes on postgis layers using the Audit Trigger 91 plus","body":"# About\r\n\r\nPostgres 91 plus Auditor is [QGIS](http://www.qgis.org) plugin providing an interface to rollback on postgis layers using the [Audit Trigger 91 plus](http://wiki.postgresql.org/wiki/Audit_trigger_91plus)\r\n\r\n\r\n# The Audit Trigger 91 plus\r\n\r\nThe [Audit Trigger 91 plus](http://wiki.postgresql.org/wiki/Audit_trigger_91plus) is a generic trigger function used for recording changes to tables into an audit log table. It records quite a bit more detail than the [older](http://wiki.postgresql.org/wiki/Audit_trigger) Audit trigger and does so in a more structured manner.\r\n\r\nThe trigger should be up-to-date on Postgres website but the trigger code lives on [github](https://github.com/2ndQuadrant/audit-trigger).\r\n\r\nFollow the setps described on Postgres wiki to install and use the trigger.\r\n\r\n# Rolling-back\r\n\r\nThe plugin allows you to rollback individual features. It is more aimed at correcting editing errors than viewing a whole dataset at a previous state.\r\nYou can restore or recreate a feature from any logged action. The rollback will not erase the logged actions but rather create a new state. In other words, the rollbacks is considered as an update and a new row will therefore be added to the logged actions table.\r\nHence, even a rollback can be rollbacked.\r\n\r\n# Plugin setup\r\n\r\nOnce ou have enabled the trigger, just add the *logged_actions* table as a no geometry layer. Then, _define the logged actions layer_ from the plugin menu.\r\n\r\nThe option **Redefine layer subset to increase performance** is recommended. While looking for actions, instead of looping over all rows it will redefine a SQL layer subset which is drastically faster.\r\n\r\n# Use the plugin\r\n\r\nYou can start looking for any changes by clicking the plugin icon ![icon](https://raw.github.com/3nids/postgres91plusauditor/master/icons/qaudit-20.png). Choose a layer and eventually specify a feature ID.\r\nRestrictions can be set to search insert/update/delete action, only geometry changes or by date.\r\n\r\nYou can also search for a specific feature changes, by right-clicking on the feature edit form and choosing _History audit_.\r\n\r\nOnce logged actions have been found, click on a row to see the differences with current feature if it exists.\r\n\r\nIf the corresponding layer is in editing mode, the feature can be reset.\r\n\r\n# Screenshots\r\n\r\n![screenshot 1](https://raw.github.com/3nids/postgres91plusauditor/master/doc/screenshot-1.png)\r\n![screenshot 2](https://raw.github.com/3nids/postgres91plusauditor/master/doc/screenshot-2.png)\r\n\r\n\r\n\r\n\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file diff --git a/postgres91plusauditor.py b/postgres91plusauditor.py deleted file mode 100644 index 1b109cc..0000000 --- a/postgres91plusauditor.py +++ /dev/null @@ -1,78 +0,0 @@ -from qgis.core import QgsMapLayerRegistry, QgsAction -from PyQt4.QtCore import QUrl -from PyQt4.QtGui import QAction, QIcon, QDesktopServices - -from gui.auditdialog import AuditDialog -from gui.loggedactionstablechooserdialog import LoggedActionsTableChooserDialog - -actionName = "History audit" -pluginName = "postgres91plusauditor" - -import resources - -# run manually qgis.utils.plugins["postgres91plusauditor"].audit("district20130425093453834",1) - - -class Postgres91plusAuditor(): - def __init__(self, iface): - self.iface = iface - QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayersActions) - self.addLayersActions() - - def initGui(self): - # log layer chooser - self.connectLayerAction = QAction(QIcon(":/plugins/postgres91plusauditor/icons/connect.png"), - "Define logged actions table", self.iface.mainWindow()) - self.connectLayerAction.triggered.connect(self.showLogLayerChooser) - self.iface.addPluginToMenu("&Postgres 91 plus Auditor", self.connectLayerAction) - # show history action - self.auditAction = QAction(QIcon(":/plugins/postgres91plusauditor/icons/qaudit-64.png"), - "Audit logged actions", self.iface.mainWindow()) - self.auditAction.triggered.connect(self.audit) - self.iface.addToolBarIcon(self.auditAction) - self.iface.addPluginToMenu("&Postgres 91 plus Auditor", self.auditAction) - # help action - self.helpAction = QAction(QIcon(":/plugins/postgres91plusauditor/icons/help.png"), - "Help", self.iface.mainWindow()) - self.helpAction.triggered.connect(lambda: QDesktopServices.openUrl(QUrl("http://3nids.github.io/postgres91plusauditor/"))) - self.iface.addPluginToMenu("&Postgres 91 plus Auditor", self.helpAction) - - def unload(self): - self.iface.removePluginMenu("&Postgres 91 plus Auditor", self.connectLayerAction) - self.iface.removePluginMenu("&Postgres 91 plus Auditor", self.auditAction) - self.iface.removePluginMenu("&Postgres 91 plus Auditor", self.helpAction) - self.iface.removeToolBarIcon(self.auditAction) - for layer in QgsMapLayerRegistry.instance().mapLayers().values(): - if layer.dataProvider().name() == "postgres": - while True: - actions = layer.actions() - for i in range(actions.size()): - if actions[i].name() == actionName: - actions.removeAction(i) - continue - break - - def showLogLayerChooser(self): - LoggedActionsTableChooserDialog().exec_() - - def audit(self, layerId=None, featureId=None): - if layerId is False: - layerId = None - self.auditDlg = AuditDialog(self.iface, layerId, featureId) - self.auditDlg.show() - - def addLayersActions(self): - for layerid, layer in QgsMapLayerRegistry.instance().mapLayers().iteritems(): - if layer.dataProvider().name() == "postgres": - actionExists = False - actions = layer.actions() - for i in range(actions.size()): - if actions[i].name() == actionName: - actionExists = True - break - if actionExists: - continue - - actionStr = "qgis.utils.plugins['%s'].audit('%s',[%% $id %%])" % (pluginName, layerid) - - actions.addAction(QgsAction.GenericPython, actionName, actionStr) diff --git a/qgiscombomanager b/qgiscombomanager deleted file mode 160000 index 0046c45..0000000 --- a/qgiscombomanager +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0046c4535685a6e5762b0322f495f68a8694f852 diff --git a/qgissettingmanager b/qgissettingmanager deleted file mode 160000 index 44275d3..0000000 --- a/qgissettingmanager +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 44275d301e8407d8ceb8d19c490d10413b7bfe8b diff --git a/resources.qrc b/resources.qrc deleted file mode 100644 index ae959a0..0000000 --- a/resources.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - icons/connect.png - - - icons/qaudit-64.png - - - icons/help.png - - \ No newline at end of file diff --git a/stylesheets/normalize.css b/stylesheets/normalize.css new file mode 100644 index 0000000..bc2ba93 --- /dev/null +++ b/stylesheets/normalize.css @@ -0,0 +1,459 @@ +/* normalize.css 2012-02-07T12:37 UTC - http://github.com/necolas/normalize.css */ +/* ============================================================================= + HTML5 display definitions + ========================================================================== */ +/* + * Corrects block display not defined in IE6/7/8/9 & FF3 + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects inline-block display not defined in IE6/7/8/9 & FF3 + */ +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/* + * Prevents modern browsers from displaying 'audio' without controls + */ +audio:not([controls]) { + display: none; +} + +/* + * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4 + * Known issue: no IE6 support + */ +[hidden] { + display: none; +} + +/* ============================================================================= + Base + ========================================================================== */ +/* + * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units + * http://clagnut.com/blog/348/#c790 + * 2. Prevents iOS text size adjust after orientation change, without disabling user zoom + * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ + */ +html { + font-size: 100%; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -ms-text-size-adjust: 100%; + /* 2 */ +} + +/* + * Addresses font-family inconsistency between 'textarea' and other form elements. + */ +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/* + * Addresses margins handled incorrectly in IE6/7 + */ +body { + margin: 0; +} + +/* ============================================================================= + Links + ========================================================================== */ +/* + * Addresses outline displayed oddly in Chrome + */ +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers + * people.opera.com/patrickl/experiments/keyboard/test + */ +a:hover, +a:active { + outline: 0; +} + +/* ============================================================================= + Typography + ========================================================================== */ +/* + * Addresses font sizes and margins set differently in IE6/7 + * Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5 + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.75em; + margin: 2.33em 0; +} + +/* + * Addresses styling not present in IE7/8/9, S5, Chrome + */ +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to 'bolder' in FF3+, S4/5, Chrome +*/ +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/* + * Addresses styling not present in S5, Chrome + */ +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE6/7/8/9 + */ +mark { + background: #ff0; + color: #000; +} + +/* + * Addresses margins set differently in IE6/7 + */ +p, +pre { + margin: 1em 0; +} + +/* + * Corrects font family set oddly in IE6, S4/5, Chrome + * en.wikipedia.org/wiki/User:Davidgothberg/Test59 + */ +pre, +code, +kbd, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/* + * 1. Addresses CSS quotes not supported in IE6/7 + * 2. Addresses quote property not supported in S4 + */ +/* 1 */ +q { + quotes: none; +} + +/* 2 */ +q:before, +q:after { + content: ''; + content: none; +} + +small { + font-size: 75%; +} + +/* + * Prevents sub and sup affecting line-height in all browsers + * gist.github.com/413930 + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ============================================================================= + Lists + ========================================================================== */ +/* + * Addresses margins set differently in IE6/7 + */ +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/* + * Addresses paddings set differently in IE6/7 + */ +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/* + * Corrects list images handled incorrectly in IE7 + */ +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ============================================================================= + Embedded content + ========================================================================== */ +/* + * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3 + * 2. Improves image quality when scaled in IE7 + * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ + */ +img { + border: 0; + /* 1 */ + -ms-interpolation-mode: bicubic; + /* 2 */ +} + +/* + * Corrects overflow displayed oddly in IE9 + */ +svg:not(:root) { + overflow: hidden; +} + +/* ============================================================================= + Figures + ========================================================================== */ +/* + * Addresses margin not present in IE6/7/8/9, S5, O11 + */ +figure { + margin: 0; +} + +/* ============================================================================= + Forms + ========================================================================== */ +/* + * Corrects margin displayed oddly in IE6/7 + */ +form { + margin: 0; +} + +/* + * Define consistent border, margin, and padding + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE6/7/8/9 + * 2. Corrects text not wrapping in FF3 + * 3. Corrects alignment displayed oddly in IE6/7 + */ +legend { + border: 0; + /* 1 */ + padding: 0; + white-space: normal; + /* 2 */ + *margin-left: -7px; + /* 3 */ +} + +/* + * 1. Corrects font size not being inherited in all browsers + * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome + * 3. Improves appearance and consistency in all browsers + */ +button, +input, +select, +textarea { + font-size: 100%; + /* 1 */ + margin: 0; + /* 2 */ + vertical-align: baseline; + /* 3 */ + *vertical-align: middle; + /* 3 */ +} + +/* + * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet + */ +button, +input { + line-height: normal; + /* 1 */ +} + +/* + * 1. Improves usability and consistency of cursor style between image-type 'input' and others + * 2. Corrects inability to style clickable 'input' types in iOS + * 3. Removes inner spacing in IE7 without affecting normal text inputs + * Known issue: inner spacing remains in IE6 + */ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + /* 1 */ + -webkit-appearance: button; + /* 2 */ + *overflow: visible; + /* 3 */ +} + +/* + * Re-set default cursor for disabled elements + */ +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to content-box in IE8/9 + * 2. Removes excess padding in IE8/9 + * 3. Removes excess padding in IE7 + Known issue: excess padding remains in IE6 + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ + *height: 13px; + /* 3 */ + *width: 13px; + /* 3 */ +} + +/* + * 1. Addresses appearance set to searchfield in S5, Chrome + * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof) + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in S5, Chrome on OS X + */ +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in FF3+ + * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/ + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE6/7/8/9 + * 2. Improves readability and alignment in all browsers + */ +textarea { + overflow: auto; + /* 1 */ + vertical-align: top; + /* 2 */ +} + +/* ============================================================================= + Tables + ========================================================================== */ +/* + * Remove most spacing between table cells + */ +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css new file mode 100644 index 0000000..62fd970 --- /dev/null +++ b/stylesheets/pygment_trac.css @@ -0,0 +1,70 @@ +.highlight .hll { background-color: #404040 } +.highlight { color: #d0d0d0 } +.highlight .c { color: #999999; font-style: italic } /* Comment */ +.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight .g { color: #d0d0d0 } /* Generic */ +.highlight .k { color: #6ab825; font-weight: normal } /* Keyword */ +.highlight .l { color: #d0d0d0 } /* Literal */ +.highlight .n { color: #d0d0d0 } /* Name */ +.highlight .o { color: #d0d0d0 } /* Operator */ +.highlight .x { color: #d0d0d0 } /* Other */ +.highlight .p { color: #d0d0d0 } /* Punctuation */ +.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #cd2828; font-weight: normal } /* Comment.Preproc */ +.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #e50808; font-weight: normal; background-color: #520000 } /* Comment.Special */ +.highlight .gd { color: #d22323 } /* Generic.Deleted */ +.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #d22323 } /* Generic.Error */ +.highlight .gh { color: #ffffff; font-weight: normal } /* Generic.Heading */ +.highlight .gi { color: #589819 } /* Generic.Inserted */ +.highlight .go { color: #cccccc } /* Generic.Output */ +.highlight .gp { color: #aaaaaa } /* Generic.Prompt */ +.highlight .gs { color: #d0d0d0; font-weight: normal } /* Generic.Strong */ +.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ +.highlight .gt { color: #d22323 } /* Generic.Traceback */ +.highlight .kc { color: #6ab825; font-weight: normal } /* Keyword.Constant */ +.highlight .kd { color: #6ab825; font-weight: normal } /* Keyword.Declaration */ +.highlight .kn { color: #6ab825; font-weight: normal } /* Keyword.Namespace */ +.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */ +.highlight .kr { color: #6ab825; font-weight: normal } /* Keyword.Reserved */ +.highlight .kt { color: #6ab825; font-weight: normal } /* Keyword.Type */ +.highlight .ld { color: #d0d0d0 } /* Literal.Date */ +.highlight .m { color: #3677a9 } /* Literal.Number */ +.highlight .s { color: #ff8 } /* Literal.String */ +.highlight .na { color: #bbbbbb } /* Name.Attribute */ +.highlight .nb { color: #24909d } /* Name.Builtin */ +.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */ +.highlight .no { color: #40ffff } /* Name.Constant */ +.highlight .nd { color: #ffa500 } /* Name.Decorator */ +.highlight .ni { color: #d0d0d0 } /* Name.Entity */ +.highlight .ne { color: #bbbbbb } /* Name.Exception */ +.highlight .nf { color: #447fcf } /* Name.Function */ +.highlight .nl { color: #d0d0d0 } /* Name.Label */ +.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */ +.highlight .nx { color: #d0d0d0 } /* Name.Other */ +.highlight .py { color: #d0d0d0 } /* Name.Property */ +.highlight .nt { color: #6ab825;} /* Name.Tag */ +.highlight .nv { color: #40ffff } /* Name.Variable */ +.highlight .ow { color: #6ab825; font-weight: normal } /* Operator.Word */ +.highlight .w { color: #666666 } /* Text.Whitespace */ +.highlight .mf { color: #3677a9 } /* Literal.Number.Float */ +.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */ +.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */ +.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */ +.highlight .sb { color: #ff8 } /* Literal.String.Backtick */ +.highlight .sc { color: #ff8 } /* Literal.String.Char */ +.highlight .sd { color: #ff8 } /* Literal.String.Doc */ +.highlight .s2 { color: #ff8 } /* Literal.String.Double */ +.highlight .se { color: #ff8 } /* Literal.String.Escape */ +.highlight .sh { color: #ff8 } /* Literal.String.Heredoc */ +.highlight .si { color: #ff8 } /* Literal.String.Interpol */ +.highlight .sx { color: #ffa500 } /* Literal.String.Other */ +.highlight .sr { color: #ff8 } /* Literal.String.Regex */ +.highlight .s1 { color: #ff8 } /* Literal.String.Single */ +.highlight .ss { color: #ff8 } /* Literal.String.Symbol */ +.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #40ffff } /* Name.Variable.Class */ +.highlight .vg { color: #40ffff } /* Name.Variable.Global */ +.highlight .vi { color: #40ffff } /* Name.Variable.Instance */ +.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/stylesheets/styles.css b/stylesheets/styles.css new file mode 100644 index 0000000..980ee2b --- /dev/null +++ b/stylesheets/styles.css @@ -0,0 +1,1010 @@ +/* +Leap Day for GitHub Pages +by Matt Graham +*/ +@font-face { + font-family: 'Quattrocento Sans'; + src: url("../fonts/quattrocentosans-bold-webfont.eot"); + src: url("../fonts/quattrocentosans-bold-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/quattrocentosans-bold-webfont.woff") format("woff"), url("../fonts/quattrocentosans-bold-webfont.ttf") format("truetype"), url("../fonts/quattrocentosans-bold-webfont.svg#QuattrocentoSansBold") format("svg"); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Quattrocento Sans'; + src: url("../fonts/quattrocentosans-bolditalic-webfont.eot"); + src: url("../fonts/quattrocentosans-bolditalic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/quattrocentosans-bolditalic-webfont.woff") format("woff"), url("../fonts/quattrocentosans-bolditalic-webfont.ttf") format("truetype"), url("../fonts/quattrocentosans-bolditalic-webfont.svg#QuattrocentoSansBoldItalic") format("svg"); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'Quattrocento Sans'; + src: url("../fonts/quattrocentosans-italic-webfont.eot"); + src: url("../fonts/quattrocentosans-italic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/quattrocentosans-italic-webfont.woff") format("woff"), url("../fonts/quattrocentosans-italic-webfont.ttf") format("truetype"), url("../fonts/quattrocentosans-italic-webfont.svg#QuattrocentoSansItalic") format("svg"); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'Quattrocento Sans'; + src: url("../fonts/quattrocentosans-regular-webfont.eot"); + src: url("../fonts/quattrocentosans-regular-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/quattrocentosans-regular-webfont.woff") format("woff"), url("../fonts/quattrocentosans-regular-webfont.ttf") format("truetype"), url("../fonts/quattrocentosans-regular-webfont.svg#QuattrocentoSansRegular") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Copse'; + src: url("../fonts/copse-regular-webfont.eot"); + src: url("../fonts/copse-regular-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/copse-regular-webfont.woff") format("woff"), url("../fonts/copse-regular-webfont.ttf") format("truetype"), url("../fonts/copse-regular-webfont.svg#CopseRegular") format("svg"); + font-weight: normal; + font-style: normal; +} + +/* normalize.css 2012-02-07T12:37 UTC - http://github.com/necolas/normalize.css */ +/* ============================================================================= + HTML5 display definitions + ========================================================================== */ +/* + * Corrects block display not defined in IE6/7/8/9 & FF3 + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects inline-block display not defined in IE6/7/8/9 & FF3 + */ +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/* + * Prevents modern browsers from displaying 'audio' without controls + */ +audio:not([controls]) { + display: none; +} + +/* + * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4 + * Known issue: no IE6 support + */ +[hidden] { + display: none; +} + +/* ============================================================================= + Base + ========================================================================== */ +/* + * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units + * http://clagnut.com/blog/348/#c790 + * 2. Prevents iOS text size adjust after orientation change, without disabling user zoom + * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ + */ +html { + font-size: 100%; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -ms-text-size-adjust: 100%; + /* 2 */ +} + +/* + * Addresses font-family inconsistency between 'textarea' and other form elements. + */ +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/* + * Addresses margins handled incorrectly in IE6/7 + */ +body { + margin: 0; +} + +/* ============================================================================= + Links + ========================================================================== */ +/* + * Addresses outline displayed oddly in Chrome + */ +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers + * people.opera.com/patrickl/experiments/keyboard/test + */ +a:hover, +a:active { + outline: 0; +} + +/* ============================================================================= + Typography + ========================================================================== */ +/* + * Addresses font sizes and margins set differently in IE6/7 + * Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5 + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.75em; + margin: 2.33em 0; +} + +/* + * Addresses styling not present in IE7/8/9, S5, Chrome + */ +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to 'bolder' in FF3+, S4/5, Chrome +*/ +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/* + * Addresses styling not present in S5, Chrome + */ +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE6/7/8/9 + */ +mark { + background: #ff0; + color: #000; +} + +/* + * Addresses margins set differently in IE6/7 + */ +p, +pre { + margin: 1em 0; +} + +/* + * Corrects font family set oddly in IE6, S4/5, Chrome + * en.wikipedia.org/wiki/User:Davidgothberg/Test59 + */ +pre, +code, +kbd, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/* + * 1. Addresses CSS quotes not supported in IE6/7 + * 2. Addresses quote property not supported in S4 + */ +/* 1 */ +q { + quotes: none; +} + +/* 2 */ +q:before, +q:after { + content: ''; + content: none; +} + +small { + font-size: 75%; +} + +/* + * Prevents sub and sup affecting line-height in all browsers + * gist.github.com/413930 + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ============================================================================= + Lists + ========================================================================== */ +/* + * Addresses margins set differently in IE6/7 + */ +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/* + * Addresses paddings set differently in IE6/7 + */ +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/* + * Corrects list images handled incorrectly in IE7 + */ +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ============================================================================= + Embedded content + ========================================================================== */ +/* + * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3 + * 2. Improves image quality when scaled in IE7 + * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ + */ +img { + border: 0; + /* 1 */ + -ms-interpolation-mode: bicubic; + /* 2 */ +} + +/* + * Corrects overflow displayed oddly in IE9 + */ +svg:not(:root) { + overflow: hidden; +} + +/* ============================================================================= + Figures + ========================================================================== */ +/* + * Addresses margin not present in IE6/7/8/9, S5, O11 + */ +figure { + margin: 0; +} + +/* ============================================================================= + Forms + ========================================================================== */ +/* + * Corrects margin displayed oddly in IE6/7 + */ +form { + margin: 0; +} + +/* + * Define consistent border, margin, and padding + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE6/7/8/9 + * 2. Corrects text not wrapping in FF3 + * 3. Corrects alignment displayed oddly in IE6/7 + */ +legend { + border: 0; + /* 1 */ + padding: 0; + white-space: normal; + /* 2 */ + *margin-left: -7px; + /* 3 */ +} + +/* + * 1. Corrects font size not being inherited in all browsers + * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome + * 3. Improves appearance and consistency in all browsers + */ +button, +input, +select, +textarea { + font-size: 100%; + /* 1 */ + margin: 0; + /* 2 */ + vertical-align: baseline; + /* 3 */ + *vertical-align: middle; + /* 3 */ +} + +/* + * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet + */ +button, +input { + line-height: normal; + /* 1 */ +} + +/* + * 1. Improves usability and consistency of cursor style between image-type 'input' and others + * 2. Corrects inability to style clickable 'input' types in iOS + * 3. Removes inner spacing in IE7 without affecting normal text inputs + * Known issue: inner spacing remains in IE6 + */ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + /* 1 */ + -webkit-appearance: button; + /* 2 */ + *overflow: visible; + /* 3 */ +} + +/* + * Re-set default cursor for disabled elements + */ +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to content-box in IE8/9 + * 2. Removes excess padding in IE8/9 + * 3. Removes excess padding in IE7 + Known issue: excess padding remains in IE6 + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ + *height: 13px; + /* 3 */ + *width: 13px; + /* 3 */ +} + +/* + * 1. Addresses appearance set to searchfield in S5, Chrome + * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof) + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in S5, Chrome on OS X + */ +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in FF3+ + * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/ + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE6/7/8/9 + * 2. Improves readability and alignment in all browsers + */ +textarea { + overflow: auto; + /* 1 */ + vertical-align: top; + /* 2 */ +} + +/* ============================================================================= + Tables + ========================================================================== */ +/* + * Remove most spacing between table cells + */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +body { + font: 14px/22px "Quattrocento Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #666; + font-weight: 300; + margin: 0px; + padding: 0px 0 20px 0px; + background: url(../images/body-background.png) #eae6d1; +} + +h1, h2, h3, h4, h5, h6 { + color: #333; + margin: 0 0 10px; +} + +p, ul, ol, table, pre, dl { + margin: 0 0 20px; +} + +h1, h2, h3 { + line-height: 1.1; +} + +h1 { + font-size: 28px; +} + +h2 { + font-size: 24px; + color: #393939; +} + +h3, h4, h5, h6 { + color: #666666; +} + +h3 { + font-size: 18px; + line-height: 24px; +} + +a { + color: #3399cc; + font-weight: 400; + text-decoration: none; +} + +a small { + font-size: 11px; + color: #666; + margin-top: -0.6em; + display: block; +} + +ul { + list-style-image: url("../images/bullet.png"); +} + +strong { + font-weight: bold; + color: #333; +} + +.wrapper { + width: 650px; + margin: 0 auto; + position: relative; +} + +section img { + max-width: 100%; +} + +blockquote { + border-left: 1px solid #ffcc00; + margin: 0; + padding: 0 0 0 20px; + font-style: italic; +} + +code { + font-family: "Lucida Sans", Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal; + font-size: 13px; + color: #efefef; + text-shadow: 0px 1px 0px #000; + margin: 0 4px; + padding: 2px 6px; + background: #333; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} + +pre { + padding: 8px 15px; + background: #333333; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; + -khtml-border-radius: 3px; + border-radius: 3px; + border: 1px solid #c7c7c7; + overflow: auto; + overflow-y: hidden; +} +pre code { + margin: 0px; + padding: 0px; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th { + text-align: left; + padding: 5px 10px; + border-bottom: 1px solid #e5e5e5; + color: #444; +} + +td { + text-align: left; + padding: 5px 10px; + border-bottom: 1px solid #e5e5e5; + border-right: 1px solid #ffcc00; +} +td:first-child { + border-left: 1px solid #ffcc00; +} + +hr { + border: 0; + outline: none; + height: 11px; + background: transparent url("../images/hr.gif") center center repeat-x; + margin: 0 0 20px; +} + +dt { + color: #444; + font-weight: 700; +} + +header { + padding: 25px 20px 40px 20px; + margin: 0; + position: fixed; + top: 0; + left: 0; + right: 0; + width: 100%; + text-align: center; + background: url(../images/background.png) #4276b6; + -moz-box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.75); + -webkit-box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.75); + -o-box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.75); + box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.75); + z-index: 99; + -webkit-font-smoothing: antialiased; + min-height: 76px; +} +header h1 { + font: 40px/48px "Copse", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #f3f3f3; + text-shadow: 0px 2px 0px #235796; + margin: 0px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; +} +header p { + color: #d8d8d8; + text-shadow: rgba(0, 0, 0, 0.2) 0 1px 0; + font-size: 18px; + margin: 0px; +} + +#banner { + z-index: 100; + left: 0; + right: 50%; + height: 50px; + margin-right: -382px; + position: fixed; + top: 115px; + background: #ffcc00; + border: 1px solid #f0b500; + -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -o-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -moz-border-radius: 0px 2px 2px 0px; + -webkit-border-radius: 0px 2px 2px 0px; + -o-border-radius: 0px 2px 2px 0px; + -ms-border-radius: 0px 2px 2px 0px; + -khtml-border-radius: 0px 2px 2px 0px; + border-radius: 0px 2px 2px 0px; + padding-right: 10px; +} +#banner .button { + border: 1px solid #dba500; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffe788), color-stop(100%, #ffce38)); + background: -webkit-linear-gradient(#ffe788, #ffce38); + background: -moz-linear-gradient(#ffe788, #ffce38); + background: -o-linear-gradient(#ffe788, #ffce38); + background: -ms-linear-gradient(#ffe788, #ffce38); + background: linear-gradient(#ffe788, #ffce38); + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; + -moz-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.4), 0px 1px 1px rgba(0, 0, 0, 0.1); + -webkit-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.4), 0px 1px 1px rgba(0, 0, 0, 0.1); + -o-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.4), 0px 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.4), 0px 1px 1px rgba(0, 0, 0, 0.1); + background-color: #FFE788; + margin-left: 5px; + padding: 10px 12px; + margin-top: 6px; + line-height: 14px; + font-size: 14px; + color: #333; + font-weight: bold; + display: inline-block; + text-align: center; +} +#banner .button:hover { + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffe788), color-stop(100%, #ffe788)); + background: -webkit-linear-gradient(#ffe788, #ffe788); + background: -moz-linear-gradient(#ffe788, #ffe788); + background: -o-linear-gradient(#ffe788, #ffe788); + background: -ms-linear-gradient(#ffe788, #ffe788); + background: linear-gradient(#ffe788, #ffe788); + background-color: #ffeca0; +} +#banner .fork { + position: fixed; + left: 50%; + margin-left: -325px; + padding: 10px 12px; + margin-top: 6px; + line-height: 14px; + font-size: 14px; + background-color: #FFE788; +} +#banner .downloads { + float: right; + margin: 0 45px 0 0; +} +#banner .downloads span { + float: left; + line-height: 52px; + font-size: 90%; + color: #9d7f0d; + text-transform: uppercase; + text-shadow: rgba(255, 255, 255, 0.2) 0 1px 0; +} +#banner ul { + list-style: none; + height: 40px; + padding: 0; + float: left; + margin-left: 10px; +} +#banner ul li { + display: inline; +} +#banner ul li a.button { + background-color: #FFE788; +} +#banner #logo { + position: absolute; + height: 36px; + width: 36px; + right: 7px; + top: 7px; + display: block; + background: url(../images/octocat-logo.png); +} + +section { + width: 590px; + padding: 30px 30px 50px 30px; + margin: 20px 0; + margin-top: 190px; + position: relative; + background: #fbfbfb; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; + -khtml-border-radius: 3px; + border-radius: 3px; + border: 1px solid #cbcbcb; + -moz-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.09), inset 0px 0px 2px 2px rgba(255, 255, 255, 0.5), inset 0 0 5px 5px rgba(255, 255, 255, 0.4); + -webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.09), inset 0px 0px 2px 2px rgba(255, 255, 255, 0.5), inset 0 0 5px 5px rgba(255, 255, 255, 0.4); + -o-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.09), inset 0px 0px 2px 2px rgba(255, 255, 255, 0.5), inset 0 0 5px 5px rgba(255, 255, 255, 0.4); + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.09), inset 0px 0px 2px 2px rgba(255, 255, 255, 0.5), inset 0 0 5px 5px rgba(255, 255, 255, 0.4); +} + +small { + font-size: 12px; +} + +nav { + width: 230px; + position: fixed; + top: 220px; + left: 50%; + margin-left: -580px; + text-align: right; +} +nav ul { + list-style: none; + list-style-image: none; + font-size: 14px; + line-height: 24px; +} +nav ul li { + padding: 5px 0px; + line-height: 16px; +} +nav ul li.tag-h1 { + font-size: 1.2em; +} +nav ul li.tag-h1 a { + font-weight: bold; + color: #333; +} +nav ul li.tag-h2 + .tag-h1 { + margin-top: 10px; +} +nav ul a { + color: #666; +} +nav ul a:hover { + color: #999; +} + +footer { + width: 180px; + position: fixed; + left: 50%; + margin-left: -530px; + bottom: 20px; + text-align: right; + line-height: 16px; +} + +@media print, screen and (max-width: 1060px) { + div.wrapper { + width: auto; + margin: 0; + } + + nav { + display: none; + } + + header, section, footer { + float: none; + } + header h1, section h1, footer h1 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + } + + #banner { + width: 100%; + } + #banner .downloads { + margin-right: 60px; + } + #banner #logo { + margin-right: 15px; + } + + section { + border: 1px solid #e5e5e5; + border-width: 1px 0; + padding: 20px auto; + margin: 190px auto 20px; + max-width: 600px; + } + + footer { + text-align: center; + margin: 20px auto; + position: relative; + left: auto; + bottom: auto; + width: auto; + } +} +@media print, screen and (max-width: 720px) { + body { + word-wrap: break-word; + } + + header { + padding: 20px 20px; + margin: 0; + } + header h1 { + font-size: 32px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + } + header p { + display: none; + } + + #banner { + top: 80px; + } + #banner .fork { + float: left; + display: inline-block; + margin-left: 0px; + position: fixed; + left: 20px; + } + + section { + margin-top: 130px; + margin-bottom: 0px; + width: auto; + } + + header ul, header p.view { + position: static; + } +} +@media print, screen and (max-width: 480px) { + header { + position: relative; + padding: 5px 0px; + min-height: 0px; + } + header h1 { + font-size: 24px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + } + + section { + margin-top: 5px; + } + + #banner { + display: none; + } + + header ul { + display: none; + } +} +@media print { + body { + padding: 0.4in; + font-size: 12pt; + color: #444; + } +} +@media print, screen and (max-height: 680px) { + footer { + text-align: center; + margin: 20px auto; + position: relative; + left: auto; + bottom: auto; + width: auto; + } +} +@media print, screen and (max-height: 480px) { + nav { + display: none; + } + + footer { + text-align: center; + margin: 20px auto; + position: relative; + left: auto; + bottom: auto; + width: auto; + } +} diff --git a/ui/__init__.py b/ui/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ui/ui_audit.ui b/ui/ui_audit.ui deleted file mode 100644 index 28508c3..0000000 --- a/ui/ui_audit.ui +++ /dev/null @@ -1,303 +0,0 @@ - - - Denis Rouzaud - audit - - - - 0 - 0 - 810 - 568 - - - - Postgres 91 plus Auditor :: search history - - - - - - - 0 - 0 - - - - - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Feature - - - - - - - Qt::LeftToRight - - - search - - - - - - - stop - - - - - - - - - - Layer - - - - - - - 24 - - - - - - - - - - - 0 - 0 - - - - Advanced search - - - true - - - - 6 - - - - - - 0 - 0 - - - - Search only for geometry changes - - - - - - - Delete - - - true - - - - - - - before - - - - - - - true - - - - - - - Updates - - - true - - - - - - - after - - - - - - - Insert - - - true - - - - - - - QAbstractSpinBox::UpDownArrows - - - - 1970 - 1 - 1 - - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Maximum - - - - 30 - 20 - - - - - - - - - - - Qt::Horizontal - - - - - 6 - - - 3 - - - - - ... - - - - - - - Pan and show geometry - - - true - - - - - - - - - - - - 0 - - - - - Restore feature - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 30 - 20 - - - - - - - - - QgsCollapsibleGroupBoxBasic - QGroupBox -
    qgis.gui.h
    - 1 -
    -
    - - -
    diff --git a/ui/ui_columnchooser.ui b/ui/ui_columnchooser.ui deleted file mode 100644 index b615a26..0000000 --- a/ui/ui_columnchooser.ui +++ /dev/null @@ -1,132 +0,0 @@ - - - columnChooser - - - - 0 - 0 - 304 - 268 - - - - Logged actions table :: column chooser - - - - - - - Date - - - Checked - - - - - User - - - Checked - - - - - Action - - - Checked - - - - - Changed geometry - - - Checked - - - - - Changed fields - - - Checked - - - - - Application - - - Unchecked - - - - - Client IP - - - Unchecked - - - - - Client port - - - Unchecked - - - - - - - - Qt::Vertical - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - columnChooser - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - columnChooser - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/ui/ui_loggedactionstablechooser.ui b/ui/ui_loggedactionstablechooser.ui deleted file mode 100644 index 9902555..0000000 --- a/ui/ui_loggedactionstablechooser.ui +++ /dev/null @@ -1,84 +0,0 @@ - - - LoggedActionsTableChooser - - - - 0 - 0 - 359 - 106 - - - - false - - - Postgres 91 plus Auditor :: logged action table chooser - - - - - - Logged action table - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - Redefine layer subset to increase performance - - - - - - - - - buttonBox - accepted() - LoggedActionsTableChooser - accept() - - - 313 - 107 - - - 157 - 83 - - - - - buttonBox - rejected() - LoggedActionsTableChooser - reject() - - - 313 - 107 - - - 286 - 83 - - - - -