def is_size_ok(self, index): model = self.sourceModel() size = model.data(index, QtCore.Qt.UserRole+5).toPyObject() if size is None: return True width, height = size if width * height == 0: photo_id = model.data(index, QtCore.Qt.UserRole+7).toPyObject() path = model.data(index, QtCore.Qt.UserRole+6).toPyObject() if path is not None and photo_id is not None and os.path.exists(path): # Fix up the database by reading the image image = Image.open(str(path)) width, height = image.size Photo.upsert({'id': photo_id, 'width': width, 'height': height}) else: return False if (width * height) < 20000: return False space_used = (6 * height) / (8 * width) if space_used > 1: space_used = 1 / space_used if space_used < 0.95: return False return True
def person_updated(self, origin): if not origin - set(['CropFrame']): return if self.person.current_photo_id is None: return if self.photo is not None and self.photo.id == self.person.current_photo_id: return if self.photo is not None: self.photo.updated.disconnect(self.photo_updated) self.photo = Photo.get(id=self.person.current_photo_id) self.photo.updated.connect(self.photo_updated) self.photo_load_retries = 0 self.photo_updated(set(['init']))
def load_person(self, id, refresh=False): if self.photo_load_failed: return p = self.image_list_items[id].person photo = self.image_list_items[id].photo # Suppress history updates when changing the item with # back/forwards, because they have special handling if not self.suppress_history and self.current_photo is not None and self.current_person.id != id: self.history_back.append(self.current_person.id) self.back.setDisabled(False) self.history_forwards.clear() self.forwards.setDisabled(True) while len(self.history_back) > 10: self.history_back.popleft() self.clear_image() self.history_model.clear() self.current_person = p self.info_person_id.setText('%d' % self.current_person.id) self.info_fullname.setText(self.current_person.fullname) self.info_title.setText(self.current_person.title) self.info_firstname.setText(self.current_person.firstname) self.info_lastname.setText(self.current_person.lastname) self.info_police_status.setText(self.current_person.police_status) self.info_person_fetched_at.setText(time.ctime(self.current_person.last_checked_at)) if photo is not None and photo.full_path() is not None: self.current_photo = photo filename = self.current_photo.local_filename() self.info_photo_filename.setText(filename if filename else '') self.info_photo_fetched_at.setText(time.ctime(self.current_photo.date_fetched)) self.person_name.setText(u'Loading %s...' % p) self.upload_wizard.upload_photos_thisname.setText(unicode(p)) self.main_photo_cache.load_image(photo.id, photo.full_path(), photo.url, ready_cb=self.handle_photo_ready, fail_cb=self.handle_photo_fail, urgent=True, refresh=refresh, ) else: self.person_name.setText(unicode(self.current_person)) photos = Photo.by_person(self.current_person.id) self.history_model.clear() self.history_items = {} for photo in sorted(photos, key=lambda photo: photo.date_fetched, reverse=True): item = QtGui.QStandardItem() msg = "Fetched at %s" % time.ctime(photo.date_fetched) if self.current_person.current_photo_id == photo.id: msg = msg + "\nCurrent photo" else: msg = msg + "\n%s" % photo.opinion item.setText(msg) item.setTextAlignment(QtCore.Qt.AlignCenter) item.setData(photo.id) self.history_items[photo.id] = item self.history_model.appendRow(item) self.list_photo_cache.load_image(photo.id, photo.full_path(), photo.url, ready_cb=self.handle_history_photo_ready)
def __init__(self, dbmanager, parent=None): super(QtGui.QWidget, self).__init__(parent) self.setupUi(self) self.setWindowTitle('Image Editing v' + ef.__version__) self.settings = QtCore.QSettings() self.main_stack.setCurrentIndex(0) self.username = self.settings.value('ef-username', '').toString() self.ef_username.setText(self.username) self.password = '' self.try_login = TryLogin() self.try_login.completed.connect(self.try_login_completed) self.try_login.error.connect(self.try_login_error) self.ef_login.clicked.connect(self.try_ef_login) self.ef_password.returnPressed.connect(self.try_ef_login) self.history_make_current.setIcon(self.style().standardIcon(QtGui.QStyle.SP_ArrowRight)) self.back.setIcon(self.style().standardIcon(QtGui.QStyle.SP_ArrowBack)) self.forwards.setIcon(self.style().standardIcon(QtGui.QStyle.SP_ArrowForward)) self.back.setDisabled(True) self.forwards.setDisabled(True) self.photodownloader = PhotoDownloader() self.list_photo_cache = ThumbnailCache(self.photodownloader, 100) self.main_photo_cache = PhotoImageCache(self.photodownloader, 10) self.fetcher = Fetcher() self.reportsfetcher = ReportsFetcher() self.uploader = Uploader() self.current_person = None self.current_photo = None self.current_image = None self.loading_now = False self.photo_load_failed = False self.registration_loaded = self.person_loaded = False self.history_back = deque() self.history_forwards = deque() self.suppress_history = False self.upload_wizard = UploadPeopleWizard() self.image_list_items = {} self.edit_scene = QtGui.QGraphicsScene(self) self.main_image.setScene(self.edit_scene) self.main_pixmap = EditPixmap(self.wheel_event) self.edit_scene.addItem(self.main_pixmap) self.crop_frame = CropFrame(self.main_pixmap, self.output_updated) self.main_pixmap.setZValue(1) self.crop_frame.setZValue(2) self.events = {} self.event_load_handlers = {} self.person_model = QtGui.QStandardItemModel(self) self.person_model.setColumnCount(1) self.person_model_proxy = FilterProxyModel() self.person_model_proxy.setDynamicSortFilter(True) self.person_model_proxy.setSourceModel(self.person_model) self.person_model_proxy.setSortCaseSensitivity(False) self.person_model_proxy.setSortRole(QtCore.Qt.UserRole+1) self.person_model_proxy.sort(0) self.person_model_proxy.rowsInserted.connect(self.handle_filter_count) self.person_model_proxy.rowsRemoved.connect(self.handle_filter_count) self.person_model_proxy.modelReset.connect(self.handle_filter_count) self.filter_opinion.currentIndexChanged[str].connect(self.person_model_proxy.set_opinion) self.filter_DNU.currentIndexChanged[str].connect(self.person_model_proxy.set_DNU) self.filter_event.currentIndexChanged[int].connect(self.handle_filter_event_changed) self.filter_category.currentIndexChanged[str].connect(self.person_model_proxy.set_category) self.filter_police.currentIndexChanged[str].connect(self.person_model_proxy.set_police_status) self.filter_by_size.stateChanged.connect(self.person_model_proxy.set_only_bad_sizes) self.filter_only_missing.stateChanged.connect(self.person_model_proxy.set_only_missing) self.filter_only_upload.stateChanged.connect(self.person_model_proxy.set_only_upload) self.filters_reset.clicked.connect(self.handle_reset_filters) self.export_people.clicked.connect(self.handle_export_people) self.history_model = QtGui.QStandardItemModel(self) self.history_model.setColumnCount(1) self.history_list.setModel(self.history_model) self.history_items = {} self.history_make_current.clicked.connect(self.handle_historymakecurrent) self.dbmanager = dbmanager dbmanager.created.connect(self.handle_db_created) dbmanager.exception.connect(self.handle_db_exception) dbmanager.existing_done.connect(self.handle_db_existing_done) dbmanager.process_done.connect(self.handle_db_process_done) Photo.signal_existing_created() Registration.signal_existing_created() Event.signal_existing_created() Person.signal_existing_created() self.output_updated.connect(self.handle_crop) self.wheel_event.connect(self.crop_frame.handle_wheel) self.opinion_ok.clicked.connect(self.handle_opinion_ok) self.opinion_bad.clicked.connect(self.handle_opinion_bad) self.opinion_unsure.clicked.connect(self.handle_opinion_unsure) self.do_not_upload.stateChanged.connect(self.handle_do_not_upload) self.back.clicked.connect(self.handle_back) self.forwards.clicked.connect(self.handle_forwards) self.search.clicked.connect(self.handle_search) self.search_for.returnPressed.connect(self.handle_search) self.action_fetch.triggered.connect(self.handle_fetch_wizard) self.fetch_this_person.clicked.connect(self.handle_fetch_person) self.fetcher.completed.connect(self.handle_fetch_completed) self.fetcher.error.connect(self.handle_fetch_error) self.fetcher.progress.connect(self.handle_fetch_progress) self.reportsfetcher.error.connect(self.handle_reportsfetch_error) self.action_upload.triggered.connect(self.handle_upload_wizard) self.upload_wizard.accepted.connect(self.handle_upload) self.upload_wizard.rejected.connect(self.handle_upload_rejected) self.uploader.completed.connect(self.handle_upload_completed) self.uploader.error.connect(self.handle_upload_error) self.uploader.progress.connect(self.handle_upload_progress) self.rotate.valueChanged.connect(self.handle_rotate) self.rotate_0.clicked.connect(lambda: self.rotate.setValue(0)) self.rotate_l90.clicked.connect(lambda: self.rotate.setValue(-90)) self.rotate_l180.clicked.connect(lambda: self.rotate.setValue(-180)) self.rotate_r90.clicked.connect(lambda: self.rotate.setValue(90)) self.rotate_r180.clicked.connect(lambda: self.rotate.setValue(180)) self.brightness_slider.valueChanged.connect(self.handle_brightness) self.contrast_slider.valueChanged.connect(self.handle_contrast) self.gamma_slider.valueChanged.connect(lambda v: self.gamma_spin.setValue(v/10)) self.gamma_spin.valueChanged.connect(lambda v: self.gamma_slider.setValue(v*10)) self.gamma_slider.valueChanged.connect(self.handle_gamma) self.action_openeventsforce.triggered.connect(self.handle_openeventsforce) self.openeventsforce.clicked.connect(self.handle_openeventsforce) self.action_reloadphoto.triggered.connect(self.handle_reloadphoto) self.action_editimage.triggered.connect(self.handle_editimage) self.editimage.clicked.connect(self.handle_editimage) self.action_importphoto.triggered.connect(self.handle_import_photo) self.openimage = QtGui.QFileDialog(self, 'Import image') self.openimage.setFileMode(QtGui.QFileDialog.ExistingFile) self.openimage.setNameFilter('*.jpg *.jpeg') self.openimage.restoreState(self.settings.value('openimage-state', '').toByteArray()) self.action_chooseeditor.triggered.connect(self.handle_chooseeditor) self.chooseeditor = QtGui.QFileDialog(self, 'Choose image editor') self.chooseeditor.setFileMode(QtGui.QFileDialog.ExistingFile) if os.name == 'nt': self.chooseeditor.setNameFilter('*.exe') self.chooseeditor.restoreState(self.settings.value('chooseeditor-state', '').toByteArray()) self.savereport = QtGui.QFileDialog(self, 'Save report') self.savereport.setFileMode(QtGui.QFileDialog.AnyFile) self.savereport.setAcceptMode(QtGui.QFileDialog.AcceptSave) self.savereport.setNameFilter('*.csv') self.savereport.setDefaultSuffix('csv') self.savereport.restoreState(self.settings.value('savereport-state', '').toByteArray()) self.image_editor = self.settings.value('image-editor', '').toString() self.action_export.triggered.connect(self.handle_export) self.action_import.triggered.connect(self.handle_import) self.saveexport = QtGui.QFileDialog(self, 'Export database') self.saveexport.setFileMode(QtGui.QFileDialog.AnyFile) self.saveexport.setAcceptMode(QtGui.QFileDialog.AcceptSave) self.saveexport.setNameFilter('*.yaml') self.saveexport.setDefaultSuffix('yaml') self.saveexport.restoreState(self.settings.value('saveexport-state', '').toByteArray()) self.openimport = QtGui.QFileDialog(self, 'Import database') self.openimport.setFileMode(QtGui.QFileDialog.ExistingFile) self.openimport.setNameFilter('*.yaml') self.openimport.restoreState(self.settings.value('openimport-state', '').toByteArray()) self.status_expiry_timer = QtCore.QTimer(self) self.status_expiry_timer.setInterval(5000) self.status_expiry_timer.timeout.connect(self.status_idle) self.status_task = '' self.status_started = None self.status_timer = QtCore.QTimer(self) self.status_timer.setInterval(500) self.status_timer.timeout.connect(self.status_timer_update) self.status_is_idle = True self.draw_timer = QtCore.QTimer(self) self.draw_timer.setInterval(50) self.draw_timer.timeout.connect(self.handle_draw) self.draw_timer.start() self.image_draw_needed = False self.photodownloader.queue_size.connect(self.status_downloader) self.photodownloader.error.connect(self.photodownload_error) self.procs = {} self.status_idle()
def photodownload_error(self, id, msg): photo = Photo.get(id=id) photo.update_load_failed(True, origin='load_failed')