class GtoWidgetProjectionSelection(QWidget):
    def __init__(self, gtomain, parent=None):
        super(GtoWidgetProjectionSelection, self).__init__(parent)
        # QWidgetAction.__init__(self,parent)
        self.iface = gtomain.iface
        self.info = gtomain.info
        try:
            self.prj = QgsProject.instance()
            # ui
            lay = QHBoxLayout(self)
            # -----
            self.lblLayer = QLabel("Projektion:")
            lay.addWidget(self.lblLayer)
            self.wid = QgsProjectionSelectionWidget(self)
            # help the QGIS widget:/
            self.wid.setMinimumWidth(350)
            self.wid.setSizePolicy(self.lblLayer.sizePolicy())
            lay.addWidget(self.wid)
            for tb in self.wid.findChildren(QToolButton):
                tb.setIconSize(self.iface.iconSize())
            # -----
            self.setLayout(lay)
            # signals
            self.prj.crsChanged.connect(self.prj_crs_changed)
            self.wid.crsChanged.connect(self.set_prj_crs)
            # start
            self.wid.setCrs(self.prj.crs())
        except Exception as e:
            self.info.err(e)

    def prj_crs_changed(self):
        try:
            self.wid.setCrs(self.prj.crs())
        except Exception as e:
            self.info.err(e)

    def set_prj_crs(self, crs):
        try:
            self.prj.setCrs(self.wid.crs())
        except Exception as e:
            self.info.err(e)
class CalculateGeometryDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        scale_factor = QApplication.instance().primaryScreen() \
                            .logicalDotsPerInch() / 96

        def create_editable_combobox(text):
            combo = QComboBox()
            combo.setEditable(True)
            combo.setEditText(text)
            return combo

        cols = lambda cx, lx: \
                (QCheckBox(cx), create_editable_combobox(lx),
                 FramedLabel(), PrecisionEdit())

        self.rowXcoord = cols(self.tr('X Coordinate'), 'xcoord')
        self.rowYcoord = cols(self.tr('Y Coordinate'), 'ycoord')
        self.rowZcoord = cols(self.tr('Z Coordinate'), 'zcoord')
        self.rowMvalue = cols(self.tr('M Value'), 'mvalue')
        unit = QgsUnitTypes.DistanceDegrees
        self.rowXcoord[2].setText(QgsUnitTypes.toString(unit).title())
        self.rowYcoord[2].setText(QgsUnitTypes.toString(unit).title())
        unit = QgsUnitTypes.DistanceMeters
        self.rowZcoord[2].setText(QgsUnitTypes.toString(unit).title())
        self.rowMvalue[2].setText(QgsUnitTypes.toString(unit).title())

        cols = lambda cx, lx: \
                (QCheckBox(cx), create_editable_combobox(lx),
                 QComboBox(), PrecisionEdit())

        self.rowLength = cols(self.tr('Length'), 'length')
        for unit in distance_units:
            self.rowLength[2].addItem(QgsUnitTypes.toString(unit).title(), unit)
        self.rowLength[2].setItemText(self.rowLength[2].count() - 1,
                                      self.tr('Map Units'))
        self.rowArea = cols(self.tr('Area'), 'area')
        for unit in area_units:
            self.rowArea[2].addItem(QgsUnitTypes.toString(unit).title(), unit)
        self.rowArea[2].setItemText(self.rowArea[2].count() - 1,
                                    self.tr('Map Units'))
        self.rowPerimeter = cols(self.tr('Perimeter'), 'perimeter')
        for i in range(self.rowLength[2].count()):
            self.rowPerimeter[2].addItem(self.rowLength[2].itemText(i),
                                         self.rowLength[2].itemData(i))

        grid = QGridLayout()
        grid.addWidget(QLabel(self.tr('Field')), 0, 1)
        grid.addWidget(QLabel(self.tr('Units')), 0, 2)
        label_prec = QLabel(self.tr('Precision'))
        grid.addWidget(label_prec, 0, 3)
        grid.itemAtPosition(0, 3).widget().show()
        width = int(QFontMetrics(QFont()).height() * scale_factor * 3)
        self.rows = (self.rowXcoord,
                     self.rowYcoord,
                     self.rowZcoord,
                     self.rowMvalue,
                     self.rowLength,
                     self.rowArea,
                     self.rowPerimeter,)
        for row, w in enumerate(self.rows):
            w[0].setChecked(True)
            w[1].setMinimumWidth(width * 2)
            w[3].setMaximumWidth(max(width, label_prec.width()))
            for col in range(len(w)):
                grid.addWidget(w[col], row + 1, col)
        for col in (1, 2):
            grid.setColumnStretch(col, 1)

        groupProp = QGroupBox(self.tr('Properties'))
        groupProp.setLayout(grid)

        self.radio1 = QRadioButton(
                self.tr('Cartesian calculation with following CRS'))
        self.radio1.setChecked(True)
        self.radio2 = QRadioButton(
                self.tr('Ellipsoidal calculation with following ellipsoid'))
        self.radios = QButtonGroup()
        self.radios.addButton(self.radio1)
        self.radios.addButton(self.radio2)

        self.selectorCrs = QgsProjectionSelectionWidget()
        self.selectorCrs.setMinimumWidth(width * 8)
        self.selectorCrs.setOptionVisible(
                QgsProjectionSelectionWidget.CurrentCrs, False)
        self.selectorCrs.setLayerCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        self.comboCrs = self.selectorCrs.layout().itemAt(0).widget()
        self.comboCrs.setCurrentIndex(
                self.comboCrs.findData(QgsProjectionSelectionWidget.LayerCrs))
        self.labelEllips = FramedLabel()

        grid = QGridLayout()
        grid.addWidget(self.radio1, 0, 0, 1, 0)
        grid.addWidget(self.selectorCrs, 1, 1)
        grid.addWidget(self.radio2, 2, 0, 1, 0)
        grid.addWidget(self.labelEllips, 3, 1)
        grid.setColumnMinimumWidth(0, QRadioButton().sizeHint().width())
        grid.setRowMinimumHeight(3, QLineEdit().sizeHint().height())

        groupSystem = QGroupBox(self.tr('Calculation System'))
        groupSystem.setLayout(grid)

        self.checkSelected = QCheckBox(self.tr('Selected features only'))
        self.checkDefault = QCheckBox(self.tr('Set expression to default value'))
        self.checkVirtual = QCheckBox(self.tr('Use virtual field for new field'))
        self.checks = QButtonGroup()
        self.checks.setExclusive(False)
        self.checks.addButton(self.checkSelected)
        self.checks.addButton(self.checkDefault)
        self.checks.addButton(self.checkVirtual)

        form = QFormLayout()
        form.addRow(groupProp)
        form.addRow(groupSystem)
        form.addRow(self.checkSelected)
        form.addRow(self.checkDefault)
        form.addRow(self.checkVirtual)

        self.buttonBox = QDialogButtonBox(
                QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
                accepted=self.accept, rejected=self.reject)

        vbox = QVBoxLayout()
        vbox.addLayout(form)
        vbox.addWidget(self.buttonBox)

        self.setLayout(vbox)
        self.setMaximumSize(QWIDGETSIZE_MAX, 0)

    def prepare_rows(self, rows):
        for row in self.rows:
            for col in range(len(row)):
                row[col].hide()
        for row in rows:
            for col in range(len(row)):
                row[col].show()

    def prepare_for_point(self, hasZ=True, hasM=True):
        rows = [self.rowXcoord, self.rowYcoord]
        if hasZ:
            rows += [self.rowZcoord]
        if hasM:
            rows += [self.rowMvalue]
        self.prepare_rows(rows)

    def prepare_for_line(self):
        self.prepare_rows([self.rowLength])

    def prepare_for_polygon(self):
        self.prepare_rows([self.rowArea, self.rowPerimeter])