示例#1
0
class Window(QMainWindow):
    def __init__(self, app, thread, devtools, page_zoom, devtools_zoom,
                 dimensions):
        assert not devtools or devtools in {'horizontal', 'vertical'}
        super().__init__()
        if dimensions and dimensions[0] and dimensions[1]:
            self.setFixedSize(*dimensions)
        self.browser = QWebEngineView()
        self.app = app
        self.thread = thread(self.browser, parent=self)
        self.thread.screenshot_signal.connect(self.screenshot)
        self.thread.exit_signal.connect(self.exit)
        self.browser.setUrl(QUrl("http://127.0.0.1:1"))
        self.browser.page().loadFinished.connect(self.onload)
        self.browser.page().setZoomFactor(page_zoom)
        self.devtools = QWebEngineView()
        self.devtools.page().setZoomFactor(devtools_zoom)
        self.browser.page().setDevToolsPage(self.devtools.page())
        wid = QWidget(self)
        self.setCentralWidget(wid)
        if devtools == 'horizontal':
            box = QVBoxLayout()
        else:
            box = QHBoxLayout()
        box.addWidget(self.browser)
        if devtools:
            box.addWidget(self.devtools)
        wid.setLayout(box)
        self.show()
        self.thread.start()

    @pyqtSlot(int)
    def exit(self, code):
        self.thread.wait(1000 * 15)
        self.app.exit(0)

    @pyqtSlot(str)
    def screenshot(self, path):
        self.browser.grab().save(path)

    def onload(self, *a, **kw):
        self.thread.load_counter += 1
示例#2
0
class BigReport(QMdiSubWindow, form_BigReport.Ui_frmBigReport):

    # create "resized" as a signal that the window can emit
    # we respond to this signal with the form's resizeMe method below
    resized = pyqtSignal()

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.mdiParent = ""
        self.myHtml = ""
        self.resized.connect(self.resizeMe)
        self.lstDates.currentRowChanged.connect(self.FillSpeciesForDate)
        self.lstLocations.currentRowChanged.connect(
            self.FillSpeciesForLocation)
        self.lstLocations.doubleClicked.connect(
            lambda: self.CreateLocation(self.lstLocations))
        self.tblNewLocationSpecies.itemDoubleClicked.connect(
            lambda: self.CreateLocation(self.tblNewLocationSpecies))
        self.lstDates.doubleClicked.connect(
            lambda: self.CreateSpeciesList(self.lstDates))
        self.lstSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.lstSpecies))
        self.lstLocationSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.lstLocationSpecies))
        self.lstLocationUniqueSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.lstLocationUniqueSpecies))
        self.lstNewLifeSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.lstNewLifeSpecies))
        self.tblNewYearSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.tblNewYearSpecies))
        self.tblNewMonthSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.tblNewMonthSpecies))
        self.tblNewCountrySpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.tblNewCountrySpecies))
        self.tblNewStateSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.tblNewStateSpecies))
        self.tblNewCountySpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.tblNewCountySpecies))
        self.tblNewLocationSpecies.doubleClicked.connect(
            lambda: self.CreateIndividual(self.tblNewLocationSpecies))
        self.tblSpecies.doubleClicked.connect(self.TblSpeciesClicked)

        # right-click menu actions to widgets as appropriate
        self.tblSpecies.addAction(self.actionSetSpeciesFilter)
        self.tblSpecies.addAction(self.actionSetFirstDateFilter)
        self.tblSpecies.addAction(self.actionSetLastDateFilter)
        self.lstLocations.addAction(self.actionSetLocationFilter)
        self.lstDates.addAction(self.actionSetDateFilter)
        self.lstSpecies.addAction(self.actionSetSpeciesFilter)
        self.lstLocationSpecies.addAction(self.actionSetSpeciesFilter)
        self.lstLocationUniqueSpecies.addAction(self.actionSetSpeciesFilter)
        self.lstNewLifeSpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewYearSpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewYearSpecies.addAction(self.actionSetDateFilterToYear)
        self.tblNewMonthSpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewMonthSpecies.addAction(self.actionSetDateFilterToMonth)
        self.tblNewCountrySpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewCountrySpecies.addAction(self.actionSetLocationFilter)
        self.tblNewStateSpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewStateSpecies.addAction(self.actionSetLocationFilter)
        self.tblNewCountySpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewCountySpecies.addAction(self.actionSetLocationFilter)
        self.tblNewLocationSpecies.addAction(self.actionSetSpeciesFilter)
        self.tblNewLocationSpecies.addAction(self.actionSetLocationFilter)

        # connect right-click actions to methods
        self.actionSetDateFilter.triggered.connect(self.setDateFilter)
        self.actionSetFirstDateFilter.triggered.connect(
            self.setFirstDateFilter)
        self.actionSetLastDateFilter.triggered.connect(self.setLastDateFilter)
        self.actionSetSpeciesFilter.triggered.connect(self.setSpeciesFilter)
        self.actionSetCountryFilter.triggered.connect(self.setLocationFilter)
        self.actionSetStateFilter.triggered.connect(self.setLocationFilter)
        self.actionSetCountyFilter.triggered.connect(self.setLocationFilter)
        self.actionSetLocationFilter.triggered.connect(self.setLocationFilter)
        self.actionSetDateFilterToYear.triggered.connect(self.setDateFilter)
        self.actionSetDateFilterToMonth.triggered.connect(self.setDateFilter)

        self.webMap = QWebEngineView(self.tabMap)
        self.webMap.setUrl(QUrl("about:blank"))
        self.webMap.setObjectName("webMap")

        self.tabAnalysis.setCurrentIndex(0)
        self.speciesList = []
        self.filter = code_Filter.Filter()
        self.filteredSightingList = []

    def CreateLocation(self, callingWidget):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        if callingWidget.objectName() == "lstLocations":
            locationName = callingWidget.currentItem().text()
        if callingWidget.objectName() == "tblNewLocationSpecies":
            locationName = callingWidget.item(callingWidget.currentRow(),
                                              0).text()
            if callingWidget.currentColumn() != 0:
                QApplication.restoreOverrideCursor()
                return
        sub = code_Location.Location()
        sub.mdiParent = self.mdiParent
        sub.FillLocation(locationName)
        self.parent().parent().addSubWindow(sub)
        self.mdiParent.PositionChildWindow(sub, self)
        sub.show()
        QApplication.restoreOverrideCursor()

    def CreateIndividual(self, callingWidget):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        if callingWidget.objectName() in ([
                "lstSpecies", "lstLocationSpecies", "lstLocationUniqueSpecies",
                "lstNewLifeSpecies"
        ]):
            species = callingWidget.currentItem().text()
        if callingWidget.objectName() in ([
                "tblNewYearSpecies", "tblNewMonthSpecies",
                "tblNewCountrySpecies", "tblNewStateSpecies",
                "tblNewCountySpecies", "tblNewLocationSpecies"
        ]):
            species = callingWidget.item(callingWidget.currentRow(), 1).text()
            if callingWidget.currentColumn() != 1:
                QApplication.restoreOverrideCursor()
                return
        sub = code_Individual.Individual()
        sub.mdiParent = self.mdiParent
        sub.FillIndividual(species)
        self.parent().parent().addSubWindow(sub)
        self.mdiParent.PositionChildWindow(sub, self)
        sub.show()
        sub.resizeMe()
        QApplication.restoreOverrideCursor()

    def CreateSpeciesList(self, callingWidget):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        if callingWidget.objectName() == "lstDates":
            date = callingWidget.currentItem().text()

        filter = code_Filter.Filter()
        filter.setStartDate(date)
        filter.setEndDate(date)

        sub = code_Lists.Lists()
        sub.mdiParent = self.mdiParent
        sub.FillSpecies(filter)
        self.parent().parent().addSubWindow(sub)
        self.mdiParent.PositionChildWindow(sub, self)
        sub.show()
        QApplication.restoreOverrideCursor()

    def FillAnalysisReport(self, filter):
        # save filter for later use
        self.filter = filter

        # create subset of master sightings list for this filter
        self.filteredSightingList = deepcopy(
            self.mdiParent.db.GetSightings(filter))
        filteredSightingList = self.filteredSightingList

        # ****Setup Species page****
        # get species and first/last date data from db
        speciesListWithDates = self.mdiParent.db.GetSpeciesWithData(
            filter, self.filteredSightingList, "Subspecies")

        # abort if filter produced no sightings
        if len(speciesListWithDates) == 0:
            return (False)

    # set up tblSpecies column headers and widths
        self.tblSpecies.setColumnCount(4)
        self.tblSpecies.setRowCount(len(speciesListWithDates))
        self.tblSpecies.horizontalHeader().setVisible(True)
        self.tblSpecies.setHorizontalHeaderLabels(
            ['Tax', 'Species', 'First', 'Last'])
        header = self.tblSpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblSpecies.setShowGrid(False)

        # add species and dates to table row by row
        R = 0
        for species in speciesListWithDates:
            taxItem = QTableWidgetItem()
            taxItem.setData(Qt.DisplayRole, R + 1)
            speciesItem = QTableWidgetItem()
            speciesItem.setText(species[0])
            speciesItem.setData(Qt.UserRole, QVariant(species[4]))
            firstDateItem = QTableWidgetItem()
            firstDateItem.setData(Qt.DisplayRole, species[1])
            lastDateItem = QTableWidgetItem()
            lastDateItem.setData(Qt.DisplayRole, species[2])
            self.tblSpecies.setItem(R, 0, taxItem)
            self.tblSpecies.setItem(R, 1, speciesItem)
            self.tblSpecies.setItem(R, 2, firstDateItem)
            self.tblSpecies.setItem(R, 3, lastDateItem)

            self.speciesList.append(species[4])

            R = R + 1

        # ****Setup Dates page****
        listDates = self.mdiParent.db.GetDates(filter, filteredSightingList)
        self.lstDates.addItems(listDates)
        self.lstDates.setSpacing(2)
        if len(listDates) > 0:
            self.lstDates.setCurrentRow(0)
            self.FillSpeciesForDate()

        # ****Setup Locations page****
        listLocations = self.mdiParent.db.GetLocations(filter, "OnlyLocations",
                                                       filteredSightingList)
        for l in listLocations:
            self.lstLocations.addItem(l)
        self.lstLocations.setSpacing(2)
        if len(listLocations) > 0:
            self.lstLocations.setCurrentRow(0)
            self.FillSpeciesForLocation()
            self.lblLocations.setText("Locations (" + str(len(listLocations)) +
                                      ")")

        # ****Setup New Species for Dates page****
        speciesListFilter = code_Filter.Filter()
        speciesListFilter.setSpeciesList(self.speciesList)
        sightingListForSpeciesSubset = self.mdiParent.db.GetSightings(
            speciesListFilter)

        yearSpecies = self.mdiParent.db.GetNewYearSpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset)
        lifeSpecies = self.mdiParent.db.GetNewLifeSpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset)
        monthSpecies = self.mdiParent.db.GetNewMonthSpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset)

        # set up tblNewYearSpecies column headers and widths
        self.tblNewYearSpecies.setColumnCount(2)
        self.tblNewYearSpecies.setRowCount(len(yearSpecies) + 1)
        self.tblNewYearSpecies.horizontalHeader().setVisible(False)
        header = self.tblNewYearSpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblNewYearSpecies.setShowGrid(False)

        if len(yearSpecies) > 0:
            R = 1
            for ys in yearSpecies:
                yearItem = QTableWidgetItem()
                yearItem.setText(ys[0])
                newYearSpeciesItem = QTableWidgetItem()
                newYearSpeciesItem.setText(ys[1])
                self.tblNewYearSpecies.setItem(R, 0, yearItem)
                self.tblNewYearSpecies.setItem(R, 1, newYearSpeciesItem)
                R = R + 1
            self.tblNewYearSpecies.removeRow(0)

        self.lblNewYearSpecies.setText("New year species (" +
                                       str(len(yearSpecies)) + ")")

        # set up tblNewMonthSpecies column headers and widths
        self.tblNewMonthSpecies.setColumnCount(2)
        self.tblNewMonthSpecies.setRowCount(len(monthSpecies) + 1)
        self.tblNewMonthSpecies.horizontalHeader().setVisible(False)
        header = self.tblNewMonthSpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblNewMonthSpecies.setShowGrid(False)

        if len(monthSpecies) > 0:
            R = 1
            for ms in monthSpecies:
                monthItem = QTableWidgetItem()
                monthItem.setText(ms[0])
                newMonthSpeciesItem = QTableWidgetItem()
                newMonthSpeciesItem.setText(ms[1])
                self.tblNewMonthSpecies.setItem(R, 0, monthItem)
                self.tblNewMonthSpecies.setItem(R, 1, newMonthSpeciesItem)
                R = R + 1
            self.tblNewMonthSpecies.removeRow(0)

        self.lblNewMonthSpecies.setText("New month species (" +
                                        str(len(monthSpecies)) + ")")

        # set up lstNewLifeSpecies
        if len(lifeSpecies) > 0:
            self.lstNewLifeSpecies.addItems(lifeSpecies)
            self.lstNewLifeSpecies.setSpacing(2)

        self.lblNewLifeSpecies.setText("New life species (" +
                                       str(len(lifeSpecies)) + ")")

        # ****Setup new Location Species page****
        countrySpecies = self.mdiParent.db.GetNewCountrySpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset,
            self.speciesList)
        stateSpecies = self.mdiParent.db.GetNewStateSpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset,
            self.speciesList)
        countySpecies = self.mdiParent.db.GetNewCountySpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset,
            self.speciesList)
        locationSpecies = self.mdiParent.db.GetNewLocationSpecies(
            filter, filteredSightingList, sightingListForSpeciesSubset,
            self.speciesList)

        # set up tblNewCountrySpecies column headers and widths
        self.tblNewCountrySpecies.setColumnCount(2)
        self.tblNewCountrySpecies.setRowCount(len(countrySpecies))
        self.tblNewCountrySpecies.horizontalHeader().setVisible(False)
        header = self.tblNewCountrySpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblNewCountrySpecies.setShowGrid(False)

        if len(countrySpecies) > 0:
            R = 0
            for ms in countrySpecies:
                countryItem = QTableWidgetItem()
                countryItem.setText(self.mdiParent.db.GetCountryName(ms[0]))
                newCountrySpeciesItem = QTableWidgetItem()
                newCountrySpeciesItem.setText(ms[1])
                self.tblNewCountrySpecies.setItem(R, 0, countryItem)
                self.tblNewCountrySpecies.setItem(R, 1, newCountrySpeciesItem)
                R = R + 1

        self.lblNewCountrySpecies.setText("New country species (" +
                                          str(len(countrySpecies)) + ")")

        # set up tblNewStateSpecies column headers and widths
        self.tblNewStateSpecies.setColumnCount(2)
        self.tblNewStateSpecies.setRowCount(len(stateSpecies))
        self.tblNewStateSpecies.horizontalHeader().setVisible(False)
        header = self.tblNewStateSpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblNewStateSpecies.setShowGrid(False)

        if len(stateSpecies) > 0:
            R = 0
            for ms in stateSpecies:
                stateItem = QTableWidgetItem()
                stateItem.setText(self.mdiParent.db.GetStateName(ms[0]))
                newStateSpeciesItem = QTableWidgetItem()
                newStateSpeciesItem.setText(ms[1])
                self.tblNewStateSpecies.setItem(R, 0, stateItem)
                self.tblNewStateSpecies.setItem(R, 1, newStateSpeciesItem)
                R = R + 1
            self.tblNewStateSpecies.sortByColumn(0, Qt.AscendingOrder)

        self.lblNewStateSpecies.setText("New state species (" +
                                        str(len(stateSpecies)) + ")")

        # set up tblNewCountySpecies column headers and widths
        self.tblNewCountySpecies.setColumnCount(2)
        self.tblNewCountySpecies.setRowCount(len(countySpecies))
        self.tblNewCountySpecies.horizontalHeader().setVisible(False)
        header = self.tblNewCountySpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblNewCountySpecies.setShowGrid(False)

        if len(countySpecies) > 0:
            R = 0
            for ms in countySpecies:
                countyItem = QTableWidgetItem()
                countyItem.setText(ms[0])
                newCountySpeciesItem = QTableWidgetItem()
                newCountySpeciesItem.setText(ms[1])
                self.tblNewCountySpecies.setItem(R, 0, countyItem)
                self.tblNewCountySpecies.setItem(R, 1, newCountySpeciesItem)
                R = R + 1

        self.lblNewCountySpecies.setText("New county species (" +
                                         str(len(countySpecies)) + ")")

        # set up tblNewLocationSpecies column headers and widths
        self.tblNewLocationSpecies.setColumnCount(2)
        self.tblNewLocationSpecies.setRowCount(len(locationSpecies))
        self.tblNewLocationSpecies.horizontalHeader().setVisible(False)
        header = self.tblNewLocationSpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblNewLocationSpecies.setShowGrid(False)

        if len(locationSpecies) > 0:
            R = 0
            for ms in locationSpecies:
                locationItem = QTableWidgetItem()
                locationItem.setText(ms[0])
                newLocationSpeciesItem = QTableWidgetItem()
                newLocationSpeciesItem.setText(ms[1])
                self.tblNewLocationSpecies.setItem(R, 0, locationItem)
                self.tblNewLocationSpecies.setItem(R, 1,
                                                   newLocationSpeciesItem)
                R = R + 1

        self.lblNewLocationSpecies.setText("New location species (" +
                                           str(len(locationSpecies)) + ")")

        # ****Setup window's main labels****
        # set main species seen lable text
        count = self.mdiParent.db.CountSpecies(self.speciesList)

        self.lblTopSpeciesSeen.setText("Species seen: " + str(count))

        # set main location label, using "All Locations" if none others are selected
        self.mdiParent.SetChildDetailsLabels(self, filter)

        self.setWindowTitle(self.lblLocation.text() + ": " +
                            self.lblDateRange.text())

        if self.lblDetails.text() != "":
            self.lblDetails.setVisible(True)
        else:
            self.lblDetails.setVisible(False)

        self.resizeMe()
        self.scaleMe()

        return (True)

    def FillSpeciesForDate(self):
        # create temporary filter for query with nothing but needed date
        self.lstSpecies.clear()
        date = self.lstDates.currentItem().text()

        tempFilter = code_Filter.Filter()

        tempFilter.setStartDate(date)
        tempFilter.setEndDate(date)

        speciesList = self.mdiParent.db.GetSpecies(tempFilter,
                                                   self.filteredSightingList)

        self.lstSpecies.addItems(speciesList)
        self.lstSpecies.setSpacing(2)

        self.lblSpeciesSeen.setText("Species seen on selected date (" +
                                    str(len(speciesList)) + "):")

    def FillMap(self):

        coordinatesDict = defaultdict()
        mapWidth = self.width() - 20
        mapHeight = self.height() - self.lblLocation.height() - (
            self.lblDateRange.height() * 7.5)
        self.webMap.setGeometry(5, 5, mapWidth, mapHeight)

        for l in range(self.lstLocations.count()):
            locationName = self.lstLocations.item(l).text()
            coordinates = self.mdiParent.db.GetLocationCoordinates(
                locationName)
            coordinatesDict[locationName] = coordinates

        thisMap = code_MapHtml.MapHtml()
        thisMap.mapHeight = mapHeight - 20
        thisMap.mapWidth = mapWidth - 20
        thisMap.coordinatesDict = coordinatesDict

        # save mapHtml in object's variable so we can reload it later
        self.mapHtml = thisMap.html()

        # pass the mapHtml we created to the QWebView widget for display
        self.webMap.setHtml(self.mapHtml)

    def FillSpeciesForLocation(self):
        # create temporary filter for query with nothing but needed location
        location = self.lstLocations.currentItem().text()

        tempFilter = code_Filter.Filter()
        tempFilter.setLocationType("Location")
        tempFilter.setLocationName(location)

        speciesList = self.mdiParent.db.GetSpecies(tempFilter,
                                                   self.filteredSightingList)

        self.lstLocationSpecies.clear()
        self.lstLocationSpecies.addItems(speciesList)
        self.lstLocationSpecies.setSpacing(2)

        uniqueSpecies = self.mdiParent.db.GetUniqueSpeciesForLocation(
            self.filter, location, speciesList, self.filteredSightingList)

        self.lstLocationUniqueSpecies.clear()
        self.lstLocationUniqueSpecies.addItems(uniqueSpecies)
        self.lstLocationUniqueSpecies.setSpacing(2)

        self.lblLocationSpecies.setText("Species at selected location (" +
                                        str(len(speciesList)) + ")")
        self.lblLocationUniqueSpecies.setText(
            "Species seen ONLY at selected location (" +
            str(len(uniqueSpecies)) + ")")

    def TblSpeciesClicked(self):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        currentColumn = self.tblSpecies.currentColumn()
        currentRow = self.tblSpecies.currentRow()

        tempFilter = deepcopy(self.filter)

        if currentColumn == 0:
            # the taxonomy order column was clicked, so abort. We won't create a report.
            # turn off the hourglass cursor before exiting
            QApplication.restoreOverrideCursor()
            return

        if currentColumn == 1:
            # species column has been clicked so create individual window for that species
            species = self.tblSpecies.item(currentRow, 1).data(Qt.UserRole)
            sub = code_Individual.Individual()
            sub.mdiParent = self.mdiParent
            sub.FillIndividual(species)
            self.parent().parent().addSubWindow(sub)
            self.mdiParent.PositionChildWindow(sub, self)
            sub.show()
            sub.resizeMe()

        if currentColumn > 1:
            # date column has been clicked so create species list frame for that dateArray
            # use same start and end date for new filter to show just the single day
            date = self.tblSpecies.item(currentRow, currentColumn).text()
            tempFilter.setStartDate(date)
            tempFilter.setEndDate(date)

            sub = code_Lists.Lists()
            sub.mdiParent = self.mdiParent
            sub.FillSpecies(tempFilter)
            self.parent().parent().addSubWindow(sub)
            self.mdiParent.PositionChildWindow(sub, self)
            sub.show()
            sub.resizeMe()

        QApplication.restoreOverrideCursor()

    def html(self):

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        # create start to basic html format
        html = """
            <!DOCTYPE html>
            <html>
            <head>
            </head>
            <style>
            * {
                font-size: 75%;
                font-family: "Times New Roman", Times, serif;
                }
            th {
                text-align: left;
            }
            </style>
            <body>
            """

        # add title information
        html = html + ("<H1>" + self.lblLocation.text() + "</H1>")

        html = html + ("<H3>" + self.lblDateRange.text() + "</H3>")

        html = html + ("<H3>" + self.lblDetails.text() + "</H3>")

        html = html + ("<H3>" + self.lblLocationsVisited.text() + "</H3>")

        html = html + ("<H3>" + self.lblTopSpeciesSeen.text() + "</H3>")

        # grab the map image from the map tap
        # process it into a byte array and encode it
        # so we can insert it inline into the html
        myPixmap = self.webMap.grab()
        myPixmap = myPixmap.scaledToWidth(600, Qt.SmoothTransformation)

        myByteArray = QByteArray()
        myBuffer = QBuffer(myByteArray)
        myBuffer.open(QIODevice.WriteOnly)
        myPixmap.save(myBuffer, "PNG")

        encodedImage = base64.b64encode(myByteArray)

        html = html + ("""
        <img src="data:image/png;base64, 
        """)

        html = html + str(encodedImage)[1:]

        html = html + ("""        
        "  />
        """)

        html = html + ("<H4>" + "Species" + "</H4>")

        html = html + ("<font size='2'>" + "<table width='100%'>" + " <tr>")

        html = html + ("<th>" + "Species" + "</th>" + "<th>" + "First" +
                       "</th> " + "<th></th> " + "<th>" + "Latest" + "</th>" +
                       "</tr>")

        for r in range(self.tblSpecies.rowCount()):
            html = html + (
                "<tr>" + "<td>" + self.tblSpecies.item(r, 1).text() + "</td>" +
                "<td>" + self.tblSpecies.item(r, 2).text() + "</td>" + "<td>" +
                "  " + "</td>" + "<td>" + self.tblSpecies.item(r, 3).text() +
                "</td>" + "</tr>")
        html = html + "</table>"

        html = html + ("<H4>" + "Dates" + "</H4>")

        html = html + ("<font size='2'>" + "<p>")

        # loopthrough the dates listed in lstDates
        # create a filter unique to each date
        # and get species for that date
        for r in range(self.lstDates.count()):
            html = html + ("<b>" + self.lstDates.item(r).text() + "</b>")

            # create filter set to our current location
            filter = deepcopy(self.filter)
            filter.setStartDate(self.lstDates.item(r).text())
            filter.setEndDate(self.lstDates.item(r).text())

            species = self.mdiParent.db.GetSpecies(filter)

            html = html + ("<br>" + "<table width='100%'>" + "<tr>")

            # set up counter R to start a new row after listing each 3 species
            R = 1
            for s in species:
                html = html + ("<td>" + s + "</td>")
                if R == 3:
                    html = html + ("</tr>" + "<tr>")
                    R = 0
                R = R + 1

            html = html + ("<br>" + "<br>" + "</table>")

        html = html + (
            "<H4>" + "Locations" + "</H4>" + "<p>" +
            "Asterisks indicate species seen only at listed location.")

        # loopthrough the locations listed in lstLocations
        # create a filter unique to each location
        # and get species for that date
        for r in range(self.lstLocations.count()):
            html = html + ("<b>" + self.lstLocations.item(r).text() + "</b>")

            # create filter set to our current location
            filter = deepcopy(self.filter)
            filter.setLocationType("Location")
            filter.setLocationName(self.lstLocations.item(r).text())

            species = self.mdiParent.db.GetSpecies(filter)

            uniqueSpecies = self.mdiParent.db.GetUniqueSpeciesForLocation(
                self.filter,
                self.lstLocations.item(r).text(), species,
                self.filteredSightingList)

            html = html + ("<br>" + "<table width='100%'>" + "<tr>")

            # set up counter R to start a new row after listing each 3 species
            R = 1
            for s in species:

                if s in uniqueSpecies:
                    s = s + "*"

                html = html + ("<td>" + s + "</td>")
                if R == 3:
                    html = html + ("</tr>" + "<tr>")
                    R = 0
                R = R + 1

            html = html + ("<br>" + "<br>" + "</table>")

        html = html + ("<p>" + "<H4>" + "New Life Species" + "</H4>" + "<p>" +
                       "<table width='100%'>"
                       "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.lstNewLifeSpecies.count() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:

            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.lstNewLifeSpecies.count()):

                html = html + ("<td>" + self.lstNewLifeSpecies.item(r).text() +
                               "</td>")

                if R == 3:
                    html = html + ("</tr>" + "<tr>")
                    R = 0

                R = R + 1

            html = html + ("<br>" + "<br>" + "</table>")

        # set up New Year Species
        html = html + ("<p>" + "<H4>" + "New Year Species" + "</H4>" + "<p>" +
                       "<table width='100%'>" + "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.tblNewYearSpecies.rowCount() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:
            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.tblNewYearSpecies.rowCount()):

                html = html + (
                    "<td>" + self.tblNewYearSpecies.item(r, 1).text() + " (" +
                    self.tblNewYearSpecies.item(r, 0).text() + ")" + "</td>")

                if R == 3:
                    html = html + ("</tr>" "<tr>")
                    R = 0

                R = R + 1

            html = html + ("</tr>" + "</table>")

        # set up New Month Species
        html = html + ("<p>" + "<H4>" + "New Month Species" + "</H4>" + "<p>" +
                       "<table width='100%'>" + "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.tblNewMonthSpecies.rowCount() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:

            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.tblNewMonthSpecies.rowCount()):

                html = html + (
                    "<td>" + self.tblNewMonthSpecies.item(r, 1).text() + " (" +
                    self.tblNewMonthSpecies.item(r, 0).text() + ")" + "</td>")

                if R == 3:
                    html = html + ("</tr>" "<tr>")
                    R = 0

                R = R + 1

            html = html + ("</tr>" + "</table>")

        # set up New Country Species
        html = html + ("<p>" + "<H4>" + "New Country Species" + "</H4>" +
                       "<p>" + "<table width='100%'>" + "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.tblNewCountrySpecies.rowCount() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:

            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.tblNewCountrySpecies.rowCount()):

                html = html + ("<td>" + self.tblNewCountrySpecies.item(
                    r, 1).text() + " (" + self.tblNewCountrySpecies.item(
                        r, 0).text() + ")" + "</td>")

                if R == 2:
                    html = html + ("</tr>" "<tr>")
                    R = 0

                R = R + 1

            html = html + ("</tr>" + "</table>")

        html = html + ("<font size>" + "</body>" + "</html>")

        # set up New State Species
        html = html + ("<p>" + "<H4>" + "New State Species" + "</H4>" + "<p>" +
                       "<table width='100%'>" + "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.tblNewStateSpecies.rowCount() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:

            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.tblNewStateSpecies.rowCount()):

                html = html + (
                    "<td>" + self.tblNewStateSpecies.item(r, 1).text() + " (" +
                    self.tblNewStateSpecies.item(r, 0).text() + ")" + "</td>")

                if R == 2:
                    html = html + ("</tr>" "<tr>")
                    R = 0

                R = R + 1

            html = html + ("</tr>" + "</table>")

        # set up New County Species
        html = html + ("<p>" + "<H4>" + "New County Species" + "</H4>" +
                       "<p>" + "<table width='100%'>" + "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.tblNewCountySpecies.rowCount() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:

            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.tblNewCountySpecies.rowCount()):

                html = html + ("<td>" + self.tblNewCountySpecies.item(
                    r, 1).text() + " (" + self.tblNewCountySpecies.item(
                        r, 0).text() + ")" + "</td>")

                if R == 2:
                    html = html + ("</tr>" "<tr>")
                    R = 0

                R = R + 1

            html = html + ("</tr>" + "</table>")

        # set up New Location Species
        html = html + ("<p>" + "<H4>" + "New Location Species" + "</H4>" +
                       "<p>" + "<table width='100%'>" + "<tr>")

        # set up counter R to start a new row after listing each 3 species
        R = 1

        if self.tblNewLocationSpecies.rowCount() == 0:
            html = html + ("<td>" + "None" + "</td>")

        else:

            # loopthrough the species listed in lstNewLifeSpecies
            for r in range(self.tblNewLocationSpecies.rowCount()):

                html = html + ("<td>" + self.tblNewLocationSpecies.item(
                    r, 1).text() + " (" + self.tblNewLocationSpecies.item(
                        r, 0).text() + ")" + "</td>")

                if R == 2:
                    html = html + ("</tr>" "<tr>")
                    R = 0

                R = R + 1

            html = html + ("</tr>" + "</table>")

        html = html + ("<font size>" + "</body>" + "</html>")

        QApplication.restoreOverrideCursor()

        return (html)

    def setDateFilter(self):
        # get location name and type from focus widget. Varies for widgets.
        if self.focusWidget().objectName() == "lstDates":
            date = self.focusWidget().currentItem().text()
            self.mdiParent.setDateFilter(date)

        if self.focusWidget().objectName() == "tblNewYearSpecies":
            date = self.focusWidget().item(self.focusWidget().currentRow(),
                                           0).text()
            startDate = date + "-01-01"
            endDate = date + "-12-31"
            self.mdiParent.setDateFilter(startDate, endDate)

        if self.focusWidget().objectName() == "tblNewMonthSpecies":
            month = self.focusWidget().item(self.focusWidget().currentRow(),
                                            0).text()
            self.mdiParent.setSeasonalRangeFilter(month)

    def setFirstDateFilter(self):
        # get location name and type from focus widget. Varies for tables.
        if self.focusWidget().objectName() == "tblSpecies":
            date = self.focusWidget().item(self.focusWidget().currentRow(),
                                           2).text()
            self.mdiParent.setDateFilter(date)

    def setLastDateFilter(self):
        # get location name and type from focus widget. Varies for tables.
        if self.focusWidget().objectName() == "tblSpecies":
            date = self.focusWidget().item(self.focusWidget().currentRow(),
                                           3).text()
            self.mdiParent.setDateFilter(date)

    def setLocationFilter(self):

        # get location name and type from focus widget. Varies for tables.
        if self.focusWidget().objectName() == "tblNewCountrySpecies":
            country = self.focusWidget().item(self.focusWidget().currentRow(),
                                              0).text()
            self.mdiParent.setCountryFilter(country)

        if self.focusWidget().objectName() == "tblNewStateSpecies":
            state = self.focusWidget().item(self.focusWidget().currentRow(),
                                            0).text()
            self.mdiParent.setStateFilter(state)

        if self.focusWidget().objectName() == "tblNewCountySpecies":
            county = self.focusWidget().item(self.focusWidget().currentRow(),
                                             0).text()
            self.mdiParent.setCountyFilter(county)

        if self.focusWidget().objectName() == "tblNewLocationSpecies":
            location = self.focusWidget().item(self.focusWidget().currentRow(),
                                               0).text()
            self.mdiParent.setLocationFilter(location)

        if self.focusWidget().objectName() == "lstLocations":
            location = self.focusWidget().currentItem().text()
            self.mdiParent.setLocationFilter(location)

    def setSpeciesFilter(self):

        # get species name from focus widget. Getting the species name is different for tables than for lists.
        if self.focusWidget().objectName() in ([
                "tblSpecies", "tblNewYearSpecies", "tblNewMonthSpecies",
                "tblNewCountrySpecies", "tblNewStateSpecies",
                "tblNewCountySpecies", "tblNewLocationSpecies"
        ]):
            species = self.focusWidget().item(self.focusWidget().currentRow(),
                                              1).text()

        if self.focusWidget().objectName() in ([
                "lstSpecies", "lstLocationSpecies", "lstLocationUniqueSpecies",
                "lstNewLifeSpecies"
        ]):
            species = self.focusWidget().currentItem().text()

        self.mdiParent.setSpeciesFilter(species)

    def resizeEvent(self, event):
        #routine to handle events on objects, like clicks, lost focus, gained forcus, etc.
        self.resized.emit()
        return super(self.__class__, self).resizeEvent(event)

    def resizeMe(self):

        windowWidth = self.frameGeometry().width()
        windowHeight = self.frameGeometry().height()
        self.scrollArea.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        self.FillMap()

    def scaleMe(self):

        scaleFactor = self.mdiParent.scaleFactor
        windowWidth = 1100 * scaleFactor
        windowHeight = 625 * scaleFactor
        self.resize(windowWidth, windowHeight)

        fontSize = self.mdiParent.fontSize
        scaleFactor = self.mdiParent.scaleFactor
        #scale the font for all widgets in window
        for w in self.scrollArea.children():
            try:
                w.setFont(QFont("Helvetica", fontSize))
            except:
                pass

        self.lblLocation.setFont(QFont("Helvetica", floor(fontSize * 1.4)))
        self.lblLocation.setStyleSheet("QLabel { font: bold }")
        self.lblDateRange.setFont(QFont("Helvetica", floor(fontSize * 1.2)))
        self.lblDateRange.setStyleSheet("QLabel { font: bold }")
        self.lblDetails.setFont(QFont("Helvetica", floor(fontSize * 1.2)))
        self.lblDetails.setStyleSheet("QLabel { font: bold }")

        metrics = self.tblSpecies.fontMetrics()
        textHeight = metrics.boundingRect("A").height()
        textWidth = metrics.boundingRect("Dummy Country").width()

        for t in ([
                self.tblNewYearSpecies, self.tblNewMonthSpecies,
                self.tblNewCountrySpecies, self.tblNewStateSpecies,
                self.tblNewCountySpecies
        ]):
            header = t.horizontalHeader()
            header.resizeSection(0, floor(1.2 * textWidth))
            for r in range(t.rowCount()):
                t.setRowHeight(r, textHeight * 1.1)

        # format tblSpecies, which is laid out differently from the other tables
        dateWidth = metrics.boundingRect("2222-22-22").width()
        header = self.tblSpecies.horizontalHeader()
        header.resizeSection(2, floor(1.5 * dateWidth))
        header.resizeSection(3, floor(1.5 * dateWidth))
        for r in range(self.tblSpecies.rowCount()):
            self.tblSpecies.setRowHeight(r, textHeight * 1.1)

        # format tblNewLocationSpecies, which needs wider location column
        header = self.tblNewLocationSpecies.horizontalHeader()
        header.resizeSection(0, floor(4 * textWidth))
        for r in range(self.tblNewLocationSpecies.rowCount()):
            t.setRowHeight(r, textHeight * 1.1)
示例#3
0
class Web(QMdiSubWindow, form_Web.Ui_frmWeb):

    resized = pyqtSignal()

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.mdiParent = ""
        self.setWindowIcon(QIcon(QPixmap(1, 1)))
        self.contentType = "Web Page"
        self.resized.connect(self.resizeMe)
        self.webView = QWebEngineView(self)
        self.webView.setObjectName("webView")
        self.webView.loadFinished.connect(self.LoadFinished)
        self.webView.loadProgress.connect(self.showLoadProgress)
        self.title = ""

    def resizeEvent(self, event):
        #routine to handle events on objects, like clicks, lost focus, gained forcus, etc.
        self.resized.emit()
        return super(self.__class__, self).resizeEvent(event)

    def resizeMe(self):

        windowWidth = self.frameGeometry().width()
        windowHeight = self.frameGeometry().height()
        self.scrollArea.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        self.webView.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        if self.contentType == "Map":
            self.webView.adjustSize()
            self.LoadLocationsMap(self.filter)

    def html(self):

        #         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        html = """
            <!DOCTYPE html>
            <html>
            <head>
            </head>
            <body>
            """

        myPixmap = self.webView.grab()
        myPixmap = myPixmap.scaledToWidth(600, Qt.SmoothTransformation)

        myByteArray = QByteArray()
        myBuffer = QBuffer(myByteArray)
        myBuffer.open(QIODevice.WriteOnly)
        myPixmap.save(myBuffer, "PNG")

        encodedImage = base64.b64encode(myByteArray)

        html = html + ("""
        <img src="data:image/png;base64, 
        """)

        html = html + str(encodedImage)[1:]

        html = html + ("""
            <font size>
            </body>
            </html>
            """)

        #         QApplication.restoreOverrideCursor()

        return (html)

    def scaleMe(self):

        fontSize = self.mdiParent.fontSize
        settings = QWebEngineSettings.globalSettings()
        settings.setFontSize(QWebEngineSettings.DefaultFontSize,
                             floor(fontSize * 1.6))

        scaleFactor = self.mdiParent.scaleFactor
        windowWidth = 800 * scaleFactor
        windowHeight = 580 * scaleFactor
        self.resize(windowWidth, windowHeight)

    def loadAboutYearbird(self):

        self.title = "About Yearbird"

        self.contentType = "About"

        html = """

            <!DOCTYPE html>
            <html>
            <head>
            <title>About Yearbird</title>
            <meta charset="utf-8">
            <style>
            * {
                font-family: "Times New Roman", Times, serif;
                }
            </style>
            </head>
            <body>
            <h1>
            Yearbird
            </h1>
            """

        html = html + "<h3>Version: " + self.mdiParent.versionNumber + "</h3>"
        html = html + "<h3>Date: " + self.mdiParent.versionDate + "</h3>"

        html = html + """
            <font size='4'>            
            <b>
            Yearbird is a free, open-source application to analyze personal eBird sightings. 
            <br><br>
            Created by Richard Trinkner.             
            </b>
            <h3>
            Licenses
            </h3>
            <p>
            <ul>
            <li>
            Yearbird is licensed under the GNU General Public License, version 3.
            </li>
            <li>
            PyQt, by Riverbank Computing, is licensed under the GNU General Public License.
            </li>
            <li>
            Map base layers are retrieved from Google.
            </li>            
            <li>
            Map layers that include points and location labels are generated using OpenLayers. OpenLayers is free, Open Source JavaScript, released under the 2-clause BSD License (also known as the FreeBSD).
            </li>
            <li>
            PyInstaller, by the PyInstaller Development Team, Giovanni Bajo and McMillan Enterprise, is licensed under the GPL General Public License.
            </li>
            </ul>
            </font size>
            </body>
            </html>        
            """

        self.webView.setHtml(html)

        self.setWindowTitle("About Yearbird")

        return (True)

    def LoadWebPage(self, url):
        #         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.webView.load(QUrl(url))
        self.resizeMe()
        self.scaleMe()

    def LoadFinished(self):
        #         QApplication.restoreOverrideCursor()
        return ()

    def LoadLocationsMap(self, filter):

        self.title = "Location Map"

        coordinatesDict = defaultdict()
        mapWidth = self.frameGeometry().width() - 10
        mapHeight = self.frameGeometry().height() - 35
        self.scrollArea.setGeometry(5, 27, mapWidth + 2, mapHeight + 2)
        self.webView.setGeometry(5, 27, mapWidth + 2, mapHeight + 2)
        self.contentType = "Map"
        self.filter = filter

        locations = self.mdiParent.db.GetLocations(filter)

        if len(locations) == 0:
            return (False)

        for l in locations:
            coordinates = self.mdiParent.db.GetLocationCoordinates(l)
            coordinatesDict[l] = coordinates

        thisMap = code_MapHtml.MapHtml()
        thisMap.mapHeight = mapHeight
        thisMap.mapWidth = mapWidth
        thisMap.coordinatesDict = coordinatesDict

        html = thisMap.html()

        self.webView.setHtml(html)

        # set window title to descriptive map name

        locationName = filter.getLocationName(
        )  # str   name of region or location  or ""
        locationType = filter.getLocationType()
        startDate = filter.getStartDate()  # str   format yyyy-mm-dd  or ""
        endDate = filter.getEndDate()  # str   format yyyy-mm-dd  or ""
        startSeasonalMonth = filter.getStartSeasonalMonth()  # str   format mm
        startSeasonalDay = filter.getStartSeasonalDay()  # str   format dd
        endSeasonalMonth = filter.getEndSeasonalMonth()  # str   format  dd
        endSeasonalDay = filter.getEndSeasonalDay()  # str   format dd
        speciesName = filter.getSpeciesName()  # str   speciesName
        family = filter.getFamily()  # str family name

        # set main location label, using "All Locations" if none others are selected

        windowTitle = speciesName

        if locationName != "":
            if locationType == "Country":
                locationName = self.mdiParent.db.GetCountryName(locationName)
            if locationType == "State":
                locationName = self.mdiParent.db.GetStateName(locationName)
            windowTitle = windowTitle + "; " + locationName

        if startDate != "":
            dateTitle = startDate + " to " + endDate
            if startDate == endDate:
                dateTitle = startDate
            windowTitle = windowTitle + "; " + dateTitle

        # set main seasonal range label, if specified
        if not ((startSeasonalMonth == "") or (endSeasonalMonth == "")):
            monthRange = [
                "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
                "Oct", "Nov", "Dec"
            ]
            rangeTitle = monthRange[
                int(startSeasonalMonth) -
                1] + "-" + startSeasonalDay + " to " + monthRange[
                    int(endSeasonalMonth) - 1] + "-" + endSeasonalDay
            windowTitle = windowTitle + "; " + rangeTitle

        if family != "":
            family = family[0:family.index("(") - 1]
            windowTitle = windowTitle + "; " + family

        if windowTitle == "":
            windowTitle = "All species, locations, dates and families"

        #remove leading "; " if needed
        if windowTitle[0:2] == "; ":
            windowTitle = windowTitle[2:]

        # add location count to window title
        windowTitle = "Map: " + windowTitle + " (" + str(
            len(coordinatesDict.keys())) + ")"

        self.setWindowTitle(windowTitle)
        self.title = windowTitle

        icon = QIcon()
        icon.addPixmap(QPixmap(":/icon_map.png"), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)

        return (True)

    def loadChoroplethUSStates(self, filter):

        from copy import deepcopy
        import folium
        from branca.colormap import LinearColormap

        self.title = "US States Choropleth"

        self.filter = deepcopy(filter)

        # find states in filtered sightings
        stateDict = defaultdict()

        minimalSightingList = self.mdiParent.db.GetMinimalFilteredSightingsList(
            filter)

        for s in minimalSightingList:

            # Consider only full species, not slash or spuh or hybrid entries
            commonName = s["commonName"]
            if "/" not in commonName and "sp." not in commonName and " x " not in commonName:

                if self.mdiParent.db.TestSighting(s, filter):

                    if s["state"][3:5] not in stateDict.keys():
                        stateDict[s["state"][3:5]] = [s]
                    else:
                        stateDict[s["state"][3:5]].append(s)

        # check if no sightings were found. Return false if none found. Abort and display message.
        if len(stateDict) == 0:
            return (False)

        stateTotals = defaultdict()
        largestTotal = 0
        for state in stateDict.keys():
            stateSpecies = set()
            for s in stateDict[state]:
                stateSpecies.add(s["commonName"])
            stateTotals[state] = len(stateSpecies)
            if len(stateSpecies) > largestTotal:
                largestTotal = len(stateSpecies)

        # Load the shape of the zone (US counties)
        geo_file = self.mdiParent.db.state_geo

        #add the state values to the geojson so we can access them for tooltips
        for f in geo_file["features"]:
            if f["id"] in stateTotals.keys():
                f["properties"]["speciesTotal"] = stateTotals[f["id"]]
            else:
                f["properties"]["speciesTotal"] = 0
                stateTotals[f["id"]] = 0

        #create color range for map, using the maximum state value found above
        colormap = LinearColormap(
            colors=[(255, 240, 227), (255, 119, 0)],
            index=[0, round(largestTotal * .75)],
            vmin=0,
            vmax=largestTotal,
        )

        # Initialize the folium map
        state_map = folium.Map(location=[39.5, -98.3], zoom_start=4)

        # Configure the chloropleth layer and add to map
        folium.GeoJson(geo_file,
                       style_function=lambda feature: {
                           'fillColor':
                           'rgb(240, 240, 240)' if stateTotals[feature['id']]
                           == 0 else colormap(stateTotals[feature['id']]),
                           'color':
                           'black',
                           'weight':
                           .2,
                           'fillOpacity':
                           .8,
                       },
                       tooltip=folium.features.GeoJsonTooltip(
                           fields=['name', 'speciesTotal'],
                           aliases=["State", "Species"])).add_to(state_map)

        # make the layer control box visible
        folium.LayerControl().add_to(state_map)

        # get the html string from the map
        html = state_map.get_root().render()

        self.webView.setHtml(html)

        return (True)

    def loadChoroplethUSCounties(self, filter):

        from copy import deepcopy
        import folium
        from branca.colormap import LinearColormap

        self.title = "US Counties Choropleth"

        self.filter = deepcopy(filter)

        # find states in filtered sightings
        countyDict = defaultdict()

        minimalSightingList = self.mdiParent.db.GetMinimalFilteredSightingsList(
            filter)

        for s in minimalSightingList:

            # only count US sightings since we're only showing the US choropleth
            if s["country"] == "US" and s["state"] not in ["US-HI", "US-AK"]:

                #only use sightings that have a county code assigned to them
                # some US sightings won't have them, such as if a checklist is for
                # an entire state, not localized down to a location or county
                if "countyCode" in s.keys():

                    # Consider only full species, not slash or spuh or hybrid entries
                    commonName = s["commonName"]
                    if "/" not in commonName and "sp." not in commonName and " x " not in commonName:

                        if self.mdiParent.db.TestSighting(s, filter):

                            if s["countyCode"] not in countyDict.keys():
                                countyDict[s["countyCode"]] = [s]
                            else:
                                countyDict[s["countyCode"]].append(s)

        # check if no sightings were found. Return false if none found. Abort and display message.
        if len(countyDict) == 0:
            return (False)

        countyTotals = defaultdict()
        largestTotal = 0
        for county in countyDict.keys():
            countySpecies = set()
            for s in countyDict[county]:
                countySpecies.add(s["commonName"])
            countyTotals[county] = len(countySpecies)
            if len(countySpecies) > largestTotal:
                largestTotal = len(countySpecies)

        # Load the shape of the zone (US counties)
        geo_file = self.mdiParent.db.county_geo

        #add the county values to the geojson so we can access them for tooltips
        for f in geo_file["features"]:
            if f["id"] in countyTotals.keys():
                f["properties"]["speciesTotal"] = countyTotals[f["id"]]
            else:
                f["properties"]["speciesTotal"] = 0
                countyTotals[f["id"]] = 0

        #create color range for map, using the maximum state value found above
        colormap = LinearColormap(
            colors=[(255, 240, 227), (255, 119, 0)],
            index=[0, round(largestTotal * .75)],
            vmin=0,
            vmax=largestTotal,
        )

        # Initialize the folium map
        county_map = folium.Map(location=[39.5, -98.3], zoom_start=4)

        # Configure the chloropleth layer and add to map
        folium.GeoJson(geo_file,
                       style_function=lambda feature: {
                           'fillColor':
                           'rgb(240, 240, 240)' if countyTotals[feature['id']]
                           == 0 else colormap(countyTotals[feature['id']]),
                           'color':
                           'black',
                           'weight':
                           1,
                           'fillOpacity':
                           .8,
                           'nan_fill_color':
                           'white'
                       },
                       tooltip=folium.features.GeoJsonTooltip(
                           fields=['name', 'state', 'speciesTotal'],
                           aliases=["County", "State",
                                    "Species"])).add_to(county_map)

        # make the layer control box visible
        folium.LayerControl().add_to(county_map)

        # get the html string from the map
        html = county_map.get_root().render()

        self.webView.setHtml(html)

        return (True)

    def loadChoroplethWorldCountries(self, filter):

        from copy import deepcopy
        import folium
        from branca.colormap import LinearColormap

        self.title = "World Choropleth"

        self.filter = deepcopy(filter)

        # find states in filtered sightings
        countryDict = defaultdict()

        minimalSightingList = self.mdiParent.db.GetMinimalFilteredSightingsList(
            filter)

        for s in minimalSightingList:

            # Consider only full species, not slash or spuh or hybrid entries
            commonName = s["commonName"]
            if "/" not in commonName and "sp." not in commonName and " x " not in commonName:

                if self.mdiParent.db.TestSighting(s, filter):

                    if s["country"] not in countryDict.keys():
                        countryDict[s["country"]] = [s]
                    else:
                        countryDict[s["country"]].append(s)

        # check if no sightings were found. Return false if none found. Abort and display message.
        if len(countryDict) == 0:
            return (False)

        countryTotals = defaultdict()
        largestTotal = 0
        for country in countryDict.keys():
            countrySpecies = set()
            for s in countryDict[country]:
                countrySpecies.add(s["commonName"])
            countryTotals[country] = len(countrySpecies)
            if len(countrySpecies) > largestTotal:
                largestTotal = len(countrySpecies)

        # Load the shape of the zone (US counties)
        geo_file = self.mdiParent.db.country_geo

        #add the country values to the geojson so we can access them for tooltips
        for f in geo_file["features"]:
            if f["id"] in countryTotals.keys():
                f["properties"]["speciesTotal"] = countryTotals[f["id"]]
            else:
                f["properties"]["speciesTotal"] = 0
                countryTotals[f["id"]] = 0

        #create color range for map, using the maximum country value found above
        colormap = LinearColormap(
            colors=[(255, 240, 227), (255, 119, 0)],
            index=[0, round(largestTotal * .75)],
            vmin=0,
            vmax=largestTotal,
        )

        # Initialize the folium map
        choro_map = folium.Map(location=[1, 1], zoom_start=1)

        # Configure the chloropleth layer and add to map
        folium.GeoJson(geo_file,
                       style_function=lambda feature: {
                           'fillColor':
                           'rgb(240, 240, 240)' if countryTotals[feature['id']]
                           == 0 else colormap(countryTotals[feature['id']]),
                           'color':
                           'black',
                           'weight':
                           1,
                           'fillOpacity':
                           .8,
                           'nan_fill_color':
                           'white'
                       },
                       tooltip=folium.features.GeoJsonTooltip(
                           fields=['name', 'speciesTotal'],
                           aliases=["Country", "Species"])).add_to(choro_map)

        # make the layer control box visible
        folium.LayerControl().add_to(choro_map)

        # get the html string from the map
        html = choro_map.get_root().render()

        self.webView.setHtml(html)

        return (True)

    def loadChoroplethWorldSubregion1(self, filter):

        return ()

    def showLoadProgress(self, percent):

        if percent < 100:
            self.setWindowTitle(self.title + ": " + str(percent) + "%")
        else:
            self.setWindowTitle(self.title)
示例#4
0
class Web(QMdiSubWindow, form_Web.Ui_frmWeb):

    resized = pyqtSignal()

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.mdiParent = ""
        self.setWindowIcon(QIcon(QPixmap(1, 1)))
        self.contentType = "Web Page"
        self.resized.connect(self.resizeMe)
        self.webView = QWebEngineView(self)
        self.webView.setObjectName("webView")
        self.webView.loadFinished.connect(self.LoadFinished)
        self.webView.loadProgress.connect(self.showLoadProgress)
        self.title = ""

    def resizeEvent(self, event):
        #routine to handle events on objects, like clicks, lost focus, gained forcus, etc.
        self.resized.emit()
        return super(self.__class__, self).resizeEvent(event)

    def resizeMe(self):

        windowWidth = self.frameGeometry().width()
        windowHeight = self.frameGeometry().height()
        self.scrollArea.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        self.webView.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        if self.contentType == "Map":
            self.webView.adjustSize()
            self.LoadLocationsMap(self.filter)

    def html(self):

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        html = """
            <!DOCTYPE html>
            <html>
            <head>
            </head>
            <body>
            """

        myPixmap = self.webView.grab()
        myPixmap = myPixmap.scaledToWidth(600, Qt.SmoothTransformation)

        myByteArray = QByteArray()
        myBuffer = QBuffer(myByteArray)
        myBuffer.open(QIODevice.WriteOnly)
        myPixmap.save(myBuffer, "PNG")

        encodedImage = base64.b64encode(myByteArray)

        html = html + ("""
        <img src="data:image/png;base64, 
        """)

        html = html + str(encodedImage)[1:]

        html = html + ("""
            <font size>
            </body>
            </html>
            """)

        QApplication.restoreOverrideCursor()

        return (html)

    def scaleMe(self):

        fontSize = self.mdiParent.fontSize
        settings = QWebEngineSettings.globalSettings()
        settings.setFontSize(QWebEngineSettings.DefaultFontSize,
                             floor(fontSize * 1.6))

        scaleFactor = self.mdiParent.scaleFactor
        windowWidth = 900 * scaleFactor
        windowHeight = 600 * scaleFactor
        self.resize(windowWidth, windowHeight)

    def loadAboutLapwing(self):

        self.title = "About Lapwing"

        self.contentType = "About"

        html = """

            <!DOCTYPE html>
            <html>
            <head>
            <title>About Lapwing</title>
            <meta charset="utf-8">
            <style>
            * {
                font-family: "Times New Roman", Times, serif;
                }
            </style>
            </head>
            <body bgcolor="#98FB98">
            <h1>
            Lapwing
            </h1>
            """

        html = html + "<h3>Version: " + self.mdiParent.versionNumber + "</h3>"
        html = html + "<h3>Date: " + self.mdiParent.versionDate + "</h3>"

        html = html + """
            <font size='4'>            
            <b>
            Lapwing is a free, open-source application to analyze personal eBird sightings. 
            <br><br>
            Created by Richard Trinkner.             
            </b>
            <h3>
            Licenses
            </h3>
            <p>
            <ul>
            <li>
            Lapwing is licensed under the GNU General Public License, version 3.
            </li>
            <li>
            PyQt, by Riverbank Computing, is licensed under the GNU General Public License.
            </li>
            <li>
            Qt, by the Qt Company, is licensed under the (L)GPL Lesser General Public License.
            </li>
            <li>
            PyInstaller, by the PyInstaller Development Team, Giovanni Bajo and McMillan Enterprise, is licensed under the GPL General Public License.
            </li>
            </ul>
            </font size>
            </body>
            </html>        
            """

        self.webView.setHtml(html)

        self.setWindowTitle("About Lapwing")

        return (True)

    def LoadWebPage(self, url):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.webView.load(QUrl(url))
        self.resizeMe()
        self.scaleMe()

    def LoadFinished(self):
        QApplication.restoreOverrideCursor()

    def LoadLocationsMap(self, filter):

        self.title = "Location Map"

        coordinatesDict = defaultdict()
        mapWidth = self.frameGeometry().width() - 10
        mapHeight = self.frameGeometry().height() - 35
        self.scrollArea.setGeometry(5, 27, mapWidth + 2, mapHeight + 2)
        self.webView.setGeometry(5, 27, mapWidth + 2, mapHeight + 2)
        self.contentType = "Map"
        self.filter = filter

        locations = self.mdiParent.db.GetLocations(filter)

        if len(locations) == 0:
            return (False)

        for l in locations:
            coordinates = self.mdiParent.db.GetLocationCoordinates(l)
            coordinatesDict[l] = coordinates

        html = """

            <!DOCTYPE html>
            <html>
            <head>
            <title>Locations Map</title>
            <meta name="viewport" content="initial-scale=1.0">
            <meta charset="utf-8">
            <style>
            * {
                font-size: 75%;
                font-family: "Times New Roman", Times, serif;
                }
            #map {
                height: 100%;
                }
            html, body {
            """
        html = html + "height: " + str(mapHeight) + "px;"
        html = html + "width: " + str(mapWidth) + "px;"

        html = html + """
                margin: 0;
                padding: 0;
                }
            </style>
            </head>
            <body>
            <div id="map"></div>
            <script>
            var map;

            function initMap() {
                map = new google.maps.Map(document.getElementById('map'), {
                    zoom: 5
                });
                
                var bounds = new google.maps.LatLngBounds();
                """
        for c in coordinatesDict.keys():
            html = html + """
                var marker = new google.maps.Marker({
                """
            html = html + "position: {lat: " + coordinatesDict[c][
                0] + ", lng: " + coordinatesDict[c][1] + "},"

            html = html + """
                    map: map,
                    title: """
            html = html + '"' + c + '"'
            html = html + """
                    }); 
                bounds.extend(marker.getPosition());                    
                
            """
        html = html + """
            
                map.setCenter(bounds.getCenter());
                
                map.fitBounds(bounds);
            }
            
            </script>
            <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDjVuwWvZmRlD5n-Jj2Jh_76njXxldDgug&callback=initMap" async defer></script>
            </body>
            </html>        
            """

        self.webView.setHtml(html)

        # set window title to descriptive map name

        locationName = filter.getLocationName(
        )  # str   name of region or location  or ""
        locationType = filter.getLocationType()
        startDate = filter.getStartDate()  # str   format yyyy-mm-dd  or ""
        endDate = filter.getEndDate()  # str   format yyyy-mm-dd  or ""
        startSeasonalMonth = filter.getStartSeasonalMonth()  # str   format mm
        startSeasonalDay = filter.getStartSeasonalDay()  # str   format dd
        endSeasonalMonth = filter.getEndSeasonalMonth()  # str   format  dd
        endSeasonalDay = filter.getEndSeasonalDay()  # str   format dd
        speciesName = filter.getSpeciesName()  # str   speciesName
        family = filter.getFamily()  # str family name

        # set main location label, using "All Locations" if none others are selected

        windowTitle = speciesName

        if locationName != "":
            if locationType == "Country":
                locationName = self.mdiParent.db.GetCountryName(locationName)
            if locationType == "State":
                locationName = self.mdiParent.db.GetStateName(locationName)
            windowTitle = windowTitle + "; " + locationName

        if startDate != "":
            dateTitle = startDate + " to " + endDate
            if startDate == endDate:
                dateTitle = startDate
            windowTitle = windowTitle + "; " + dateTitle

        # set main seasonal range label, if specified
        if not ((startSeasonalMonth == "") or (endSeasonalMonth == "")):
            monthRange = [
                "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
                "Oct", "Nov", "Dec"
            ]
            rangeTitle = monthRange[
                int(startSeasonalMonth) -
                1] + "-" + startSeasonalDay + " to " + monthRange[
                    int(endSeasonalMonth) - 1] + "-" + endSeasonalDay
            windowTitle = windowTitle + "; " + rangeTitle

        if family != "":
            family = family[0:family.index("(") - 1]
            windowTitle = windowTitle + "; " + family

        if windowTitle == "":
            windowTitle = "All species, locations, dates and families"

        #remove leading "; " if needed
        if windowTitle[0:2] == "; ":
            windowTitle = windowTitle[2:]

        # add location count to window title
        windowTitle = "Map: " + windowTitle + " (" + str(
            len(coordinatesDict.keys())) + ")"

        self.setWindowTitle(windowTitle)

        icon = QIcon()
        icon.addPixmap(QPixmap(":/icon_map.png"), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)

        return (True)

    def showLoadProgress(self, percent):

        if percent < 100:
            self.setWindowTitle(self.title + ": " + str(percent) + "%")
        else:
            self.setWindowTitle(self.title)
示例#5
0
class Location(QMdiSubWindow, form_Location.Ui_frmLocation):

    resized = pyqtSignal()

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.mdiParent = ""
        self.resized.connect(self.resizeMe)
        self.tblDates.currentItemChanged.connect(self.FillSpeciesForDate)
        self.lstSpecies.doubleClicked.connect(self.ClickedLstSpecies)
        self.tblDates.doubleClicked.connect(self.ClickedTblDates)
        self.tblSpecies.doubleClicked.connect(self.ClickedTblSpecies)
        self.tblDates.setShowGrid(False)

        self.horizontalLayout_2.setContentsMargins(5, 5, 5, 5)
        self.horizontalLayout_2.setSpacing(4)
        self.webMap = QWebEngineView(self.tabMap)
        self.webMap.setObjectName("webMap")
        self.horizontalLayout_2.addWidget(self.webMap)
        self.tabLocation.setCurrentIndex(0)

    def ClickedLstSpecies(self):
        species = self.lstSpecies.currentItem().text()
        self.CreateIndividual(species)

    def ClickedTblDates(self):
        thisDate = self.tblDates.item(self.tblDates.currentRow(), 1).text()
        thisLocation = self.lblLocation.text()

        tempFilter = code_Filter.Filter()

        tempFilter.setLocationType("Location")
        tempFilter.setLocationName(thisLocation)
        tempFilter.setStartDate(thisDate)
        tempFilter.setEndDate(thisDate)

        self.CreateSpeciesList(tempFilter)

    def ClickedTblSpecies(self):

        selectedRow = self.tblSpecies.currentRow()
        selectedColumn = self.tblSpecies.currentColumn()

        if selectedColumn > 1:
            thisDate = self.tblSpecies.item(selectedRow, selectedColumn).text()
            thisLocation = self.lblLocation.text()

            tempFilter = code_Filter.Filter()

            tempFilter.setLocationType("Location")
            tempFilter.setLocationName(thisLocation)
            tempFilter.setStartDate(thisDate)
            tempFilter.setEndDate(thisDate)

            self.CreateSpeciesList(tempFilter)

        else:
            thisSpecies = self.tblSpecies.item(selectedRow, 1).text()
            self.CreateIndividual(thisSpecies)

    def CreateIndividual(self, species):
        sub = code_Individual.Individual()
        sub.mdiParent = self.mdiParent
        sub.FillIndividual(species)
        self.parent().parent().addSubWindow(sub)
        self.mdiParent.PositionChildWindow(sub, self)
        sub.show()
        sub.resizeMe()

    def CreateSpeciesList(self, filter):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        sub = code_Lists.Lists()
        sub.mdiParent = self.mdiParent
        sub.FillSpecies(filter)
        self.parent().parent().addSubWindow(sub)
        self.mdiParent.PositionChildWindow(sub, self)
        sub.show()

        QApplication.restoreOverrideCursor()

    def FillLocation(self, location):
        self.location = location
        thisLocationDates = []

        filter = code_Filter.Filter()
        filter.setLocationType("Location")
        filter.setLocationName(location)

        thisLocationDates = self.mdiParent.db.GetDates(filter)
        thisLocationDates.sort()

        self.tblDates.setColumnCount(4)
        self.tblDates.setRowCount(len(thisLocationDates))
        self.tblDates.horizontalHeader().setVisible(True)
        self.tblDates.setHorizontalHeaderLabels(
            ['Rank', 'Date', 'Species', 'Checklists'])
        header = self.tblDates.horizontalHeader()
        header.setSectionResizeMode(2, QHeaderView.Stretch)

        self.lblLocation.setText(location)
        self.lblFirstVisited.setText("First visited: " + thisLocationDates[0])
        self.lblMostRecentlyVisited.setText(
            "Most recently visited: " +
            thisLocationDates[len(thisLocationDates) - 1])

        dateArray = []
        for d in thisLocationDates:
            if d != "":
                dSpecies = set()
                checklistCount = set()
                for sighting in self.mdiParent.db.locationDict[location]:
                    if d == sighting["date"]:
                        dSpecies.add(sighting["commonName"])
                        checklistCount.add(sighting["checklistID"])
                dateArray.append([len(dSpecies), d, len(checklistCount)])
        dateArray.sort(reverse=True)

        rank = 0
        lastDateTotal = 0
        R = 0
        for date in dateArray:
            rankItem = QTableWidgetItem()
            if date[0] != lastDateTotal:
                rank = R + 1
            rankItem.setData(Qt.DisplayRole, rank)
            dateItem = QTableWidgetItem()
            dateItem.setText(date[1])
            totalSpeciesItem = QTableWidgetItem()
            totalSpeciesItem.setData(Qt.DisplayRole, date[0])
            totalChecklistsItem = QTableWidgetItem()
            totalChecklistsItem.setData(Qt.DisplayRole, date[2])
            self.tblDates.setItem(R, 0, rankItem)
            self.tblDates.setItem(R, 1, dateItem)
            self.tblDates.setItem(R, 2, totalSpeciesItem)
            self.tblDates.setItem(R, 3, totalChecklistsItem)
            lastDateTotal = date[0]
            R = R + 1

        self.tblDates.selectRow(0)

        if self.tblDates.rowCount() == 1:
            self.lblDatesSeen.setText("Date (1)")
        else:
            self.lblDatesSeen.setText("Dates (" +
                                      str(self.tblDates.rowCount()) + ")")
        # display all dates for the selected location
        self.tblDates.setSortingEnabled(True)
        self.tblDates.sortItems(0, 0)
        self.tblDates.setCurrentCell(0, 1)

        self.coordinates = self.mdiParent.db.GetLocationCoordinates(location)

        # display the species in the species for date list
        self.FillSpeciesForDate()
        # display the main all-species list
        self.FillSpecies()

        self.scaleMe()
        self.resizeMe()

    def FillMap(self):

        coordinatesDict = defaultdict()
        coordinatesDict[self.location] = self.coordinates

        mapWidth = self.width() - 40
        mapHeight = self.height() - 170

        thisMap = code_MapHtml.MapHtml()
        thisMap.mapHeight = mapHeight
        thisMap.mapWidth = mapWidth
        thisMap.coordinatesDict = coordinatesDict

        html = thisMap.html()
        self.webMap.setHtml(html)

    def FillSpecies(self):
        location = self.lblLocation.text()
        tempFilter = code_Filter.Filter()
        tempFilter.setLocationType("Location")
        tempFilter.setLocationName(location)
        speciesList = []

        # get species data from db
        thisWindowList = self.mdiParent.db.GetSpeciesWithData(tempFilter)

        # set up tblSpecies column headers and widths
        self.tblSpecies.setColumnCount(6)
        self.tblSpecies.setRowCount(len(thisWindowList) + 1)
        self.tblSpecies.horizontalHeader().setVisible(True)
        self.tblSpecies.setHorizontalHeaderLabels(
            ['Tax', 'Species', 'First', 'Last', 'Chlists', '% of Chlists'])
        header = self.tblSpecies.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.tblSpecies.setShowGrid(False)

        # add species and dates to table row by row
        R = 1
        for species in thisWindowList:
            taxItem = QTableWidgetItem()
            taxItem.setData(Qt.DisplayRole, R)
            speciesItem = QTableWidgetItem()
            speciesItem.setText(species[0])
            firstItem = QTableWidgetItem()
            firstItem.setData(Qt.DisplayRole, species[1])
            lastItem = QTableWidgetItem()
            lastItem.setData(Qt.DisplayRole, species[2])
            checklistsItem = QTableWidgetItem()
            checklistsItem.setData(Qt.DisplayRole, species[5])
            percentageItem = QTableWidgetItem()
            percentageItem.setData(Qt.DisplayRole, species[6])

            self.tblSpecies.setItem(R, 0, taxItem)
            self.tblSpecies.setItem(R, 1, speciesItem)
            self.tblSpecies.setItem(R, 2, firstItem)
            self.tblSpecies.setItem(R, 3, lastItem)
            self.tblSpecies.setItem(R, 4, checklistsItem)
            self.tblSpecies.setItem(R, 5, percentageItem)

            speciesList.append(species[0])
            R = R + 1

        self.tblSpecies.removeRow(0)

        count = self.mdiParent.db.CountSpecies(speciesList)
        self.lblSpecies.setText("Species (" + str(count) + "):")

    def SetDate(self, date):
        if self.tblDates.rowCount() > 0:
            for d in range(self.tblDates.rowCount()):
                if self.tblDates.item(d, 1).text() == date:
                    self.tblDates.setCurrentCell(d, 1)
                    self.FillSpeciesForDate()
                    self.tabLocation.setCurrentIndex(1)
                    break

    def FillSpeciesForDate(self):
        self.lstSpecies.clear()
        location = self.lblLocation.text()
        if self.tblDates.item(self.tblDates.currentRow(), 1) is not None:

            date = self.tblDates.item(self.tblDates.currentRow(), 1).text()

            tempFilter = code_Filter.Filter()
            tempFilter.setStartDate(date)
            tempFilter.setEndDate(date)
            tempFilter.setLocationName(location)
            tempFilter.setLocationType("Location")

            species = self.mdiParent.db.GetSpecies(tempFilter)

            self.lstSpecies.addItems(species)
            self.lstSpecies.setCurrentRow(0)
            self.lstSpecies.setSpacing(2)

            count = self.mdiParent.db.CountSpecies(species)

            self.lblSpeciesSeen.setText("Species for selected date (" +
                                        str(count) + ")")

    def html(self):

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        # create start to basic html format
        html = """
            <!DOCTYPE html>
            <html>
            <head>
            </head>
            <style>
            * {
                font-size: 75%;
                font-family: "Times New Roman", Times, serif;
                }
            th {
                text-align: left;
            }
            </style>
            <body>
            """

        # add title information
        html = html + ("<H1>" + self.lblLocation.text() + "</H1>")

        html = html + ("<H3>" + self.lblFirstVisited.text() + "</H3>")

        html = html + ("<H3>" + self.lblMostRecentlyVisited.text() + "</H3>")

        # grab the map image from the map tap
        # process it into a byte array and encode it
        # so we can insert it inline into the html
        myPixmap = self.webMap.grab()
        myPixmap = myPixmap.scaledToWidth(600, Qt.SmoothTransformation)

        myByteArray = QByteArray()
        myBuffer = QBuffer(myByteArray)
        myBuffer.open(QIODevice.WriteOnly)
        myPixmap.save(myBuffer, "PNG")

        encodedImage = b64encode(myByteArray)

        html = html + ("""
        <img src="data:image/png;base64, 
        """)

        html = html + str(encodedImage)[1:]

        html = html + ("""        
        "  />
        """)

        html = html + ("<H4>" + "Species" "</H4>")

        html = html + ("<font size='2'>" + "<p>")

        # loopthrough the species listed in tblSpecies
        for r in range(self.tblSpecies.rowCount()):
            html = html + (self.tblSpecies.item(r, 1).text() + "<br>")

        html = html + ("<H4>" + "Dates" + "</H4>")

        # create filter set to our current location
        filter = code_Filter.Filter()
        filter.setLocationType = "Location"
        filter.setLocationName = self.lblLocation.text()

        # for each date in tblDates, find the species and display them in a table
        for r in range(self.tblDates.rowCount()):

            html = html + ("<b>" + self.tblDates.item(r, 1).text() + "</b>")

            filter.setStartDate(self.tblDates.item(r, 1).text())
            filter.setEndDate(self.tblDates.item(r, 1).text())
            species = self.mdiParent.db.GetSpecies(filter)

            html = html + ("<br>" "<table width='100%'>" "<tr>")

            # set up counter R to start a new row after listing each 3 species
            R = 1
            for s in species:
                html = html + ("<td>" + s + "</td>")
                if R == 3:
                    html = html + ("</tr>" "<tr>")
                    R = 0
                R = R + 1

            html = html + ("<br>" + "<br>" + "<br>" + "</table>")

        html = html + ("<font size>" + "</body>" + "</html>")

        QApplication.restoreOverrideCursor()

        return (html)

    def resizeEvent(self, event):
        #routine to handle events on objects, like clicks, lost focus, gained forcus, etc.
        self.resized.emit()
        return super(self.__class__, self).resizeEvent(event)

    def resizeMe(self):

        windowWidth = self.frameGeometry().width()
        windowHeight = self.frameGeometry().height()
        self.scrollArea.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        self.FillMap()

    def scaleMe(self):

        scaleFactor = self.mdiParent.scaleFactor
        windowWidth = 800 * scaleFactor
        windowHeight = 600 * scaleFactor
        self.resize(windowWidth, windowHeight)

        fontSize = self.mdiParent.fontSize
        scaleFactor = self.mdiParent.scaleFactor
        #scale the font for all widgets in window
        for w in self.children():
            try:
                w.setFont(QFont("Helvetica", fontSize))
            except:
                pass

        baseFont = QFont(QFont("Helvetica", fontSize))
        locationFont = QFont(QFont("Helvetica", floor(fontSize * 1.4)))
        locationFont.setBold(True)
        self.lblLocation.setFont(locationFont)
        self.lblFirstVisited.setFont(baseFont)
        self.lblMostRecentlyVisited.setFont(baseFont)

        header = self.tblSpecies.horizontalHeader()
        metrics = self.tblSpecies.fontMetrics()

        dateTextWidth = metrics.boundingRect("2222-22-22").width()
        dateTextHeight = metrics.boundingRect("2222-22-22").height()
        taxText = str(self.tblSpecies.rowCount())
        taxTextWidth = metrics.boundingRect(taxText).width()
        header.resizeSection(0, floor(1.7 * taxTextWidth))
        header.resizeSection(2, floor(1.3 * dateTextWidth))
        header.resizeSection(3, floor(1.3 * dateTextWidth))
        for R in range(self.tblSpecies.rowCount()):
            self.tblSpecies.setRowHeight(R, dateTextHeight)

        header = self.tblDates.horizontalHeader()
        textWidth = metrics.boundingRect("Rank").width()
        header.resizeSection(0, floor(1.5 * textWidth))
        header.resizeSection(1, floor(1.5 * dateTextWidth))
        for R in range(self.tblDates.rowCount()):
            self.tblDates.setRowHeight(R, dateTextHeight)

        self.FillMap()
示例#6
0
class Web(QMdiSubWindow, form_Web.Ui_frmWeb):

    resized = pyqtSignal()

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.mdiParent = ""
        self.setWindowIcon(QIcon(QPixmap(1, 1)))
        self.contentType = "Web Page"
        self.resized.connect(self.resizeMe)
        self.webView = QWebEngineView(self)
        self.webView.setObjectName("webView")
        self.webView.loadFinished.connect(self.LoadFinished)
        self.webView.loadProgress.connect(self.showLoadProgress)
        self.title = ""

    def resizeEvent(self, event):
        #routine to handle events on objects, like clicks, lost focus, gained forcus, etc.
        self.resized.emit()
        return super(self.__class__, self).resizeEvent(event)

    def resizeMe(self):

        windowWidth = self.frameGeometry().width()
        windowHeight = self.frameGeometry().height()
        self.scrollArea.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        self.webView.setGeometry(5, 27, windowWidth - 10, windowHeight - 35)
        if self.contentType == "Map":
            self.webView.adjustSize()
            self.LoadLocationsMap(self.filter)

    def html(self):

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        html = """
            <!DOCTYPE html>
            <html>
            <head>
            </head>
            <body>
            """

        myPixmap = self.webView.grab()
        myPixmap = myPixmap.scaledToWidth(600, Qt.SmoothTransformation)

        myByteArray = QByteArray()
        myBuffer = QBuffer(myByteArray)
        myBuffer.open(QIODevice.WriteOnly)
        myPixmap.save(myBuffer, "PNG")

        encodedImage = base64.b64encode(myByteArray)

        html = html + ("""
        <img src="data:image/png;base64, 
        """)

        html = html + str(encodedImage)[1:]

        html = html + ("""
            <font size>
            </body>
            </html>
            """)

        QApplication.restoreOverrideCursor()

        return (html)

    def scaleMe(self):

        fontSize = self.mdiParent.fontSize
        settings = QWebEngineSettings.globalSettings()
        settings.setFontSize(QWebEngineSettings.DefaultFontSize,
                             floor(fontSize * 1.6))

        scaleFactor = self.mdiParent.scaleFactor
        windowWidth = 800 * scaleFactor
        windowHeight = 580 * scaleFactor
        self.resize(windowWidth, windowHeight)

    def loadAboutLapwing(self):

        self.title = "About Lapwing"

        self.contentType = "About"

        html = """

            <!DOCTYPE html>
            <html>
            <head>
            <title>About Lapwing</title>
            <meta charset="utf-8">
            <style>
            * {
                font-family: "Times New Roman", Times, serif;
                }
            </style>
            </head>
            <body>
            <h1>
            Lapwing
            </h1>
            """

        html = html + "<h3>Version: " + self.mdiParent.versionNumber + "</h3>"
        html = html + "<h3>Date: " + self.mdiParent.versionDate + "</h3>"

        html = html + """
            <font size='4'>            
            <b>
            Lapwing is a free, open-source application to analyze personal eBird sightings. 
            <br><br>
            Created by Richard Trinkner.             
            </b>
            <h3>
            Licenses
            </h3>
            <p>
            <ul>
            <li>
            Lapwing is licensed under the GNU General Public License, version 3.
            </li>
            <li>
            PyQt, by Riverbank Computing, is licensed under the GNU General Public License.
            </li>
            <li>
            Map base layers are retrieved from Google.
            </li>            
            <li>
            Map layers that include points and location labels are generated using OpenLayers. OpenLayers is free, Open Source JavaScript, released under the 2-clause BSD License (also known as the FreeBSD).
            </li>
            <li>
            PyInstaller, by the PyInstaller Development Team, Giovanni Bajo and McMillan Enterprise, is licensed under the GPL General Public License.
            </li>
            </ul>
            </font size>
            </body>
            </html>        
            """

        self.webView.setHtml(html)

        self.setWindowTitle("About Lapwing")

        return (True)

    def LoadWebPage(self, url):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.webView.load(QUrl(url))
        self.resizeMe()
        self.scaleMe()

    def LoadFinished(self):
        QApplication.restoreOverrideCursor()

    def LoadLocationsMap(self, filter):

        self.title = "Location Map"

        coordinatesDict = defaultdict()
        mapWidth = self.frameGeometry().width() - 10
        mapHeight = self.frameGeometry().height() - 35
        self.scrollArea.setGeometry(5, 27, mapWidth + 2, mapHeight + 2)
        self.webView.setGeometry(5, 27, mapWidth + 2, mapHeight + 2)
        self.contentType = "Map"
        self.filter = filter

        locations = self.mdiParent.db.GetLocations(filter)

        if len(locations) == 0:
            return (False)

        for l in locations:
            coordinates = self.mdiParent.db.GetLocationCoordinates(l)
            coordinatesDict[l] = coordinates

        thisMap = code_MapHtml.MapHtml()
        thisMap.mapHeight = mapHeight
        thisMap.mapWidth = mapWidth
        thisMap.coordinatesDict = coordinatesDict

        html = thisMap.html()

        self.webView.setHtml(html)

        # set window title to descriptive map name

        locationName = filter.getLocationName(
        )  # str   name of region or location  or ""
        locationType = filter.getLocationType()
        startDate = filter.getStartDate()  # str   format yyyy-mm-dd  or ""
        endDate = filter.getEndDate()  # str   format yyyy-mm-dd  or ""
        startSeasonalMonth = filter.getStartSeasonalMonth()  # str   format mm
        startSeasonalDay = filter.getStartSeasonalDay()  # str   format dd
        endSeasonalMonth = filter.getEndSeasonalMonth()  # str   format  dd
        endSeasonalDay = filter.getEndSeasonalDay()  # str   format dd
        speciesName = filter.getSpeciesName()  # str   speciesName
        family = filter.getFamily()  # str family name

        # set main location label, using "All Locations" if none others are selected

        windowTitle = speciesName

        if locationName != "":
            if locationType == "Country":
                locationName = self.mdiParent.db.GetCountryName(locationName)
            if locationType == "State":
                locationName = self.mdiParent.db.GetStateName(locationName)
            windowTitle = windowTitle + "; " + locationName

        if startDate != "":
            dateTitle = startDate + " to " + endDate
            if startDate == endDate:
                dateTitle = startDate
            windowTitle = windowTitle + "; " + dateTitle

        # set main seasonal range label, if specified
        if not ((startSeasonalMonth == "") or (endSeasonalMonth == "")):
            monthRange = [
                "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
                "Oct", "Nov", "Dec"
            ]
            rangeTitle = monthRange[
                int(startSeasonalMonth) -
                1] + "-" + startSeasonalDay + " to " + monthRange[
                    int(endSeasonalMonth) - 1] + "-" + endSeasonalDay
            windowTitle = windowTitle + "; " + rangeTitle

        if family != "":
            family = family[0:family.index("(") - 1]
            windowTitle = windowTitle + "; " + family

        if windowTitle == "":
            windowTitle = "All species, locations, dates and families"

        #remove leading "; " if needed
        if windowTitle[0:2] == "; ":
            windowTitle = windowTitle[2:]

        # add location count to window title
        windowTitle = "Map: " + windowTitle + " (" + str(
            len(coordinatesDict.keys())) + ")"

        self.setWindowTitle(windowTitle)
        self.title = windowTitle

        icon = QIcon()
        icon.addPixmap(QPixmap(":/icon_map.png"), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)

        return (True)

    def showLoadProgress(self, percent):

        if percent < 100:
            self.setWindowTitle(self.title + ": " + str(percent) + "%")
        else:
            self.setWindowTitle(self.title)