示例#1
0
    def _add_results(self, preselect: int = -1, row_number: int = 0):
        '''
        adds results to the map canvas and to the result list of the dialog
        '''
        provider = self.preview_layer.layer.dataProvider()

        for i, result in enumerate(self.results):
            feature = QgsFeature()
            coords = result['geometry']['coordinates']
            geom = QgsGeometry.fromPointXY(QgsPointXY(coords[0], coords[1]))
            feature.setGeometry(geom)
            feature.setAttributes([
                i + 1,
                result['properties']['text'],
            ])
            provider.addFeature(feature)

            properties = result['properties']
            radio = QRadioButton(properties['text'])

            preview = QLabel()
            preview.setMaximumWidth(20)
            preview.setMinimumWidth(20)
            self.results_contents.addWidget(preview, i + row_number, 0)
            self.results_contents.addWidget(radio, i + row_number, 1)
            if self.show_score:
                score = QLabel(f'Score {properties["score"]}')
                self.results_contents.addWidget(score, i + row_number, 2)
            img_path = os.path.join(ICON_PATH, f'marker_{i+1}.png')
            if os.path.exists(img_path):
                pixmap = QPixmap(img_path)
                preview.setPixmap(
                    pixmap.scaled(preview.size(), Qt.KeepAspectRatio,
                                  Qt.SmoothTransformation))

            #  results clicked in the dialog are highlighted on the map
            radio.toggled.connect(
                lambda c, i=i, f=feature: self._toggle_result(i, f))
            if i == preselect:
                radio.setChecked(True)

        self.preview_layer.layer.commitChanges()
        extent = self.preview_layer.layer.extent()
        if not extent.isEmpty():
            transform = QgsCoordinateTransform(
                self.preview_layer.layer.crs(),
                self.canvas.mapSettings().destinationCrs(),
                QgsProject.instance())
            self.canvas.setExtent(transform.transform(extent))
            self.canvas.zoomByFactor(1.5)
        self.canvas.refresh()
    def initGui(self):
        self.setWindowTitle('New remote')
        layout = QVBoxLayout()
        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Close)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(30)
        horizontalLayout.setMargin(0)
        nameLabel = QLabel('Name')
        nameLabel.setMinimumWidth(120)
        nameLabel.setMaximumWidth(120)
        self.nameBox = QLineEdit()
        if self.name is not None:
            self.nameBox.setText(self.name)
        horizontalLayout.addWidget(nameLabel)
        horizontalLayout.addWidget(self.nameBox)
        layout.addLayout(horizontalLayout)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(30)
        horizontalLayout.setMargin(0)
        urlLabel = QLabel('URL')
        urlLabel.setMinimumWidth(120)
        urlLabel.setMaximumWidth(120)
        self.urlBox = QLineEdit()
        if self.url is not None:
            self.urlBox.setText(self.url)
        horizontalLayout.addWidget(urlLabel)
        horizontalLayout.addWidget(self.urlBox)
        layout.addLayout(horizontalLayout)

        layout.addWidget(buttonBox)
        self.setLayout(layout)

        buttonBox.accepted.connect(self.okPressed)
        buttonBox.rejected.connect(self.cancelPressed)

        self.resize(400, 200)
    def initGui(self):
        self.setWindowTitle('New connection')
        layout = QVBoxLayout()
        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Close)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(30)
        horizontalLayout.setMargin(0)
        nameLabel = QLabel('Name')
        nameLabel.setMinimumWidth(120)
        nameLabel.setMaximumWidth(120)
        self.nameBox = QLineEdit()
        if self.name is not None:
            self.nameBox.setText(self.name)
        horizontalLayout.addWidget(nameLabel)
        horizontalLayout.addWidget(self.nameBox)
        layout.addLayout(horizontalLayout)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(30)
        horizontalLayout.setMargin(0)
        urlLabel = QLabel('URL')
        urlLabel.setMinimumWidth(120)
        urlLabel.setMaximumWidth(120)
        self.urlBox = QLineEdit()
        if self.url is not None:
            self.urlBox.setText(self.url)
        horizontalLayout.addWidget(urlLabel)
        horizontalLayout.addWidget(self.urlBox)
        layout.addLayout(horizontalLayout)


        layout.addWidget(buttonBox)
        self.setLayout(layout)

        buttonBox.accepted.connect(self.okPressed)
        buttonBox.rejected.connect(self.cancelPressed)

        self.resize(400, 200)
class DockWidgetGimpSelectionFeature(QDockWidget):
    def __init__(self, iface):
        def setupUi():
            def getLayout(parent, widgets):
                lyt = QGridLayout(parent)
                for item in widgets:
                    if 'spam' in item:
                        sRow, sCol = item['spam']['row'], item['spam']['col']
                        lyt.addWidget(item['widget'], item['row'], item['col'],
                                      sRow, sCol, Qt.AlignLeft)
                    else:
                        lyt.addWidget(item['widget'], item['row'], item['col'],
                                      Qt.AlignLeft)
                return lyt

            def getGroupBox(name, parent, widgets):
                lyt = getLayout(parent, widgets)
                gbx = QGroupBox(name, parent)
                gbx.setLayout(lyt)
                return gbx

            def getSpinBoxOffset(wgt, value):
                sp = QDoubleSpinBox(wgt)
                sp.setRange(0.0, 50.0)
                sp.setSingleStep(12.5)
                sp.setDecimals(2)
                sp.setSuffix(' %')
                sp.setValue(value)
                return sp

            def getSpinRemoveAreaPixels(wgt, value):
                sp = QSpinBox(wgt)
                sp.setRange(0, 1000)
                sp.setSingleStep(1)
                sp.setSuffix(' pixels')
                sp.setValue(value)
                return sp

            def getSpinBoxAzimuth(wgt, value):
                sp = QSpinBox(wgt)
                sp.setRange(0, 45)
                sp.setSingleStep(1)
                sp.setSuffix(' degrees')
                sp.setValue(value)
                msg = QCoreApplication.translate(
                    'GimpSelectionFeature',
                    'Degrees of azimuth between vertexs')
                sp.setToolTip(msg)
                return sp

            def getSpinBoxIteration(wgt, value):
                sp = QSpinBox(wgt)
                sp.setRange(0, 3)
                sp.setSingleStep(1)
                sp.setValue(value)
                return sp

            self.setObjectName('gimpselectionfeature_dockwidget')
            wgt = QWidget(self)
            wgt.setAttribute(Qt.WA_DeleteOnClose)
            # Image
            width = 180
            self.lblLegendImages = QLabel('', wgt)
            self.lblLegendImages.setWordWrap(True)
            self.lblLegendImages.setMaximumWidth(width)
            l_wts = [{'widget': self.lblLegendImages, 'row': 0, 'col': 0}]
            name = self.formatTitleImages.format(0)
            self.gbxImage = getGroupBox(name, wgt, l_wts)
            # Transfer
            msg = QCoreApplication.translate('GimpSelectionFeature',
                                             'Send image')
            self.btnSendImage = QPushButton(msg, wgt)
            #
            msg = QCoreApplication.translate('GimpSelectionFeature',
                                             'Get features')
            self.btnGetFeatures = QPushButton(msg, wgt)
            msg = QCoreApplication.translate('GimpSelectionFeature',
                                             'Remove last features')
            self.btnRemoveLastFeatures = QPushButton(msg, wgt)
            #
            msg = QCoreApplication.translate('GimpSelectionFeature',
                                             'Adjust the borders')
            self.chkAdjustBorder = QCheckBox(msg, wgt)
            self.leditAnnotation = QLineEdit(wgt)
            self.sbRemoveAreaPixels = getSpinRemoveAreaPixels(wgt, 10)
            self.sbAzimuthThreshold = getSpinBoxAzimuth(wgt, 0)
            self.spSmoothOffset = getSpinBoxOffset(wgt, 25)
            self.sbSmoothIteration = getSpinBoxIteration(wgt, 1)
            msgLevel = QCoreApplication.translate('GimpSelectionFeature',
                                                  'Level(0-3):')
            msgFraction = QCoreApplication.translate(
                'GimpSelectionFeature', 'Fraction of line(0-50):')
            l_wts = [{
                'widget': QLabel(msgLevel, wgt),
                'row': 0,
                'col': 0
            }, {
                'widget': self.sbSmoothIteration,
                'row': 0,
                'col': 1
            }, {
                'widget': QLabel(msgFraction, wgt),
                'row': 1,
                'col': 0
            }, {
                'widget': self.spSmoothOffset,
                'row': 1,
                'col': 1
            }]
            msg = QCoreApplication.translate('GimpSelectionFeature', 'Smooth')
            gbxSmooth = getGroupBox(msg, wgt, l_wts)
            spamSmooth = {'row': 1, 'col': 2}
            msgAnnotation = QCoreApplication.translate('GimpSelectionFeature',
                                                       'Annotation:')
            msgRemoveArea = QCoreApplication.translate('GimpSelectionFeature',
                                                       'Remove Area:')
            msgRemoveVertex = QCoreApplication.translate(
                'GimpSelectionFeature', 'Remove Vertex:')
            l_wts = [{
                'widget': QLabel(msgAnnotation, wgt),
                'row': 0,
                'col': 0
            }, {
                'widget': self.leditAnnotation,
                'row': 0,
                'col': 1
            }, {
                'widget': QLabel(msgRemoveArea, wgt),
                'row': 1,
                'col': 0
            }, {
                'widget': self.sbRemoveAreaPixels,
                'row': 1,
                'col': 1
            }, {
                'widget': QLabel(msgRemoveVertex, wgt),
                'row': 2,
                'col': 0
            }, {
                'widget': self.sbAzimuthThreshold,
                'row': 2,
                'col': 1
            }, {
                'widget': gbxSmooth,
                'row': 3,
                'col': 0,
                'spam': spamSmooth
            }, {
                'widget': self.chkAdjustBorder,
                'row': 4,
                'col': 0,
            }]
            msg = QCoreApplication.translate('GimpSelectionFeature', 'Setting')
            self.gbxSettingFeatures = getGroupBox(msg, wgt, l_wts)
            spamSetting = {'row': 1, 'col': 2}
            l_wts = [{
                'widget': self.btnGetFeatures,
                'row': 0,
                'col': 0
            }, {
                'widget': self.btnRemoveLastFeatures,
                'row': 0,
                'col': 1
            }, {
                'widget': self.gbxSettingFeatures,
                'row': 1,
                'col': 0,
                'spam': spamSetting
            }]
            gbxGQ = getGroupBox("GIMP->QGIS", wgt, l_wts)
            l_wts = [{'widget': self.btnSendImage, 'row': 0, 'col': 0}]
            gbxQG = getGroupBox("QGIS->GIMP", wgt, l_wts)
            spamGroup = {'row': 1, 'col': 2}
            l_wts = [{
                'widget': gbxQG,
                'row': 0,
                'col': 0,
                'spam': spamGroup
            }, {
                'widget': gbxGQ,
                'row': 1,
                'col': 0,
                'spam': spamGroup
            }]
            msg = QCoreApplication.translate('GimpSelectionFeature',
                                             'Transfer')
            gbxTransfer = getGroupBox(msg, wgt, l_wts)
            #
            l_wts = [{
                'widget': self.gbxImage,
                'row': 0,
                'col': 0
            }, {
                'widget': gbxTransfer,
                'row': 1,
                'col': 0
            }]
            lyt = getLayout(wgt, l_wts)
            lyt.setSizeConstraint(QLayout.SetMaximumSize)
            wgt.setLayout(lyt)
            self.setWidget(wgt)

        super().__init__("Gimp Selection Feature", iface.mainWindow())
        #
        msg = QCoreApplication.translate('GimpSelectionFeature',
                                         'Visibles Images(total {})')
        self.formatTitleImages = msg
        setupUi()
        self.gsf = GimpSelectionFeature(iface, self)

    # def __del__(self):
    #     del self.gsf

    def clean(self):
        del self.gsf
示例#5
0
class ProgressDialog(QDialog):
    """ Progress dialog shows progress bar for algorithm.
    """

    def __init__(self, iface):
        QDialog.__init__(self, iface.mainWindow())
        self.workerThread = None
        self.state = False
        self.resultStatus = None
        self.doReRun = False
        self.wasCanceled = False
        self.wasSuccessful = False
        self.savedProj = None
        self.result = None
        self.messageTxt = {
            'msg_optimierung': self.tr('Berechnung der optimalen Stuetzenpositionen...'),
            'msg_seillinie': self.tr('Berechnung der optimale Seillinie...')
        }
        
        # Build GUI Elements
        self.setWindowTitle(self.tr("SEILAPLAN wird ausgefuehrt"))
        self.resize(500, 100)
        self.container = QVBoxLayout()
        self.progressBar = QProgressBar(self)
        self.progressBar.setMinimumWidth(500)
        self.statusLabel = QLabel(self)
        self.hbox = QHBoxLayout()
        self.cancelButton = QDialogButtonBox()
        self.closeButton = QDialogButtonBox()
        self.resultLabel = QLabel(self)
        self.resultLabel.setMaximumWidth(500)
        self.resultLabel.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding))
        self.resultLabel.setWordWrap(True)
        spacer1 = QSpacerItem(20, 20, QSizePolicy.Fixed,
                              QSizePolicy.Fixed)
        self.rerunButton = QPushButton(self.tr("zurueck zum Startfenster"))
        self.rerunButton.setVisible(False)
        spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel)
        self.cancelButton.button(QDialogButtonBox.Cancel).setText(self.tr("Abbrechen"))
        self.cancelButton.clicked.connect(self.onAbort)
        self.closeButton.setStandardButtons(QDialogButtonBox.Close)
        self.closeButton.button(QDialogButtonBox.Close).setText(self.tr("Schliessen"))
        self.closeButton.clicked.connect(self.onClose)
        self.hbox.addWidget(self.rerunButton)
        self.hbox.addItem(spacer2)
        self.hbox.addWidget(self.cancelButton)
        self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter)
        self.hbox.addWidget(self.closeButton)
        self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter)
        self.closeButton.hide()
        
        self.container.addWidget(self.progressBar)
        self.container.addWidget(self.statusLabel)
        self.container.addWidget(self.resultLabel)
        self.container.addItem(spacer1)
        self.container.addLayout(self.hbox)
        self.container.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(self.container)

    # noinspection PyMethodMayBeStatic
    def tr(self, message, **kwargs):
        """Get the translation for a string using Qt translation API.
        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString

        Parameters
        ----------
        **kwargs
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate(type(self).__name__, message)
        
    def setThread(self, workerThread):
        self.workerThread = workerThread
        self.connectThreadSignals()
    
    def connectThreadSignals(self):
        # Connect signals of thread
        self.workerThread.sig_jobEnded.connect(self.jobEnded)
        self.workerThread.sig_jobError.connect(self.onError)
        self.workerThread.sig_value.connect(self.valueFromThread)
        self.workerThread.sig_range.connect(self.rangeFromThread)
        self.workerThread.sig_text.connect(self.textFromThread)
        self.workerThread.sig_result.connect(self.resultFromThread)
        self.rerunButton.clicked.connect(self.onRerun)
        
    def run(self):
        # Show modal dialog window (QGIS is still responsive)
        self.show()
        # start event loop
        self.exec()
    
    def jobEnded(self, success):
        self.setWindowTitle("SEILAPLAN")
        if success:
            self.progressBar.setValue(self.progressBar.maximum())
            self.wasSuccessful = True
            # Close progress dialog so that adjustment window can be opened
            self.close()
        else:  # If there was an abort by the user
            self.statusLabel.setText(self.tr("Berechnungen abgebrochen."))
            self.progressBar.setValue(self.progressBar.minimum())
            self.finallyDo()
    
    def valueFromThread(self, value):
        self.progressBar.setValue(int(value))
    
    def rangeFromThread(self, range_vals):
        self.progressBar.setRange(int(round(range_vals[0])), int(round(range_vals[1])))
    
    def maxFromThread(self, max):
        self.progressBar.setValue(self.progressBar.maximum())
    
    def textFromThread(self, message):
        self.statusLabel.setText(self.messageTxt[message])
    
    def resultFromThread(self, resultStatus):
        self.resultStatus = resultStatus
        # resultStatus:
        #   1 = Optimization successful
        #   2 = Cable takes off from support
        #   3 = Optimization partially successful
    
    def onAbort(self):
        self.setWindowTitle('SEILAPLAN')
        self.statusLabel.setText(self.tr(
            'Laufender Prozess wird abgebrochen...'))
        self.workerThread.cancel()  # Terminates process cleanly
        self.wasCanceled = True
    
    def onError(self, exception_string):
        self.setWindowTitle(self.tr('SEILAPLAN: Berechnung fehlgeschlagen'))
        self.statusLabel.setText(self.tr('Ein Fehler ist aufgetreten:'))
        self.resultLabel.setText(self.tr(exception_string))
        self.resultLabel.setHidden(False)
        self.progressBar.setValue(self.progressBar.minimum())
        self.setLayout(self.container)
        self.finallyDo()
    
    def onRerun(self):
        self.doReRun = True
        self.onClose()
    
    def finallyDo(self):
        self.rerunButton.setVisible(True)
        self.cancelButton.hide()
        self.closeButton.show()
    
    def onClose(self):
        self.close()
class DockWidgetGimpSelectionFeature(QDockWidget):
  def __init__(self, iface):
    def setupUi():
      def getLayout(parent, widgets):
        lyt = QGridLayout( parent )
        for item in widgets:
          if 'spam' in item:
            sRow, sCol = item['spam']['row'], item['spam']['col']
            lyt.addWidget( item['widget'], item['row'], item['col'], sRow, sCol, Qt.AlignLeft )
          else:
            lyt.addWidget( item['widget'], item['row'], item['col'], Qt.AlignLeft )
        return lyt

      def getGroupBox(name, parent, widgets):
        lyt = getLayout( parent, widgets )
        gbx = QGroupBox(name, parent )
        gbx.setLayout( lyt )
        return gbx

      def getSpinBoxOffset(wgt, value):
        sp = QDoubleSpinBox( wgt)
        sp.setRange(0.0, 50.0)
        sp.setSingleStep(12.5)
        sp.setDecimals(2)
        sp.setSuffix(' %')
        sp.setValue(value)
        return sp

      def getSpinRemoveAreaPixels(wgt, value):
        sp = QSpinBox( wgt)
        sp.setRange(0, 1000)
        sp.setSingleStep(1)
        sp.setSuffix(' pixels')
        sp.setValue(value)
        return sp

      def getSpinBoxAzimuth(wgt, value):
        sp = QSpinBox( wgt)
        sp.setRange(0, 45)
        sp.setSingleStep(1)
        sp.setSuffix(' degrees')
        sp.setValue(value)
        msg = QCoreApplication.translate('GimpSelectionFeature', 'Degrees of azimuth between vertexs')
        sp.setToolTip( msg )
        return sp

      def getSpinBoxIteration(wgt, value):
        sp = QSpinBox( wgt)
        sp.setRange(0, 3)
        sp.setSingleStep(1)
        sp.setValue(value)
        return sp

      self.setObjectName('gimpselectionfeature_dockwidget')
      wgt = QWidget( self )
      wgt.setAttribute(Qt.WA_DeleteOnClose)
      # Image
      width = 180
      self.lblLegendImages = QLabel('', wgt )
      self.lblLegendImages.setWordWrap( True )
      self.lblLegendImages.setMaximumWidth(width )
      l_wts = [ { 'widget': self.lblLegendImages,     'row': 0, 'col': 0 } ]
      name = self.formatTitleImages.format(0)
      self.gbxImage = getGroupBox(name, wgt, l_wts)
      # Transfer
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Send image')
      self.btnSendImage = QPushButton(msg, wgt )
      #
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Get features')
      self.btnGetFeatures = QPushButton( msg, wgt )
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Remove last features')
      self.btnRemoveLastFeatures = QPushButton( msg, wgt )
      #
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Adjust the borders' )
      self.chkAdjustBorder = QCheckBox( msg, wgt )
      self.leditAnnotation = QLineEdit( wgt )
      self.sbRemoveAreaPixels = getSpinRemoveAreaPixels( wgt, 10 )
      self.sbAzimuthThreshold = getSpinBoxAzimuth( wgt, 0 )
      self.spSmoothOffset = getSpinBoxOffset( wgt, 25 )
      self.sbSmoothIteration  = getSpinBoxIteration( wgt, 1)
      msgLevel = QCoreApplication.translate('GimpSelectionFeature','Level(0-3):')
      msgFraction = QCoreApplication.translate('GimpSelectionFeature','Fraction of line(0-50):')
      l_wts = [
        { 'widget': QLabel( msgLevel, wgt ),    'row': 0, 'col': 0 },
        { 'widget': self.sbSmoothIteration,     'row': 0, 'col': 1 },
        { 'widget': QLabel( msgFraction, wgt ), 'row': 1, 'col': 0 },
        { 'widget': self.spSmoothOffset,        'row': 1, 'col': 1 }
      ]
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Smooth')
      gbxSmooth = getGroupBox( msg, wgt, l_wts)
      spamSmooth = { 'row': 1, 'col': 2 }
      msgAnnotation   = QCoreApplication.translate('GimpSelectionFeature', 'Annotation:' )
      msgRemoveArea   = QCoreApplication.translate('GimpSelectionFeature', 'Remove Area:' )
      msgRemoveVertex = QCoreApplication.translate('GimpSelectionFeature', 'Remove Vertex:' )
      l_wts = [
        { 'widget': QLabel( msgAnnotation, wgt ),   'row': 0, 'col': 0 },
        { 'widget': self.leditAnnotation,           'row': 0, 'col': 1 },
        { 'widget': QLabel( msgRemoveArea, wgt ),   'row': 1, 'col': 0 },
        { 'widget': self.sbRemoveAreaPixels,          'row': 1, 'col': 1 },
        { 'widget': QLabel( msgRemoveVertex, wgt ), 'row': 2, 'col': 0 },
        { 'widget': self.sbAzimuthThreshold,        'row': 2, 'col': 1 },
        { 'widget': gbxSmooth,                      'row': 3, 'col': 0, 'spam': spamSmooth },
        { 'widget': self.chkAdjustBorder,           'row': 4, 'col': 0, }
      ]
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Setting' )
      self.gbxSettingFeatures = getGroupBox( msg, wgt, l_wts)
      spamSetting = { 'row': 1, 'col': 2 }
      l_wts = [
        { 'widget': self.btnGetFeatures,        'row': 0, 'col': 0 },
        { 'widget': self.btnRemoveLastFeatures, 'row': 0, 'col': 1 },
        { 'widget': self.gbxSettingFeatures,    'row': 1, 'col': 0, 'spam': spamSetting }
      ]
      gbxGQ = getGroupBox( "GIMP->QGIS", wgt, l_wts)
      l_wts = [
        { 'widget': self.btnSendImage,        'row': 0, 'col': 0 }
      ]
      gbxQG = getGroupBox( "QGIS->GIMP", wgt, l_wts)
      spamGroup = { 'row': 1, 'col': 2 }
      l_wts = [
        { 'widget': gbxQG,                'row': 0, 'col': 0, 'spam': spamGroup },
        { 'widget': gbxGQ,                'row': 1, 'col': 0, 'spam': spamGroup }
      ]
      msg = QCoreApplication.translate('GimpSelectionFeature', 'Transfer' )
      gbxTransfer = getGroupBox( msg, wgt, l_wts)
      #
      l_wts = [
        { 'widget': self.gbxImage,  'row': 0, 'col': 0 },
        { 'widget': gbxTransfer,    'row': 1, 'col': 0 }
      ]
      lyt = getLayout( wgt, l_wts )
      lyt.setSizeConstraint( QLayout.SetMaximumSize )
      wgt.setLayout( lyt )
      self.setWidget( wgt )

    super().__init__( "Gimp Selection Feature", iface.mainWindow() )
    #
    msg = QCoreApplication.translate('GimpSelectionFeature', 'Visibles Images(total  {})')
    self.formatTitleImages = msg
    setupUi()
    self.gsf = GimpSelectionFeature( iface, self )

  def __del__(self):
    del self.gsf