# -*- coding: utf-8 -*-
"""
/***************************************************************************
 SPAQLunicornDialog
                                 A QGIS plugin
 This plugin adds a GeoJSON layer from a Wikidata SPARQL query.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2019-10-28
        git sha              : $Format:%H$
        copyright            : (C) 2019 by SPARQL Unicorn
        email                : rse@fthiery.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os
import re
import json
from qgis.PyQt import uic
from qgis.PyQt import QtWidgets
from qgis.PyQt import QtCore
from qgis.core import QgsProject,QgsMessageLog, Qgis,QgsApplication
from qgis.PyQt.QtCore import QRegExp, QSortFilterProxyModel, Qt, QUrl
from qgis.PyQt.QtGui import QRegExpValidator, QStandardItemModel, QDesktopServices
from qgis.PyQt.QtWidgets import QComboBox, QCompleter, QTableWidgetItem, QHBoxLayout, QPushButton, QWidget, \
    QAbstractItemView, QListView, QMessageBox, QApplication, QMenu, QAction, QProgressDialog,QFileDialog
from rdflib.plugins.sparql import prepareQuery
from ..dialogs.whattoenrichdialog import EnrichmentDialog
from ..dialogs.convertcrsdialog import ConvertCRSDialog
from ..util.tooltipplaintext import ToolTipPlainText
from ..util.sparqlutils import SPARQLUtils
from ..tabs.enrichmenttab import EnrichmentTab
from ..tabs.interlinkingtab import InterlinkingTab
from ..dialogs.triplestoredialog import TripleStoreDialog
from ..dialogs.triplestorequickadddialog import TripleStoreQuickAddDialog
from ..dialogs.searchdialog import SearchDialog
from ..util.sparqlhighlighter import SPARQLHighlighter
from ..tasks.querylayertask import QueryLayerTask
from ..tasks.subclassquerytask import SubClassQueryTask
from ..tasks.instanceamountquerytask import InstanceAmountQueryTask
from ..tasks.instancelistquerytask import InstanceListQueryTask
from ..dialogs.valuemappingdialog import ValueMappingDialog
from ..dialogs.bboxdialog import BBOXDialog
from ..dialogs.dataschemadialog import DataSchemaDialog
from ..dialogs.instancedatadialog import InstanceDataDialog
from ..dialogs.loadgraphdialog import LoadGraphDialog

# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'ui/sparql_unicorn_dialog_base.ui'))

MESSAGE_CATEGORY = 'SPARQLUnicornDialog'

##
#  @brief The main dialog window of the SPARQLUnicorn QGIS Plugin.
class SPARQLunicornDialog(QtWidgets.QDialog, FORM_CLASS):
    ## The triple store configuration file
    triplestoreconf = None
    ## Prefix map
    prefixes = None

    enrichtab = None

    interlinktab = None

    conceptList = None

    completerClassList = None

    columnvars = {}

    def __init__(self, triplestoreconf={}, prefixes=[], addVocabConf={}, autocomplete={},
                 prefixstore={"normal": {}, "reversed": {}}, savedQueriesJSON={}, maindlg=None, parent=None):
        """Constructor."""
        super(SPARQLunicornDialog, self).__init__(parent)
        self.setupUi(self)
        self.prefixes = prefixes
        self.maindlg = maindlg
        self.savedQueriesJSON = savedQueriesJSON
        self.enrichtab = EnrichmentTab(self)
        self.interlinktab = InterlinkingTab(self)
        self.addVocabConf = addVocabConf
        self.autocomplete = autocomplete
        self.prefixstore = prefixstore
        self.triplestoreconf = triplestoreconf
        self.searchTripleStoreDialog = TripleStoreDialog(self.triplestoreconf, self.prefixes, self.prefixstore,
                                                         self.comboBox)
        self.geoTreeView.setHeaderHidden(True)
        self.geoTreeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.geoTreeView.setAlternatingRowColors(True)
        self.geoTreeView.setWordWrap(True)
        self.geoTreeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.geoTreeView.customContextMenuRequested.connect(self.onContext)
        self.geoTreeViewModel = QStandardItemModel()
        self.geoTreeView.setModel(self.geoTreeViewModel)
        self.classTreeView.setHeaderHidden(True)
        self.classTreeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.classTreeView.setAlternatingRowColors(True)
        self.classTreeView.setWordWrap(True)
        self.classTreeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.classTreeView.customContextMenuRequested.connect(self.onContext4)
        self.featureCollectionClassListModel = QStandardItemModel()
        self.geometryCollectionClassListModel = QStandardItemModel()
        self.classTreeViewModel = QStandardItemModel()
        self.proxyModel = QSortFilterProxyModel(self)
        self.proxyModel.sort(0)
        self.proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxyModel.setSourceModel(self.geoTreeViewModel)
        self.proxyModel.setRecursiveFilteringEnabled(True)
        self.featureCollectionProxyModel = QSortFilterProxyModel(self)
        self.featureCollectionProxyModel.sort(0)
        self.featureCollectionProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.featureCollectionProxyModel.setSourceModel(self.featureCollectionClassListModel)
        self.geometryCollectionProxyModel = QSortFilterProxyModel(self)
        self.geometryCollectionProxyModel.sort(0)
        self.geometryCollectionProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.geometryCollectionProxyModel.setSourceModel(self.geometryCollectionClassListModel)
        self.classTreeViewProxyModel =  QSortFilterProxyModel(self)
        self.classTreeViewProxyModel.sort(0)
        self.classTreeViewProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.classTreeViewProxyModel.setSourceModel(self.classTreeViewModel)
        self.classTreeViewProxyModel.setRecursiveFilteringEnabled(True)
        self.classTreeView.setModel(self.classTreeViewProxyModel)
        self.geoTreeView.setModel(self.proxyModel)
        self.geoTreeViewModel.clear()
        self.rootNode = self.geoTreeViewModel.invisibleRootItem()
        self.featureCollectionClassList.setModel(self.featureCollectionProxyModel)
        self.featureCollectionClassList.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.featureCollectionClassList.setAlternatingRowColors(True)
        self.featureCollectionClassList.setWordWrap(True)
        self.featureCollectionClassList.setHeaderHidden(True)
        self.featureCollectionClassList.setContextMenuPolicy(Qt.CustomContextMenu)
        self.featureCollectionClassList.customContextMenuRequested.connect(self.onContext2)
        self.featureCollectionClassListModel.clear()
        self.geometryCollectionClassList.setModel(self.geometryCollectionProxyModel)
        self.geometryCollectionClassList.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.geometryCollectionClassList.setAlternatingRowColors(True)
        self.geometryCollectionClassList.setWordWrap(True)
        self.geometryCollectionClassList.setHeaderHidden(True)
        self.geometryCollectionClassList.setContextMenuPolicy(Qt.CustomContextMenu)
        self.geometryCollectionClassList.customContextMenuRequested.connect(self.onContext3)
        self.geometryCollectionClassListModel.clear()
        self.geoTreeView.doubleClicked.connect(self.createLayerFromTreeEntry)
        self.classTreeView.doubleClicked.connect(self.createLayerFromTreeEntry)
        self.queryLimit.setValidator(QRegExpValidator(QRegExp("[0-9]*")))
        self.filterConcepts.textChanged.connect(self.setFilterFromText)
        self.inp_sparql2 = ToolTipPlainText(self.queryTab, self.triplestoreconf, self.comboBox, self.columnvars,
                                            self.prefixes, self.autocomplete)
        self.inp_sparql2.move(10, 130)
        self.inp_sparql2.setMinimumSize(780, 431)
        self.inp_sparql2.document().defaultFont().setPointSize(16)
        self.inp_sparql2.setPlainText(
            "SELECT ?item ?lat ?lon WHERE {\n ?item ?b ?c .\n ?item <http://www.wikidata.org/prop:P123> ?def .\n}")
        self.inp_sparql2.columnvars = {}
        self.inp_sparql2.textChanged.connect(self.validateSPARQL)
        self.sparqlhighlight = SPARQLHighlighter(self.inp_sparql2)
        # self.areaconcepts.hide()
        # self.areas.hide()
        # self.label_8.hide()
        # self.label_9.hide()
        # self.savedQueries.hide()
        # self.loadQuery.hide()
        # self.saveQueryButton.hide()
        # self.saveQueryName.hide()
        # self.savedQueryLabel.hide()
        # self.saveQueryName_2.hide()
        self.enrichTableResult.hide()
        self.queryTemplates.currentIndexChanged.connect(self.viewselectactionClassTree)
        self.bboxButton.clicked.connect(self.getPointFromCanvas)
        self.interlinkTable.cellClicked.connect(self.createInterlinkSearchDialog)
        self.enrichTable.cellClicked.connect(self.createEnrichSearchDialog)
        self.convertTTLCRS.clicked.connect(self.buildConvertCRSDialog)
        self.chooseLayerInterlink.clear()
        self.searchClass.clicked.connect(self.createInterlinkSearchDialog)
        urlregex = QRegExp("http[s]?://(?:[a-zA-Z#]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")
        urlvalidator = QRegExpValidator(urlregex, self)
        self.interlinkNameSpace.setValidator(urlvalidator)
        self.interlinkNameSpace.textChanged.connect(self.check_state3)
        self.interlinkNameSpace.textChanged.emit(self.interlinkNameSpace.text())
        self.addEnrichedLayerButton.clicked.connect(self.enrichtab.addEnrichedLayer)
        self.startEnrichment.clicked.connect(self.enrichtab.enrichLayerProcess)
        self.exportInterlink.clicked.connect(self.enrichtab.exportEnrichedLayer)
        self.loadQuery.clicked.connect(self.loadQueryFunc)
        self.saveQueryButton.clicked.connect(self.saveQueryFunc)
        self.exportMappingButton.clicked.connect(self.interlinktab.exportMapping)
        self.importMappingButton.clicked.connect(self.interlinktab.loadMapping)
        self.loadLayerInterlink.clicked.connect(self.loadLayerForInterlink)
        self.loadLayerEnrich.clicked.connect(self.loadLayerForEnrichment)
        self.addEnrichedLayerRowButton.clicked.connect(self.addEnrichRow)
        self.geoTreeView.selectionModel().currentChanged.connect(self.viewselectactionGeoTree)
        self.classTreeView.selectionModel().currentChanged.connect(self.viewselectactionClassTree)
        self.conceptViewTabWidget.currentChanged.connect(self.tabchanged)
        self.conceptViewTabWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.conceptViewTabWidget.customContextMenuRequested.connect(self.tabContextMenu)
        self.featureCollectionClassList.selectionModel().currentChanged.connect(self.viewselectactionFeatureCollection)
        self.geometryCollectionClassList.selectionModel().currentChanged.connect(self.viewselectactionGeometryCollection)
        self.loadFileButton.clicked.connect(self.buildLoadGraphDialog)
        self.refreshLayersInterlink.clicked.connect(self.loadUnicornLayers)
        self.btn_loadunicornlayers.clicked.connect(self.loadUnicornLayers)
        self.whattoenrich.clicked.connect(self.createWhatToEnrich)
        self.quickAddTripleStore.clicked.connect(self.buildQuickAddTripleStore)
        self.loadTripleStoreButton.clicked.connect(self.buildCustomTripleStoreDialog)
        self.loadUnicornLayers()


    def loadQueryFunc(self):
        if self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"] in self.savedQueriesJSON:
            self.inp_sparql2.setPlainText(
                self.savedQueriesJSON[self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"]][
                    self.savedQueries.currentIndex()]["query"])

    def saveQueryFunc(self):
        queryName = self.saveQueryName.text()
        if queryName is not None and queryName != "":
            __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
            if not self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"] in self.savedQueriesJSON:
                self.savedQueriesJSON[self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"]] = []
            self.savedQueriesJSON[self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"]].append(
                {"label": queryName, "query": self.inp_sparql2.toPlainText()})
            self.savedQueries.addItem(queryName)
            f = open(os.path.join(__location__, 'savedqueries.json'), "w")
            f.write(json.dumps(self.savedQueriesJSON))
            f.close()

    currentContext=None
    currentContextModel=None
    currentProxyModel=None

    def onContext(self,position):
        self.currentContext=self.geoTreeView
        self.currentContextModel = self.geoTreeViewModel
        self.currentProxyModel = self.proxyModel
        self.createMenu(position)

    def onContext2(self, position):
        self.currentContext=self.featureCollectionClassList
        self.currentContextModel = self.featureCollectionClassListModel
        self.currentProxyModel = self.featureCollectionProxyModel
        self.createMenu(position)

    def onContext3(self, position):
        self.currentContext = self.geometryCollectionClassList
        self.currentContextModel = self.geometryCollectionClassListModel
        self.currentProxyModel = self.geometryCollectionProxyModel
        self.createMenu(position)

    def tabContextMenu(self,position):
        menu = QMenu("Menu", self.conceptViewTabWidget)
        actionsaveRDF=QAction("Save Contents as RDF")
        menu.addAction(actionsaveRDF)
        actionsaveRDF.triggered.connect(self.saveTreeToRDF)
        menu.exec_(self.currentContext.viewport().mapToGlobal(position))

    def saveTreeToRDF(self):
        filename, _filter = QFileDialog.getSaveFileName(
                self, "Select   output file ", "", "Linked Data (*.ttl *.n3 *.nt *.graphml)", )
        if filename == "":
                return
        result=set()
        root=self.currentContextModel.invisibleRootItem()
        self.iterateTree(root.child(0),result)
        QgsMessageLog.logMessage('Started task "{}"'.format(""+str(result)), MESSAGE_CATEGORY, Qgis.Info)
        with open(filename, 'w') as output_file:
            output_file.write("".join(result))
        return result
        
    def iterateTree(self,node,result):
        QgsMessageLog.logMessage('Started task "{}"'.format(""+str(node)), MESSAGE_CATEGORY, Qgis.Info)
        for i in range(node.rowCount()):
            if node.child(i).hasChildren():
                iterateTree(self,node.child(i),result)
            if node.child(i).data(257)==SPARQLUtils.geoclassnode or node.child(i).data(257)==SPARQLUtils.classnode:
                result.add("<"+str(node.child(i).data(256))+"> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <"+str(node.data(256))+"> .\n")
            elif node.child(i).data(257)==SPARQLUtils.geoinstancenode or node.child(i).data(257)==SPARQLUtils.instancenode:
                result.add("<"+str(node.child(i).data(256))+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <"+str(node.data(256))+"> .\n")

    def createMenu(self,position):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        menu = QMenu("Menu", self.currentContext)
        actionclip=QAction("Copy IRI to clipboard")
        menu.addAction(actionclip)
        actionclip.triggered.connect(self.copyClipBoard)
        action = QAction("Open in Webbrowser")
        menu.addAction(action)
        action.triggered.connect(self.openURL)
        if nodetype!=SPARQLUtils.instancenode and nodetype!=SPARQLUtils.geoinstancenode:
            actioninstancecount=QAction("Check instance count")
            menu.addAction(actioninstancecount)
            actioninstancecount.triggered.connect(self.instanceCount)
            actiondataschema = QAction("Query data schema")
            menu.addAction(actiondataschema)
            actiondataschema.triggered.connect(self.dataSchemaView)
            actionqueryinstances = QAction("Query instances")
            menu.addAction(actionqueryinstances)
            actionqueryinstances.triggered.connect(self.instanceList)
            if "subclassquery" in self.triplestoreconf[self.comboBox.currentIndex()]:
                action2 = QAction("Load subclasses")
                menu.addAction(action2)
                action2.triggered.connect(self.loadSubClasses)
            actionsubclassquery = QAction("Create subclass query")
            menu.addAction(actionsubclassquery)
            actionsubclassquery.triggered.connect(self.subclassQuerySelectAction)
            actionaddallInstancesAsLayer = QAction("Add all instances as new layer")
            menu.addAction(actionaddallInstancesAsLayer)
            actionaddallInstancesAsLayer.triggered.connect(self.dataAllInstancesAsLayer)
        else:
            actiondataschema = QAction("Query data")
            menu.addAction(actiondataschema)
            actiondataschema.triggered.connect(self.dataInstanceView)
            actionaddInstanceAsLayer = QAction("Add instance as new layer")
            menu.addAction(actionaddInstanceAsLayer)
            actionaddInstanceAsLayer.triggered.connect(self.dataInstanceAsLayer)
        menu.exec_(self.currentContext.viewport().mapToGlobal(position))
        """
        actionapplicablestyles=QAction("Find applicable styles")
        menu.addAction(actionapplicablestyles)
        actionapplicablestyles.triggered.connect(self.appStyles)
        """


    def onContext4(self, position):
        self.currentContext = self.classTreeView
        self.currentContextModel = self.classTreeViewModel
        self.currentProxyModel = self.classTreeViewProxyModel
        self.createMenu(position)

    def openURL(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        url = QUrl(concept)
        QDesktopServices.openUrl(url)

    def copyClipBoard(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        cb = QApplication.clipboard()
        cb.clear(mode=cb.Clipboard)
        cb.setText(concept, mode=cb.Clipboard)

    def instanceCount(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        label = self.currentContextModel.itemFromIndex(curindex).text()
        if not label.endswith("]"):
            self.qtaskinstance = InstanceAmountQueryTask(
                "Getting instance count for " + str(concept),
                self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"], self, self.currentContextModel.itemFromIndex(curindex),self.triplestoreconf[self.comboBox.currentIndex()])
            QgsApplication.taskManager().addTask(self.qtaskinstance)

    def instanceList(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        alreadyloadedindicator = self.currentContextModel.itemFromIndex(curindex).data(259)
        label = self.currentContextModel.itemFromIndex(curindex).text()
        if alreadyloadedindicator!=SPARQLUtils.instancesloadedindicator:
            self.qtaskinstanceList = InstanceListQueryTask(
                "Getting instance count for " + str(concept),
                self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"], self, self.currentContextModel.itemFromIndex(curindex),self.triplestoreconf[self.comboBox.currentIndex()])
            QgsApplication.taskManager().addTask(self.qtaskinstanceList)

    def dataSchemaView(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        label = self.currentContextModel.itemFromIndex(curindex).text()
        self.dataschemaDialog = DataSchemaDialog(concept,label,self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],self.triplestoreconf,self.prefixes,self.comboBox.currentIndex())
        self.dataschemaDialog.setWindowTitle("Data Schema View for "+SPARQLUtils.labelFromURI(str(concept),self.triplestoreconf[self.comboBox.currentIndex()]["prefixesrev"]))
        self.dataschemaDialog.exec_()

    def dataInstanceView(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        label = self.currentContextModel.itemFromIndex(curindex).text()
        self.instancedataDialog = InstanceDataDialog(concept,label,self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],self.triplestoreconf,self.prefixes,self.comboBox.currentIndex())
        self.instancedataDialog.setWindowTitle("Data Schema View for "+SPARQLUtils.labelFromURI(str(concept),self.triplestoreconf[self.comboBox.currentIndex()]["prefixesrev"]))
        self.instancedataDialog.exec_()

    def treeAsRDF(self,root,result):
        if root is not None:
            for row in range(root.rowCount()):

                row_item = root.child(row, 0)
                if row_item.hasChildren():
                    for childIndex in range(row_item.rowCount()):
                        # Take second column from "child"-row
                        child = row_item.child(childIndex, 1)
                        yield child

    def dataInstanceAsLayer(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        if nodetype==SPARQLUtils.geoinstancenode:
            if "geotriplepattern" in self.triplestoreconf[self.comboBox.currentIndex()]:
                self.qlayerinstance = QueryLayerTask(
                    "Instance to Layer: " + str(concept),
                    self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                    "SELECT ?"+" ?".join(self.triplestoreconf[self.comboBox.currentIndex()]["mandatoryvariables"])+" ?rel ?val\n WHERE\n {\n BIND( <" + str(concept) + "> AS ?item)\n ?item ?rel ?val . " +
                    self.triplestoreconf[self.comboBox.currentIndex()]["geotriplepattern"][0] + "\n }",
                    self.triplestoreconf[self.comboBox.currentIndex()], False, SPARQLUtils.labelFromURI(concept), None)
            else:
                self.qlayerinstance = QueryLayerTask(
                "Instance to Layer: " + str(concept),
                self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                "SELECT ?item ?rel ?val \n WHERE\n {\n BIND( <"+str(concept)+"> AS ?item)\n ?item ?rel ?val . \n }",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),None)
        else:
            self.qlayerinstance = QueryLayerTask(
                "Instance to Layer: " + str(concept),
                self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n BIND( <"+str(concept)+"> AS ?item)\n ?item ?rel ?val .\n }",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),None)
        QgsApplication.taskManager().addTask(self.qlayerinstance)

    def dataAllInstancesAsLayer(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        if nodetype==SPARQLUtils.geoclassnode:
            if "geotriplepattern" in self.triplestoreconf[self.comboBox.currentIndex()]:
                self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                    self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                "SELECT ?"+" ?".join(self.triplestoreconf[self.comboBox.currentIndex()]["mandatoryvariables"])+" ?rel ?val\n WHERE\n {\n ?item <"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"> <"+str(concept)+"> . ?item ?rel ?val . "+self.triplestoreconf[self.comboBox.currentIndex()]["geotriplepattern"][0]+"\n }",
                self.triplestoreconf[self.comboBox.currentIndex()],False, SPARQLUtils.labelFromURI(concept),None)
            else:
                self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                    self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n ?item <"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"> <"+str(concept)+"> .\n ?item ?rel ?val .\n }",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),None)
        else:
            self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n ?item <"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"> <"+str(concept)+"> . ?item ?rel ?val .\n }",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),None)
        QgsApplication.taskManager().addTask(self.qlayerinstance)

    def appStyles(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        label = self.currentContextModel.itemFromIndex(curindex).text()
        #self.dataschemaDialog = DataSchemaDialog(concept,label,self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],self.triplestoreconf,self.prefixes,self.comboBox.currentIndex())
        #self.dataschemaDialog.setWindowTitle("Data Schema View for "+str(concept))
        #self.dataschemaDialog.exec_()

    def createLayerFromTreeEntry(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        if nodetype==SPARQLUtils.geoclassnode or nodetype==SPARQLUtils.classnode:
            self.dataAllInstancesAsLayer()
        elif nodetype==SPARQLUtils.geoinstancenode or nodetype==SPARQLUtils.instancenode:
            self.dataInstanceAsLayer()

    def loadSubClasses(self):
        print("Load SubClasses")
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        if "subclassquery" in self.triplestoreconf[self.comboBox.currentIndex()]:
            if "wikidata" in self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"]:
                query=self.triplestoreconf[self.comboBox.currentIndex()]["subclassquery"].replace("%%concept%%",str("wd:" + concept[concept.find('(')+1:-1]))
            else:
                query=self.triplestoreconf[self.comboBox.currentIndex()]["subclassquery"].replace("%%concept%%","<"+str(concept)+">")
            prefixestoadd=""
            for endpoint in self.triplestoreconf[self.comboBox.currentIndex()]["prefixes"]:
                    prefixestoadd += "PREFIX " + endpoint + ": <" + self.triplestoreconf[self.comboBox.currentIndex()]["prefixes"][
                        endpoint] + "> \n"
            self.qtasksub = SubClassQueryTask("Querying QGIS Layer from " + self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                                    self.triplestoreconf[self.comboBox.currentIndex()]["endpoint"],
                                    prefixestoadd + query,None,self,
                                    self.currentContextModel.itemFromIndex(curindex),concept,self.triplestoreconf[self.comboBox.currentIndex()])
            QgsApplication.taskManager().addTask(self.qtasksub)

    def setFilterFromText(self):
        self.currentProxyModel.setFilterRegExp(self.filterConcepts.text())

    def tabchanged(self,index):
        #QgsMessageLog.logMessage('Started task "{}"'.format("Tab changed! "+str(index)), MESSAGE_CATEGORY, Qgis.Info)
        if self.currentProxyModel!=None:
            self.currentProxyModel.setFilterRegExp("")
        self.filterConcepts.setText("")
        if index==0:
            self.currentProxyModel=self.proxyModel
        elif index==1:
            self.currentProxyModel=self.featureCollectionProxyModel
        elif index==2:
            self.currentProxyModel=self.geometryCollectionProxyModel
        elif index==3:
            self.currentProxyModel=self.classTreeViewProxyModel

    ## 
    #  @brief Creates a What To Enrich dialog with parameters given.
    #  
    #  @param self The object pointer
    def buildLoadGraphDialog(self):
        self.searchTripleStoreDialog = LoadGraphDialog(self.triplestoreconf, self.maindlg, self)
        self.searchTripleStoreDialog.setWindowTitle("Load Graph")
        self.searchTripleStoreDialog.exec_()

    def buildConvertCRSDialog(self):
        self.searchTripleStoreDialog = ConvertCRSDialog(self.triplestoreconf, self.maindlg, self)
        self.searchTripleStoreDialog.setWindowTitle("Convert CRS")
        self.searchTripleStoreDialog.exec_()

    ## 
    #  @brief Creates a What To Enrich dialog with parameters given.
    #  
    #  @param self The object pointer
    def buildQuickAddTripleStore(self):
        self.searchTripleStoreDialog = TripleStoreQuickAddDialog(self.triplestoreconf, self.prefixes, self.prefixstore,
                                                                 self.comboBox)
        self.searchTripleStoreDialog.setMinimumSize(580, 186)
        self.searchTripleStoreDialog.setWindowTitle("Configure Own Triple Store")
        self.searchTripleStoreDialog.exec_()

    ## 
    #  @brief Creates a What To Enrich dialog with parameters given.
    #  
    #  @param self The object pointer
    def buildCustomTripleStoreDialog(self):
        self.searchTripleStoreDialog = TripleStoreDialog(self.triplestoreconf, self.prefixes, self.prefixstore,
                                                         self.comboBox)
        self.searchTripleStoreDialog.setMinimumSize(700, 500)
        self.searchTripleStoreDialog.setWindowTitle("Configure Own Triple Store")
        self.searchTripleStoreDialog.exec_()

    ## 
    #  @brief Creates a What To Enrich dialog with parameters given.
    #  
    #  @param self The object pointer
    def createWhatToEnrich(self):
        if self.enrichTable.rowCount() == 0:
            return
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.chooseLayerEnrich.currentIndex()
        layer = layers[selectedLayerIndex].layer()
        self.searchTripleStoreDialog = EnrichmentDialog(self.triplestoreconf, self.prefixes, self.enrichTable, layer,
                                                        None, None)
        self.searchTripleStoreDialog.setMinimumSize(700, 500)
        self.searchTripleStoreDialog.setWindowTitle("Enrichment Search")
        self.searchTripleStoreDialog.exec_()

    def check_state3(self):
        self.searchTripleStoreDialog.check_state(self.interlinkNameSpace)

    def createEnrichSearchDialog(self, row=-1, column=-1):
        if column == 1:
            self.buildSearchDialog(row, column, False, self.enrichTable, False, False, None, self.addVocabConf)
        if column == 6:
            self.buildSearchDialog(row, column, False, self.enrichTable, False, False, None, self.addVocabConf)

    def createEnrichSearchDialogProp(self, row=-1, column=-1):
        self.buildSearchDialog(row, column, False, self.findIDPropertyEdit, True, False, None, self.addVocabConf)

    ## 
    #  @brief Creates a search dialog with parameters for interlinking.
    #  
    #  @param self The object pointer
    #  @param row The row of the table for which to map the search result
    #  @param column The column of the table for which to map the search result
    def createInterlinkSearchDialog(self, row=-1, column=-1):
        if column > 3 and column < 7:
            self.buildSearchDialog(row, column, True, self.interlinkTable, True, False, None, self.addVocabConf)
        elif column >= 7:
            layers = QgsProject.instance().layerTreeRoot().children()
            selectedLayerIndex = self.chooseLayerInterlink.currentIndex()
            layer = layers[selectedLayerIndex].layer()
            self.buildValueMappingDialog(row, column, True, self.interlinkTable, layer)
        elif column == -1:
            self.buildSearchDialog(row, column, -1, self.interlinkOwlClassInput, False, False, None, self.addVocabConf)

    ## 
    #  @brief Shows the configuration table after creating an enrichment result.
    #  
    #  @param  self The object pointer
    #  
    def showConfigTable(self):
        self.enrichTableResult.hide()
        self.enrichTable.show()
        self.startEnrichment.setText("Start Enrichment")
        self.startEnrichment.clicked.disconnect()
        self.startEnrichment.clicked.connect(self.enrichtab.enrichLayerProcess)

    def collectionSelectAction(self):
        endpointIndex = self.comboBox.currentIndex()
        if endpointIndex == 0:
            self.justloadingfromfile = False
            return
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None:
            concept = self.currentContextModel.itemFromIndex(curindex).data(256)
            querytext = self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()][
            "query"].replace("?item a <%%concept%%>", "<"+concept+"> rdfs:member ?item ")
            self.inp_sparql2.setPlainText(querytext)
            self.inp_sparql2.columnvars = {}

    def viewselectactionGeometryCollection(self,selected=None, deselected=None):
        self.currentContext=self.geometryCollectionClassList
        self.currentProxyModel=self.geometryCollectionProxyModel
        self.currentContextModel=self.geometryCollectionClassListModel
        self.collectionSelectAction()

    def viewselectactionFeatureCollection(self,selected=None, deselected=None):
        self.currentContext=self.featureCollectionClassList
        self.currentProxyModel=self.featureCollectionProxyModel
        self.currentContextModel=self.featureCollectionClassListModel
        self.collectionSelectAction()

    def viewselectactionClassTree(self):
        self.currentContext=self.classTreeView
        self.currentProxyModel=self.classTreeViewProxyModel
        self.currentContextModel=self.classTreeViewModel
        self.conceptSelectAction()

    def viewselectactionGeoTree(self):
        self.currentContext=self.geoTreeView
        self.currentProxyModel=self.proxyModel
        self.currentContextModel=self.geoTreeViewModel
        self.conceptSelectAction()

    def subclassQuerySelectAction(self):
        endpointIndex = self.comboBox.currentIndex()
        if endpointIndex == 0:
            self.justloadingfromfile = False
            return
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None:
            concept = self.currentContextModel.itemFromIndex(curindex).data(256)
            querytext = self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()][
            "query"].replace("?item a <%%concept%%>", "?item a ?con . ?con rdfs:subClassOf* <"+concept+"> ")
            self.inp_sparql2.setPlainText(querytext)
            self.inp_sparql2.columnvars = {}

    def conceptSelectAction(self):
        endpointIndex = self.comboBox.currentIndex()
        if endpointIndex == 0:
            self.justloadingfromfile = False
            return
        concept = ""
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None and re.match(r'.*Q[0-9]+.*', self.currentContextModel.itemFromIndex(
            curindex).text()) and not self.currentContextModel.itemFromIndex(curindex).text().startswith("http"):
            self.inp_label.setText(
                self.currentContextModel.itemFromIndex(curindex).text().split("(")[0].lower().replace(" ", "_"))
            concept = "Q" + self.currentContextModel.itemFromIndex(curindex).text().split("Q")[1].replace(")", "")
        elif self.currentContextModel.itemFromIndex(curindex) is not None:
            concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        if "querytemplate" in self.triplestoreconf[endpointIndex]:
            if "wd:Q%%concept%% ." in \
                    self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()]["query"]:
                querytext = ""
                if concept != None and concept.startswith("http"):
                    querytext = \
                        self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()][
                            "query"].replace("wd:Q%%concept%% .", "wd:" + concept[concept.rfind('/') + 1:] + " .")
                elif concept != None:
                    querytext = \
                        self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()][
                            "query"].replace("wd:Q%%concept%% .", "wd:" + concept + " .")
            else:
                querytext = self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()][
                    "query"].replace("%%concept%%", concept)
            if self.queryLimit.text().isnumeric() and querytext.rfind("LIMIT") != -1:
                querytext = querytext[0:querytext.rfind("LIMIT")] + "LIMIT " + self.queryLimit.text()
            elif self.queryLimit.text().isnumeric() and querytext.rfind("LIMIT") == -1:
                querytext = querytext + " LIMIT " + self.queryLimit.text()
            self.inp_sparql2.setPlainText(querytext)
            self.inp_sparql2.columnvars = {}
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None and "#" in self.currentContextModel.itemFromIndex(curindex).text():
            self.inp_label.setText(self.currentContextModel.itemFromIndex(curindex).text()[
                                   self.currentContextModel.itemFromIndex(curindex).text().rfind(
                                       '#') + 1:].lower().replace(" ", "_"))
        elif self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None:
            self.inp_label.setText(self.currentContextModel.itemFromIndex(curindex).text()[
                                   self.currentContextModel.itemFromIndex(curindex).text().rfind(
                                       '/') + 1:].lower().replace(" ", "_"))


    def itemModelToMap(self, model):
        resdict = {}
        for row in range(model.rowCount()):
            index = model.index(row, 0, self)
            resdict[model.itemFromIndex(index).text()] = model.itemFromIndex(index).data(1)
        return resdict

        ##

    #  @brief Deletes a row from the table in the enrichment dialog.
    #
    #  @param  send The sender of the request
    #
    def deleteEnrichRow(self, send):
        w = send.sender().parent()
        row = self.enrichTable.indexAt(w.pos()).row()
        self.enrichTable.removeRow(row)
        self.enrichTable.setCurrentCell(0, 0)

    ## 
    #  @brief Adds a new row to the table in the enrichment dialog.
    #  
    #  @param  self The object pointer
    # 
    def addEnrichRow(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.chooseLayerEnrich.currentIndex()
        layer = layers[selectedLayerIndex].layer()
        self.enrichTableResult.hide()
        fieldnames = [field.name() for field in layer.fields()]
        item = QTableWidgetItem("new_column")
        # item.setFlags(QtCore.Qt.ItemIsEnabled)
        row = self.enrichTable.rowCount()
        self.enrichTable.insertRow(row)
        self.enrichTable.setItem(row, 0, item)
        cbox = QComboBox()
        cbox.addItem("Get Remote")
        cbox.addItem("No Enrichment")
        cbox.addItem("Exclude")
        self.enrichTable.setCellWidget(row, 3, cbox)
        cbox = QComboBox()
        cbox.addItem("Enrich Value")
        cbox.addItem("Enrich URI")
        cbox.addItem("Enrich Both")
        self.enrichTable.setCellWidget(row, 4, cbox)
        cbox = QComboBox()
        for fieldd in fieldnames:
            cbox.addItem(fieldd)
        self.enrichTable.setCellWidget(row, 5, cbox)
        itemm = QTableWidgetItem("http://www.w3.org/2000/01/rdf-schema#label")
        self.enrichTable.setItem(row, 6, itemm)
        itemm = QTableWidgetItem("")
        self.enrichTable.setItem(row, 7, itemm)
        itemm = QTableWidgetItem("")
        self.enrichTable.setItem(row, 8, itemm)

    ## Validates the SPARQL query in the input field and outputs errors in a label.
    #  @param self The object pointer.
    def validateSPARQL(self):
        if self.prefixes is not None and self.comboBox is not None and self.comboBox.currentIndex() is not None and self.prefixes[
            self.comboBox.currentIndex()] is not None \
                and self.inp_sparql2.toPlainText() is not None \
                and self.inp_sparql2.toPlainText() != "":
            try:
                if self.prefixes[self.comboBox.currentIndex()] != "":
                    prepareQuery(
                        "".join(self.prefixes[self.comboBox.currentIndex()]) + "\n" + self.inp_sparql2.toPlainText())
                self.errorLabel.setText("Valid Query")
                self.errorline = -1
                self.sparqlhighlight.errorhighlightline = self.errorline
                self.sparqlhighlight.currentline = 0
                self.inp_sparql2.errorline = None
            except Exception as e:
                match = re.search(r'line:([0-9]+),', str(e))
                match2 = re.search(r'col:([0-9]+),', str(e))
                start = int(match.group(1)) - len(self.triplestoreconf[self.comboBox.currentIndex()]["prefixes"]) - 1
                self.errorLabel.setText(re.sub("line:([0-9]+),", "line: " + str(start) + ",", str(e)))
                self.inp_sparql2.errorline = start - 1
                if "line" in str(e):
                    ex = str(e)
                    start = ex.find('line:') + 5
                    end = ex.find(',', start)
                    start2 = ex.find('col:') + 4
                    end2 = ex.find(')', start2)
                    self.errorline = ex[start:end]
                    self.sparqlhighlight.errorhighlightcol = ex[start2:end2]
                    self.sparqlhighlight.errorhighlightline = self.errorline
                    self.sparqlhighlight.currentline = 0

    ## 
    #  @brief Builds the search dialog to search for a concept or class.
    #  @param  self The object pointer
    #  @param  row the row to insert the result
    #  @param  column the column to insert the result
    #  @param  interlinkOrEnrich indicates if the dialog is meant for interlinking or enrichment
    #  @param  table the GUI element to display the result 
    def buildSearchDialog(self, row, column, interlinkOrEnrich, table, propOrClass, bothOptions=False,
                          currentprefixes=None, addVocabConf=None):
        self.currentcol = column
        self.currentrow = row
        self.interlinkdialog = SearchDialog(column, row, self.triplestoreconf, self.prefixes, interlinkOrEnrich, table,
                                            propOrClass, bothOptions, currentprefixes, addVocabConf)
        self.interlinkdialog.setMinimumSize(650, 400)
        self.interlinkdialog.setWindowTitle("Search Interlink Concept")
        self.interlinkdialog.exec_()

    ## 
    #  @brief Builds a boundingbox dialog allows to pick a bounding box for a SPARQL query.
    #  
    #  @param self The object pointer
    def getPointFromCanvas(self):
        self.d = BBOXDialog(self.inp_sparql2, self.triplestoreconf, self.comboBox.currentIndex())
        self.d.setWindowTitle("Choose BoundingBox")
        self.d.exec_()

    ## 
    #  @brief Builds a value mapping dialog window for ther interlinking dialog.
    #  
    #  @param self The object pointer
    #  @param row The row of the table for which to map the value
    #  @param column The column of the table for which to map the value
    #  @param table The table in which to save the value mapping result
    #  @param layer The layer which is concerned by the enrichment oder interlinking
    def buildValueMappingDialog(self, row, column, interlinkOrEnrich, table, layer):
        self.currentcol = column
        self.currentrow = row
        valuemap = None
        if table.item(row, column) != None and table.item(row, column).text() != "":
            valuemap = table.item(row, column).data(1)
        self.interlinkdialog = ValueMappingDialog(column, row, self.triplestoreconf, interlinkOrEnrich, table,
                                                  table.item(row, 3).text(), layer, valuemap)
        self.interlinkdialog.setMinimumSize(650, 400)
        self.interlinkdialog.setWindowTitle("Get Value Mappings for column " + table.item(row, 3).text())
        self.interlinkdialog.exec_()

    ## 
    #  @brief Loads a QGIS layer for interlinking into the interlinking dialog.
    #  
    #  @param self The object pointer
    def loadLayerForInterlink(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.chooseLayerInterlink.currentIndex()
        if len(layers) == 0:
            return
        layer = layers[selectedLayerIndex].layer()
        try:
            fieldnames = [field.name() for field in layer.fields()]
            while self.interlinkTable.rowCount() > 0:
                self.interlinkTable.removeRow(0);
            row = 0
            self.interlinkTable.setHorizontalHeaderLabels(
                ["Export?", "IDColumn?", "GeoColumn?", "Column", "ColumnProperty", "PropertyType", "ColumnConcept",
                 "ValueConcepts"])
            self.interlinkTable.setColumnCount(8)
            for field in fieldnames:
                item = QTableWidgetItem(field)
                item.setFlags(QtCore.Qt.ItemIsEnabled)
                item2 = QTableWidgetItem()
                item2.setCheckState(True)
                item3 = QTableWidgetItem()
                item3.setCheckState(False)
                item4 = QTableWidgetItem()
                item4.setCheckState(False)
                self.interlinkTable.insertRow(row)
                self.interlinkTable.setItem(row, 3, item)
                self.interlinkTable.setItem(row, 0, item2)
                self.interlinkTable.setItem(row, 1, item3)
                self.interlinkTable.setItem(row, 2, item4)
                cbox = QComboBox()
                cbox.addItem("Automatic")
                cbox.addItem("AnnotationProperty")
                cbox.addItem("DataProperty")
                cbox.addItem("ObjectProperty")
                cbox.addItem("SubClass")
                self.interlinkTable.setCellWidget(row, 5, cbox)
                currentRowCount = self.interlinkTable.rowCount()
                row += 1
        except:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Layer not compatible for interlinking!")
            msgBox.setText("The chosen layer is not supported for interlinking. You possibly selected a raster layer")
            msgBox.exec()
            return

    ##
    #  @brief Loads a QGIS layer for enrichment into the enrichment dialog.
    #  
    #  @param self The object pointer
    def loadLayerForEnrichment(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.chooseLayerEnrich.currentIndex()
        if len(layers) == 0:
            return
        layer = layers[selectedLayerIndex].layer()
        self.enrichTableResult.hide()
        while self.enrichTableResult.rowCount() > 0:
            self.enrichTableResult.removeRow(0);
        self.enrichTable.show()
        self.addEnrichedLayerRowButton.setEnabled(True)
        try:
            fieldnames = [field.name() for field in layer.fields()]
            while self.enrichTable.rowCount() > 0:
                self.enrichTable.removeRow(0);
            row = 0
            self.enrichTable.setColumnCount(9)
            self.enrichTable.setHorizontalHeaderLabels(
                ["Column", "EnrichmentConcept", "TripleStore", "Strategy", "content", "ID Column", "ID Property",
                 "ID Domain", "Language"])
            for field in fieldnames:
                item = QTableWidgetItem(field)
                item.setFlags(QtCore.Qt.ItemIsEnabled)
                currentRowCount = self.enrichTable.rowCount()
                self.enrichTable.insertRow(row)
                self.enrichTable.setItem(row, 0, item)
                cbox = QComboBox()
                cbox.addItem("No Enrichment")
                cbox.addItem("Keep Local")
                cbox.addItem("Keep Remote")
                cbox.addItem("Replace Local")
                cbox.addItem("Merge")
                cbox.addItem("Ask User")
                cbox.addItem("Exclude")
                self.enrichTable.setCellWidget(row, 3, cbox)
                cbox = QComboBox()
                cbox.addItem("Enrich Value")
                cbox.addItem("Enrich URI")
                cbox.addItem("Enrich Both")
                self.enrichTable.setCellWidget(row, 4, cbox)
                cbox = QComboBox()
                for fieldd in fieldnames:
                    cbox.addItem(fieldd)
                self.enrichTable.setCellWidget(row, 5, cbox)
                itemm = QTableWidgetItem("http://www.w3.org/2000/01/rdf-schema#label")
                self.enrichTable.setItem(row, 6, itemm)
                itemm = QTableWidgetItem("")
                self.enrichTable.setItem(row, 7, itemm)
                itemm = QTableWidgetItem("")
                self.enrichTable.setItem(row, 8, itemm)
                celllayout = QHBoxLayout()
                upbutton = QPushButton("Up")
                removebutton = QPushButton("Remove", self)
                removebutton.clicked.connect(self.deleteEnrichRow)
                downbutton = QPushButton("Down")
                celllayout.addWidget(upbutton)
                celllayout.addWidget(downbutton)
                celllayout.addWidget(removebutton)
                w = QWidget()
                w.setLayout(celllayout)
                optitem = QTableWidgetItem()
                # self.enrichTable.setCellWidget(row,4,w)
                # self.enrichTable.setItem(row,3,cbox)
                row += 1
            self.originalRowCount = row
        except:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Layer not compatible for enrichment!")
            msgBox.setText("The chosen layer is not supported for enrichment. You possibly selected a raster layer")
            msgBox.exec()
            return

    ## Fetch the currently loaded layers.
    #  @param self The object pointer.
    def loadUnicornLayers(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        # Populate the comboBox with names of all the loaded unicorn layers
        self.loadedLayers.clear()
        self.chooseLayerInterlink.clear()
        self.chooseLayerEnrich.clear()
        for layer in layers:
            ucl = layer.name()
            # if type(layer) == QgsMapLayer.VectorLayer:
            self.loadedLayers.addItem(layer.name())
            self.chooseLayerInterlink.addItem(layer.name())
            self.chooseLayerEnrich.addItem(layer.name())
