예제 #1
0
    def getIssueCoverMatchScore(
            self,
            comicVine,
            issue_id,
            primary_img_url,
            primary_thumb_url,
            page_url,
            localCoverHashList,
            useRemoteAlternates=False,
            useLog=True):
        # localHashes is a list of pre-calculated hashs.
        # useRemoteAlternates - indicates to use alternate covers from CV

        try:
            url_image_data = ImageFetcher().fetch(
                primary_thumb_url, blocking=True)
        except ImageFetcherException:
            self.log_msg(
                "Network issue while fetching cover image from Comic Vine. Aborting...")
            raise IssueIdentifierNetworkError

        if self.cancel:
            raise IssueIdentifierCancelled

        # alert the GUI, if needed
        if self.coverUrlCallback is not None:
            self.coverUrlCallback(url_image_data)

        remote_cover_list = []
        item = dict()
        item['url'] = primary_img_url

        item['hash'] = self.calculateHash(url_image_data)
        remote_cover_list.append(item)

        if self.cancel:
            raise IssueIdentifierCancelled

        if useRemoteAlternates:
            alt_img_url_list = comicVine.fetchAlternateCoverURLs(
                issue_id, page_url)
            for alt_url in alt_img_url_list:
                try:
                    alt_url_image_data = ImageFetcher().fetch(
                        alt_url, blocking=True)
                except ImageFetcherException:
                    self.log_msg(
                        "Network issue while fetching alt. cover image from Comic Vine. Aborting...")
                    raise IssueIdentifierNetworkError

                if self.cancel:
                    raise IssueIdentifierCancelled

                # alert the GUI, if needed
                if self.coverUrlCallback is not None:
                    self.coverUrlCallback(alt_url_image_data)

                item = dict()
                item['url'] = alt_url
                item['hash'] = self.calculateHash(alt_url_image_data)
                remote_cover_list.append(item)

                if self.cancel:
                    raise IssueIdentifierCancelled

        if useLog and useRemoteAlternates:
            self.log_msg(
                "[{0} alt. covers]".format(len(remote_cover_list) - 1), False)
        if useLog:
            self.log_msg("[ ", False)

        score_list = []
        done = False
        for local_cover_hash in localCoverHashList:
            for remote_cover_item in remote_cover_list:
                score = ImageHasher.hamming_distance(
                    local_cover_hash, remote_cover_item['hash'])
                score_item = dict()
                score_item['score'] = score
                score_item['url'] = remote_cover_item['url']
                score_item['hash'] = remote_cover_item['hash']
                score_list.append(score_item)
                if useLog:
                    self.log_msg("{0}".format(score), False)

                if score <= self.strong_score_thresh:
                    # such a good score, we can quit now, since for sure we
                    # have a winner
                    done = True
                    break
            if done:
                break

        if useLog:
            self.log_msg(" ]", False)

        best_score_item = min(score_list, key=lambda x: x['score'])

        return best_score_item
예제 #2
0
class CoverImageWidget(QWidget):
	
	ArchiveMode = 0
	AltCoverMode = 1
	URLMode = 1
	DataMode = 3
	
	def __init__(self, parent, mode, expand_on_click = True ):
		super(CoverImageWidget, self).__init__(parent)
		
		uic.loadUi(ComicTaggerSettings.getUIFile('coverimagewidget.ui' ), self)

		utils.reduceWidgetFontSize( self.label )

		self.mode = mode
		self.comicVine = ComicVineTalker()
		self.page_loader = None
		self.showControls = True

		self.btnLeft.setIcon(QIcon(ComicTaggerSettings.getGraphic('left.png')))
		self.btnRight.setIcon(QIcon(ComicTaggerSettings.getGraphic('right.png')))
		
		self.btnLeft.clicked.connect( self.decrementImage )
		self.btnRight.clicked.connect( self.incrementImage )
		self.resetWidget()
		if expand_on_click:
			clickable(self.lblImage).connect(self.showPopup)
		else:
			self.lblImage.setToolTip( "" )

		self.updateContent()

	def resetWidget(self):
		self.comic_archive = None
		self.issue_id = None
		self.comicVine = None
		self.cover_fetcher = None
		self.url_list = []
		if self.page_loader is not None:
			self.page_loader.abandoned = True
		self.page_loader = None
		self.imageIndex = -1
		self.imageCount = 1
		self.imageData = None
		
	def clear( self ):
		self.resetWidget()
		self.updateContent()
		
	def incrementImage( self ):
		self.imageIndex += 1
		if self.imageIndex == self.imageCount:
			self.imageIndex = 0
		self.updateContent()

	def decrementImage( self ):
		self.imageIndex -= 1
		if self.imageIndex == -1:
			self.imageIndex = self.imageCount -1
		self.updateContent()
			
	def setArchive( self, ca, page=0 ):
		if self.mode == CoverImageWidget.ArchiveMode:
			self.resetWidget()
			self.comic_archive = ca
			self.imageIndex = page
			self.imageCount = ca.getNumberOfPages()
			self.updateContent()

	def setURL( self, url ):
		if self.mode == CoverImageWidget.URLMode:
			self.resetWidget()
			self.updateContent()
			
			self.url_list = [ url ] 
			self.imageIndex = 0
			self.imageCount = 1
			self.updateContent()

	def setIssueID( self, issue_id ):
		if self.mode == CoverImageWidget.AltCoverMode:
			self.resetWidget()
			self.updateContent()
			
			self.issue_id = issue_id

			self.comicVine = ComicVineTalker()
			self.comicVine.urlFetchComplete.connect( self.primaryUrlFetchComplete )	
			self.comicVine.asyncFetchIssueCoverURLs( int(self.issue_id) )

	def setImageData( self, image_data ):
		if self.mode == CoverImageWidget.DataMode:
			self.resetWidget()
			
			if image_data is None:
				self.imageIndex = -1
			else:
				self.imageIndex = 0
				self.imageData = image_data
				
			self.updateContent()
			
	def primaryUrlFetchComplete( self, primary_url, thumb_url, issue_id ):
		self.url_list.append(str(primary_url))
		self.imageIndex = 0
		self.imageCount = len(self.url_list)
		self.updateContent()

		#defer the alt cover search 		
		QTimer.singleShot(1, self.startAltCoverSearch)

	def startAltCoverSearch( self ):

		# now we need to get the list of alt cover URLs
		self.label.setText("Searching for alt. covers...")
		
		# page URL should already be cached, so no need to defer
		self.comicVine = ComicVineTalker()
		issue_page_url = self.comicVine.fetchIssuePageURL( self.issue_id )
		self.comicVine.altUrlListFetchComplete.connect( self.altCoverUrlListFetchComplete )	
		self.comicVine.asyncFetchAlternateCoverURLs( int(self.issue_id),  issue_page_url)
		
	def altCoverUrlListFetchComplete( self, url_list, issue_id ):
		if len(url_list) > 0:
			self.url_list.extend(url_list)
			self.imageCount = len(self.url_list)
		self.updateControls()

	def setPage( self, pagenum ):
		if self.mode == CoverImageWidget.ArchiveMode:
			self.imageIndex = pagenum
			self.updateContent()
	
	def updateContent( self ):
		self.updateImage()
		self.updateControls()
		
	def updateImage( self ):
		if self.imageIndex == -1:
			self.loadDefault()
		elif self.mode in [ CoverImageWidget.AltCoverMode,  CoverImageWidget.URLMode ]:
			self.loadURL()
		elif self.mode == CoverImageWidget.DataMode:
			self.coverRemoteFetchComplete( self.imageData, 0 )
		else:
			self.loadPage()
	
	def updateControls( self ):
		if not self.showControls or self.mode == CoverImageWidget.DataMode:
			self.btnLeft.hide()
			self.btnRight.hide()
			self.label.hide()
			return
			
		if self.imageIndex == -1  or self.imageCount == 1:
			self.btnLeft.setEnabled(False)
			self.btnRight.setEnabled(False)
			self.btnLeft.hide()
			self.btnRight.hide()
		else:
			self.btnLeft.setEnabled(True)
			self.btnRight.setEnabled(True)
			self.btnLeft.show()
			self.btnRight.show()
		
		if self.imageIndex == -1  or self.imageCount == 1:
			self.label.setText("")		
		elif self.mode == CoverImageWidget.AltCoverMode:		
			self.label.setText("Cover {0} ( of {1} )".format(self.imageIndex+1, self.imageCount))
		else:
			self.label.setText("Page {0} ( of {1} )".format(self.imageIndex+1, self.imageCount))
	
	def loadURL( self ):
		self.loadDefault()
		self.cover_fetcher = ImageFetcher( )
		self.cover_fetcher.fetchComplete.connect(self.coverRemoteFetchComplete)
		self.cover_fetcher.fetch( self.url_list[self.imageIndex] )
		#print "ATB cover fetch started...."
				
	# called when the image is done loading from internet
	def coverRemoteFetchComplete( self, image_data, issue_id ):
		img = QImage()
		img.loadFromData( image_data )
		self.current_pixmap = QPixmap(img)
		self.setDisplayPixmap( 0, 0)
		#print "ATB cover fetch complete!"

	def loadPage( self ):
		if self.comic_archive is not None:
			if self.page_loader is not None:
				self.page_loader.abandoned = True
			self.page_loader = PageLoader( self.comic_archive, self.imageIndex )
			self.page_loader.loadComplete.connect( self.pageLoadComplete )	
			self.page_loader.start()

	def pageLoadComplete( self, img ):
		self.current_pixmap = QPixmap(img)
		self.setDisplayPixmap( 0, 0)
		self.page_loader = None
					
	def loadDefault( self ):
		self.current_pixmap = QPixmap(ComicTaggerSettings.getGraphic('nocover.png'))
		#print "loadDefault called"
		self.setDisplayPixmap( 0, 0)

	def resizeEvent( self, resize_event ):
		if self.current_pixmap is not None:
			delta_w = resize_event.size().width() - resize_event.oldSize().width()
			delta_h = resize_event.size().height() - resize_event.oldSize().height()
			#print "ATB resizeEvent deltas", resize_event.size().width(), resize_event.size().height()
			self.setDisplayPixmap( delta_w , delta_h )
							
	def setDisplayPixmap( self, delta_w , delta_h ):
			# the deltas let us know what the new width and height of the label will be
			"""
			new_h = self.frame.height() + delta_h
			new_w = self.frame.width() + delta_w
			print "ATB setDisplayPixmap deltas", delta_w , delta_h
			print "ATB self.frame", self.frame.width(), self.frame.height()
			print "ATB self.", self.width(), self.height()
			
			frame_w = new_w
			frame_h = new_h
			"""
			new_h = self.frame.height() 
			new_w = self.frame.width() 
			frame_w = self.frame.width() 
			frame_h = self.frame.height() 

			new_h -= 4
			new_w -= 4
			
			if new_h < 0:
				new_h = 0;
			if new_w < 0:
				new_w = 0;

			#print "ATB setDisplayPixmap deltas", delta_w , delta_h
			#print "ATB self.frame", frame_w, frame_h
			#print "ATB new size", new_w, new_h
			
			# scale the pixmap to fit in the frame
			scaled_pixmap = self.current_pixmap.scaled(new_w, new_h, Qt.KeepAspectRatio)			
			self.lblImage.setPixmap( scaled_pixmap )
			
			# move and resize the label to be centered in the fame
			img_w = scaled_pixmap.width()
			img_h = scaled_pixmap.height()
			self.lblImage.resize( img_w, img_h )
			self.lblImage.move( (frame_w - img_w)/2, (frame_h - img_h)/2 )
			
	def showPopup( self ):
		self.popup = ImagePopup(self, self.current_pixmap)
예제 #3
0
	def loadURL( self ):
		self.loadDefault()
		self.cover_fetcher = ImageFetcher( )
		self.cover_fetcher.fetchComplete.connect(self.coverRemoteFetchComplete)
		self.cover_fetcher.fetch( self.url_list[self.imageIndex] )
예제 #4
0
class CoverImageWidget(QWidget):

    ArchiveMode = 0
    AltCoverMode = 1
    URLMode = 1
    DataMode = 3

    def __init__(self, parent, mode, expand_on_click=True):
        super(CoverImageWidget, self).__init__(parent)

        uic.loadUi(ComicTaggerSettings.getUIFile('coverimagewidget.ui'), self)

        reduceWidgetFontSize(self.label)

        self.mode = mode
        self.comicVine = ComicVineTalker()
        self.page_loader = None
        self.showControls = True

        self.btnLeft.setIcon(QIcon(ComicTaggerSettings.getGraphic('left.png')))
        self.btnRight.setIcon(
            QIcon(ComicTaggerSettings.getGraphic('right.png')))

        self.btnLeft.clicked.connect(self.decrementImage)
        self.btnRight.clicked.connect(self.incrementImage)
        self.resetWidget()
        if expand_on_click:
            clickable(self.lblImage).connect(self.showPopup)
        else:
            self.lblImage.setToolTip("")

        self.updateContent()

    def resetWidget(self):
        self.comic_archive = None
        self.issue_id = None
        self.comicVine = None
        self.cover_fetcher = None
        self.url_list = []
        if self.page_loader is not None:
            self.page_loader.abandoned = True
        self.page_loader = None
        self.imageIndex = -1
        self.imageCount = 1
        self.imageData = None

    def clear(self):
        self.resetWidget()
        self.updateContent()

    def incrementImage(self):
        self.imageIndex += 1
        if self.imageIndex == self.imageCount:
            self.imageIndex = 0
        self.updateContent()

    def decrementImage(self):
        self.imageIndex -= 1
        if self.imageIndex == -1:
            self.imageIndex = self.imageCount - 1
        self.updateContent()

    def setArchive(self, ca, page=0):
        if self.mode == CoverImageWidget.ArchiveMode:
            self.resetWidget()
            self.comic_archive = ca
            self.imageIndex = page
            self.imageCount = ca.getNumberOfPages()
            self.updateContent()

    def setURL(self, url):
        if self.mode == CoverImageWidget.URLMode:
            self.resetWidget()
            self.updateContent()

            self.url_list = [url]
            self.imageIndex = 0
            self.imageCount = 1
            self.updateContent()

    def setIssueID(self, issue_id):
        if self.mode == CoverImageWidget.AltCoverMode:
            self.resetWidget()
            self.updateContent()

            self.issue_id = issue_id

            self.comicVine = ComicVineTalker()
            self.comicVine.urlFetchComplete.connect(
                self.primaryUrlFetchComplete)
            self.comicVine.asyncFetchIssueCoverURLs(int(self.issue_id))

    def setImageData(self, image_data):
        if self.mode == CoverImageWidget.DataMode:
            self.resetWidget()

            if image_data is None:
                self.imageIndex = -1
            else:
                self.imageIndex = 0
                self.imageData = image_data

            self.updateContent()

    def primaryUrlFetchComplete(self, primary_url, thumb_url, issue_id):
        self.url_list.append(str(primary_url))
        self.imageIndex = 0
        self.imageCount = len(self.url_list)
        self.updateContent()

        # defer the alt cover search
        QTimer.singleShot(1, self.startAltCoverSearch)

    def startAltCoverSearch(self):

        # now we need to get the list of alt cover URLs
        self.label.setText("Searching for alt. covers...")

        # page URL should already be cached, so no need to defer
        self.comicVine = ComicVineTalker()
        issue_page_url = self.comicVine.fetchIssuePageURL(self.issue_id)
        self.comicVine.altUrlListFetchComplete.connect(
            self.altCoverUrlListFetchComplete)
        self.comicVine.asyncFetchAlternateCoverURLs(int(self.issue_id),
                                                    issue_page_url)

    def altCoverUrlListFetchComplete(self, url_list, issue_id):
        if len(url_list) > 0:
            self.url_list.extend(url_list)
            self.imageCount = len(self.url_list)
        self.updateControls()

    def setPage(self, pagenum):
        if self.mode == CoverImageWidget.ArchiveMode:
            self.imageIndex = pagenum
            self.updateContent()

    def updateContent(self):
        self.updateImage()
        self.updateControls()

    def updateImage(self):
        if self.imageIndex == -1:
            self.loadDefault()
        elif self.mode in [
                CoverImageWidget.AltCoverMode, CoverImageWidget.URLMode
        ]:
            self.loadURL()
        elif self.mode == CoverImageWidget.DataMode:
            self.coverRemoteFetchComplete(self.imageData, 0)
        else:
            self.loadPage()

    def updateControls(self):
        if not self.showControls or self.mode == CoverImageWidget.DataMode:
            self.btnLeft.hide()
            self.btnRight.hide()
            self.label.hide()
            return

        if self.imageIndex == -1 or self.imageCount == 1:
            self.btnLeft.setEnabled(False)
            self.btnRight.setEnabled(False)
            self.btnLeft.hide()
            self.btnRight.hide()
        else:
            self.btnLeft.setEnabled(True)
            self.btnRight.setEnabled(True)
            self.btnLeft.show()
            self.btnRight.show()

        if self.imageIndex == -1 or self.imageCount == 1:
            self.label.setText("")
        elif self.mode == CoverImageWidget.AltCoverMode:
            self.label.setText("Cover {0} (of {1})".format(
                self.imageIndex + 1, self.imageCount))
        else:
            self.label.setText("Page {0} (of {1})".format(
                self.imageIndex + 1, self.imageCount))

    def loadURL(self):
        self.loadDefault()
        self.cover_fetcher = ImageFetcher()
        self.cover_fetcher.fetchComplete.connect(self.coverRemoteFetchComplete)
        self.cover_fetcher.fetch(self.url_list[self.imageIndex])
        #print("ATB cover fetch started...")

    # called when the image is done loading from internet
    def coverRemoteFetchComplete(self, image_data, issue_id):
        img = getQImageFromData(image_data)
        self.current_pixmap = QPixmap(img)
        self.setDisplayPixmap(0, 0)
        #print("ATB cover fetch complete!")

    def loadPage(self):
        if self.comic_archive is not None:
            if self.page_loader is not None:
                self.page_loader.abandoned = True
            self.page_loader = PageLoader(self.comic_archive, self.imageIndex)
            self.page_loader.loadComplete.connect(self.pageLoadComplete)
            self.page_loader.start()

    def pageLoadComplete(self, img):
        self.current_pixmap = QPixmap(img)
        self.setDisplayPixmap(0, 0)
        self.page_loader = None

    def loadDefault(self):
        self.current_pixmap = QPixmap(
            ComicTaggerSettings.getGraphic('nocover.png'))
        #print("loadDefault called")
        self.setDisplayPixmap(0, 0)

    def resizeEvent(self, resize_event):
        if self.current_pixmap is not None:
            delta_w = resize_event.size().width() - \
                resize_event.oldSize().width()
            delta_h = resize_event.size().height() - \
                resize_event.oldSize().height()
            # print "ATB resizeEvent deltas", resize_event.size().width(),
            # resize_event.size().height()
            self.setDisplayPixmap(delta_w, delta_h)

    def setDisplayPixmap(self, delta_w, delta_h):
        """The deltas let us know what the new width and height of the label will be"""

        #new_h = self.frame.height() + delta_h
        #new_w = self.frame.width() + delta_w
        # print "ATB setDisplayPixmap deltas", delta_w , delta_h
        # print "ATB self.frame", self.frame.width(), self.frame.height()
        # print "ATB self.", self.width(), self.height()

        #frame_w = new_w
        #frame_h = new_h

        new_h = self.frame.height()
        new_w = self.frame.width()
        frame_w = self.frame.width()
        frame_h = self.frame.height()

        new_h -= 4
        new_w -= 4

        if new_h < 0:
            new_h = 0
        if new_w < 0:
            new_w = 0

        # print "ATB setDisplayPixmap deltas", delta_w , delta_h
        # print "ATB self.frame", frame_w, frame_h
        # print "ATB new size", new_w, new_h

        # scale the pixmap to fit in the frame
        scaled_pixmap = self.current_pixmap.scaled(new_w, new_h,
                                                   Qt.KeepAspectRatio)
        self.lblImage.setPixmap(scaled_pixmap)

        # move and resize the label to be centered in the fame
        img_w = scaled_pixmap.width()
        img_h = scaled_pixmap.height()
        self.lblImage.resize(img_w, img_h)
        self.lblImage.move((frame_w - img_w) / 2, (frame_h - img_h) / 2)

    def showPopup(self):
        self.popup = ImagePopup(self, self.current_pixmap)
예제 #5
0
 def loadURL(self):
     self.loadDefault()
     self.cover_fetcher = ImageFetcher()
     self.cover_fetcher.fetchComplete.connect(self.coverRemoteFetchComplete)
     self.cover_fetcher.fetch(self.url_list[self.imageIndex])
예제 #6
0
 def clearCache(self):
     ImageFetcher().clearCache()
     ComicVineCacher().clearCache()
     QtGui.QMessageBox.information(self, self.name,
                                   "Cache has been cleared.")