コード例 #1
0
class ShowTestDialog(QDialog):
    def __init__(self, s):
        QDialog.__init__(self)
        self.setModal(True)
        self.resize(600, 400)
        self.setWindowTitle(self.tr('Unit test'))
        layout = QVBoxLayout()
        self.text = QTextEdit()
        self.text.setFontFamily("monospace")
        self.text.setEnabled(True)
        self.text.setText(s)
        layout.addWidget(self.text)
        self.setLayout(layout)
        QMetaObject.connectSlotsByName(self)
コード例 #2
0
ファイル: TestTools.py プロジェクト: Water-DD/QGIS
class ShowTestDialog(QDialog):
    def __init__(self, s):
        QDialog.__init__(self)
        self.setModal(True)
        self.resize(600, 400)
        self.setWindowTitle(self.tr('Unit test'))
        layout = QVBoxLayout()
        self.text = QTextEdit()
        self.text.setFontFamily("monospace")
        self.text.setEnabled(True)
        # Add two spaces in front of each text for faster copy/paste
        self.text.setText('  {}'.format(s.replace('\n', '\n  ')))
        layout.addWidget(self.text)
        self.setLayout(layout)
        QMetaObject.connectSlotsByName(self)
コード例 #3
0
ファイル: TestTools.py プロジェクト: PeterTFS/QGIS
class ShowTestDialog(QDialog):

    def __init__(self, s):
        QDialog.__init__(self)
        self.setModal(True)
        self.resize(600, 400)
        self.setWindowTitle(self.tr('Unit test'))
        layout = QVBoxLayout()
        self.text = QTextEdit()
        self.text.setFontFamily("monospace")
        self.text.setEnabled(True)
        self.text.setText(s)
        layout.addWidget(self.text)
        self.setLayout(layout)
        QMetaObject.connectSlotsByName(self)
コード例 #4
0
class ShowTestDialog(QDialog):

    def __init__(self, s):
        QDialog.__init__(self)
        self.setModal(True)
        self.resize(600, 400)
        self.setWindowTitle(self.tr('Unit test'))
        layout = QVBoxLayout()
        self.text = QTextEdit()
        self.text.setFontFamily("monospace")
        self.text.setEnabled(True)
        # Add two spaces in front of each text for faster copy/paste
        self.text.setText('  {}'.format(s.replace('\n', '\n  ')))
        layout.addWidget(self.text)
        self.setLayout(layout)
        QMetaObject.connectSlotsByName(self)
コード例 #5
0
    def attrPrinter(self, fieldsList: object, feature: QgsFeature,
                    place: QTextEdit):
        """print the attribute table on preview panel

        :param fieldsList object: List the attribute value of feature
        :param feature QgsFeature: The feature will be printed
        :param place QTextEdit: The place for editing text
        
        """
        temp = ''

        for f in fieldsList:
            temp += f.name()
            temp += ' : '
            temp += str(feature.attribute(f.name()))
            temp += '\n'
        # print(place)
        place.setText(temp)
コード例 #6
0
ファイル: about_box.py プロジェクト: Barahir44/qgis-plugin
class AboutBox(QDialog):
    """
    About box of the plugin
    """
    def __init__(self, parent=None):

        QWidget.__init__(self, parent)

        mainLayout = QVBoxLayout()

        logo_file_path = PluginGlobals.instance().logo_file_path
        self.logo = QLabel()
        self.logo.setPixmap(QPixmap(logo_file_path))
        mainLayout.addWidget(self.logo)

        title = u"À propos de l'extension GéoGrandEst…"
        description = u"""Extension pour QGIS donnant un accès simplifié aux ressources géographiques utiles aux 
partenaires de GéoGrandEst
Version {0}
Plus d'informations à l'adresse suivante :
{1}
        """.format(PluginGlobals.instance().PLUGIN_VERSION,
                   PluginGlobals.instance().PLUGIN_SOURCE_REPOSITORY)

        self.textArea = QTextEdit()
        self.textArea.setReadOnly(True)
        self.textArea.setText(description)
        self.textArea.setFrameShape(QFrame.NoFrame)
        mainLayout.addWidget(self.textArea)

        self.setModal(True)
        self.setSizeGripEnabled(False)

        self.setLayout(mainLayout)

        self.setFixedSize(400, 250)
        self.setWindowTitle(title)
コード例 #7
0
class MainPSWindow(QMainWindow):
    click_ref = pyqtSignal(QgsPoint, Qt.MouseButton)
    close = pyqtSignal()

    def __init__(self, iface, parent=None):
        QMainWindow.__init__(self, parent=parent)

        # build ui
        self.ui = Ui_Form()  #Appelle la fenêtre
        self.ui.setupUi(self)  #Construit l'interface
        self.setCentralWidget(self.ui.PS_Time_Viewer
                              )  #Définit la fenêtre principal de l'interface
        self.first_point = True

        # Set up the user interface from Designer.
        self.iface = iface
        self.canvas = iface.mapCanvas()  #Lie QGIS et la fenêtre

        # connect signals
        self.make_connection()  #Relie les boutons aux actions

    def set_ps_layer(self, ps_layer):
        self.ps_layer = ps_layer

    def setupUi2(self, Form):
        """Ajoutons ce qu'il manque à la fenêtre"""
        self.ui.setupUi(self, Form)
        Form.closeEvent = self.close_Event

    def closeEvent(self, event):
        result = QMessageBox.question(self, "Confirm Exit...",
                                      "Are you sure you want to exit ?",
                                      QMessageBox.Yes | QMessageBox.No)
        event.ignore()

        if result == QMessageBox.Yes:
            self.close.emit()
            event.accept()

    def addDlg(self, dlg):
        self.dlg = dlg
        self.ui.graph_loc.addWidget(self.dlg.toolbar, 0,
                                    Qt.AlignTop)  #gridLayout_21
        self.ui.graph_loc.addWidget(self.dlg.plot, 40,
                                    Qt.AlignTop)  #verticalLayout_2
        self.ui.graph_loc.addWidget(self.dlg.nav, 2,
                                    Qt.AlignTop)  #verticalLayout_2

    def get_diff(self, list_item):
        x, y = [], []  # lists containg x,y values
        idx_selected = []

        for i in range(len(list_item)):
            if list_item[i].isSelected() == True:
                idx_selected.append(i)

        if len(idx_selected) == 2:
            for elem in range(2):
                #fid.append(int(str(elem.text()).split()[-1]))
                idx = idx_selected[elem]
                x.append(self.dlg.plot.collections[idx].x)
                y.append(self.dlg.plot.collections[idx].y)
        else:
            QMessageBox.information(self.iface.mainWindow(),
                                    "PS Time Series Viewer",
                                    "Sélectionner 2 points", QMessageBox.Ok)

        return x, y

    def plot_diff(self):
        list_item = []
        for i in range(self.ui.list_series.count()):
            list_item.append(self.ui.list_series.item(i))
        selected = self.get_diff(list_item)

        #Transformer les datetime
        yeari = []
        monthi = []
        dayi = []
        for j in range(len(selected[0])):
            for i in range(len(selected[0][0])):
                yeari.append(selected[0][j][i].year)
                monthi.append(selected[0][j][i].month)
                dayi.append(selected[0][j][i].day)

        if yeari[0:int(len(yeari) / 2)] == yeari[int(len(yeari) / 2):]:
            xdiff = selected[0][0]
            ydiff = []
            for i in range(len(selected[1][0])):
                ydiff.append(
                    float(selected[1][0][i]) - float(selected[1][1][i]))
        else:
            QMessageBox.warning(self.iface.mainWindow(),
                                "PS Time Series Viewer",
                                "No match in time." % self.ts_tablename)

        self.nb_series = 0
        layer = self.iface.activeLayer()
        infoFields = {}
        ps_fields = layer.dataProvider().fields()
        for idx, fld in enumerate(ps_fields):
            infoFields[idx] = fld

        if self.nb_series == 0 or self.first_point == True:
            self.dlg = PSTimeSeries_Dlg(layer, infoFields)
            self.dlg.plot.setData(xdiff, ydiff)
            self.dlg.addPlotPS(xdiff, ydiff)
            self.dlg.plot._updateLists()
            self.addDlg(self.dlg)
            self.nb_series += 1
            self.first_point = False

        else:
            self.window.dlg.addLayer(layer, infoFields)
            self.window.dlg.plot.setData(xdiff, ydiff)
            self.window.dlg.addPlotPS(xdiff, ydiff)
            self.window.dlg.plot._updateLists()
            self.window.dlg.refresh()
            self.nb_series += 1

    ##### Buttons#####################################################################################################

    def search_time_series(self):
        self.dlg_files = QFileDialog()
        directory = QFileDialog.getOpenFileName(None, "Select a directory", "",
                                                "Shapefile (*.shp)")  #,
        QgsMessageLog.logMessage(str(directory))
        if not (directory == ""):
            self.ui.time_series.setText(directory[0])
            print("ok")
        else:
            print("")

    def search_metadata(self):
        self.dlg_files = QFileDialog()
        directory = QFileDialog.getOpenFileName(None, "Select a directory", "",
                                                "CSV (*.csv)")  #,
        QgsMessageLog.logMessage(str(directory))
        if not (directory == ""):
            self.ui.metadata.setText(directory[0])
            print("ok")
        else:
            print("")

    def search_gnss(self):
        self.dlg_files = QFileDialog()
        directory = QFileDialog.getOpenFileName(None, "Select a directory", "",
                                                "CSV (*.csv)")  #,
        QgsMessageLog.logMessage(str(directory))
        if not (directory == ""):
            self.ui.gnss_2.setText(directory[0])
            print("ok")
        else:
            print("")

    def search_ref(self):
        self.dlg_files = QFileDialog()
        directory = QFileDialog.getOpenFileName(None, "Select a directory", "",
                                                "Shapefile (*.shp)")  #,
        QgsMessageLog.logMessage(str(directory))
        if not (directory == ""):
            self.ui.ref_2.setText(directory[0])
            print("ok")
        else:
            print("")

    def load_time_series(self):
        self.ui.layers_for_options.addItem(self.ui.time_series.toPlainText())
        self.ui.list_series.addItem(self.ui.time_series.toPlainText())
        self.ui.list_time_series_with_new_ref.addItem(
            self.ui.time_series.toPlainText())

    def load_gnss(self):
        self.ui.gnss_selection_list.addItem(self.ui.gnss_2.toPlainText())

    def load_ref(self):
        self.ui.ref_list.addItem(self.ui.ref_2.toPlainText())
        layer = self.iface.addVectorLayer(self.ui.ref_2.toPlainText(), "ref",
                                          "ogr")
        if not layer:
            print("Layer failed to load!")
        click_ref = pyqtSignal(QgsPoint, Qt.MouseButton)

    def remove_ts(self):
        toRemove = self.ui.list_series.selectedItems()
        if toRemove != []:
            #QgsMessageLog.logMessage("Items selectionnés mais pas supprimés")
            for elem in toRemove:
                idx = self.ui.list_series.row(elem)
                self.ui.layers_for_options.takeItem(idx)
                self.ui.list_series.takeItem(idx)
                self.ui.list_time_series_with_new_ref.takeItem(idx)
                self.dlg.plot._removeCollection(self.dlg.plot.collections[idx])
                self.dlg.refresh()
                QgsMessageLog.logMessage(str(idx) + "   " + str(len(toRemove)))

    def new_ref(self):
        self.dlg_ref = QFileDialog()
        directory = QFileDialog.getExistingDirectory(None, 'Select a folder:',
                                                     '',
                                                     QFileDialog.ShowDirsOnly)

        QgsMessageLog.logMessage(str(directory))
        if not (directory == ""):
            self.ui.create_new_ref.setText(directory)
            print("ok")
        else:
            print("")
        # layer = iface.addVectorLayer(self.ui.create_new_ref.toPlainText(), "ref", "ogr")
        # if not layer:
        # 	print("Layer failed to load!")

    #run method that performs all the real work
    def create_new_ref(self):
        self.point = None
        self.w = QWidget()
        self.w.resize(250, 150)
        self.w.move(300, 300)
        self.w.setWindowTitle('New Reference Area')
        self.label = QLabel(self.tr(u'Set a radius value'))
        self.TextEdit = QTextEdit()
        self.label2 = QLabel(
            self.tr(u'Click on the QGIS interface to set area s center'))
        self.TextEdit2 = QTextEdit()
        self.btn = QPushButton('Ok', self.w)
        self.vbox = QVBoxLayout(self.w)
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.TextEdit)
        self.vbox.addWidget(self.label2)
        self.vbox.addWidget(self.TextEdit2)
        self.vbox.addWidget(self.btn)
        self.w.setLayout(self.vbox)
        self.w.show()
        self.canvas = self.iface.mapCanvas()

        # out click tool will emit a QgsPoint on every click
        self.clickTool = QgsMapToolEmitPoint(self.canvas)

        # create our GUI dialog
        self.clickTool.canvasClicked.connect(self.handleMouseDown)
        self.btn.clicked.connect(self.draw_ref)
        self.canvas.setMapTool(self.clickTool)

    def handleMouseDown(self, point, button):
        self.point = point
        self.TextEdit2.setText(str(point.x()) + " , " + str(point.y()))

    def draw_ref(self):
        QMessageBox.information(self.iface.mainWindow(),
                                "PS Time Series Viewer", "Ok")
        try:
            self.radius = float(self.TextEdit.toPlainText())
        except:
            QMessageBox.information(self.iface.mainWindow(),
                                    "PS Time Series Viewer",
                                    "Please set a float")

        if self.point:
            pathText = self.ui.create_new_ref.toPlainText()
            if pathText == "":
                pathText = "D:"
            path = pathText + "/reference_area.shp"
            uri = path + "|referenceArea"
            vpoly = QgsVectorLayer(uri, 'referenceArea', "ogr")  #
            feature = QgsFeature()
            feature.setGeometry(
                QgsGeometry.fromPointXY(self.point).buffer(self.radius, 100))
            provider = vpoly.dataProvider()
            vpoly.startEditing()
            provider.addFeatures([feature])
            vpoly.commitChanges()
        else:
            QMessageBox.information(self.iface.mainWindow(),
                                    "PS Time Series Viewer", "No point ")

        #QMessageBox.information( self.iface.mainWindow(),"Info", "X,Y = %s,%s" % (str(point.x()),str(point.y())) )

    # def plot_legend(self):
    # 	path=self.ui.layers_for_options.selectedItems()
    # 	myVectorLayer = QgsVectorLayer(path+"|layer", "layer", 'ogr')
    # 	myTargetField = 'target_field'
    # 	myRangeList = []
    # 	myOpacity = 1
    # 	# Make our first symbol and range...
    # 	myMin = 0.0
    # 	myMax = 50.0
    # 	myLabel = 'Group 1'
    # 	myColour = QtGui.QColor('#ffee00')
    # 	mySymbol1 = QgsSymbol.defaultSymbol(myVectorLayer.geometryType())
    # 	mySymbol1.setColor(myColour)
    # 	mySymbol1.setOpacity(myOpacity)
    # 	myRange1 = QgsRendererRange(myMin, myMax, mySymbol1, myLabel)
    # 	myRangeList.append(myRange1)
    # 	#now make another symbol and range...
    # 	myMin = 50.1
    # 	myMax = 100
    # 	myLabel = 'Group 2'
    # 	myColour = QtGui.QColor('#00eeff')
    # 	mySymbol2 = QgsSymbol.defaultSymbol(
    # 		myVectorLayer.geometryType())
    # 	mySymbol2.setColor(myColour)
    # 	mySymbol2.setOpacity(myOpacity)
    # 	myRange2 = QgsRendererRange(myMin, myMax, mySymbol2, myLabel)
    # 	myRangeList.append(myRange2)
    # 	myRenderer = QgsGraduatedSymbolRenderer('', myRangeList)
    # 	myRenderer.setMode(QgsGraduatedSymbolRenderer.EqualInterval)
    # 	myRenderer.setClassAttribute(myTargetField)
    #
    # 	myVectorLayer.setRenderer(myRenderer)
    # 	QgsProject.instance().addMapLayer(myVectorLayer)
    # 	for legendLyr in self.iface.mapCanvas().layers():
    # 		if legendLyr.name() != "os1250_line" and legendLyr.name() != "os1250_text":
    # 			renderer = legendLyr.rendererV2()
    # 			if renderer.type() == "categorizedSymbol":
    # 				myRenderer = renderer.clone()
    # 				idx=0
    # 				for cat in myRenderer.categories():
    # 					myRenderer.updateCategoryLabel (idx,"foo")
    # 					idx+=1
    # 				legendLyr.setRendererV2(myRenderer)
    # 				legendLyr.triggerRepaint()


#######################################################################################################################

    def make_connection(self):
        """
		Create connection for window item
		"""

        #searching file for loading
        self.ui.time_series_search.clicked.connect(
            self.search_time_series)  #(self.ui.time_series)
        self.ui.gnss_search.clicked.connect(self.search_gnss)
        self.ui.ref_search.clicked.connect(self.search_ref)

        #pushing files
        self.ui.time_series_push.clicked.connect(self.load_time_series)
        self.ui.gnss_push.clicked.connect(self.load_gnss)
        self.ui.ref_push.clicked.connect(self.load_ref)
        self.ui.remove_push.clicked.connect(self.remove_ts)
        self.ui.plot_difference.clicked.connect(self.plot_diff)
        self.ui.new_ref.clicked.connect(self.new_ref)
        self.ui.create_new_ref_push.clicked.connect(self.create_new_ref)
コード例 #8
0
class CalculatorModelerParametersDialog(ModelerParametersDialog):
    def setupUi(self):
        self.valueItems = {}
        self.dependentItems = {}
        self.resize(650, 450)
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.infoText = QTextEdit()
        numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
        text = self.tr(
            'You can refer to model values in your formula, using '
            'single-letter variables, as follows:\n',
            'CalculatorModelerParametersDialog')
        ichar = 97
        if numbers:
            for number in numbers:
                text += chr(ichar) + '->' + self.resolveValueDescription(
                    number) + '\n'
                ichar += 1
        else:
            text += self.tr('\n - No numerical variables are available.',
                            'CalculatorModelerParametersDialog')
        self.infoText.setText(text)
        self.infoText.setEnabled(False)
        self.formulaText = QLineEdit()
        if hasattr(self.formulaText, 'setPlaceholderText'):
            self.formulaText.setPlaceholderText(
                self.tr('[Enter your formula here]',
                        'CalculatorModelerParametersDialog'))
        if self._algName is not None:
            alg = self.model.algs[self._algName]
            self.formulaText.setText(alg.params[FORMULA])
        self.setWindowTitle(
            self.tr('Calculator', 'CalculatorModelerParametersDialog'))
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setSpacing(2)
        self.verticalLayout.setMargin(0)
        self.verticalLayout.addWidget(self.infoText)
        self.verticalLayout.addWidget(self.formulaText)
        self.verticalLayout.addWidget(self.buttonBox)
        self.setLayout(self.verticalLayout)
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)
        QMetaObject.connectSlotsByName(self)

    def createAlgorithm(self):
        alg = Algorithm('modelertools:calculator')
        alg.setName(self.model)
        alg.description = self.tr('Calculator',
                                  'CalculatorModelerParametersDialog')

        formula = self.formulaText.text()
        alg.params[FORMULA] = formula

        for i in xrange(AVAILABLE_VARIABLES):
            paramname = NUMBER + unicode(i)
            alg.params[paramname] = None

        numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
        used = []
        for i in range(len(numbers)):
            if unicode(chr(i + 97)) in formula:
                used.append(numbers[i])

        for i, variable in enumerate(used):
            paramname = NUMBER + unicode(i)
            alg.params[paramname] = variable

        # TODO check formula is correct
        return alg
コード例 #9
0
class CalculatorModelerParametersDialog(ModelerParametersDialog):

    def setupUi(self):
        self.valueItems = {}
        self.dependentItems = {}
        self.resize(650, 450)
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.infoText = QTextEdit()
        numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
        text = self.tr('You can refer to model values in your formula, using '
                       'single-letter variables, as follows:\n', 'CalculatorModelerParametersDialog')
        ichar = 97
        if numbers:
            for number in numbers:
                text += chr(ichar) + '->' + self.resolveValueDescription(number) + '\n'
                ichar += 1
        else:
            text += self.tr('\n - No numerical variables are available.', 'CalculatorModelerParametersDialog')
        self.infoText.setText(text)
        self.infoText.setEnabled(False)
        self.formulaText = QLineEdit()
        if hasattr(self.formulaText, 'setPlaceholderText'):
            self.formulaText.setPlaceholderText(self.tr('[Enter your formula here]', 'CalculatorModelerParametersDialog'))
        if self._algName is not None:
            alg = self.model.algs[self._algName]
            self.formulaText.setText(alg.params[FORMULA])
        self.setWindowTitle(self.tr('Calculator', 'CalculatorModelerParametersDialog'))
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setSpacing(2)
        self.verticalLayout.setMargin(0)
        self.verticalLayout.addWidget(self.infoText)
        self.verticalLayout.addWidget(self.formulaText)
        self.verticalLayout.addWidget(self.buttonBox)
        self.setLayout(self.verticalLayout)
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)
        QMetaObject.connectSlotsByName(self)

    def createAlgorithm(self):
        alg = Algorithm('modelertools:calculator')
        alg.setName(self.model)
        alg.description = self.tr('Calculator', 'CalculatorModelerParametersDialog')

        formula = self.formulaText.text()
        alg.params[FORMULA] = formula

        for i in range(AVAILABLE_VARIABLES):
            paramname = NUMBER + str(i)
            alg.params[paramname] = None

        numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
        used = []
        for i in range(len(numbers)):
            if str(chr(i + 97)) in formula:
                used.append(numbers[i])

        for i, variable in enumerate(used):
            paramname = NUMBER + str(i)
            alg.params[paramname] = variable

        # TODO check formula is correct
        return alg
コード例 #10
0
class ExploreMapWindow(QMainWindow):
    """This class offers a canvas and tools to preview and explore data 
        provided by Geocubes. Preview raster layers are fetched from the Geocubes
        cached WMTS server. The user can simply view the data or get legend info
        on a single point."""

    # the window is initiated with the Geocubes url base defined on the main plugin
    # this means that the base doesn't have to be manually changed here if it changes
    def __init__(self, url_base):
        QMainWindow.__init__(self)

        # creating map canvas, which draws the maplayers
        # setting up features like canvas color
        self.canvas = QgsMapCanvas()
        self.canvas.setMinimumSize(550, 700)
        self.canvas.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.canvas.setCanvasColor(Qt.white)
        #self.canvas.enableAntiAliasing(True)

        self.url_base = url_base

        # Qmainwindow requires a central widget. Canvas is placed
        self.setCentralWidget(self.canvas)
        """'tile widths' refer to the Map proxy WMTS server's settings for displaying
        data of different resolutions. If I understood correctly, these values 
        (got by examining properties of a layer from that server in QGIS) are
        the thresholds at which a different resolution is loaded on the GRIDI-FIN
        tileset. The values represent the tile size in map units (meters). 
        
        Each tile widths is tied to the corresponding resolution, which is used
        to get the correct resolution legend info. The method is only an estimation,
        but ought to produce good enough results for this purpose.
        Smallest resolutions (1, 2, 5) are omitted since only some layers 
        have them. """
        self.tile_widths = {
            2560: 10,
            5120: 20,
            12800: 50,
            25600: 100,
            51200: 200,
            128000: 500,
            256000: 1000
        }

        # get all keys i.e. widths
        self.all_widths = [i for i in self.tile_widths]

        # creating background layer box and housing it with the hardcoded options
        self.bg_layer_box = QComboBox()
        # if ortokuva ever updates to newer versions, just change the year here
        bg_layers = ['Taustakartta', 'Ortokuva_2018', 'No reference layer']

        # set 'No reference layer' as the default option
        self.bg_layer_box.addItems(layer for layer in bg_layers)
        self.bg_layer_box.setCurrentIndex(2)
        self.bg_layer_box.currentIndexChanged.connect(self.addBackgroundLayer)

        # initialize the slider that will control BG layer opacity/transparency
        self.opacity_slider = QSlider(Qt.Horizontal)
        self.opacity_slider.setMinimum(0)
        self.opacity_slider.setMaximum(100)
        self.opacity_slider.setSingleStep(1)
        self.opacity_slider.setMaximumWidth(100)
        self.opacity_slider.valueChanged.connect(self.setBackgroundMapOpacity)

        self.legend_checkbox = QCheckBox("Get attribute info on all layers")

        # explanatory texts for the different widgets are stored as label widgets
        bg_layer_label = QLabel(" Background: ")
        bg_opacity_label = QLabel(" BG opacity: ")
        data_label = QLabel("Data: ")
        spacing = QLabel(" ")

        # all of the data layers are housed in this combobox
        self.layer_box = QComboBox()
        self.layer_box.currentIndexChanged.connect(self.addLayer)

        # creating each desired action
        self.actionPan = QAction("Pan tool", self)
        self.actionLegend = QAction("Attribute info tool", self)
        self.actionCancel = QAction("Close window", self)
        self.actionZoom = QAction("Zoom to full extent", self)

        # these two work as on/off. the rest are clickable
        self.actionPan.setCheckable(True)
        self.actionLegend.setCheckable(True)

        # when actions are clicked, do corresponding function
        self.actionPan.triggered.connect(self.pan)
        self.actionLegend.triggered.connect(self.info)
        self.actionCancel.triggered.connect(self.cancel)
        self.actionZoom.triggered.connect(self.zoomToExtent)

        # defining two toolbars: first one houses layer and opacity selection
        # the other has all the tools and functions
        self.layers_toolbar = self.addToolBar("Select layers")
        self.layers_toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
        self.layers_toolbar.setMovable(False)
        self.addToolBarBreak()
        self.tools_toolbar = self.addToolBar("Tools")
        self.tools_toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
        self.tools_toolbar.setMovable(False)

        # change order here to change their placement on window
        # starting with the layer widgets and the corresponding label texts
        self.layers_toolbar.addWidget(data_label)
        self.layers_toolbar.addWidget(self.layer_box)
        self.layers_toolbar.addWidget(bg_layer_label)
        self.layers_toolbar.addWidget(self.bg_layer_box)
        self.layers_toolbar.addWidget(bg_opacity_label)
        self.layers_toolbar.addWidget(self.opacity_slider)
        self.layers_toolbar.addWidget(spacing)
        self.layers_toolbar.addWidget(self.legend_checkbox)

        # then setting all the canvas tools on the second toolbar
        self.tools_toolbar.addAction(self.actionLegend)
        self.tools_toolbar.addAction(self.actionPan)
        self.tools_toolbar.addAction(self.actionZoom)
        self.tools_toolbar.addAction(self.actionCancel)

        # a large text box that will house the legend info
        self.text_browser = QTextEdit("Legend will be shown here")
        self.text_browser.setReadOnly(True)

        # a dock widget is required for the text browser. Docked to main window
        dock_widget = QDockWidget()
        dock_widget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dock_widget.setWindowTitle("Legend")
        dock_widget.setWidget(self.text_browser)

        self.addDockWidget(Qt.RightDockWidgetArea, dock_widget)

        # link actions to premade map tools
        self.toolPan = QgsMapToolPan(self.canvas)
        self.toolPan.setAction(self.actionPan)

        self.toolClick = QgsMapToolEmitPoint(self.canvas)
        self.toolClick.canvasClicked.connect(self.getLegendInfo)

        # this is to ensure that the map isn't zoomed out everytime the layer changes
        self.first_start = True

        # this boolean is true while there is no active background layer
        # needed to ensure that e.g. opacity isn't attempted to be set on a nonexisting layer
        self.no_bg_layer_flag = True

        # set pantool as default
        self.pan()

    def pan(self):
        """Simply activates the tool and deactivates the other tool if active"""
        self.canvas.setMapTool(self.toolPan)
        # make sure the other button isn't checked to avoid confusion
        self.actionLegend.setChecked(False)

    def info(self):
        self.canvas.setMapTool(self.toolClick)
        self.actionLegend.setChecked(True)
        self.actionPan.setChecked(False)

    def zoomToExtent(self):
        """zooms out/in so that the raster layer is centered"""
        self.canvas.setExtent(self.layer.extent())
        self.canvas.refresh()

    def setBackgroundMapOpacity(self):
        if self.no_bg_layer_flag:
            return
        else:
            self.bg_layer.renderer().setOpacity(self.getBackgroundMapOpacity())
            self.canvas.refresh()

    def getBackgroundMapOpacity(self):
        """Returns the current BG layer opacity as a double [0, 1]. Slider only
            accepts integers, therefore the initial value is divided by hundred."""
        return (self.opacity_slider.value() / 100)

    def showCanvas(self, all_datasets):
        """Called to activate the the window. Input is all of the datasets on 
            the Geocubes server as a dictionary (see main plugin py-file). First a
            default layer (background map, which is on the WMTS server
            but not on Geocubes files) is inserted to the combobox. Then the 
            keys of the dictionary (which are in format layer_name;year) are inserted."""

        # empty box on restart
        self.layer_box.clear()
        self.all_datasets = all_datasets
        self.no_bg_layer_flag = True

        for key in self.all_datasets:
            self.layer_box.addItem(key)

        # zoom to the full extent of the current map
        self.zoomToExtent()

        # default values set
        self.text_browser.setText("Legend will be shown here")
        self.bg_layer_box.setCurrentIndex(2)
        self.opacity_slider.setValue(50)
        self.show()

    def getLegendInfo(self, point):
        """Activated when the canvas is clicked. The click returns a point, which
            is parsed to a string of X and Y coordinates separated by a comma.
            An url to get legend info on this point is formed and used.
            If the request is succesful, the response string is decoded and passed
            to be inserted to the text browser."""
        formatted_point = str(int(point.x())) + "," + str(int(point.y()))

        url = self.formLegendUrl(formatted_point)

        if not url:
            return

        response = requests.get(url, timeout=6)

        # 200 = succesful request
        # the field won't be updated in case of a failed request
        if response.status_code == 200:
            legend_string = response.content.decode("utf-8")
            self.setTextToBrowser(legend_string)

    def setTextToBrowser(self, string):
        """Formats and inserts legend text to the browser. Input is string of 
        raw text data. This is split at semicolons if there are multiple features."""

        # empty on multiple clicks
        self.text_browser.clear()
        strings = string.split(';')

        # no need for a loop if there's only one line
        if len(strings) == 1:
            self.text_browser.setText(string)
        else:
            for text_string in strings:
                # appending allows to insert multi-line texts
                self.text_browser.append(text_string)

    def formLegendUrl(self, formatted_point):
        """Forms an url for querying legend data on a specific coordinate point.
            Data is queried either from the currently selected layer or, if selected
            by the user, from all available layers."""
        key = self.layer_box.currentText()
        resolution = self.getResolutionFromExtent()

        if not key:
            return

        if not resolution:
            resolution = 100

        if self.legend_checkbox.isChecked():
            layer_name = "all"
            year = "2015"
        else:
            value = self.all_datasets[key]
            layer_name, year = value[0], value[3]

        url = (self.url_base + "/legend/" + str(resolution) + "/" +
               layer_name + "/" + formatted_point + "/" + year)

        return url

    def getResolutionFromExtent(self):
        """Estimates the resolution of the imagery currently viewed by user
         based on the width of the canvas. Returns said resolution. Used by
         the legend tool to get info of the correct dataset."""
        # extent as a QgsRectangle
        canvas_extent = self.canvas.extent()

        # width (in meters, since CRS is EPSG:3067) of the current canvas view
        width = canvas_extent.xMaximum() - canvas_extent.xMinimum()

        # find the width threshold closest to the current one
        try:
            closest_width = min(self.all_widths, key=lambda x: abs(x - width))
        except Exception:
            return

        # use the width key to get the corrensponding resolution
        closest_resolution = self.tile_widths[closest_width]

        return closest_resolution

    def addLayer(self):
        """Adds a new layer on the map canvas based on the selection on the combobox.
            Everything else is hardcoded, but the layer name of course changes.
            Layers are identified by name and year (i.e. km2_2018). These type
            of strings are formed first, then the whole url"""
        # often a layer already exists. If so, remove
        try:
            QgsProject.instance().removeMapLayer(self.layer)
        except Exception:
            pass

        key = self.layer_box.currentText()

        if not key:
            return
        # background map doesn't have a specific year attached to it
        if key == "Taustakartta":
            layer_name = key
        else:
            # the desired parameters are housed in the dictionary. Luckily the
            # combobox houses the keys to it. gets a tuple with four values
            value = self.all_datasets[key]
            # name is first value, year last. separated with an underscore
            layer_name = value[0] + "_" + value[3]

        url = ("https://vm0160.kaj.pouta.csc.fi/ogiir_cache/wmts/1.0.0/" +
               "WMTSCapabilities.xml&crs=EPSG:3067&dpiMode=7&format=image/" +
               "png&layers=" + layer_name +
               "&styles=default&tileMatrixSet=GRIDI-FIN")

        self.layer = QgsRasterLayer("url=" + url,
                                    'GEOCUBES DATALAYER - TEMPORARY', 'wms')

        if self.layer.isValid():
            QgsProject.instance().addMapLayer(self.layer, False)
            # if layer is valid and added to the instance, insert it to the canvas
            self.setMapLayers()
            # zoom to the full extent of the map if canvas is started for the first time
            if self.first_start:
                self.zoomToExtent()
                self.first_start = False

    def addBackgroundLayer(self):
        """Adds a background layer to help user locating what they want.
            This layer will be either background map (taustakarta), ortographic
            imagery or nothing at all. BG layer has an opacity value that set by
            the user. Function is called when user selects a layer on the
            combobox."""
        layer_name = self.bg_layer_box.currentText()

        # remove the old background layer, if one exists
        try:
            QgsProject.instance().removeMapLayer(self.bg_layer)
        except Exception:
            pass

        # if user wants no background layer, return without setting a new layer
        if not layer_name or layer_name == 'No reference layer':
            self.no_bg_layer_flag = True
            self.canvas.refresh()
            return
        else:
            self.bg_layer = QgsRasterLayer(
                "url=https://vm0160.kaj.pouta.csc.fi/ogiir_cache/wmts/1.0.0/" +
                "WMTSCapabilities.xml&crs=EPSG:3067&dpiMode=7&format=image/" +
                "png&layers=" + layer_name.lower() +
                "&styles=default&tileMatrixSet=GRIDI-FIN",
                'GEOCUBES BG-LAYER - TEMPORARY', 'wms')

            if self.bg_layer.isValid():
                self.no_bg_layer_flag = False
                QgsProject.instance().addMapLayer(self.bg_layer, False)
                self.bg_layer.renderer().setOpacity(
                    self.getBackgroundMapOpacity())
                self.setMapLayers()

    def setMapLayers(self):
        """Called anytime a new layer is added to the project instance.
        Setting layers to canvas decides what's shown to the user and in which
        order. If there's a background layer, it must be set before the data layer."""
        if self.no_bg_layer_flag:
            self.canvas.setLayers([self.layer])
        else:
            self.canvas.setLayers([self.bg_layer, self.layer])

        self.canvas.refresh()

    def cancel(self):
        self.close()

    def closeEvent(self, event):
        """Activated anytime Mapwindow is closed either by buttons given or
            if the user finds some other way to close the window. 
            Deletes scrap maplayers."""
        try:
            QgsProject.instance().removeMapLayer(self.layer)
            QgsProject.instance().removeMapLayer(self.bg_layer)
        except Exception:
            pass
        QMainWindow.closeEvent(self, event)