Ejemplo n.º 1
0
 def get_file_data(self):
     if not os.path.isdir(self.root):
         return None
     file_list = []
     for root, dirs, files in os.walk(self.root):
         for name in files:
             base, ext = os.path.splitext(name)
             if ext.lower() in self.image_types:
                 file_list.append(os.path.join(root, name))
     file_data = {}
     for path in file_list:
         metadata = Metadata(path)
         timestamp = metadata.date_taken
         if not timestamp:
             timestamp = metadata.date_digitised
         if not timestamp:
             timestamp = metadata.date_modified
         if not timestamp:
             # use file date as last resort
             timestamp = datetime.fromtimestamp(os.path.getmtime(path))
         else:
             timestamp = timestamp.datetime
         name = os.path.basename(path)
         file_data[name] = {
             'camera'    : metadata.camera_model,
             'path'      : path,
             'name'      : name,
             'timestamp' : timestamp,
             }
     return file_data
Ejemplo n.º 2
0
 def reload_metadata(self):
     self.metadata = Metadata(self.path,
                              notify=self.show_status,
                              utf_safe=self.app.options.utf_safe)
     self.show_status(False)
     self.load_thumbnail()
     self.image_list.emit_selection()
Ejemplo n.º 3
0
 def __init__(self, path, image_list, thumb_size=80, *arg, **kw):
     super(Image, self).__init__(*arg, **kw)
     self.path = path
     self.image_list = image_list
     self.name, ext = os.path.splitext(os.path.basename(self.path))
     self.selected = False
     self.thumb_size = thumb_size
     # read metadata
     self.metadata = Metadata(self.path)
     self.metadata.unsaved.connect(self.show_status)
     self.file_times = (os.path.getatime(self.path),
                        os.path.getmtime(self.path))
     # set file type
     self.file_type = self.metadata.get_mime_type()
     if not self.file_type:
         self.file_type = mimetypes.guess_type(self.path)[0]
     if not self.file_type:
         self.file_type = imghdr.what(self.path)
         if self.file_type:
             self.file_type = 'image/' + self.file_type
     # anything not recognised is assumed to be 'raw'
     if not self.file_type:
         self.file_type = 'image/raw'
     # sub widgets
     layout = QtWidgets.QGridLayout()
     layout.setSpacing(0)
     layout.setContentsMargins(3, 3, 3, 3)
     self.setLayout(layout)
     self.setToolTip(self.path)
     # label to display image
     self.image = QtWidgets.QLabel()
     self.image.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
     layout.addWidget(self.image, 0, 0, 1, 2)
     # label to display file name
     self.label = QtWidgets.QLabel()
     self.label.setAlignment(Qt.AlignRight)
     scale_font(self.label, 80)
     layout.addWidget(self.label, 1, 1)
     # label to display status
     self.status = QtWidgets.QLabel()
     self.status.setAlignment(Qt.AlignLeft)
     set_symbol_font(self.status)
     scale_font(self.status, 80)
     layout.addWidget(self.status, 1, 0)
     self.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Plain)
     self.setObjectName("thumbnail")
     self.set_selected(False)
     self.show_status(False)
     self._set_thumb_size(self.thumb_size)
Ejemplo n.º 4
0
 def get_file_info(self, path):
     metadata = Metadata(path, None)
     timestamp = metadata.date_taken
     if not timestamp:
         timestamp = metadata.date_digitised
     if not timestamp:
         timestamp = metadata.date_modified
     if not timestamp:
         # use file date as last resort
         timestamp = datetime.fromtimestamp(os.path.getmtime(path))
     else:
         timestamp = timestamp.datetime
     folder, name = os.path.split(path)
     return {
         'camera': six.text_type(metadata.camera_model),
         'path': path,
         'name': name,
         'timestamp': timestamp,
     }
Ejemplo n.º 5
0
 def __init__(self, path, image_list, thumb_size=80, *arg, **kw):
     super(Image, self).__init__(*arg, **kw)
     self.app = QtWidgets.QApplication.instance()
     self.path = path
     self.image_list = image_list
     self.name, ext = os.path.splitext(os.path.basename(self.path))
     self.selected = False
     self.thumb_size = thumb_size
     # read metadata
     self.metadata = Metadata(self.path,
                              notify=self.show_status,
                              utf_safe=self.app.options.utf_safe)
     self.file_times = (os.path.getatime(self.path),
                        os.path.getmtime(self.path))
     # set file type
     self.file_type = self.metadata.mime_type
     # sub widgets
     layout = QtWidgets.QGridLayout()
     layout.setSpacing(0)
     layout.setContentsMargins(3, 3, 3, 3)
     self.setLayout(layout)
     self.setToolTip(self.path)
     # label to display image
     self.image = QtWidgets.QLabel()
     self.image.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
     layout.addWidget(self.image, 0, 0, 1, 2)
     # label to display file name
     self.label = QtWidgets.QLabel()
     self.label.setAlignment(Qt.AlignRight)
     scale_font(self.label, 80)
     layout.addWidget(self.label, 1, 1)
     # label to display status
     self.status = QtWidgets.QLabel()
     self.status.setAlignment(Qt.AlignLeft)
     set_symbol_font(self.status)
     scale_font(self.status, 80)
     layout.addWidget(self.status, 1, 0)
     self.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Plain)
     self.setObjectName("thumbnail")
     self.set_selected(False)
     self.show_status(False)
     self._set_thumb_size(self.thumb_size)
Ejemplo n.º 6
0
 def get_file_data(self):
     if not os.path.isdir(self.root):
         return None
     file_list = []
     for root, dirs, files in os.walk(self.root):
         # ignore special directories such as .thumbs
         dirs[:] = [x for x in dirs if x[0] != '.']
         for name in files:
             base, ext = os.path.splitext(name)
             if ext.lower() in self.image_types:
                 file_list.append(os.path.join(root, name))
     file_data = {}
     for path in file_list:
         metadata = Metadata(path)
         timestamp = metadata.date_taken
         if not timestamp:
             timestamp = metadata.date_digitised
         if not timestamp:
             timestamp = metadata.date_modified
         if not timestamp:
             # use file date as last resort
             timestamp = datetime.fromtimestamp(os.path.getmtime(path))
         else:
             timestamp = timestamp['datetime']
         sc_path = metadata.find_sidecar()
         name = os.path.basename(path)
         camera = metadata.camera_model
         if camera:
             camera = camera['model']
         file_data[name] = {
             'camera': camera,
             'path': path,
             'sc_path': sc_path,
             'name': name,
             'timestamp': timestamp,
         }
     return file_data
Ejemplo n.º 7
0
 def __init__(self, path, image_list, thumb_size=80, *arg, **kw):
     super(Image, self).__init__(*arg, **kw)
     self.path = path
     self.image_list = image_list
     self.name, ext = os.path.splitext(os.path.basename(self.path))
     self.selected = False
     self.thumb_size = thumb_size
     # read image
     with open(self.path, 'rb') as pf:
         image_data = pf.read()
     # read metadata
     self.metadata = Metadata(
         self.path, image_data, new_status=self.show_status)
     # set file type
     ext = ext.lower()
     self.file_type = imghdr.what(self.path) or 'raw'
     if self.file_type == 'tiff' and ext not in ('.tif', '.tiff'):
         self.file_type = 'raw'
     # make 'master' thumbnail
     self.pixmap = QtGui.QPixmap()
     self.pixmap.loadFromData(image_data)
     unrotate = self.file_type == 'raw'
     if self.pixmap.isNull():
         # image read failed so attempt to use exif thumbnail
         thumb = self.metadata.get_exif_thumbnail()
         if thumb:
             self.pixmap.loadFromData(bytearray(thumb))
             unrotate = False
     if not self.pixmap.isNull():
         if max(self.pixmap.width(), self.pixmap.height()) > 450:
             # store a scaled down version of image to save memory
             self.pixmap = self.pixmap.scaled(
                 300, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
         if unrotate:
             # loading preview which is already re-oriented
             orientation = self.metadata.orientation
             if orientation and orientation.value > 1:
                 # need to unrotate and or unreflect image
                 transform = QtGui.QTransform()
                 if orientation.value in (3, 4):
                     transform = transform.rotate(180.0)
                 elif orientation.value in (5, 6):
                     transform = transform.rotate(-90.0)
                 elif orientation.value in (7, 8):
                     transform = transform.rotate(90.0)
                 if orientation.value in (2, 4, 5, 7):
                     transform = transform.scale(-1.0, 1.0)
                 self.pixmap = self.pixmap.transformed(transform)
     # sub widgets
     layout = QtWidgets.QGridLayout()
     layout.setSpacing(0)
     layout.setContentsMargins(3, 3, 3, 3)
     self.setLayout(layout)
     self.setToolTip(self.path)
     # label to display image
     self.image = QtWidgets.QLabel()
     self.image.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
     layout.addWidget(self.image, 0, 0, 1, 2)
     # label to display file name
     self.label = QtWidgets.QLabel()
     self.label.setAlignment(Qt.AlignRight)
     self.label.setStyleSheet("QLabel { font-size: 12px }")
     layout.addWidget(self.label, 1, 1)
     # label to display status
     self.status = QtWidgets.QLabel()
     self.status.setAlignment(Qt.AlignLeft)
     self.status.setStyleSheet("QLabel { font-size: 12px }")
     self.status.setFont(QtGui.QFont("Dejavu Sans"))
     if not self.status.fontInfo().exactMatch():
         # probably on Windows, try a different font
         self.status.setFont(QtGui.QFont("Segoe UI Symbol"))
     layout.addWidget(self.status, 1, 0)
     self.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Plain)
     self.setObjectName("thumbnail")
     self.set_selected(False)
     self.show_status(False)
     self._set_thumb_size(self.thumb_size)
Ejemplo n.º 8
0
 def reload_metadata(self):
     self.metadata = Metadata(self.path)
     self.metadata.unsaved.connect(self.show_status)
     self.show_status(False)
     self.load_thumbnail()
     self.image_list.emit_selection()
Ejemplo n.º 9
0
 def diff_metadata(self):
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setWindowTitle(translate('ImageList', 'Metadata differences'))
     dialog.setLayout(QtWidgets.QVBoxLayout())
     table = TableWidget()
     table.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                         QtWidgets.QSizePolicy.Expanding)
     table.setColumnCount(3)
     table.setHorizontalHeaderLabels([
         translate('ImageList', 'new value'),
         translate('ImageList', 'undo'),
         translate('ImageList', 'old value')
     ])
     labels = []
     row = 0
     undo = {}
     new_md = self.metadata
     old_md = Metadata(self.path)
     for key in ('title', 'description', 'keywords', 'rating', 'copyright',
                 'creator', 'date_taken', 'date_digitised', 'date_modified',
                 'orientation', 'lens_model', 'lens_make', 'lens_serial',
                 'lens_spec', 'focal_length', 'focal_length_35', 'aperture',
                 'latlong', 'altitude', 'location_taken', 'location_shown',
                 'thumbnail'):
         values = getattr(new_md, key), getattr(old_md, key)
         if values[0] == values[1]:
             continue
         table.setRowCount(row + 1)
         for n, value in enumerate(values):
             if not value:
                 value = ''
             elif isinstance(value, MultiString):
                 value = '\n'.join(value)
             else:
                 value = six.text_type(value)
             item = QtWidgets.QTableWidgetItem(value)
             table.setItem(row, n * 2, item)
         undo[key] = QtWidgets.QTableWidgetItem()
         undo[key].setFlags(undo[key].flags() | Qt.ItemIsUserCheckable)
         undo[key].setCheckState(False)
         table.setItem(row, 1, undo[key])
         labels.append(key)
         row += 1
     table.setVerticalHeaderLabels(labels)
     table.resizeColumnsToContents()
     table.resizeRowsToContents()
     dialog.layout().addWidget(table)
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addWidget(button_box)
     if dialog.exec_() != QtWidgets.QDialog.Accepted:
         return
     changed = False
     dirty = False
     for key, widget in undo.items():
         if widget.checkState() == Qt.Checked:
             setattr(new_md, key, getattr(old_md, key))
             changed = True
         else:
             dirty = True
     if not dirty:
         self.reload_metadata()
     elif changed:
         self.image_list.emit_selection()
Ejemplo n.º 10
0
 def copy_metadata(self, image, path):
     # copy metadata, forcing IPTC creation
     md = Metadata(path, None)
     md.copy(image.metadata)
     md.save(True, 'none', True)
Ejemplo n.º 11
0
 def diff_selected_metadata(self):
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setLayout(QtWidgets.QVBoxLayout())
     dialog.setFixedSize(min(800,
                             self.window().width()),
                         min(400,
                             self.window().height()))
     table = QtWidgets.QTableWidget()
     table.setColumnCount(3)
     table.setHorizontalHeaderLabels([
         translate('ImageList', 'new value'),
         translate('ImageList', 'undo'),
         translate('ImageList', 'old value')
     ])
     table.horizontalHeader().setSectionResizeMode(
         0, QtWidgets.QHeaderView.Stretch)
     table.horizontalHeader().setSectionResizeMode(
         2, QtWidgets.QHeaderView.Stretch)
     dialog.layout().addWidget(table)
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addWidget(button_box)
     changed = False
     position = None
     for image in self.get_selected_images():
         if not image.metadata.changed():
             continue
         dialog.setWindowTitle(
             translate('ImageList',
                       'Metadata differences: {}').format(image.name))
         labels = []
         row = 0
         undo = {}
         table.clearContents()
         new_md = image.metadata
         old_md = Metadata(image.path)
         for key in ('title', 'description', 'keywords', 'rating',
                     'copyright', 'creator', 'date_taken', 'date_digitised',
                     'date_modified', 'orientation', 'camera_model',
                     'lens_model', 'lens_spec', 'focal_length',
                     'focal_length_35', 'aperture', 'latlong', 'altitude',
                     'location_taken', 'location_shown', 'thumbnail'):
             values = getattr(new_md, key), getattr(old_md, key)
             if values[0] == values[1]:
                 continue
             values = [str(x or '') for x in values]
             table.setRowCount(row + 1)
             for n, value in enumerate(values):
                 item = QtWidgets.QTableWidgetItem(value)
                 table.setItem(row, n * 2, item)
             undo[key] = QtWidgets.QTableWidgetItem()
             undo[key].setFlags(undo[key].flags() | Qt.ItemIsUserCheckable)
             undo[key].setCheckState(Qt.Unchecked)
             table.setItem(row, 1, undo[key])
             labels.append(key)
             row += 1
         if not row:
             continue
         table.setVerticalHeaderLabels(labels)
         table.resizeColumnsToContents()
         table.resizeRowsToContents()
         if position:
             dialog.move(position)
         if dialog.exec_() != QtWidgets.QDialog.Accepted:
             return
         position = dialog.pos()
         undo_all = True
         for key, widget in undo.items():
             if widget.checkState() == Qt.Checked:
                 setattr(new_md, key, getattr(old_md, key))
                 changed = True
             else:
                 undo_all = False
         if undo_all:
             image.reload_metadata()
     if changed:
         self.emit_selection()