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 . 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
-
-
-
-
-
-
-
-
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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 . 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
+
+
+
+
+
+
+
+
+
\ 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 . 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\r\n\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
-
- 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
-
-
-
-
-