def reloadPlugins(self):
        self.modules = []
        self.plugins = []

        if self.allPlugins:
            plugin_dir = QDir(
                os.path.join(os.path.dirname(QFile.decodeName(__file__)),
                             "plugins"))
            plugins = plugin_dir.entryList(QDir.Dirs | QDir.NoSymLinks
                                           | QDir.NoDotAndDotDot)
        else:
            p = QSettings().value("/PhyloGeoRec/plugins", "", type=unicode)
            plugins = p.split(",") if p else []

        import importlib
        for name in plugins:
            try:
                modname = "PhyloGeoRec.plugins." + str(name)
                module = reload(
                    sys.modules[modname]
                ) if modname in sys.modules else importlib.import_module(
                    modname)
                self.modules.append(module)
                self.plugins.append(getattr(module, "plugin_class"))
            except ImportError:
                logMessage("Failed to load plugin: " + str(name))
示例#2
0
    def properties(self):
        p = {}
        for w in self.propertyWidgets:
            v = None
            if isinstance(w, QComboBox):
                index = w.currentIndex()
                if index == -1:
                    v = None
                else:
                    v = w.itemData(index)
            elif isinstance(w, QRadioButton):
                if not w.isChecked():
                    continue
                v = w.isChecked()
            elif isinstance(w, QCheckBox):
                v = w.isChecked()
            elif isinstance(w, (QSlider, QSpinBox)):
                v = w.value()
            elif isinstance(w, QLineEdit):
                v = w.text()
            elif isinstance(w, StyleWidget):
                v = w.values()
            else:
                logMessage("[propertypages.py] Not recognized widget type: " +
                           unicode(type(w)))

            p[w.objectName()] = v
        return p
    def _readTransparency(self, widgetValues, f=None):
        vals = widgetValues

        if vals["comboData"] == TransparencyWidgetFunc.VALUE:
            try:
                return int(vals["editText"])
            except ValueError:
                return 0

        alpha = None
        symbol = self.layer.rendererV2().symbolForFeature(f)
        if symbol is None:
            logMessage(u'Symbol for feature cannot be found: {0}'.format(self.layer.name()))
            symbol = self.layer.rendererV2().symbols()[0]
        else:
            sl = symbol.symbolLayer(0)
            if sl:    # and sl.hasDataDefinedProperties():
                expr = sl.dataDefinedProperty("color")
                if expr:
                    # data defined transparency
                    cs_rgba = expr.evaluate(f, f.fields())
                    rgba = cs_rgba.split(",")
                    if len(rgba) == 4:
                        alpha = float(rgba[3]) / 255

        if alpha is None:
            alpha = symbol.alpha()

        opacity = float(100 - self.layer.layerTransparency()) / 100
        opacity *= alpha      # opacity = layer_opacity * feature_opacity
        return int((1.0 - opacity) * 100)
    def values(self, f=None):
        vals = []
        for i in range(32):   # big number for style count
            p = "styleWidget" + str(i)
            if p not in self.properties:
                break

            widgetValues = self.properties[p]
            if len(widgetValues) == 0:
                break

            widgetType = widgetValues["type"]
            comboData = widgetValues.get("comboData")
            if widgetType in [StyleWidget.COLOR, StyleWidget.OPTIONAL_COLOR]:
                vals.append(self._readColor(widgetValues, f, widgetType == StyleWidget.OPTIONAL_COLOR))

            elif widgetType == StyleWidget.COLOR_TEXTURE:
                if comboData == ColorTextureWidgetFunc.MAP_CANVAS:
                    vals.append(comboData)
                elif comboData == ColorTextureWidgetFunc.LAYER:
                    vals.append(widgetValues.get("layerIds", []))
                else:
                    vals.append(self._readColor(widgetValues, f))

            elif widgetType == StyleWidget.TRANSPARENCY:
                vals.append(self._readTransparency(widgetValues, f))

            elif widgetType == StyleWidget.FILEPATH:
                if comboData == FilePathWidgetFunc.FILEPATH or f is None:
                    vals.append(widgetValues["editText"])
                else:
                    # prefix + attribute
                    fieldName = widgetValues["comboText"].strip('"')
                    value = f.attribute(fieldName)
                    if value == NULL:
                        value = ""
                        logMessage(u"Empty attribute value in the field '{0}'".format(fieldName))
                    vals.append(os.path.join(widgetValues["editText"], value.strip('"')))

            elif widgetType == StyleWidget.CHECKBOX:
                vals.append(widgetValues["checkBox"])

            elif widgetType == StyleWidget.HEIGHT:
                if widgetValues["comboData"] in [HeightWidgetFunc.RELATIVE, HeightWidgetFunc.ABSOLUTE, HeightWidgetFunc.Z_VALUE] or f is None:
                    vals.append(self.toFloat(widgetValues["editText"]))
                else:
                    # attribute value + addend
                    fieldName = widgetValues["comboText"].lstrip("+").strip(' "')
                    vals.append(self.toFloat(f.attribute(fieldName)) + self.toFloat(widgetValues["editText"]))

            else:
                if comboData == FieldValueWidgetFunc.ABSOLUTE or f is None:
                    vals.append(widgetValues["editText"])
                else:
                    # attribute value * multiplier
                    fieldName = widgetValues["comboText"].strip('"')
                    val = self.toFloat(f.attribute(fieldName)) * self.toFloat(widgetValues["editText"])
                    vals.append(str(val))
        return vals
 def saveExportSettings(self, filename):
     import codecs
     import json
     try:
         with codecs.open(filename, "w", "UTF-8") as f:
             json.dump(self.exportSettings,
                       f,
                       ensure_ascii=False,
                       indent=2,
                       sort_keys=True)
         return True
     except Exception as e:
         logMessage("Failed to save export settings: " + str(e))
         return False
示例#6
0
    def demProviderByLayerId(self, id):
        if not id:
            return FlatDEMProvider()

        if id.startswith("plugin:"):
            provider = self.pluginManager.findDEMProvider(id[7:])
            if provider:
                return provider(str(self.crs.toWkt()))

            logMessage('Plugin "{0}" not found'.format(id))
            return FlatDEMProvider()

        else:
            layer = QgsMapLayerRegistry.instance().mapLayer(id)
            return GDALDEMProvider(layer.source(), str(self.crs.toWkt()), source_wkt=str(layer.crs().toWkt()))    # use CRS set to the layer in QGIS
    def write(self,
              f):  #TODO: separated image files (not in localBrowsingMode)
        if len(self._list) == 0:
            return

        f.write(u'\n// Base64 encoded images\n')
        for index, image in enumerate(self._list):
            imageType = image[0]
            if imageType == self.IMAGE_FILE:
                image_path = image[1]

                exists = os.path.exists(image_path)
                if exists and os.path.isfile(image_path):
                    size = QImageReader(image_path).size()
                    args = (index, size.width(), size.height(),
                            gdal2threejs.base64image(image_path))
                else:
                    f.write(u"project.images[%d] = {data:null};\n" % index)

                    if exists:
                        err_msg = u"Not image file path"
                    else:
                        err_msg = u"Image file not found"
                    logMessage(u"{0}: {1}".format(err_msg, image_path))
                    continue

            elif imageType == self.MAP_IMAGE:
                width, height, extent, transp_background = image[1]
                args = (index, width, height,
                        self.renderedImage(width, height, extent,
                                           transp_background))

            elif imageType == self.LAYER_IMAGE:
                layerids, width, height, extent, transp_background = image[1]
                args = (index, width, height,
                        self.renderedImage(width, height, extent,
                                           transp_background, layerids))

            else:  #imageType == self.CANVAS_IMAGE:
                transp_background = image[1]
                size = self.exportSettings.mapSettings.outputSize()
                args = (index, size.width(), size.height(),
                        self.mapCanvasImage(transp_background))

            f.write(u'project.images[%d] = {width:%d,height:%d,data:"%s"};\n' %
                    args)
    def _renderedImage2(self,
                        width,
                        height,
                        extent,
                        transp_background=False,
                        layerids=None):
        """rendering function for GIS < 2.7"""
        antialias = True

        if self._renderer is None:
            self._initRenderer()

        canvas = self.exportSettings.canvas
        if canvas is None:
            logMessage(
                "With this QGIS version (<= 2.6), map canvas needs to be set to the export settings"
            )
            return

        if layerids is None:
            layerids = [mapLayer.id() for mapLayer in canvas.layers()]

        renderer = self._renderer  # QgsMapRenderer
        renderer.setLayerSet(layerids)

        image = QImage(width, height, QImage.Format_ARGB32_Premultiplied)
        if transp_background:
            image.fill(QColor(Qt.transparent).rgba())  #
        else:
            image.fill(canvas.canvasColor().rgba())  #

        renderer.setOutputSize(image.size(), image.logicalDpiX())
        renderer.setExtent(extent.unrotatedRect())

        painter = QPainter()
        painter.begin(image)
        if antialias:
            painter.setRenderHint(QPainter.Antialiasing)
        renderer.render(painter)
        painter.end()

        return tools.base64image(image)
    def run(self):
        from vectorobject import ObjectTypeManager
        from pluginmanager import PluginManager
        from phylogeorecdialog import PhyloGeoRecDialog

        if self.objectTypeManager is None:
            self.objectTypeManager = ObjectTypeManager()

        if self.pluginManager is None:
            self.pluginManager = PluginManager()

        # restore export settings
        proj_path = QgsProject.instance().fileName()
        settingsFilePath = proj_path + ".qto3settings" if proj_path else None

        if not self.exportSettings or settingsFilePath != self.settingsFilePath:
            if settingsFilePath and os.path.exists(settingsFilePath):
                self.loadExportSettings(settingsFilePath)
                logMessage(
                    u"Restored export settings of this project: {0}".format(
                        os.path.basename(
                            proj_path)))  #QgsProject.instance().title()

        dialog = PhyloGeoRecDialog(self.iface, self.objectTypeManager,
                                   self.pluginManager, self.exportSettings,
                                   self.lastTreeItemData)

        # show dialog
        dialog.show()
        ret = dialog.exec_()

        self.exportSettings = dialog.settings(True)

        item = dialog.ui.treeWidget.currentItem()
        self.lastTreeItemData = item.data(0, Qt.UserRole) if item else None

        # if export succeeded, save export settings in the directory that project file exists
        if ret and settingsFilePath:
            self.saveExportSettings(settingsFilePath)

        self.settingsFilePath = settingsFilePath
    def _readColor(self, widgetValues, f=None, isBorder=False):
        global colorNames

        mode = widgetValues["comboData"]
        if mode == OptionalColorWidgetFunc.NONE:
            return None

        if mode == ColorWidgetFunc.RGB:
            return widgetValues["editText"]

        if mode == ColorWidgetFunc.RANDOM or f is None:
            if len(colorNames) == 0:
                colorNames = QColor.colorNames()
            colorName = random.choice(colorNames)
            colorNames.remove(colorName)
            return QColor(colorName).name().replace("#", "0x")

        # feature color
        symbol = self.layer.rendererV2().symbolForFeature(f)
        if symbol is None:
            logMessage(u'Symbol for feature cannot be found: {0}'.format(self.layer.name()))
            symbol = self.layer.rendererV2().symbols()[0]
        else:
            sl = symbol.symbolLayer(0)
            if sl and isBorder:
                return sl.outlineColor().name().replace("#", "0x")

            if sl:    # and sl.hasDataDefinedProperties():  # needs >= 2.2
                expr = sl.dataDefinedProperty("color")
                if expr:
                    # data defined color
                    cs_rgb = expr.evaluate(f, f.fields())

                    # "rrr,ggg,bbb" (dec) to "0xRRGGBB" (hex)
                    rgb = map(int, cs_rgb.split(",")[0:3])
                    return "0x" + "".join(map(chr, rgb)).encode("hex")

        return symbol.color().name().replace("#", "0x")
示例#11
0
 def setProperties(self, properties):
     for n, v in properties.items():
         w = getattr(self, n, None)
         if w is None:
             continue
         if isinstance(w, QComboBox):
             if v is not None:
                 index = w.findData(v)
                 if index != -1:
                     w.setCurrentIndex(index)
         elif isinstance(
                 w,
             (QRadioButton, QCheckBox)):  # subclass of QAbstractButton
             w.setChecked(v)
         elif isinstance(w, (QSlider, QSpinBox)):
             w.setValue(v)
         elif isinstance(w, QLineEdit):
             w.setText(v)
         elif isinstance(w, StyleWidget):
             if len(v):
                 w.setValues(v)
         else:
             logMessage("[propertypages.py] Cannot restore %s property" % n)
    def write(self, f):
        if len(self._list) == 0:
            return

        f.write(u'\n// 3D model data\n')
        for index, model in enumerate(self._list):
            model_type, path = model
            exists = os.path.exists(path)
            if exists and os.path.isfile(path):
                with open(path) as model_file:
                    data = model_file.read().replace("\\", "\\\\").replace(
                        "'", "\\'").replace("\t", "\\t").replace(
                            "\r", "\\r").replace("\n", "\\n")
                f.write(u"project.models[%d] = {type:'%s',data:'%s'};\n" %
                        (index, model_type, data))
            else:
                f.write(u"project.models[%d] = {type:'%s',data:null};\n" %
                        (index, model_type))

                if exists:
                    err_msg = u"Not 3D model file path"
                else:
                    err_msg = u"3D model file not found"
                logMessage(u"{0}: {1} ({2})".format(err_msg, path, model_type))
示例#13
0
def writeVectors(writer, legendInterface=None, progress=None):
    settings = writer.settings
    baseExtent = settings.baseExtent
    progress = progress or dummyProgress
    renderer = QgsMapRenderer()

    layers = []
    if legendInterface is None:
        for parentId in [
                ObjectTreeItem.ITEM_POINT, ObjectTreeItem.ITEM_LINE,
                ObjectTreeItem.ITEM_POLYGON
        ]:
            for layerId, properties in settings.get(parentId, {}).iteritems():
                if properties.get("visible", False):
                    layers.append([layerId, properties])
    else:
        # use vector layer order in legendInterface
        for layer in legendInterface.layers():
            if layer.type() != QgsMapLayer.VectorLayer:
                continue

            parentId = ObjectTreeItem.parentIdByLayer(layer)
            properties = settings.get(parentId, {}).get(layer.id(), {})
            if properties.get("visible", False):
                layers.append([layer.id(), properties])

    finishedLayers = 0
    for layerId, properties in layers:
        mapLayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        if mapLayer is None:
            continue

        prop = VectorPropertyReader(writer.objectTypeManager, mapLayer,
                                    properties)
        obj_mod = writer.objectTypeManager.module(prop.mod_index)
        if obj_mod is None:
            logMessage("Module not found")
            continue

        # prepare triangle mesh
        geom_type = mapLayer.geometryType()
        if geom_type == QGis.Polygon and prop.type_index == 1 and prop.isHeightRelativeToDEM(
        ):  # Overlay
            progress(None, "Initializing triangle mesh for overlay polygons")
            writer.triangleMesh()

        progress(
            30 + 30 * finishedLayers / len(layers),
            u"Writing vector layer ({0} of {1}): {2}".format(
                finishedLayers + 1, len(layers), mapLayer.name()))

        # write layer object
        layer = VectorLayer(writer, mapLayer, prop, obj_mod)
        writer.writeLayer(layer.layerObject(), layer.fieldNames)

        # initialize symbol rendering
        mapLayer.rendererV2().startRender(
            renderer.rendererContext(),
            mapLayer.pendingFields()
            if QGis.QGIS_VERSION_INT >= 20300 else mapLayer)

        # features to export
        request = QgsFeatureRequest()
        clipGeom = None
        if properties.get("radioButton_IntersectingFeatures", False):
            request.setFilterRect(
                layer.transform.transformBoundingBox(
                    baseExtent.boundingBox(),
                    QgsCoordinateTransform.ReverseTransform))
            if properties.get("checkBox_Clip"):
                extent = baseExtent.clone().scale(
                    0.999999
                )  # clip with slightly smaller extent than map canvas extent
                clipGeom = extent.geometry()

        for feat in layer.features(request, clipGeom):
            # write geometry
            obj_mod.write(writer, layer,
                          feat)  # writer.writeFeature(layer, feat, obj_mod)

            # stack attributes in writer
            if layer.writeAttrs:
                writer.addAttributes(feat.attributes())

        # write attributes
        if layer.writeAttrs:
            writer.writeAttributes()

        # write materials
        writer.writeMaterials(layer.materialManager)

        mapLayer.rendererV2().stopRender(renderer.rendererContext())
        finishedLayers += 1
示例#14
0
    def features(self, request=None, clipGeom=None):
        settings = self.writer.settings
        mapTo3d = settings.mapTo3d()
        baseExtent = settings.baseExtent
        baseExtentGeom = baseExtent.geometry()
        rotation = baseExtent.rotation()
        prop = self.prop

        useZ = prop.useZ()
        if useZ:
            srs_from = osr.SpatialReference()
            srs_from.ImportFromProj4(str(self.layer.crs().toProj4()))
            srs_to = osr.SpatialReference()
            srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4()))

            ogr_transform = osr.CreateCoordinateTransformation(
                srs_from, srs_to)
            clipGeomWkb = clipGeom.asWkb() if clipGeom else None
            ogr_clipGeom = ogr.CreateGeometryFromWkb(
                clipGeomWkb) if clipGeomWkb else None

        else:
            # z_func: function to get elevation at given point (x, y) on surface
            if prop.isHeightRelativeToDEM():
                if self.geomType == QGis.Polygon and prop.type_index == 1:  # Overlay
                    z_func = lambda x, y: 0
                else:
                    # get elevation from DEM
                    z_func = lambda x, y: self.writer.demProvider.readValue(
                        x, y)
            else:
                z_func = lambda x, y: 0

        request = request or QgsFeatureRequest()
        for f in self.layer.getFeatures(request):
            geometry = f.geometry()
            if geometry is None:
                logMessage("null geometry skipped")
                continue

            # coordinate transformation - layer crs to project crs
            geom = QgsGeometry(geometry)
            if geom.transform(self.transform) != 0:
                logMessage("Failed to transform geometry")
                continue

            # check if geometry intersects with the base extent (rotated rect)
            if rotation and not baseExtentGeom.intersects(geom):
                continue

            # create feature
            feat = Feature(self.writer, self, f)

            # transform_func: function to transform the map coordinates to 3d coordinates
            relativeHeight = prop.relativeHeight(f)

            def transform_func(x, y, z):
                return mapTo3d.transform(x, y, z + relativeHeight)

            if useZ:
                ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb())

                # transform geometry from layer CRS to project CRS
                if ogr_geom.Transform(ogr_transform) != 0:
                    logMessage("Failed to transform geometry")
                    continue

                # clip geometry
                if ogr_clipGeom and self.geomType == QGis.Line:
                    ogr_geom = ogr_geom.Intersection(ogr_clipGeom)
                    if ogr_geom is None:
                        continue

                # check if geometry is empty
                if ogr_geom.IsEmpty():
                    logMessage("empty geometry skipped")
                    continue

                feat.geom = self.geomClass.fromOgrGeometry25D(
                    ogr_geom, transform_func)

            else:
                # clip geometry
                if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]:
                    geom = geom.intersection(clipGeom)
                    if geom is None:
                        continue

                # check if geometry is empty
                if geom.isGeosEmpty():
                    logMessage("empty geometry skipped")
                    continue

                if self.geomType == QGis.Polygon:
                    feat.geom = self.geomClass.fromQgsGeometry(
                        geom, z_func, transform_func, self.hasLabel())
                    if prop.type_index == 1 and prop.isHeightRelativeToDEM(
                    ):  # Overlay and relative to DEM
                        feat.geom.splitPolygon(self.writer.triangleMesh())

                else:
                    feat.geom = self.geomClass.fromQgsGeometry(
                        geom, z_func, transform_func)

            if feat.geom is None:
                continue

            yield feat
示例#15
0
 def log(self, message):
     logMessage(message)
 def toFloat(cls, val):
     try:
         return float(val)
     except Exception as e:
         logMessage(u'{0} (value: {1})'.format(e.message, unicode(val)))
         return 0