def tblListClicked(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) currentRow = self.tblList.currentRow() currentColumn = self.tblList.currentColumn() if self.listType in ["Species", "Single Checklist"]: if currentColumn in [0, 5]: # the taxonomy order or percentage 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 speciesName = self.tblList.item(currentRow, 1).text() # abort if a spuh or slash species was clicked (we can't show an individual for this) if "sp." in speciesName or "/" in speciesName: QApplication.restoreOverrideCursor() return sub = code_Individual.Individual() sub.mdiParent = self.mdiParent sub.FillIndividual(speciesName) if currentColumn in [2, 3]: # If list is already a checklist, we abort if self.filter.getChecklistID() != "": QApplication.restoreOverrideCursor() return # date column has been clicked so create species list frame for that dateArray date = self.tblList.item(currentRow, self.tblList.currentColumn()).text() speciesName = self.tblList.item(currentRow, 1).data(Qt.UserRole) filter = code_Filter.Filter() filter.setSpeciesName(speciesName) filter.setStartDate(date) filter.setEndDate(date) # get all checklists that have this date and species checklists = self.mdiParent.db.GetChecklists(filter) # see if only one checklist meets filter # create a SpeciesList window to display a checklist if only one is found # create a checklists list window if more than one if found if len(checklists) == 1: filter.setSpeciesName("") filter.setChecklistID(checklists[0][0]) filter.setLocationType("Location") filter.setLocationName(checklists[0][3]) sub = Lists() sub.mdiParent = self.mdiParent sub.FillSpecies(filter) if len(checklists) > 1: sub = Lists() sub.mdiParent = self.mdiParent sub.FillChecklists(filter) if currentColumn == 4: # If list is already a checklist, we abort if self.filter.getChecklistID() != "": QApplication.restoreOverrideCursor() return # checklist count column has been clicked so create checklist list for widget's filter and species speciesName = self.tblList.item(currentRow, 1).text() filter = deepcopy(self.filter) filter.setSpeciesName(speciesName) # get all checklists that have this date and species checklists = self.mdiParent.db.GetChecklists(filter) if len(checklists) > 0: sub = Lists() sub.mdiParent = self.mdiParent sub.FillChecklists(filter) if self.listType == "Locations": if currentColumn == 0: # species column has been clicked so create individual window for that species locationName = self.tblList.item(currentRow, 0).text() sub = code_Location.Location() sub.mdiParent = self.mdiParent sub.FillLocation(locationName) if currentColumn > 0: # date column has been clicked so create species list frame for that dateArray clickedText = self.tblList.item( currentRow, self.tblList.currentColumn()).text() date = clickedText.split(" ")[0] time = clickedText.split(" ")[1] locationName = self.tblList.item(currentRow, 0).text() filter = code_Filter.Filter() filter.setLocationName(locationName) filter.setLocationType("Location") filter.setStartDate(date) filter.setEndDate(date) filter.setTime(time) # get all checklists that have this date and location checklists = self.mdiParent.db.GetChecklists(filter) # see if only one checklist meets filter # create a SpeciesList window to display a checklist if only one is found # create a checklists list window if more than one if found if len(checklists) == 1: filter.setSpeciesName("") filter.setChecklistID(checklists[0][0]) filter.setLocationType("Location") filter.setLocationName(checklists[0][3]) sub = Lists() sub.mdiParent = self.mdiParent sub.FillSpecies(filter) if len(checklists) > 1: sub = Lists() sub.mdiParent = self.mdiParent sub.FillChecklists(filter) if self.listType in ["Checklists", "Find Results"]: checklistID = self.tblList.item(currentRow, 0).data(Qt.UserRole) filter = code_Filter.Filter() filter.setChecklistID(checklistID) location = self.mdiParent.db.GetLocations(filter)[0] date = self.mdiParent.db.GetDates(filter)[0] filter = code_Filter.Filter() filter.setChecklistID(checklistID) filter.setLocationName(location) filter.setLocationType("Location") filter.setStartDate(date) filter.setEndDate(date) sub = Lists() sub.mdiParent = self.mdiParent sub.FillSpecies(filter) self.parent().parent().addSubWindow(sub) self.mdiParent.PositionChildWindow(sub, self) sub.show() sub.resizeMe() QApplication.restoreOverrideCursor()
def FillIndividual(self, Species): self.setWindowTitle(Species) self.lblCommonName.setText(Species) red = code_Stylesheet.speciesColor.red() green = code_Stylesheet.speciesColor.green() blue = code_Stylesheet.speciesColor.blue() self.lblCommonName.setStyleSheet( 'QLabel {font-weight: bold; color: rgb(' + str(red) + ',' + str(green) + ',' + str(blue) + ');}') self.lblScientificName.setText( self.mdiParent.db.GetScientificName(Species)) orderAndFamilyText = self.mdiParent.db.GetOrderName(Species) # check if taxonomy data has been loaded. If so, add a semi-colon and the family name if orderAndFamilyText != "": orderAndFamilyText = orderAndFamilyText + "; " + self.mdiParent.db.GetFamilyName( Species) self.lblOrderName.setText(orderAndFamilyText) # if available, add BBL banding code bblCode = self.mdiParent.db.GetBBLCode(Species) if bblCode != "": self.lblSpeciesCode.setText("IBP Banding Code: " + bblCode) else: # add species Quick Entry Code code used by eBird self.lblSpeciesCode.setText( "eBird Entry Code: " + self.mdiParent.db.GetQuickEntryCode(Species).upper()) # find list of dates for species, to find oldest and newest filter = code_Filter.Filter() filter.setSpeciesName(Species) dbDates = self.mdiParent.db.GetDates(filter) firstDate = dbDates[0] lastDate = dbDates[len(dbDates) - 1] # create filter to find the first location seen filter = code_Filter.Filter() filter.setStartDate(firstDate) filter.setEndDate(firstDate) filter.setSpeciesName(Species) firstDateLocations = self.mdiParent.db.GetLocations( filter, "Checklist") firstDateLocations = sorted(firstDateLocations, key=lambda x: (x[3])) firstLocation = firstDateLocations[0][0] # create filter to find the last location seen filter = code_Filter.Filter() filter.setStartDate(lastDate) filter.setEndDate(lastDate) filter.setSpeciesName(Species) lastDateLocations = self.mdiParent.db.GetLocations(filter, "Checklist") lastDateLocations = sorted(lastDateLocations, key=lambda x: (x[3])) lastLocation = lastDateLocations[len(lastDateLocations) - 1][0] self.lblFirstSeen.setText("First seen: " + dbDates[0] + " at " + firstLocation) self.lblMostRecentlySeen.setText("Most recently seen: " + dbDates[len(dbDates) - 1] + " at " + lastLocation) # display all locations for the species filter = code_Filter.Filter() filter.setSpeciesName(Species) locationList = self.mdiParent.db.GetLocations(filter, "LocationHierarchy") dateList = self.mdiParent.db.GetDates(filter) # fill treeview Locations widget self.trLocations.setColumnCount(1) theseCountries = set() sortedLocationList = sorted(locationList, key=lambda x: (x[0], x[1], x[2])) # add the top-level country tree items for l in sortedLocationList: theseCountries.add(l[0][0:2]) locationCount = 0 theseCountries = list(theseCountries) theseCountries.sort() for c in theseCountries: thisCountryItem = QTreeWidgetItem() thisCountry = self.mdiParent.db.GetCountryName(c) thisCountryItem.setText(0, thisCountry) self.trLocations.addTopLevelItem(thisCountryItem) thisCountryItem.setSizeHint(0, QSize(20, 20)) theseStates = set() for l in sortedLocationList: if l[0][0:2] == c: theseStates.add(l[0]) theseStates = list(theseStates) theseStates.sort() for s in theseStates: thisState = self.mdiParent.db.GetStateName(s) stateTreeItem = QTreeWidgetItem() stateTreeItem.setText(0, thisState) thisCountryItem.addChild(stateTreeItem) stateTreeItem.setSizeHint(0, QSize(20, 20)) theseCounties = set() for l in sortedLocationList: if l[0] == s: theseCounties.add(l[1]) theseCounties = list(theseCounties) theseCounties.sort() for co in theseCounties: countyTreeItem = QTreeWidgetItem() if co == "": countyTreeItem.setText(0, "No County Name") else: countyTreeItem.setText(0, co) stateTreeItem.addChild(countyTreeItem) countyTreeItem.setSizeHint(0, QSize(20, 20)) theseLocations = [] for l in sortedLocationList: if l[0] == s and l[1] == co: theseLocations.append(l[2]) theseLocations.sort() for lo in theseLocations: locationTreeItem = QTreeWidgetItem() locationTreeItem.setText(0, lo) countyTreeItem.addChild(locationTreeItem) locationTreeItem.setSizeHint(0, QSize(20, 20)) locationCount = locationCount + len(theseLocations) # Fill Year Tree widget theseYears = set() for d in dateList: theseYears.add(d[0:4]) theseYears = list(theseYears) theseYears.sort() dateCount = 0 for y in theseYears: thisYearItem = QTreeWidgetItem() thisYearItem.setText(0, str(y)) self.trDates.addTopLevelItem(thisYearItem) thisYearItem.setSizeHint(0, QSize(20, 20)) theseMonths = set() for d in dateList: if y == d[0:4]: theseMonths.add(d[5:7]) theseMonths = list(theseMonths) theseMonths.sort() for m in theseMonths: monthName = self.mdiParent.db.GetMonthName(m) monthTreeItem = QTreeWidgetItem() monthTreeItem.setText(0, str(monthName)) thisYearItem.addChild(monthTreeItem) monthTreeItem.setSizeHint(0, QSize(20, 20)) theseDates = set() for da in dateList: if da[0:4] == y: if da[5:7] == m: theseDates.add(da) theseDates = list(theseDates) theseDates.sort() for td in theseDates: dateTreeItem = QTreeWidgetItem() dateTreeItem.setText(0, str(td)) monthTreeItem.addChild(dateTreeItem) dateTreeItem.setSizeHint(0, QSize(20, 20)) dateCount = dateCount + len(theseDates) # Fill Month Tree widget theseMonths = [] theseMonths = set() for d in dateList: theseMonths.add(d[5:7]) theseMonths = list(theseMonths) theseMonths.sort() dateCount = 0 for m in theseMonths: monthName = self.mdiParent.db.GetMonthName(m) thisMonthItem = QTreeWidgetItem() thisMonthItem.setText(0, monthName) self.trMonthDates.addTopLevelItem(thisMonthItem) thisMonthItem.setSizeHint(0, QSize(20, 20)) theseYears = set() for d in dateList: if m == d[5:7]: theseYears.add(d[0:4]) theseYears = list(theseYears) theseYears.sort() for y in theseYears: yearTreeItem = QTreeWidgetItem() yearTreeItem.setText(0, y) thisMonthItem.addChild(yearTreeItem) yearTreeItem.setSizeHint(0, QSize(20, 20)) theseDates = set() for da in dateList: if da[0:4] == y: if da[5:7] == m: theseDates.add(da) theseDates = list(theseDates) theseDates.sort() for td in theseDates: dateTreeItem = QTreeWidgetItem() dateTreeItem.setText(0, str(td)) yearTreeItem.addChild(dateTreeItem) dateTreeItem.setSizeHint(0, QSize(20, 20)) dateCount = dateCount + len(theseDates) if locationCount == 1: self.lblLocations.setText("Location (1)") else: self.lblLocations.setText("Locations (" + str(locationCount) + ")") # add a photo button if the db holds photos of this species filter = code_Filter.Filter() filter.setSpeciesName(Species) photoSightings = self.mdiParent.db.GetSightingsWithPhotos(filter) if len(photoSightings) > 0: btnPhotos = QPushButton() btnPhotos.setText("Photos") btnPhotos.clicked.connect(self.createPhotos) self.verticalLayout_10.addWidget(btnPhotos) self.scaleMe() self.resizeMe()
def html(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) html = """ <!DOCTYPE html> <html> <head> </head> <style> * { font-size: 75%; font-family: "Times New Roman", Times, serif; } table, th, td { border-collapse: collapse; } th, td { padding: 5px; } th { text-align: left; } </style> <body> """ html = html + ("<H1>" + self.lblCommonName.text() + "</H1>") html = html + ("<H2>" + self.lblScientificName.text() + "</H2>") html = html + ("<H4>" + self.lblOrderName.text() + "</H4>") html = html + ("<H4>" + self.lblFirstSeen.text() + "</H4>") html = html + ("<H4>" + self.lblMostRecentlySeen.text() + "</H4>") html = html + ("<br>" + "<H4>" + "Locations" "</H4>") html = html + ("<font size='2'>") root = self.trLocations.invisibleRootItem() for i in range(root.childCount()): for ii in range(root.child(i).childCount()): for iii in range(root.child(i).child(ii).childCount()): for iv in range( root.child(i).child(ii).child(iii).childCount()): html = html + ( "<b>" + root.child(i).text(0) + ", " + root.child(i).child(ii).text(0) + ", " + root.child(i).child(ii).child(iii).text(0) + ", " + root.child(i).child(ii).child(iii).child(iv).text( 0)) filter = code_Filter.Filter() filter.setSpeciesName = self.lblCommonName.text() filter.setLocationType("Location") filter.setLocationName( root.child(i).child(ii).child(iii).child(iv).text( 0)) dates = self.mdiParent.db.GetDates(filter) html = html + (" (" + str(len(dates))) if len(dates) > 1: html = html + " dates)" else: html = html + " date)" html = html + ("</b>" "<br>" "<table width='100%'>" "<tr>") R = 1 for d in dates: html = html + ("<td>" + d + "</td>") if R == 5: 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 FillLocations(self, callingWidget): species = self.lblCommonName.text() currentItem = callingWidget.currentItem() filter = code_Filter.Filter() filter.setSpeciesName(species) if callingWidget.objectName() == "trDates": locationWidget = self.tblYearLocations # check if currentItem is a year if currentItem.parent() is None: filter.setStartDate(currentItem.text(0) + "-01-01") filter.setEndDate(currentItem.text(0) + "-12-31") # check if currentItem is a month elif currentItem.parent().parent() is None: month = currentItem.text(0) monthNumberString = self.mdiParent.db.monthNumberDict[month] lastDayOfThisMonth = self.mdiParent.db.GetLastDayOfMonth( monthNumberString) year = currentItem.parent().text(0) filter.setStartDate(year + "-" + monthNumberString + "-01") filter.setEndDate(year + "-" + monthNumberString + "-" + lastDayOfThisMonth) # item is a just a single date else: filter.setStartDate(currentItem.text(0)) filter.setEndDate(currentItem.text(0)) if callingWidget.objectName() == "trMonthDates": locationWidget = self.tblMonthLocations # check if currentItem is a month if currentItem.parent() is None: monthNumberString = self.mdiParent.db.monthNumberDict[ currentItem.text(0)] lastDayOfThisMonth = self.mdiParent.db.GetLastDayOfMonth( monthNumberString) filter.setStartSeasonalMonth(monthNumberString) filter.setStartSeasonalDay("01") filter.setEndSeasonalMonth(monthNumberString) filter.setEndSeasonalDay(lastDayOfThisMonth) # check if currentItem is a year elif currentItem.parent().parent() is None: year = currentItem.text(0) monthString = currentItem.parent().text(0) monthNumberString = self.mdiParent.db.monthNumberDict[ monthString] filter.setStartDate(year + "-" + monthNumberString + "-01") filter.setEndDate(year + "-" + monthNumberString + "-31") # item is a just a single date else: filter.setStartDate(currentItem.text(0)) filter.setEndDate(currentItem.text(0)) locations = self.mdiParent.db.GetLocations(filter, "Checklist") locationWidget.clear() locationWidget.setColumnCount(2) locationWidget.setRowCount(len(locations)) locationWidget.horizontalHeader().setVisible(False) locationWidget.verticalHeader().setVisible(False) header = locationWidget.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.Stretch) locationWidget.setShowGrid(False) metrics = locationWidget.fontMetrics() textHeight = metrics.boundingRect("A").height() R = 0 for l in locations: locationItem = QTableWidgetItem() locationItem.setText(l[0]) # store checklist ID in hidden data component of item locationItem.setData(Qt.UserRole, QVariant(l[2])) speciesCountItem = QTableWidgetItem() speciesCountItem.setData(Qt.DisplayRole, l[1]) locationWidget.setItem(R, 0, locationItem) locationWidget.setItem(R, 1, speciesCountItem) locationWidget.setRowHeight(R, textHeight * 1.1) R = R + 1 self.lblLocationsForDate.setText("Checklists (" + str(locationWidget.rowCount()) + ")")
def CreateSpeciesList(self, callingWidget): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) filter = code_Filter.Filter() filter.setSpeciesName(self.lblCommonName.text()) # Get checklistID(s) and location, depending on the calling widget if callingWidget.objectName() in [ "tblYearLocations", "tblMonthLocations" ]: currentRow = callingWidget.currentRow() checklistID = callingWidget.item(currentRow, 0).data(Qt.UserRole) filter.setChecklistID(checklistID) filter.setLocationType("Location") filter.setLocationName(callingWidget.item(currentRow, 0).text()) date = self.mdiParent.db.GetDates(filter)[0] # even though there is only one checklist here, we need a list to we can # loop it later checklists = [[checklistID]] if callingWidget.objectName() in ["lstDates"]: date = str(callingWidget.currentItem().text()) currentItem = self.trLocations.currentItem() locationName = currentItem.text(0) #need to get the location type based on the tree hierarchy if currentItem.parent() is None: filter.setLocationType("Country") locationName = self.mdiParent.db.GetCountryCode(locationName) elif currentItem.parent().parent() is None: filter.setLocationType("State") locationName = self.mdiParent.db.GetStateCode(locationName) elif currentItem.parent().parent().parent() is None: filter.setLocationType("County") else: filter.setLocationType("Location") filter.setLocationName(locationName) filter.setStartDate(date) filter.setEndDate(date) checklists = self.mdiParent.db.GetChecklists(filter) for c in checklists: cFilter = code_Filter.Filter() cFilter.setChecklistID(c[0]) cLocation = self.mdiParent.db.GetLocations(cFilter, "OnlyLocations")[0] cFilter.setStartDate(date) cFilter.setEndDate(date) cFilter.setLocationType("Location") cFilter.setLocationName(cLocation) sub = code_Lists.Lists() sub.mdiParent = self.mdiParent sub.FillSpecies(cFilter) 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 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 FillSpecies(self): location = self.lblLocation.text() tempFilter = code_Filter.Filter() tempFilter.setLocationType("Location") tempFilter.setLocationName(location) # 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) font = QFont() font.setBold(True) count = 0 nonSpeciesTaxaCount = 0 # add species and dates to table row by row R = 0 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) self.tblSpecies.item(R, 1).setFont(font) # set the species to gray if it's not a true species if " x " in species[0] or "sp." in species[0] or "/" in species[0]: self.tblSpecies.item(R, 1).setForeground(Qt.gray) nonSpeciesTaxaCount += 1 else: self.tblSpecies.item(R, 1).setForeground( code_Stylesheet.speciesColor) count += 1 R += 1 labelText = "Species: " + str(count) if nonSpeciesTaxaCount > 0: labelText = labelText + " + " + str(nonSpeciesTaxaCount) + " taxa" self.lblSpecies.setText(labelText)
def btnResetClicked(self, row): self.fillingCombos = True # get widgets from the row that was clicked container = self.gridPhotos.itemAtPosition(row, 1).widget() for w in container.children(): if "cboLocation" in w.objectName(): cboLocation = w if "cboDate" in w.objectName(): cboDate = w if "cboTime" in w.objectName(): cboTime = w if "cboCommonName" in w.objectName(): cboCommonName = w if "cboRating" in w.objectName(): cboRating = w originalLocation = self.metaDataByRow[row]["location"] originalDate = self.metaDataByRow[row]["date"] originalTime = self.metaDataByRow[row]["time"] originalCommonName = self.metaDataByRow[row]["commonName"] originalRating = self.metaDataByRow[row]["rating"] # set the locations cbo box to original location index = cboLocation.findText(originalLocation) cboLocation.setCurrentIndex(index) # fill date combo box with all dates associated with selected location filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(cboLocation.currentText()) filterForThisPhoto.setLocationType("Location") dates = self.mdiParent.db.GetDates(filterForThisPhoto) cboDate.clear() cboDate.addItems(dates) # set the date cbo box to original date index = cboDate.findText(originalDate) cboDate.setCurrentIndex(index) # fill time combo box with all times associated with selected location and date filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(cboLocation.currentText()) filterForThisPhoto.setLocationType("Location") filterForThisPhoto.setStartDate(originalDate) filterForThisPhoto.setEndDate(originalDate) times = self.mdiParent.db.GetStartTimes(filterForThisPhoto) cboTime.clear() cboTime.addItems(times) # set the time cbo box to original time index = cboTime.findText(originalTime) cboTime.setCurrentIndex(index) # fill commonName combo box with all names associated with selected location, date and time filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(cboLocation.currentText()) filterForThisPhoto.setLocationType("Location") filterForThisPhoto.setStartDate(originalDate) filterForThisPhoto.setEndDate(originalDate) filterForThisPhoto.setTime(originalTime) commonNames = self.mdiParent.db.GetSpecies(filterForThisPhoto) cboCommonName.clear() cboCommonName.addItem("**None Selected**") cboCommonName.addItem("**Detach Photo**") cboCommonName.addItems(commonNames) # set the time cbo box to original time index = cboCommonName.findText(originalCommonName) cboCommonName.setCurrentIndex(index) # set the rating cbo to the original rating index = int(originalRating) cboRating.setCurrentIndex(index) # # turn off highlighting for all cbo boxes self.removeHighlight(cboLocation) self.removeHighlight(cboDate) self.removeHighlight(cboTime) self.removeHighlight(cboCommonName) self.removeHighlight(cboRating) self.fillingCombos = False
def FillPhotosByFilter(self, filter): # it's tempting to think that we could use the insertPhotoIntoTable routine, # but we can't here, because if we're filling photos by filter, we already know # each photo's meta data. The insertPhotoIntoTable routine tries to guess the # location, time, species, etc. from the photo file's embedded meta data. QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.scaleMe() self.resizeMe() self.fillingCombos = True # save the filter settings passed to this routine to the form itself for future use self.filter = filter photoSightings = self.mdiParent.db.GetSightingsWithPhotos(filter) if len(photoSightings) == 0: return False row = 0 # count photos for message display photoCount = 0 for s in photoSightings: photoCount = photoCount + len(s["photos"]) photoCount = str(photoCount) for s in photoSightings: for p in s["photos"]: self.mdiParent.lblStatusBarMessage.setVisible(True) self.mdiParent.lblStatusBarMessage.setText( "Processing photo " + str(row + 1) + " of " + photoCount) # p is a filename. Use it to add the image to the label as a pixmap buttonPhoto = QPushButton() buttonPhoto.setMinimumHeight(281) buttonPhoto.setMinimumWidth(500) # get thumbnail from file to display pixMap = self.GetPixmapForThumbnail(p["fileName"]) buttonPhoto.setIcon(QIcon(pixMap)) # size to 500x281 buttonPhoto.setIconSize(QSize(500, 281)) buttonPhoto.setStyleSheet( "QPushButton {background-color: #343333; border: 0px}") # display thumbnail to new row in grid self.gridPhotos.addWidget(buttonPhoto, row, 0) # set up layout in second column of row to house combo boxes # give each object a name according to the row so we can access them later container = QWidget() container.setObjectName("container" + str(row)) detailsLayout = QVBoxLayout(container) detailsLayout.setObjectName("layout" + str(row)) detailsLayout.setAlignment(Qt.AlignTop) self.gridPhotos.addWidget(container, row, 1) # create combo boxes for details # add connection for when user changes a combo box cboLocation = QComboBox() cboLocation.currentIndexChanged.connect( partial(self.cboLocationChanged, row)) cboDate = QComboBox() cboDate.currentIndexChanged.connect( partial(self.cboDateChanged, row)) cboTime = QComboBox() cboTime.currentIndexChanged.connect( partial(self.cboTimeChanged, row)) cboCommonName = QComboBox() cboCommonName.currentIndexChanged.connect( partial(self.cboCommonNameChanged, row)) cboRating = QComboBox() cboRating.addItems(["Not Rated", "1", "2", "3", "4", "5"]) cboRating.currentIndexChanged.connect( partial(self.cboRatingChanged, row)) # set stylesheet for cmbo boxes for c in [ cboLocation, cboDate, cboTime, cboCommonName, cboRating ]: self.removeHighlight(c) # fill location combo box with all locations in db locations = self.mdiParent.db.locationList cboLocation.addItems(locations) # set location combo box to the photo's location index = cboLocation.findText(s["location"]) if index >= 0: cboLocation.setCurrentIndex(index) # fill date combo box with all dates associated with selected location filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(s["location"]) filterForThisPhoto.setLocationType("Location") dates = self.mdiParent.db.GetDates(filterForThisPhoto) cboDate.addItems(dates) # set date combo box to the photo's associated date index = cboDate.findText(s["date"]) if index >= 0: cboDate.setCurrentIndex(index) # fill time combo box with all times associated with selected location and date filterForThisPhoto.setStartDate(s["date"]) filterForThisPhoto.setEndDate(s["date"]) startTimes = self.mdiParent.db.GetStartTimes( filterForThisPhoto) cboTime.addItems(startTimes) # set time combo box to the photo's associated checklist time index = cboTime.findText(s["time"]) if index >= 0: cboTime.setCurrentIndex(index) # get common names from checklist associated with photo filterForThisPhoto.setChecklistID(s["checklistID"]) commonNames = self.mdiParent.db.GetSpecies(filterForThisPhoto) cboCommonName.addItem("**Detach Photo**") cboCommonName.addItems(commonNames) # set combo box to common name index = cboCommonName.findText(s["commonName"]) if index >= 0: cboCommonName.setCurrentIndex(index) # set combo box to rating value index = int(p["rating"]) cboRating.setCurrentIndex(index) # assign names to combo boxes for future access cboLocation.setObjectName("cboLocation" + str(row)) cboDate.setObjectName("cboDate" + str(row)) cboTime.setObjectName("cboTime" + str(row)) cboCommonName.setObjectName("cboCommonName" + str(row)) cboRating.setObjectName("cboRating" + str(row)) # add combo boxes to the layout in second column detailsLayout.addWidget(cboLocation) detailsLayout.addWidget(cboDate) detailsLayout.addWidget(cboTime) detailsLayout.addWidget(cboCommonName) detailsLayout.addWidget(cboRating) # create and add resent button btnReset = QPushButton() btnReset.setText("Reset") btnReset.clicked.connect(partial(self.btnResetClicked, row)) detailsLayout.addWidget(btnReset) # save meta data for future use when user clicks cbo boxes thisPhotoMetaData = {} thisPhotoMetaData["photoFileName"] = p["fileName"] thisPhotoMetaData["location"] = s["location"] thisPhotoMetaData["date"] = s["date"] thisPhotoMetaData["time"] = s["time"] thisPhotoMetaData["commonName"] = s["commonName"] thisPhotoMetaData["photoData"] = p thisPhotoMetaData["rating"] = p["rating"] self.metaDataByRow[row] = thisPhotoMetaData # initialize the "new" data so that there are values there, even if they're not really new # user can change the cbo boxes later, which will also change the "new" data self.saveNewMetaData(row) row = row + 1 qApp.processEvents() self.mdiParent.lblStatusBarMessage.setText("") self.mdiParent.lblStatusBarMessage.setVisible(False) QApplication.processEvents() icon = QIcon() icon.addPixmap(QPixmap(":/icon_camera.png"), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.setWindowTitle("Manage Photos") self.fillingCombos = False QApplication.restoreOverrideCursor() # tell MainWindow that we succeeded filling the list return (True)
def insertPhotoIntoTable(self, row, photoData, photoMatchData, pixMap): QApplication.processEvents() self.fillingCombos = True photoLocation = photoMatchData["photoLocation"] photoDate = photoMatchData["photoDate"] photoTime = photoMatchData["photoTime"] photoCommonName = photoMatchData["photoCommonName"] # p is a filename. Use it to add the image to the label as a pixmap buttonPhoto = QPushButton() buttonPhoto.setMinimumHeight(281) buttonPhoto.setMinimumWidth(500) buttonPhoto.setIcon(QIcon(pixMap)) # size to 500x281 buttonPhoto.setIconSize(QSize(500, 281)) buttonPhoto.setStyleSheet( "QPushButton {background-color: #343333; border: 0px}") # display thumbnail to new row in grid self.gridPhotos.addWidget(buttonPhoto, row, 0) # set up layout in second column of row to house combo boxes # give each object a name according to the row so we can access them later container = QWidget() container.setObjectName("container" + str(row)) detailsLayout = QVBoxLayout(container) detailsLayout.setObjectName("layout" + str(row)) detailsLayout.setAlignment(Qt.AlignTop) self.gridPhotos.addWidget(container, row, 1) # create combo boxes for details # add connection for when user changes a combo box cboLocation = QComboBox() cboLocation.currentIndexChanged.connect( partial(self.cboLocationChanged, row)) cboDate = QComboBox() cboDate.currentIndexChanged.connect(partial(self.cboDateChanged, row)) cboTime = QComboBox() cboTime.currentIndexChanged.connect(partial(self.cboTimeChanged, row)) cboCommonName = QComboBox() cboCommonName.currentIndexChanged.connect( partial(self.cboCommonNameChanged, row)) cboRating = QComboBox() cboRating.addItems(["Not Rated", "1", "2", "3", "4", "5"]) cboRating.currentIndexChanged.connect( partial(self.cboRatingChanged, row)) # set stylesheet for cbo boxes for c in [cboLocation, cboDate, cboTime, cboCommonName, cboRating]: self.removeHighlight(c) # fill location combo box with all locations in db locations = self.mdiParent.db.locationList cboLocation.addItems(locations) # set location combo box to the photo's location if photoLocation != "": index = cboLocation.findText(photoLocation) if index >= 0: cboLocation.setCurrentIndex(index) # fill date combo box with all dates associated with selected location filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(photoLocation) filterForThisPhoto.setLocationType("Location") dates = self.mdiParent.db.GetDates(filterForThisPhoto) cboDate.addItems(dates) # set date combo box to the photo's associated date index = cboDate.findText(photoDate) if index >= 0: cboDate.setCurrentIndex(index) # fill time combo box with all times associated with selected location and date filterForThisPhoto.setStartDate(photoDate) filterForThisPhoto.setEndDate(photoDate) startTimes = self.mdiParent.db.GetStartTimes( filterForThisPhoto) cboTime.addItems(startTimes) # set time combo box to the photo's associated checklist time index = cboTime.findText(photoTime) if index >= 0: cboTime.setCurrentIndex(index) # get common names from checklist associated with photo filterForThisPhoto.setTime(photoTime) commonNames = self.mdiParent.db.GetSpecies(filterForThisPhoto) cboCommonName.addItem("**Detach Photo**") cboCommonName.addItems(commonNames) # set combo box to common name index = cboCommonName.findText(photoCommonName) if index >= 0: cboCommonName.setCurrentIndex(index) # assign names to combo boxes for future access cboLocation.setObjectName("cboLocation" + str(row)) cboDate.setObjectName("cboDate" + str(row)) cboTime.setObjectName("cboTime" + str(row)) cboCommonName.setObjectName("cboCommonName" + str(row)) cboRating.setObjectName("cboRating" + str(row)) lblFileName = QLabel() lblFileName.setText("File: " + os.path.basename(photoData["fileName"])) lblFileDate = QLabel() lblFileDate.setText("Date: " + photoData["date"]) lblFileTime = QLabel() lblFileTime.setText("Time: " + photoData["time"]) # add combo boxes to the layout in second column detailsLayout.addWidget(lblFileName) detailsLayout.addWidget(lblFileDate) detailsLayout.addWidget(lblFileTime) detailsLayout.addWidget(cboLocation) detailsLayout.addWidget(cboDate) detailsLayout.addWidget(cboTime) detailsLayout.addWidget(cboCommonName) detailsLayout.addWidget(cboRating) # create and add resent button btnReset = QPushButton() btnReset.setText("Reset") btnReset.clicked.connect(partial(self.btnResetClicked, row)) detailsLayout.addWidget(btnReset) # save meta data for future use when user clicks cbo boxes thisPhotoMetaData = {} thisPhotoMetaData["photoFileName"] = photoData["fileName"] thisPhotoMetaData["location"] = photoLocation thisPhotoMetaData["date"] = photoDate thisPhotoMetaData["time"] = cboTime.currentText() thisPhotoMetaData["commonName"] = photoCommonName thisPhotoMetaData["photoData"] = photoData thisPhotoMetaData["rating"] = thisPhotoMetaData["photoData"]["rating"] self.metaDataByRow[row] = thisPhotoMetaData # initialize the "new" data so that there are values there, even if they're not really new # user can change the cbo boxes later, which will also change the "new" data self.saveNewMetaData(row) self.fillingCombos = False
def savePhotoSettings(self): # call database function to remove modified photos from db for r in range(self.gridPhotos.rowCount()): # check if we're processing photos new to the db or ones already in the db if self.photosAlreadyInDb is True: # since photos are already in db, we remove them before adding them back with new meta data # only remove ones whose data has changed metaDataChanged = False if self.metaDataByRow[r]["location"] != self.metaDataByRow[r][ "newLocation"]: metaDataChanged = True if self.metaDataByRow[r]["date"] != self.metaDataByRow[r][ "newDate"]: metaDataChanged = True if self.metaDataByRow[r]["time"] != self.metaDataByRow[r][ "newTime"]: metaDataChanged = True if self.metaDataByRow[r]["commonName"] != self.metaDataByRow[ r]["newCommonName"]: metaDataChanged = True if self.metaDataByRow[r]["rating"] != self.metaDataByRow[r][ "newRating"]: metaDataChanged = True if metaDataChanged is True: # remove the photo from the database self.mdiParent.db.removePhotoFromDatabase( self.metaDataByRow[r]["location"], self.metaDataByRow[r]["date"], self.metaDataByRow[r]["time"], self.metaDataByRow[r]["commonName"], self.metaDataByRow[r]["photoFileName"]) # check whether we're not removing this photo from db # set flag to True, and then set it to False if non-write conditions exist attachPhoto = True if self.metaDataByRow[r]["commonName"] != self.metaDataByRow[ r]["newCommonName"]: if "**" in self.metaDataByRow[r]["newCommonName"]: attachPhoto = False if attachPhoto is True: # Add the photo to the database using its new settings filter = code_Filter.Filter() # use the new values for the filter to save the photo filter.setLocationName( self.metaDataByRow[r]["newLocation"]) filter.setLocationType("Location") filter.setStartDate(self.metaDataByRow[r]["newDate"]) filter.setEndDate(self.metaDataByRow[r]["newDate"]) filter.setTime(self.metaDataByRow[r]["newTime"]) filter.setSpeciesName( self.metaDataByRow[r]["newCommonName"]) self.metaDataByRow[r]["photoData"][ "rating"] = self.metaDataByRow[r]["newRating"] self.mdiParent.db.addPhotoToDatabase( filter, self.metaDataByRow[r]["photoData"]) if self.photosAlreadyInDb is False: # we're processing photo files that aren't yet in the db, so add them # Add the photo to the database using its new settings # set flag to True, and then set it to False if non-write conditions exist attachPhoto = True if "**" in self.metaDataByRow[r]["newCommonName"]: attachPhoto = False if self.metaDataByRow[r]["newCommonName"] == "": attachPhoto = False if attachPhoto is True: filter = code_Filter.Filter() # use the new values for the filter to save the photo filter.setLocationName( self.metaDataByRow[r]["newLocation"]) filter.setLocationType("Location") filter.setStartDate(self.metaDataByRow[r]["newDate"]) filter.setEndDate(self.metaDataByRow[r]["newDate"]) filter.setTime(self.metaDataByRow[r]["newTime"]) filter.setSpeciesName( self.metaDataByRow[r]["newCommonName"]) self.metaDataByRow[r]["photoData"][ "rating"] = self.metaDataByRow[r]["newRating"] self.mdiParent.db.addPhotoToDatabase( filter, self.metaDataByRow[r]["photoData"]) if self.photosAlreadyInDb is False: # ensure that photo filter is visible, if we've added new photos. self.mdiParent.dckPhotoFilter.setVisible(True) # update the photo filter's cbo boxes self.mdiParent.fillPhotoComboBoxes() # set flag indicating that some photo data isn't yet saved to file self.mdiParent.db.photosNeedSaving = True self.mdiParent.db.refreshPhotoLists() self.mdiParent.fillPhotoComboBoxes() # close the window self.close()