예제 #1
0
 def __init__(self, image_list, parent=None):
     super(TabWidget, self).__init__(parent)
     self.app = QtWidgets.QApplication.instance()
     self.geocoder = self.app.open_cage
     self.image_list = image_list
     self.setLayout(QtWidgets.QHBoxLayout())
     ## left side
     left_side = QtWidgets.QGridLayout()
     # latitude & longitude
     self.coords = LatLongDisplay(self.image_list)
     left_side.addWidget(self.coords.label, 0, 0)
     self.coords.changed.connect(self.new_coords)
     left_side.addWidget(self.coords, 0, 1)
     # convert lat/lng to location info
     self.auto_location = QtWidgets.QPushButton(
         translate('AddressTab', 'Get address from lat, long'))
     self.auto_location.setEnabled(False)
     self.auto_location.clicked.connect(self.get_address)
     left_side.addWidget(self.auto_location, 1, 0, 1, 2)
     # terms and conditions
     terms = self.geocoder.search_terms(search=False)
     left_side.addWidget(terms[0], 3, 0, 1, 2)
     left_side.addWidget(terms[1], 4, 0, 1, 2)
     left_side.setColumnStretch(1, 1)
     left_side.setRowStretch(2, 1)
     self.layout().addLayout(left_side)
     ## right side
     # location info
     self.location_widgets = []
     self.location_info = QtWidgets.QTabWidget()
     tab_bar = QTabBar()
     self.location_info.setTabBar(tab_bar)
     tab_bar.context_menu.connect(self.location_tab_context_menu)
     tab_bar.tabMoved.connect(self.location_tab_moved)
     self.location_info.setElideMode(Qt.ElideLeft)
     self.location_info.setMovable(True)
     self.location_info.setEnabled(False)
     self.layout().addWidget(self.location_info, stretch=1)
     # other init
     self.image_list.image_list_changed.connect(self.image_list_changed)
예제 #2
0
class TabWidget(QtWidgets.QWidget):
    @staticmethod
    def tab_name():
        return translate('AddressTab', '&Address')

    def __init__(self, image_list, parent=None):
        super(TabWidget, self).__init__(parent)
        self.app = QtWidgets.QApplication.instance()
        self.geocoder = self.app.open_cage
        self.image_list = image_list
        self.setLayout(QtWidgets.QHBoxLayout())
        ## left side
        left_side = QtWidgets.QGridLayout()
        # latitude & longitude
        self.coords = LatLongDisplay(self.image_list)
        left_side.addWidget(self.coords.label, 0, 0)
        self.coords.changed.connect(self.new_coords)
        left_side.addWidget(self.coords, 0, 1)
        # convert lat/lng to location info
        self.auto_location = QtWidgets.QPushButton(
            translate('AddressTab', 'Get address from lat, long'))
        self.auto_location.setEnabled(False)
        self.auto_location.clicked.connect(self.get_address)
        left_side.addWidget(self.auto_location, 1, 0, 1, 2)
        # terms and conditions
        terms = self.geocoder.search_terms(search=False)
        left_side.addWidget(terms[0], 3, 0, 1, 2)
        left_side.addWidget(terms[1], 4, 0, 1, 2)
        left_side.setColumnStretch(1, 1)
        left_side.setRowStretch(2, 1)
        self.layout().addLayout(left_side)
        ## right side
        # location info
        self.location_widgets = []
        self.location_info = QtWidgets.QTabWidget()
        tab_bar = QTabBar()
        self.location_info.setTabBar(tab_bar)
        tab_bar.context_menu.connect(self.location_tab_context_menu)
        tab_bar.tabMoved.connect(self.location_tab_moved)
        self.location_info.setElideMode(Qt.ElideLeft)
        self.location_info.setMovable(True)
        self.location_info.setEnabled(False)
        self.layout().addWidget(self.location_info, stretch=1)
        # other init
        self.image_list.image_list_changed.connect(self.image_list_changed)

    @QtSlot()
    @catch_all
    def image_list_changed(self):
        self.coords.refresh()
        self.auto_location.setEnabled(bool(self.coords.get_value()))
        self.display_location()

    def refresh(self):
        pass

    def do_not_close(self):
        return False

    @QtSlot()
    @catch_all
    def new_coords(self):
        self.auto_location.setEnabled(bool(self.coords.get_value()))

    @QtSlot(QtGui.QContextMenuEvent)
    @catch_all
    def location_tab_context_menu(self, event):
        idx = self.location_info.tabBar().tabAt(event.pos())
        self.location_info.setCurrentIndex(idx)
        menu = QtWidgets.QMenu(self)
        menu.addAction(translate('AddressTab', 'Duplicate location'),
                       self.duplicate_location)
        menu.addAction(translate('AddressTab', 'Delete location'),
                       self.delete_location)
        action = menu.exec_(event.globalPos())

    @QtSlot()
    @catch_all
    def duplicate_location(self):
        idx = self.location_info.currentIndex()
        for image in self.image_list.get_selected_images():
            # duplicate data
            location = Location(self._get_location(image, idx) or {})
            # shuffle data up
            location_list = list(image.metadata.location_shown or [])
            location_list.insert(idx, location)
            image.metadata.location_shown = location_list
        # display data
        self.display_location()

    @QtSlot()
    @catch_all
    def delete_location(self):
        idx = self.location_info.currentIndex()
        for image in self.image_list.get_selected_images():
            # shuffle data down
            location_list = list(image.metadata.location_shown or [])
            if idx == 0:
                if location_list:
                    location = location_list.pop(0)
                else:
                    location = None
                image.metadata.location_taken = location
            elif idx <= len(location_list):
                del location_list[max(idx - 1, 0)]
            image.metadata.location_shown = location_list
        # display data
        self.display_location()

    @QtSlot(int, int)
    @catch_all
    def location_tab_moved(self, idx_a, idx_b):
        self.pending_move = idx_a, idx_b
        # do actual swap when idle to avoid seg fault
        QtCore.QTimer.singleShot(0, self._location_tab_moved)

    @QtSlot()
    @catch_all
    def _location_tab_moved(self):
        idx_a, idx_b = self.pending_move
        # swap data
        for image in self.image_list.get_selected_images():
            temp_a = self._get_location(image, idx_a)
            temp_b = self._get_location(image, idx_b)
            self._set_location(image, idx_a, temp_b)
            self._set_location(image, idx_b, temp_a)
        # adjust tab names
        for idx in range(min(idx_a, idx_b), max(idx_a, idx_b) + 1):
            self.set_tab_text(idx)
        # display data
        self.display_location()

    def _get_location(self, image, idx):
        if idx == 0:
            return image.metadata.location_taken
        elif not image.metadata.location_shown:
            return None
        elif idx <= len(image.metadata.location_shown):
            return image.metadata.location_shown[idx - 1]
        return None

    def _set_location(self, image, idx, location):
        if idx == 0:
            image.metadata.location_taken = location
        else:
            location_list = list(image.metadata.location_shown or [])
            while len(location_list) < idx:
                location_list.append(None)
            location_list[idx - 1] = location
            image.metadata.location_shown = location_list

    @QtSlot(object, dict)
    @catch_all
    def new_location(self, widget, new_value):
        idx = self.location_info.indexOf(widget)
        for image in self.image_list.get_selected_images():
            temp = dict(self._get_location(image, idx) or {})
            temp.update(new_value)
            self._set_location(image, idx, temp)
        # new_location can be called when changing tab, so don't delete
        # tabs until later
        QtCore.QTimer.singleShot(0, self.display_location)

    def set_tab_text(self, idx):
        if idx == 0:
            text = translate('AddressTab', 'camera')
        else:
            text = translate('AddressTab', 'subject {}').format(idx)
        self.location_info.setTabText(idx, text)

    @QtSlot()
    @catch_all
    def display_location(self):
        images = self.image_list.get_selected_images()
        # get required number of tabs
        count = 0
        for image in images:
            if image.metadata.location_shown:
                count = max(count, len(image.metadata.location_shown))
        count += 2
        # add or remove tabs
        if self.location_info.currentIndex() >= count:
            self.location_info.setCurrentIndex(count - 1)
        idx = self.location_info.count()
        while idx < count:
            if not self.location_widgets:
                widget = LocationInfo()
                widget.new_value.connect(self.new_location)
                self.location_widgets.append(widget)
            self.location_info.addTab(self.location_widgets.pop(), '')
            self.set_tab_text(idx)
            idx += 1
        while idx > count:
            idx -= 1
            self.location_widgets.append(self.location_info.widget(idx))
            self.location_info.removeTab(idx)
        # display data
        for idx in range(count):
            widget = self.location_info.widget(idx)
            if images:
                values = defaultdict(list)
                for image in images:
                    location = self._get_location(image, idx) or {}
                    for key in widget.members:
                        value = None
                        if key in location:
                            value = location[key]
                        if value not in values[key]:
                            values[key].append(value)
                for key in widget.members:
                    if len(values[key]) > 1:
                        widget.members[key].set_multiple(
                            choices=filter(None, values[key]))
                    else:
                        widget.members[key].set_value(values[key][0])
            else:
                for key in widget.members:
                    widget.members[key].set_value(None)

    @QtSlot(list)
    @catch_all
    def new_selection(self, selection):
        self.location_info.setEnabled(bool(selection))
        self.coords.refresh()
        self.auto_location.setEnabled(bool(self.coords.get_value()))
        self.display_location()

    @QtSlot()
    @catch_all
    def get_address(self):
        location = self.geocoder.get_address(self.coords.get_value())
        if location:
            self.new_location(self.location_info.currentWidget(), location)