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
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)
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)
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)
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()
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)