Skip to content
Snippets Groups Projects
utils.py 37.9 KiB
Newer Older
    if pathUi not in FORM_CLASSES.keys():
        #parse *.ui xml and replace *.h by qgis.gui
        doc = QDomDocument()

        #remove new-lines. this prevents uic.loadUiType(buffer, resource_suffix=RC_SUFFIX)
        #to mess up the *.ui xml
        f = open(pathUi, 'r')
        txt = ''.join(f.readlines())
        f.close()
        doc.setContent(txt)

        # Replace *.h file references in <customwidget> with <class>Qgs...</class>, e.g.
        #       <header>qgscolorbutton.h</header>
        # by    <header>qgis.gui</header>
        # this is require to compile QgsWidgets on-the-fly
        elem = doc.elementsByTagName('customwidget')
        for child in [elem.item(i) for i in range(elem.count())]:
            child = child.toElement()
            className = str(child.firstChildElement('class').firstChild().nodeValue())
            if className.startswith('Qgs'):
                cHeader = child.firstChildElement('header').firstChild()
                cHeader.setNodeValue('qgis.gui')

        #collect resource file locations
        elem = doc.elementsByTagName('include')
        qrcPathes = []
        for child in [elem.item(i) for i in range(elem.count())]:
            path = child.attributes().item(0).nodeValue()
            if path.endswith('.qrc'):
                qrcPathes.append(path)



        buffer = io.StringIO()  # buffer to store modified XML
        buffer.write(doc.toString())
        buffer.flush()
        buffer.seek(0)


        #make resource file directories available to the python path (sys.path)
        baseDir = os.path.dirname(pathUi)
        tmpDirs = []
        for qrcPath in qrcPathes:
            d = os.path.dirname(os.path.join(baseDir, os.path.dirname(qrcPath)))
            if d not in sys.path:
                tmpDirs.append(d)
        sys.path.extend(tmpDirs)

        #load form class
        try:
            FORM_CLASS, _ = uic.loadUiType(buffer, resource_suffix=RC_SUFFIX)
        except SyntaxError as ex:
            FORM_CLASS, _ = uic.loadUiType(pathUi, resource_suffix=RC_SUFFIX)
        buffer.close()
        FORM_CLASSES[pathUi] = FORM_CLASS

        #remove temporary added directories from python path
        for d in tmpDirs:
            sys.path.remove(d)

    return FORM_CLASSES[pathUi]

def zipdir(pathDir, pathZip):
    """
    :param pathDir: directory to compress
    :param pathZip: path to new zipfile
    """
    #thx to https://stackoverflow.com/questions/1855095/how-to-create-a-zip-archive-of-a-directory
    """
    import zipfile
    assert os.path.isdir(pathDir)
    zipf = zipfile.ZipFile(pathZip, 'w', zipfile.ZIP_DEFLATED)
    for root, dirs, files in os.walk(pathDir):
        for file in files:
            zipf.write(os.path.join(root, file))
    zipf.close()
    """
    import zipfile
    relroot = os.path.abspath(os.path.join(pathDir, os.pardir))
    with zipfile.ZipFile(pathZip, "w", zipfile.ZIP_DEFLATED) as zip:
        for root, dirs, files in os.walk(pathDir):
            # add directory (needed for empty dirs)
            zip.write(root, os.path.relpath(root, relroot))
            for file in files:
                filename = os.path.join(root, file)
                if os.path.isfile(filename):  # regular files only
                    arcname = os.path.join(os.path.relpath(root, relroot), file)
                    zip.write(filename, arcname)

def initQgisApplication(pythonPlugins=None, PATH_QGIS=None, qgisDebug=False, qgisResourceDir=None):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    """
    Initializes the QGIS Environment
    :return: QgsApplication instance of local QGIS installation
    """
    import site
    if pythonPlugins is None:
        pythonPlugins = []
    assert isinstance(pythonPlugins, list)

    if isinstance(qgisResourceDir, str) and os.path.isdir(qgisResourceDir):
        import importlib, re
        modules = [m for m in os.listdir(qgisResourceDir) if re.search(r'[^_].*\.py', m)]
        modules = [m[0:-3] for m in modules]
        for m in modules:
            mod = importlib.import_module('qgisresources.{}'.format(m))
            if "qInitResources" in dir(mod):
                mod.qInitResources()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    envVar = os.environ.get('QGIS_PLUGINPATH', None)
    if isinstance(envVar, list):
        pythonPlugins.extend(re.split('[;:]', envVar))
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    # make plugin paths available to QGIS and Python
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    os.environ['QGIS_PLUGINPATH'] = ';'.join(pythonPlugins)
    os.environ['QGIS_DEBUG'] = '1' if qgisDebug else '0'
    for p in pythonPlugins:
        sys.path.append(p)

    if isinstance(QgsApplication.instance(), QgsApplication):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        return QgsApplication.instance()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    else:

        if PATH_QGIS is None:
            # find QGIS Path
            if sys.platform == 'darwin':
                # search for the QGIS.app
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                import qgis, re
                assert '.app' in qgis.__file__, 'Can not locate path of QGIS.app'
                PATH_QGIS_APP = re.split(r'\.app[\/]', qgis.__file__)[0] + '.app'
                PATH_QGIS = os.path.join(PATH_QGIS_APP, *['Contents', 'MacOS'])
Benjamin Jakimow's avatar
Benjamin Jakimow committed

                if not 'GDAL_DATA' in os.environ.keys():
                    os.environ['GDAL_DATA'] = r'/Library/Frameworks/GDAL.framework/Versions/Current/Resources/gdal'
Benjamin Jakimow's avatar
Benjamin Jakimow committed

                QApplication.addLibraryPath(os.path.join(PATH_QGIS_APP, *['Contents', 'PlugIns']))
                QApplication.addLibraryPath(os.path.join(PATH_QGIS_APP, *['Contents', 'PlugIns', 'qgis']))
Benjamin Jakimow's avatar
Benjamin Jakimow committed


            else:
                # assume OSGeo4W startup
                PATH_QGIS = os.environ['QGIS_PREFIX_PATH']

        assert os.path.exists(PATH_QGIS)

        qgsApp = QgsApplication([], True)
        qgsApp.setPrefixPath(PATH_QGIS, True)
        qgsApp.initQgis()
        qgsApp.registerOgrDrivers()

        from qgis.gui import QgsGui
        QgsGui.editorWidgetRegistry().initEditors()

        def printQgisLog(tb, error, level):
            if error not in ['Python warning']:
                print(tb)

        QgsApplication.instance().messageLog().messageReceived.connect(printQgisLog)

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        return qgsApp

def createCRSTransform(src, dst):
    assert isinstance(src, QgsCoordinateReferenceSystem)
    assert isinstance(dst, QgsCoordinateReferenceSystem)
    t = QgsCoordinateTransform()
    t.setSourceCrs(src)
    t.setDestinationCrs(dst)
    return t

if __name__ == '__main__':
    #nice predecessors
    qgsApp = initQgisApplication()
    assert nicePredecessor(26) == 25
    assert nicePredecessor(25) == 25
    assert nicePredecessor(23) == 20
    assert nicePredecessor(999) == 950
    assert nicePredecessor(1001) == 1000
    assert nicePredecessor(1.2) == 1.0      #
    assert nicePredecessor(0.8) == 0.5
    assert nicePredecessor(0.2) == 0.1
    assert nicePredecessor(0.021) == 0.01
    assert nicePredecessor(0.0009991) == 0.0005