Exemple #1
0
 def getGlobalCommonParamsWindow(self, parent=None):
     window = QtWidgets.QDialog()
     window.setWindowTitle("Global and common parameters")
     scrollarea = QtWidgets.QScrollArea()
     form = QtWidgets.QFormLayout()
     form.addRow(QtWidgets.QLabel("Common Parameters:"))
     for param in self.common:
         (l1, l2) = self.getUIOneliner(param, global_common=True)
         form.addRow(l1, l2)
     form.addRow(QtWidgets.QLabel("Global Parameters:"))
     for param in self.globals:
         (l1, l2) = self.getUIOneliner(param, global_common=True)
         form.addRow(l1, l2)
     closebtn = QtWidgets.QPushButton("Close")
     closebtn.clicked.connect(lambda: self.closeGlobalCommonParamsWindow(window))
     groupbox = QtWidgets.QGroupBox()
     groupbox.setLayout(form)
     scrollarea.setWidget(groupbox)
     window.setFixedHeight(600)
     window.setFixedWidth(600)
     scrollbox = QtWidgets.QVBoxLayout()
     scrollbox.addWidget(scrollarea)
     scrollbox.addWidget(closebtn)
     window.setLayout(scrollbox)
     return window
Exemple #2
0
    def initUI(self):
        self.ui = QtWidgets.QDialog()
        lo = QtWidgets.QFormLayout()
        self.ui.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
                              QtWidgets.QSizePolicy.Maximum)
        lo.addRow(QtWidgets.QLabel("Load ALS file(s):"))
        self.dropspace = QpalsDropTextbox.QpalsDropTextbox(
            layerlist=self.layerlist)
        self.dropspace.setMinimumContentsLength(20)
        self.dropspace.setSizeAdjustPolicy(
            QtWidgets.QComboBox.AdjustToMinimumContentsLength)
        self.dropspace.editingFinished.connect(self.inFileUpdated)
        lo.addRow(self.dropspace)
        self.visMethod = QtWidgets.QComboBox()
        self.visMethod.addItem(VISUALISATION_METHODS[0])
        self.visMethod.addItem(VISUALISATION_METHODS[1])
        self.visMethod.addItem(VISUALISATION_METHODS[2])
        self.visMethod.addItem(VISUALISATION_METHODS[3])
        self.visMethod.addItem(VISUALISATION_METHODS[4])
        self.visMethod.addItem(VISUALISATION_METHODS[5])
        self.visMethod.addItem(VISUALISATION_METHODS[6])
        self.visMethod.addItem(VISUALISATION_METHODS[7])
        self.visMethod.addItem(VISUALISATION_METHODS[8])
        self.visMethod.addItem(VISUALISATION_METHODS[9])
        self.visMethod.currentIndexChanged.connect(self.updatevisMethod)
        self.cellSizeLbl = QtWidgets.QLabel("Set cell size:")
        self.cellSizeBox = QtWidgets.QLineEdit()
        self.cellFeatLbl = QtWidgets.QLabel("Set feature:")
        self.cellFeatCmb = QtWidgets.QComboBox()
        self.cellAttrLbl = QtWidgets.QLabel("Select attribute:")
        self.cellAttrCmb = QtWidgets.QComboBox()
        self.cellAttrCmb.addItem("Z")
        self.cellAttrCmb.setSizeAdjustPolicy(
            QtWidgets.QComboBox.AdjustToContents)
        self.isoInteLbl = QtWidgets.QLabel("Set isoline interval:")
        self.isoInteBox = QtWidgets.QLineEdit()
        self.isoInteBox.setText("10")
        cellInst = QpalsModuleBase.QpalsModuleBase(
            os.path.join(self.project.opalspath, "opalsCell.exe"),
            self.project)
        cellInst.load()
        for param in cellInst.params:
            if param.name.lower() == "cellsize":
                self.cellSizeBox.setText(param.val)
                break
        self.cellFeatCmb.addItems(self.features)
        self.cellFeatCmb.setCurrentIndex(4)
        lo.addRow(self.cellAttrLbl, self.cellAttrCmb)
        lo.addRow(self.cellSizeLbl, self.cellSizeBox)
        lo.addRow(self.cellFeatLbl, self.cellFeatCmb)
        lo.addRow(self.isoInteLbl, self.isoInteBox)
        lo.addRow(self.visMethod)
        self.okBtn = QtWidgets.QPushButton("Load")
        self.okBtn.clicked.connect(self.loadHelper)
        lo.addRow(self.okBtn)
        self.ui.setLayout(lo)
        self.ui.setWindowTitle("Open ALS file")

        self.visMethod.setCurrentIndex(1)
Exemple #3
0
    def run_load_project(self):
        formats = ["AequilibraE Project(*.sqlite)"]
        path, dtype = GetOutputFileName(
            QtWidgets.QDialog(),
            "AequilibraE Project",
            formats,
            ".sqlite",
            standard_path(),
        )

        # Cleans the project descriptor
        tab_count = 1
        for i in range(tab_count):
            self.projectManager.removeTab(i)

        if dtype is not None:
            self.contents = []
            self.showing.setVisible(True)
            self.project = Project()
            self.project.load(path)
            self.project.conn = qgis.utils.spatialite_connect(path)
            self.project.network.conn = self.project.conn

            uri = QgsDataSourceUri()
            uri.setDatabase(path)
            uri.setDataSource('', 'links', 'geometry')
            self.link_layer = QgsVectorLayer(uri.uri(), 'links', 'spatialite')
            QgsProject.instance().addMapLayer(self.link_layer)

            uri.setDataSource('', 'nodes', 'geometry')
            self.node_layer = QgsVectorLayer(uri.uri(), 'nodes', 'spatialite')
            QgsProject.instance().addMapLayer(self.node_layer)

            descr = QWidget()
            descrlayout = QVBoxLayout()
            # We create a tab with the main description of the project
            p1 = QLabel('Project: {}'.format(path))
            p2 = QLabel('Modes: {}'.format(', '.join(
                self.project.network.modes())))
            p3 = QLabel('Total Links: {:,}'.format(
                self.project.network.count_links()))
            p4 = QLabel('Total Nodes: {:,}'.format(
                self.project.network.count_nodes()))

            for p in [p1, p2, p3, p4]:
                descrlayout.addWidget(p)

            descr.setLayout(descrlayout)
            self.tabContents = [(descr, "Project")]
            self.projectManager.addTab(descr, "Project")
Exemple #4
0
 def getUI(self):
     self.ui = QtWidgets.QDialog()
     self.ui.resize(720, 300)
     self.ui.setWindowTitle("qpals AttributeManager")
     lo = QtWidgets.QFormLayout()
     vb = QtWidgets.QVBoxLayout()
     hb = QtWidgets.QHBoxLayout()
     self.pointcloud = QpalsDropTextbox.QpalsDropTextbox(layerlist=self.layerlist)
     hb.addWidget(self.pointcloud,1)
     lo.addRow("ODM File", hb)
     vb.addLayout(lo,0)
     self.attable = QtWidgets.QTableView()
     self.newnamebox = QtWidgets.QComboBox()
     self.newnamebox.setEditable(True)
     for attr in odm_predef_attributes:
         self.newnamebox.addItem(attr)
     self.newnamebox.lineEdit().setPlaceholderText("_Name")
     self.typedropdown = QtWidgets.QComboBox()
     for type in odm_data_types:
         self.typedropdown.addItem(type)
     self.formulabox = QtWidgets.QLineEdit("")
     self.formulabox.setPlaceholderText("opalsAddInfo formula")
     self.helpbtn = QtWidgets.QPushButton('?')
     self.helpbtn.setMaximumWidth(self.helpbtn.fontMetrics().boundingRect("?").width() + 7)
     self.addchangebtn = QtWidgets.QPushButton('Add/Change attribute')
     self.closebtn = QtWidgets.QPushButton('Close')
     hb2 = QtWidgets.QHBoxLayout()
     hb2.addWidget(self.newnamebox)
     hb2.addWidget(QtWidgets.QLabel("("))
     hb2.addWidget(self.typedropdown)
     hb2.addWidget(QtWidgets.QLabel(")"))
     hb2.addWidget(QtWidgets.QLabel("="))
     hb2.addWidget(self.formulabox)
     hb2.addWidget(self.addchangebtn)
     hb2.addWidget(self.helpbtn)
     hb2.addStretch()
     hb2.addWidget(self.closebtn)
     vb.addWidget(self.attable, 1)
     vb.addLayout(hb2)
     self.ui.setLayout(vb)
     self.pointcloud.editingFinished.connect(self.pcChanged)
     self.newnamebox.editTextChanged.connect(self.newnameChanged)
     self.closebtn.clicked.connect(self.close)
     self.helpbtn.clicked.connect(self.addinfoHelp)
     self.addchangebtn.clicked.connect(self.fieldcalc)
     self.newnamebox.lineEdit().setText("_")
     return self.ui
Exemple #5
0
    def createWidget(self):
        self.advanced_widget = QtWidgets.QDialog()
        self.simple_widget = QtWidgets.QDialog()
        self.tabs = QtWidgets.QTabWidget()
        ### SIMPLE ###
        self.ls = QtWidgets.QFormLayout()
        self.ls.addRow(QtWidgets.QLabel("Choose input file:"))
        self.txtinfileSimple = QpalsDropTextbox.QpalsDropTextbox(
            layerlist=self.layerlist, filterrex=".*\.odm$")
        hboxsimple1 = QtWidgets.QHBoxLayout()
        hboxsimple1.addWidget(self.txtinfileSimple, 1)
        self.txtinfileSimple.textChanged.connect(self.simpleIsLoaded)
        self.ls.addRow(QtWidgets.QLabel("Input file (odm)"), hboxsimple1)
        self.linetoolBtn = QtWidgets.QPushButton("Pick section")
        self.linetoolBtn.clicked.connect(self.activateLineTool)
        self.linetoolBtn.setEnabled(False)
        self.ls.addRow(self.linetoolBtn)

        self.runSecBtnSimple = QtWidgets.QPushButton("Create section")
        self.runSecBtnSimple.clicked.connect(self.ltool.runsec)
        self.runSecBtnSimple.setEnabled(False)
        self.runSecBtnSimple.setStyleSheet("background-color: rgb(50,240,50)")

        self.runSecBtnView = QtWidgets.QPushButton("Open section in opalsView")
        self.runSecBtnView.clicked.connect(self.ltool.runview)
        self.runSecBtnView.setEnabled(False)
        self.runSecBtnView.setStyleSheet("background-color: rgb(100,100,240)")
        hb = QtWidgets.QHBoxLayout()
        hb.addWidget(self.runSecBtnSimple)
        hb.addWidget(self.runSecBtnView)

        self.simpleLineLayer = QgsMapLayerComboBox()
        self.simpleLineLayer.setFilters(QgsMapLayerProxyModel.LineLayer)
        self.simpleLineLayerChk = QtWidgets.QCheckBox(
            "Visualize (3D) Line Layer:")
        self.ls.addRow(self.simpleLineLayerChk, self.simpleLineLayer)
        self.showSection = QtWidgets.QCheckBox("Show section")
        self.filterStr = QtWidgets.QLineEdit("Class[Ground]")
        self.filterAttrBox = QCollapsibleGroupBox.QCollapsibleGroupBox(
            'Show attribute selection')
        self.filterAttrBox.setLayout(QtWidgets.QGridLayout())
        self.filterAttrBox.setChecked(False)  # hide it
        self.filterAttrs = {}
        self.progress = QtWidgets.QProgressBar()
        self.stateSwitch = QToggleSwitch.QToggleSwitch("vispy", "matplotlib")
        self.showSection.stateChanged.connect(self.checkBoxChanged)
        self.showSection.setCheckState(2)
        self.showSection.setTristate(False)
        self.ls.addRow(self.showSection)
        self.ls.addRow("Filter String:", self.filterStr)
        self.ls.addRow(self.filterAttrBox)
        self.ls.addRow(hb)
        self.ls.addRow(self.progress)
        self.ls.addRow(self.stateSwitch)
        self.simple_widget.setLayout(self.ls)
        ### ADVANCED ###
        lo = QtWidgets.QFormLayout()
        ######
        lo.addRow(
            QtWidgets.QLabel("Step 1. Choose point cloud and visualize it:"))
        self.txtinfile = QpalsDropTextbox.QpalsDropTextbox(
            layerlist=self.layerlist)
        hbox1 = QtWidgets.QHBoxLayout()
        hbox1.addWidget(self.txtinfile, 1)
        lo.addRow(QtWidgets.QLabel("Input file (odm)"), hbox1)
        self.runShdBtn = QtWidgets.QPushButton("Create shading")
        self.runShdBtn.clicked.connect(self.loadShading)
        lo.addRow(self.runShdBtn)
        ######
        self.status = QtWidgets.QListWidgetItem("hidden status")
        lo.addRow(QtWidgets.QLabel("Step 2. Create sections"))
        self.secInst = QpalsModuleBase.QpalsModuleBase(
            execName=os.path.join(self.project.opalspath, "opalsSection.exe"),
            QpalsProject=self.project)
        self.secInst.load()
        self.secInst.listitem = self.status
        secUi = self.secInst.getParamUi()
        lo.addRow(secUi)

        self.runSecBtn = QtWidgets.QPushButton("Calculate sections")
        self.runSecBtn.clicked.connect(self.runSection)
        lo.addRow(self.runSecBtn)
        #######
        lo.addRow(
            QtWidgets.QLabel(
                "Step 3. Use the Section picking tool to show Sections"))
        self.pickSecBtn = QtWidgets.QPushButton("Pick section")
        self.pickSecBtn.clicked.connect(self.activateTool)
        lo.addRow(self.pickSecBtn)

        self.advanced_widget.setLayout(lo)
        self.tabs.addTab(self.simple_widget, "Simple")
        self.tabs.addTab(self.advanced_widget, "Advanced")

        self.scrollwidget = QtWidgets.QScrollArea()
        self.scrollwidget.setWidgetResizable(True)
        self.scrollwidget.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
                                        QtWidgets.QSizePolicy.Ignored)
        self.scrollwidget.setWidget(self.tabs)

        return self.scrollwidget
Exemple #6
0
        self.gridLayout.addWidget(self.editPassword, 1, 1, 1, 1)
        self.buttonBox = QtWidgets.QDialogButtonBox(LoginDialog)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel
                                          | QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 2)
        self.label_5.setBuddy(self.editUser)
        self.label_6.setBuddy(self.editPassword)

        self.retranslateUi(LoginDialog)
        self.buttonBox.accepted.connect(LoginDialog.accept)
        self.buttonBox.rejected.connect(LoginDialog.reject)
        QtCore.QMetaObject.connectSlotsByName(LoginDialog)

    def retranslateUi(self, LoginDialog):
        _translate = QtCore.QCoreApplication.translate
        LoginDialog.setWindowTitle(_translate("LoginDialog", "Login"))
        self.label_5.setText(_translate("LoginDialog", "User:"******"LoginDialog", "Password:"******"__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    LoginDialog = QtWidgets.QDialog()
    ui = Ui_LoginDialog()
    ui.setupUi(LoginDialog)
    LoginDialog.show()
    sys.exit(app.exec_())
Exemple #7
0
    def createWidget(self):
        self.scrollwidget = QtWidgets.QScrollArea()
        self.scrollwidget.setWidgetResizable(True)
        self.tabs = QtWidgets.QTabWidget()
        self.scrollwidget.setWidget(self.tabs)
        self.names = [
            'Settings', 'DTM', 'Slope', '2D-Approximation',
            'Topologic correction', 'Editing', '3D-Modelling', 'Editing (3D)',
            'Export'
        ]
        self.widgets = {}
        self.settings = {}
        self.modules = {}

        for idx, name in enumerate(self.names):
            self.widgets[name] = QtWidgets.QDialog()
            ls = QtWidgets.QFormLayout()
            # Tab-specific options
            if name == "Settings":
                desc = QtWidgets.QLabel(
                    "Welcome to the qpals LineModeler GUI! \nThis tool will help you to detect and "
                    "model breaklines based on a DTM and/or a point cloud using the opals module "
                    "opalsLineModeler.\nThe process includes manual editing in QGIS (\"Editing\") "
                    "as well as automatic dectection and modelling.\n\n"
                    "To begin, please enter some basic information.")
                desc.setWordWrap(True)
                ls.addRow(desc)
                boxRun = QtWidgets.QGroupBox(
                    "Run multiple steps automatically:")
                boxVL = QtWidgets.QVBoxLayout()
                boxRun.setLayout(boxVL)
                self.settings['settings'] = OrderedDict([
                    ('name', QtWidgets.QLineEdit()),
                    ('inFile',
                     QpalsDropTextbox.QpalsDropTextbox(
                         layerlist=self.layerlist)),
                    ('tempFolder', QpalsDropTextbox.QpalsDropTextbox()),
                    ('outFolder', QpalsDropTextbox.QpalsDropTextbox()),
                    ('chkDTM', QtWidgets.QCheckBox("DTM")),
                    ('chkSlope', QtWidgets.QCheckBox("Slope")),
                    ('chk2D', QtWidgets.QCheckBox("2D-Approximation")),
                    ('chktopo2D',
                     QtWidgets.QCheckBox("Topological correction")),
                    ('chkEditing2d',
                     QtWidgets.QLabel(
                         "--- Manual editing of 2D-Approximations ---")),
                    ('chk3Dmodel', QtWidgets.QCheckBox("3D-Modelling")),
                    ('chkEditing3d',
                     QtWidgets.QLabel("--- Manual editing of 3D-Lines ---")),
                    ('chkExport', QtWidgets.QCheckBox("Export")),
                ])
                for key, value in list(self.settings['settings'].items()):
                    if isinstance(value, QpalsDropTextbox.QpalsDropTextbox):
                        value.setMinimumContentsLength(20)
                        value.setSizeAdjustPolicy(
                            QtWidgets.QComboBox.AdjustToMinimumContentsLength)
                    if key.startswith("chk"):
                        boxVL.addWidget(value)

                ls.addRow(QtWidgets.QLabel("Project name"),
                          self.settings['settings']['name'])
                hbox_wrap = QtWidgets.QHBoxLayout()
                hbox_wrap.addWidget(self.settings['settings']['inFile'],
                                    stretch=1)
                ls.addRow(QtWidgets.QLabel("Input file (TIFF/LAS/ODM)"),
                          hbox_wrap)
                hbox_wrap = QtWidgets.QHBoxLayout()
                hbox_wrap.addWidget(self.settings['settings']['tempFolder'],
                                    stretch=1)
                self.settings['settings']['tempFolder'].setPlaceholderText(
                    "drop folder here (will be created if not exists)")
                ls.addRow(QtWidgets.QLabel("Folder for temporary files"),
                          hbox_wrap)
                hbox_wrap = QtWidgets.QHBoxLayout()
                self.settings['settings']['outFolder'].setPlaceholderText(
                    "drop folder here (will be created if not exists)")
                hbox_wrap.addWidget(self.settings['settings']['outFolder'],
                                    stretch=1)
                ls.addRow(QtWidgets.QLabel("Folder for output files"),
                          hbox_wrap)
                ls.addRow(QtWidgets.QLabel(""))
                boxBtnRun = QtWidgets.QPushButton("Run selected steps now")
                boxBtnRun.clicked.connect(lambda: self.run_step("all"))
                boxBtnExp = QtWidgets.QPushButton(
                    "Export selected steps to .bat")
                boxBtnExp.clicked.connect(self.createBatFile)
                # saveBtn = QtWidgets.QPushButton("Save to project file")
                # saveBtn.clicked.connect(self.save)
                boxVL.addWidget(boxBtnRun)
                boxVL.addWidget(boxBtnExp)
                # boxVL.addWidget(saveBtn)
                ls.addRow(boxRun)

            if name == "DTM":
                desc = QtWidgets.QLabel(
                    "This first step will create a digital terrain model (DTM) from your point cloud data. "
                    "Also, a shading of your DTM "
                    "will be created for visualisation purposes. If the input file is not an ODM, one has to be "
                    "created for the modelling process later on.")
                desc.setWordWrap(True)
                ls.addRow(desc)

                impmod, impscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsImport", "opalsImport", self.project,
                    {'outFile': 'pointcloud.odm'}, ["inFile", "outFile"])
                self.modules['dtmImp'] = impmod
                self.widgets['dtmImp'] = impscroll
                ls.addRow(impscroll)

                dtmmod, dtmscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsGrid", "opalsGrid", self.project, {
                        'interpolation': 'movingPlanes',
                        'gridSize': '1',
                        'outFile': 'DTM_1m.tif'
                    }, [
                        "inFile", "outFile", "neighbours", "searchRadius",
                        "interpolation"
                    ])
                self.modules['dtmGrid'] = dtmmod
                self.widgets['dtmGrid'] = dtmscroll
                dtmmod.afterRun = self.addDtm
                ls.addRow(dtmscroll)

                shdmod, shdscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsShade", "opalsShade", self.project, {
                        'inFile': 'DTM_1m.tif',
                        'outFile': 'DTM_1m_shd.tif'
                    }, [
                        "inFile",
                        "outFile",
                    ])
                self.modules['dtmShade'] = shdmod
                shdmod.afterRun = self.addShd
                ls.addRow(shdscroll)

            if name == "Slope":
                desc = QtWidgets.QLabel(
                    "To automatically detect breaklines, a slope map is calculated. This map uses the neighboring 9"
                    " pixels to estimate a plane. The gradient (steepest slope) is then taken, converted to a slope"
                    "in degrees, and assigned to the pixel.")
                desc.setWordWrap(True)
                ls.addRow(desc)

                gfmod, gfscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsGridFeature", "opalsGridFeature", self.project, {
                        'feature': 'slpDeg',
                        'inFile': 'DTM_1m.tif',
                        'outFile': 'DTM_1m_slope.tif'
                    }, ["inFile", "outFile", "feature"])
                self.modules['slope'] = gfmod
                ls.addRow(gfscroll)

            if name == "2D-Approximation":
                desc = QtWidgets.QLabel(
                    "The slope map is used to detect breaklines. For this, the algorithm by Canny (1986) is used.\n"
                    "First, the slope map is convoluted with a gaussian kernel for smoothing, then the derivative "
                    "is calculated. The two threshold parameters represent the upper and lower values for the "
                    "binarization of the derivative map. Edges that have at least one pixel > upper threshold will be "
                    "followed until they have a pixel < lower threshold.")
                desc.setWordWrap(True)
                ls.addRow(desc)

                edgeDmod, edgeDscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsEdgeDetect", "opalsEdgeDetect", self.project, {
                        'threshold': '2;4',
                        'sigmaSmooth': '1.8',
                        'inFile': 'DTM_1m_slope_slpDeg.tif',
                        'outFile': 'detected_edges.tif'
                    }, ["inFile", "outFile", "threshold", "sigmaSmooth"])
                self.modules['edgeDetect'] = edgeDmod
                ls.addRow(edgeDscroll)

                desc = QtWidgets.QLabel(
                    "Since the output of opalsEdgeDetect is still a raster, we need to vectorize it:"
                )
                desc.setWordWrap(True)
                ls.addRow(desc)

                vecmod, vecscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsVectorize", "opalsVectorize", self.project, {
                        'inFile': 'detected_edges.tif',
                        'outFile': 'detected_edges.shp'
                    }, ["inFile", "outFile"])
                self.modules['vectorize'] = vecmod
                ls.addRow(vecscroll)

            if name == "Topologic correction":
                desc = QtWidgets.QLabel(
                    "Vectorized binary rasters usually need some topological cleaning. Here, this is done in three steps: \n"
                    "1) Find the longest line and remove all lines < 10m\n"
                    "2) Merge lines iteratively\n"
                    "3) Clean up")
                desc.setWordWrap(True)
                ls.addRow(desc)

                lt1mod, lt1scroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsLineTopology", "opalsLineTopology (1)", self.project,
                    {
                        'method': 'longest',
                        'minLength': '10',
                        'snapRadius': '0',
                        'maxTol': '0.5',
                        'maxAngleDev': '75;15',
                        'avgDist': '3',
                        'inFile': 'detected_edges.shp',
                        'outFile': 'edges1.shp'
                    }, ["inFile", "outFile", "method", "minLength", "maxTol"])
                self.modules['lt1'] = lt1mod
                ls.addRow(lt1scroll)

                lt2mod, lt2scroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsLineTopology", "opalsLineTopology (2)", self.project,
                    {
                        'method': 'merge',
                        'minLength': '10',
                        'snapRadius': '3',
                        'maxTol': '0',
                        'maxAngleDev': '150;15',
                        'avgDist': '3',
                        'merge.minWeight': '0.75',
                        'merge.relWeightLead': '0',
                        'merge.maxIter': '10',
                        'merge.revertDist': '5',
                        'merge.revertInterval': '1',
                        'merge.searchGeneration': '4',
                        'merge.preventIntersection': '1',
                        'inFile': 'edges1.shp',
                        'outFile': 'edges2.shp'
                    }, [
                        "inFile", "outFile", "method", "maxAngleDev",
                        "snapRadius", "merge\..*"
                    ])
                lt2scroll.setFixedHeight(lt2scroll.height() - 200)
                self.modules['lt2'] = lt2mod
                ls.addRow(lt2scroll)

                lt3mod, lt3scroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsLineTopology", "opalsLineTopology (3)", self.project,
                    {
                        'method': 'longest',
                        'minLength': '25',
                        'snapRadius': '0',
                        'maxTol': '0',
                        'maxAngleDev': '90;15',
                        'avgDist': '3',
                        'inFile': 'edges2.shp',
                        'outFile': 'edges3.shp'
                    }, ["inFile", "outFile", "method", "minLength", "maxTol"])
                self.modules['lt3'] = lt3mod
                ls.addRow(lt3scroll)
                lt3mod.afterRun = self.add2DLines

            if name == "Editing":
                desc = QtWidgets.QLabel(
                    "Please start editing the 2D approximations that have been loaded into qgis. Here are some tools "
                    "that might help:")
                desc.setWordWrap(True)
                ls.addRow(desc)

                box1 = QtWidgets.QGroupBox("QuickLineModeller")
                from . import QpalsQuickLM
                self.quicklm = QpalsQuickLM.QpalsQuickLM(
                    project=self.project,
                    layerlist=self.layerlist,
                    iface=self.iface)
                box1.setLayout(self.quicklm.fl)
                ls.addRow(box1)
                box2 = QtWidgets.QGroupBox("qpalsSection")
                from . import QpalsSection
                self.section = QpalsSection.QpalsSection(
                    project=self.project,
                    layerlist=self.layerlist,
                    iface=self.iface)
                self.section.createWidget()
                box2.setLayout(self.section.ls)
                box2.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                   QtWidgets.QSizePolicy.Expanding)
                ls.addRow(box2)

            if name == "3D-Modelling":
                desc = QtWidgets.QLabel(
                    "The 2D approximations can now be used to model 3D breaklines in the pointcloud/the DTM."
                )
                desc.setWordWrap(True)
                ls.addRow(desc)

                lmmod, lmscroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsLineModeler",
                    "opalsLineModeler",
                    self.project,
                    {  #"filter": "Class[Ground]",
                        "approxFile": "edges3.shp",
                        "outFile": "modelled_lines.shp"
                    },
                    [
                        "inFile", "approxFile", "outFile", "filter",
                        "patchLength", "patchWidth", "overlap", "angle",
                        "minLength", "pointCount", "sigmaApriori"
                    ])
                self.modules['lm'] = lmmod
                ls.addRow(lmscroll)

                lmmod.afterRun = self.add3DLines

            if name == "Editing (3D)":
                desc = QtWidgets.QLabel(
                    "Before exporting the final product, there are a few tools to check the "
                    "quality of the result. This includes a topological check as well as a search"
                    "for points that have a big height difference to the DTM - and might be erraneous."
                )

                desc.setWordWrap(True)
                ls.addRow(desc)

                self.startQualityCheckBtn = QtWidgets.QPushButton(
                    "Start calculation")
                self.startQualityCheckBtn.clicked.connect(
                    self.runProblemSearchAsync)
                self.QualityCheckbar = QtWidgets.QProgressBar()
                self.QualityCheckDtm = QgsMapLayerComboBox()
                self.QualityCheckDtm.setFilters(
                    QgsMapLayerProxyModel.RasterLayer)
                self.QualityCheckThreshold = QtWidgets.QLineEdit("0.5")
                ls.addRow(
                    QtWidgets.QLabel("DTM Layer to compare heights with"),
                    self.QualityCheckDtm)
                ls.addRow(
                    QtWidgets.QLabel("Set height difference threshold [m]"),
                    self.QualityCheckThreshold)
                hb = QtWidgets.QHBoxLayout()
                hb.addWidget(self.QualityCheckbar)
                hb.addWidget(self.startQualityCheckBtn)
                ls.addRow(hb)
                line = QtWidgets.QFrame()
                line.setFrameShape(QtWidgets.QFrame.HLine)
                line.setFrameShadow(QtWidgets.QFrame.Sunken)
                ls.addRow(line)

                self.editingls = ls

                self.edit3d_linelayerbox = QgsMapLayerComboBox()
                self.edit3d_linelayerbox.setFilters(
                    QgsMapLayerProxyModel.LineLayer)
                self.edit3d_pointlayerbox = QgsMapLayerComboBox()
                self.edit3d_pointlayerbox.setFilters(
                    QgsMapLayerProxyModel.PointLayer)
                self.edit3d_dtmlayerbox = QgsMapLayerComboBox()
                self.edit3d_dtmlayerbox.setFilters(
                    QgsMapLayerProxyModel.RasterLayer)
                self.edit3d_pointlayerbox.currentIndexChanged.connect(
                    self.nodeLayerChanged)

                self.edit3d_currPointId = QSpinBox()
                self.edit3d_currPointId.setMinimum(0)
                self.edit3d_currPointId.valueChanged.connect(
                    self.showProblemPoint)

                ls.addRow("Select Line Layer:", self.edit3d_linelayerbox)
                ls.addRow("Select Problem Point layer:",
                          self.edit3d_pointlayerbox)

                self.selectNodeBtn = QtWidgets.QPushButton("Next point")
                self.selectNodeBtn.clicked.connect(
                    lambda: self.edit3d_currPointId.setValue(
                        self.edit3d_currPointId.value() + 1))

                self.selectPrevNodeBtn = QtWidgets.QPushButton("Prev point")
                self.selectPrevNodeBtn.clicked.connect(
                    lambda: self.edit3d_currPointId.setValue(
                        self.edit3d_currPointId.value() - 1))
                self.edit3d_countLabel = QtWidgets.QLabel()

                self.snapToDtmBtn = QtWidgets.QPushButton("Snap to:")
                self.snapToDtmBtn.clicked.connect(self.snapToDtm)
                self.remonveNodeBtn = QtWidgets.QPushButton("Remove")
                self.remonveNodeBtn.clicked.connect(self.removeNode)

                nextBox = QtWidgets.QHBoxLayout()
                nextBox.addWidget(QtWidgets.QLabel("Current point:"))
                nextBox.addWidget(self.edit3d_currPointId)
                nextBox.addWidget(QtWidgets.QLabel("/"))
                nextBox.addWidget(self.edit3d_countLabel)
                nextBox.addStretch()

                nextBox.addWidget(self.snapToDtmBtn)
                nextBox.addWidget(self.edit3d_dtmlayerbox)
                nextBox.addWidget(self.remonveNodeBtn)
                nextBox.addWidget(self.selectPrevNodeBtn)
                nextBox.addWidget(self.selectNodeBtn)

                ls.addRow(nextBox)
                self.nodeLayerChanged()

            if name == "Export":
                exp2mod, exp2scroll = QpalsModuleBase.QpalsModuleBase.createGroupBox(
                    "opalsTranslate", "opalsTranslate", self.project, {
                        'oformat': 'shp',
                        'inFile': 'modelled_lines.shp',
                        'outFile': 'STRULI3D.shp',
                    }, ["inFile", "outFile"])

                self.modules['exp'] = exp2mod
                ls.addRow(exp2scroll)

            vl = QtWidgets.QVBoxLayout()
            vl.addLayout(ls, 1)
            navbar = QtWidgets.QHBoxLayout()
            next = QtWidgets.QPushButton("Next step >")
            next.clicked.connect(self.switchToNextTab)
            prev = QtWidgets.QPushButton("< Previous step")
            prev.clicked.connect(self.switchToPrevTab)
            runcurr = QtWidgets.QPushButton(
                "Run this step (all modules above)")
            runcurr.clicked.connect(lambda: self.run_step(None))
            if idx > 0:
                navbar.addWidget(prev)
            navbar.addStretch()
            if name in [
                    "DTM", "Slope", "2D-Approximation", "Topologic correction",
                    "3D-Modelling", "Export"
            ]:
                navbar.addWidget(runcurr)
            navbar.addStretch()
            if idx < len(self.names):
                navbar.addWidget(next)
            vl.addLayout(navbar)
            self.widgets[name].setLayout(vl)
            self.tabs.addTab(self.widgets[name], name)

        # set up connections

        self.tabs.currentChanged.connect(self.updateTabs)
        return self.scrollwidget