def autoSelect(self):

        if self.comic_archive is None:
            QtGui.QMessageBox.information(self, "Auto-Select",
                                          "You need to load a comic first!")
            return

        if self.issue_number is None or self.issue_number == "":
            QtGui.QMessageBox.information(
                self, "Auto-Select",
                "Can't auto-select without an issue number (yet!)")
            return

        self.iddialog = IDProgressWindow(self)
        self.iddialog.setModal(True)
        self.iddialog.rejected.connect(self.identifyCancel)
        self.iddialog.show()

        self.ii = IssueIdentifier(self.comic_archive, self.settings)

        md = GenericMetadata()
        md.series = self.series_name
        md.issue = self.issue_number
        md.year = self.year
        md.issueCount = self.issue_count

        self.ii.setAdditionalMetadata(md)
        self.ii.onlyUseAdditionalMetaData = True

        self.ii.cover_page_index = int(self.cover_index_list[0])

        self.id_thread = IdentifyThread(self.ii)
        self.id_thread.identifyComplete.connect(self.identifyComplete)
        self.id_thread.identifyLogMsg.connect(self.logIDOutput)
        self.id_thread.identifyProgress.connect(self.identifyProgress)

        self.id_thread.start()

        self.iddialog.exec_()
Esempio n. 2
0
    def autoSelect(self):

        if self.comic_archive is None:
            QtGui.QMessageBox.information(
                self, "Auto-Select", "You need to load a comic first!")
            return

        if self.issue_number is None or self.issue_number == "":
            QtGui.QMessageBox.information(
                self,
                "Auto-Select",
                "Can't auto-select without an issue number (yet!)")
            return

        self.iddialog = IDProgressWindow(self)
        self.iddialog.setModal(True)
        self.iddialog.rejected.connect(self.identifyCancel)
        self.iddialog.show()

        self.ii = IssueIdentifier(self.comic_archive, self.settings)

        md = GenericMetadata()
        md.series = self.series_name
        md.issue = self.issue_number
        md.year = self.year
        md.issueCount = self.issue_count

        self.ii.setAdditionalMetadata(md)
        self.ii.onlyUseAdditionalMetaData = True

        self.ii.cover_page_index = int(self.cover_index_list[0])

        self.id_thread = IdentifyThread(self.ii)
        self.id_thread.identifyComplete.connect(self.identifyComplete)
        self.id_thread.identifyLogMsg.connect(self.logIDOutput)
        self.id_thread.identifyProgress.connect(self.identifyProgress)

        self.id_thread.start()

        self.iddialog.exec_()
Esempio n. 3
0
File: cli.py Progetto: 2mny/mylar
				def myoutput( text ):
					if opts.verbose:
						IssueIdentifier.defaultWriteOutput( text )
Esempio n. 4
0
File: cli.py Progetto: 2mny/mylar
def process_file_cli( filename, opts, settings, match_results ):

	batch_mode = len( opts.file_list ) > 1
		
	ca = ComicArchive(filename, settings.rar_exe_path)
	
	if not os.path.lexists( filename ):
		print "Cannot find "+ filename
		return
		
	if not ca.seemsToBeAComicArchive():
		print "Sorry, but "+ filename + "  is not a comic archive!"
		return
	
	#if not ca.isWritableForStyle( opts.data_style ) and ( opts.delete_tags or opts.save_tags or opts.rename_file ):
	if not ca.isWritable(  ) and ( opts.delete_tags or opts.copy_tags or opts.save_tags or opts.rename_file ):
		print "This archive is not writable for that tag type"
		return

	has = [ False, False, False ]
	if ca.hasCIX(): has[ MetaDataStyle.CIX ] = True
	if ca.hasCBI(): has[ MetaDataStyle.CBI ] = True
	if ca.hasCoMet(): has[ MetaDataStyle.COMET ] = True

	if opts.print_tags:


		if opts.data_style is None:
			page_count = ca.getNumberOfPages()

			brief = ""

			if batch_mode:
				brief = u"{0}: ".format(filename)

			if ca.isZip():      brief += "ZIP archive    "
			elif ca.isRar():    brief += "RAR archive    "
			elif ca.isFolder(): brief += "Folder archive "
				
			brief += "({0: >3} pages)".format(page_count)			
			brief += "  tags:[ "

			if not ( has[ MetaDataStyle.CBI ] or has[ MetaDataStyle.CIX ] or has[ MetaDataStyle.COMET ] ):
				brief += "none "
			else:
				if has[ MetaDataStyle.CBI ]: brief += "CBL "
				if has[ MetaDataStyle.CIX ]: brief += "CR "
				if has[ MetaDataStyle.COMET ]: brief += "CoMet "
			brief += "]"
				
			print brief

		if opts.terse:
			return

		print
		
		if opts.data_style is None or opts.data_style == MetaDataStyle.CIX:
			if has[ MetaDataStyle.CIX ]:
				print "------ComicRack tags--------"
				if opts.raw:
					print u"{0}".format(unicode(ca.readRawCIX(), errors='ignore'))
				else:
					print u"{0}".format(ca.readCIX())
				
		if opts.data_style is None or opts.data_style == MetaDataStyle.CBI:
			if has[ MetaDataStyle.CBI ]:
				print "------ComicBookLover tags--------"
				if opts.raw:
					pprint(json.loads(ca.readRawCBI()))
				else:
					print u"{0}".format(ca.readCBI())
					
		if opts.data_style is None or opts.data_style == MetaDataStyle.COMET:
			if has[ MetaDataStyle.COMET ]:
				print "------CoMet tags--------"
				if opts.raw:
					print u"{0}".format(ca.readRawCoMet())
				else:
					print u"{0}".format(ca.readCoMet())
			
			
	elif opts.delete_tags:
		style_name = MetaDataStyle.name[ opts.data_style ]
		if has[ opts.data_style ]:
			if not opts.dryrun:
				if not ca.removeMetadata( opts.data_style ):
					print u"{0}: Tag removal seemed to fail!".format( filename )
				else:
					print u"{0}: Removed {1} tags.".format( filename, style_name )
			else:
				print u"{0}: dry-run.  {1} tags not removed".format( filename, style_name )		
		else:
			print u"{0}: This archive doesn't have {1} tags to remove.".format( filename, style_name )

	elif opts.copy_tags:
		dst_style_name = MetaDataStyle.name[ opts.data_style ]
		if opts.no_overwrite and has[ opts.data_style ]:
			print u"{0}: Already has {1} tags.  Not overwriting.".format(filename, dst_style_name)
			return
		if opts.copy_source == opts.data_style:
			print u"{0}: Destination and source are same: {1}.  Nothing to do.".format(filename, dst_style_name)
			return
			
		src_style_name = MetaDataStyle.name[ opts.copy_source ]
		if has[ opts.copy_source ]:
			if not opts.dryrun:
				md = ca.readMetadata( opts.copy_source )
				
				if settings.apply_cbl_transform_on_bulk_operation and opts.data_style == MetaDataStyle.CBI:
					md = CBLTransformer( md, settings ).apply()
				
				if not ca.writeMetadata( md, opts.data_style ):
					print u"{0}: Tag copy seemed to fail!".format( filename )
				else:
					print u"{0}: Copied {1} tags to {2} .".format( filename, src_style_name, dst_style_name )
			else:
				print u"{0}: dry-run.  {1} tags not copied".format( filename, src_style_name )		
		else:
			print u"{0}: This archive doesn't have {1} tags to copy.".format( filename, src_style_name )

		
	elif opts.save_tags:

		if opts.no_overwrite and has[ opts.data_style ]:
			print u"{0}: Already has {1} tags.  Not overwriting.".format(filename, MetaDataStyle.name[ opts.data_style ])
			return
		
		if batch_mode:
			print u"Processing {0}...".format(filename)
			
		md = create_local_metadata( opts, ca, has[ opts.data_style ] )
		if md.issue is None or md.issue == "":
			if opts.assume_issue_is_one_if_not_set:
				md.issue = "1"
		
		# now, search online
		if opts.search_online:
			if opts.issue_id is not None:
				# we were given the actual ID to search with
				try:
					comicVine = ComicVineTalker()
					comicVine.wait_for_rate_limit = opts.wait_and_retry_on_rate_limit
					cv_md = comicVine.fetchIssueDataByIssueID( opts.issue_id, settings )
				except ComicVineTalkerException:
					print "Network error while getting issue details.  Save aborted"
					match_results.fetchDataFailures.append(filename)
					return
				
				if cv_md is None:
					print "No match for ID {0} was found.".format(opts.issue_id)
					match_results.noMatches.append(filename)
					return
				
				if settings.apply_cbl_transform_on_cv_import:
					cv_md = CBLTransformer( cv_md, settings ).apply()
			else:
				ii = IssueIdentifier( ca, settings )
	
				if md is None or md.isEmpty:
					print "No metadata given to search online with!"
					match_results.noMatches.append(filename)
					return
	
				def myoutput( text ):
					if opts.verbose:
						IssueIdentifier.defaultWriteOutput( text )
					
				# use our overlayed MD struct to search
				ii.setAdditionalMetadata( md )
				ii.onlyUseAdditionalMetaData = True
				ii.waitAndRetryOnRateLimit = opts.wait_and_retry_on_rate_limit
				ii.setOutputFunction( myoutput )
				ii.cover_page_index = md.getCoverPageIndexList()[0]
				matches = ii.search()
				
				result = ii.search_result
				
				found_match = False
				choices = False
				low_confidence = False
				
				if result == ii.ResultNoMatches:
					pass
				elif result == ii.ResultFoundMatchButBadCoverScore:
					low_confidence = True
					found_match = True
				elif result == ii.ResultFoundMatchButNotFirstPage :
					found_match = True
				elif result == ii.ResultMultipleMatchesWithBadImageScores:
					low_confidence = True
					choices = True
				elif result == ii.ResultOneGoodMatch:
					found_match = True
				elif result == ii.ResultMultipleGoodMatches:
					choices = True
	
				if choices:
					if low_confidence:
						print "Online search: Multiple low confidence matches.  Save aborted"
						match_results.lowConfidenceMatches.append(MultipleMatch(filename,matches))
						return
					else:
						print "Online search: Multiple good matches.  Save aborted"
						match_results.multipleMatches.append(MultipleMatch(filename,matches))
						return
				if low_confidence and opts.abortOnLowConfidence:
					print "Online search: Low confidence match.  Save aborted"
					match_results.lowConfidenceMatches.append(MultipleMatch(filename,matches))
					return
				if not found_match:
					print "Online search: No match found.  Save aborted"
					match_results.noMatches.append(filename)
					return
	
	
				# we got here, so we have a single match
				
				# now get the particular issue data
				cv_md = actual_issue_data_fetch(matches[0], settings, opts)
				if cv_md is None:
					match_results.fetchDataFailures.append(filename)
					return
			
			md.overlay( cv_md )
			
		# ok, done building our metadata. time to save
		if not actual_metadata_save( ca, opts, md ):
				match_results.writeFailures.append(filename)
		else:
				match_results.goodMatches.append(filename)

	elif opts.rename_file:

		msg_hdr = ""
		if batch_mode:
			msg_hdr = u"{0}: ".format(filename)

		if opts.data_style is not None:
			use_tags = has[ opts.data_style ]
		else:
			use_tags = False
			
		md = create_local_metadata( opts, ca, use_tags )
		
		if md.series is None:
			print msg_hdr + "Can't rename without series name"
			return

		new_ext = None  # default
		if settings.rename_extension_based_on_archive:
			if ca.isZip():
				new_ext = ".cbz"
			elif ca.isRar():
				new_ext = ".cbr"
			
		renamer = FileRenamer( md )
		renamer.setTemplate( settings.rename_template )
		renamer.setIssueZeroPadding( settings.rename_issue_number_padding )
		renamer.setSmartCleanup( settings.rename_use_smart_string_cleanup )
		
		new_name = renamer.determineName( filename, ext=new_ext )
			
		if new_name == os.path.basename(filename):
			print msg_hdr + "Filename is already good!"
			return
		
		folder = os.path.dirname( os.path.abspath( filename ) )
		new_abs_path = utils.unique_file( os.path.join( folder, new_name ) )

		suffix = ""
		if not opts.dryrun:
			# rename the file
			os.rename( filename, new_abs_path )
		else:
			suffix = " (dry-run, no change)"

		print u"renamed '{0}' -> '{1}' {2}".format(os.path.basename(filename), new_name, suffix)

	elif opts.export_to_zip:
		msg_hdr = ""
		if batch_mode:
			msg_hdr = u"{0}: ".format(filename)

		if not ca.isRar():
			print msg_hdr + "Archive is not a RAR."
			return
		
		rar_file = os.path.abspath( os.path.abspath( filename ) )
		new_file = os.path.splitext(rar_file)[0] + ".cbz"
		
		if opts.abort_export_on_conflict and os.path.lexists( new_file ):
			print  msg_hdr + "{0} already exists in the that folder.".format(os.path.split(new_file)[1])
			return
		
		new_file = utils.unique_file( os.path.join( new_file ) )
	
		delete_success = False
		export_success = False
		if not opts.dryrun:
			if ca.exportAsZip( new_file ):
				export_success = True
				if opts.delete_rar_after_export:
					try:
						os.unlink( rar_file )
					except:
						print msg_hdr + "Error deleting original RAR after export"
						delete_success = False
					else:
						delete_success = True
			else:
				# last export failed, so remove the zip, if it exists
				if os.path.lexists( new_file ):
					os.remove( new_file )
		else:
			msg = msg_hdr + u"Dry-run:  Would try to create {0}".format(os.path.split(new_file)[1])
			if opts.delete_rar_after_export:
				msg += u" and delete orginal."
			print msg
			return
			
		msg = msg_hdr
		if export_success:
			msg += u"Archive exported successfully to: {0}".format( os.path.split(new_file)[1] )
			if opts.delete_rar_after_export and delete_success:
				msg += u" (Original deleted) "
		else:
			msg += u"Archive failed to export!"
			
		print msg
Esempio n. 5
0
 def myoutput(text):
     if opts.verbose:
         IssueIdentifier.defaultWriteOutput(text)
Esempio n. 6
0
def process_file_cli(filename, opts, settings, match_results):

    batch_mode = len(opts.file_list) > 1

    ca = ComicArchive(filename, settings.rar_exe_path)

    if not os.path.lexists(filename):
        print "Cannot find " + filename
        return

    if not ca.seemsToBeAComicArchive():
        print "Sorry, but " + filename + "  is not a comic archive!"
        return

    #if not ca.isWritableForStyle( opts.data_style ) and ( opts.delete_tags or opts.save_tags or opts.rename_file ):
    if not ca.isWritable() and (opts.delete_tags or opts.copy_tags
                                or opts.save_tags or opts.rename_file):
        print "This archive is not writable for that tag type"
        return

    has = [False, False, False]
    if ca.hasCIX(): has[MetaDataStyle.CIX] = True
    if ca.hasCBI(): has[MetaDataStyle.CBI] = True
    if ca.hasCoMet(): has[MetaDataStyle.COMET] = True

    if opts.print_tags:

        if opts.data_style is None:
            page_count = ca.getNumberOfPages()

            brief = ""

            if batch_mode:
                brief = u"{0}: ".format(filename)

            if ca.isZip(): brief += "ZIP archive    "
            elif ca.isRar(): brief += "RAR archive    "
            elif ca.isFolder(): brief += "Folder archive "

            brief += "({0: >3} pages)".format(page_count)
            brief += "  tags:[ "

            if not (has[MetaDataStyle.CBI] or has[MetaDataStyle.CIX]
                    or has[MetaDataStyle.COMET]):
                brief += "none "
            else:
                if has[MetaDataStyle.CBI]: brief += "CBL "
                if has[MetaDataStyle.CIX]: brief += "CR "
                if has[MetaDataStyle.COMET]: brief += "CoMet "
            brief += "]"

            print brief

        if opts.terse:
            return

        print

        if opts.data_style is None or opts.data_style == MetaDataStyle.CIX:
            if has[MetaDataStyle.CIX]:
                print "------ComicRack tags--------"
                if opts.raw:
                    print u"{0}".format(
                        unicode(ca.readRawCIX(), errors='ignore'))
                else:
                    print u"{0}".format(ca.readCIX())

        if opts.data_style is None or opts.data_style == MetaDataStyle.CBI:
            if has[MetaDataStyle.CBI]:
                print "------ComicBookLover tags--------"
                if opts.raw:
                    pprint(json.loads(ca.readRawCBI()))
                else:
                    print u"{0}".format(ca.readCBI())

        if opts.data_style is None or opts.data_style == MetaDataStyle.COMET:
            if has[MetaDataStyle.COMET]:
                print "------CoMet tags--------"
                if opts.raw:
                    print u"{0}".format(ca.readRawCoMet())
                else:
                    print u"{0}".format(ca.readCoMet())

    elif opts.delete_tags:
        style_name = MetaDataStyle.name[opts.data_style]
        if has[opts.data_style]:
            if not opts.dryrun:
                if not ca.removeMetadata(opts.data_style):
                    print u"{0}: Tag removal seemed to fail!".format(filename)
                else:
                    print u"{0}: Removed {1} tags.".format(
                        filename, style_name)
            else:
                print u"{0}: dry-run.  {1} tags not removed".format(
                    filename, style_name)
        else:
            print u"{0}: This archive doesn't have {1} tags to remove.".format(
                filename, style_name)

    elif opts.copy_tags:
        dst_style_name = MetaDataStyle.name[opts.data_style]
        if opts.no_overwrite and has[opts.data_style]:
            print u"{0}: Already has {1} tags.  Not overwriting.".format(
                filename, dst_style_name)
            return
        if opts.copy_source == opts.data_style:
            print u"{0}: Destination and source are same: {1}.  Nothing to do.".format(
                filename, dst_style_name)
            return

        src_style_name = MetaDataStyle.name[opts.copy_source]
        if has[opts.copy_source]:
            if not opts.dryrun:
                md = ca.readMetadata(opts.copy_source)

                if settings.apply_cbl_transform_on_bulk_operation and opts.data_style == MetaDataStyle.CBI:
                    md = CBLTransformer(md, settings).apply()

                if not ca.writeMetadata(md, opts.data_style):
                    print u"{0}: Tag copy seemed to fail!".format(filename)
                else:
                    print u"{0}: Copied {1} tags to {2} .".format(
                        filename, src_style_name, dst_style_name)
            else:
                print u"{0}: dry-run.  {1} tags not copied".format(
                    filename, src_style_name)
        else:
            print u"{0}: This archive doesn't have {1} tags to copy.".format(
                filename, src_style_name)

    elif opts.save_tags:

        if opts.no_overwrite and has[opts.data_style]:
            print u"{0}: Already has {1} tags.  Not overwriting.".format(
                filename, MetaDataStyle.name[opts.data_style])
            return

        if batch_mode:
            print u"Processing {0}...".format(filename)

        md = create_local_metadata(opts, ca, has[opts.data_style])
        if md.issue is None or md.issue == "":
            if opts.assume_issue_is_one_if_not_set:
                md.issue = "1"

        # now, search online
        if opts.search_online:
            if opts.issue_id is not None:
                # we were given the actual ID to search with
                try:
                    comicVine = ComicVineTalker()
                    comicVine.wait_for_rate_limit = opts.wait_and_retry_on_rate_limit
                    cv_md = comicVine.fetchIssueDataByIssueID(
                        opts.issue_id, settings)
                except ComicVineTalkerException:
                    print "Network error while getting issue details.  Save aborted"
                    match_results.fetchDataFailures.append(filename)
                    return

                if cv_md is None:
                    print "No match for ID {0} was found.".format(
                        opts.issue_id)
                    match_results.noMatches.append(filename)
                    return

                if settings.apply_cbl_transform_on_cv_import:
                    cv_md = CBLTransformer(cv_md, settings).apply()
            else:
                ii = IssueIdentifier(ca, settings)

                if md is None or md.isEmpty:
                    print "No metadata given to search online with!"
                    match_results.noMatches.append(filename)
                    return

                def myoutput(text):
                    if opts.verbose:
                        IssueIdentifier.defaultWriteOutput(text)

                # use our overlayed MD struct to search
                ii.setAdditionalMetadata(md)
                ii.onlyUseAdditionalMetaData = True
                ii.waitAndRetryOnRateLimit = opts.wait_and_retry_on_rate_limit
                ii.setOutputFunction(myoutput)
                ii.cover_page_index = md.getCoverPageIndexList()[0]
                matches = ii.search()

                result = ii.search_result

                found_match = False
                choices = False
                low_confidence = False

                if result == ii.ResultNoMatches:
                    pass
                elif result == ii.ResultFoundMatchButBadCoverScore:
                    low_confidence = True
                    found_match = True
                elif result == ii.ResultFoundMatchButNotFirstPage:
                    found_match = True
                elif result == ii.ResultMultipleMatchesWithBadImageScores:
                    low_confidence = True
                    choices = True
                elif result == ii.ResultOneGoodMatch:
                    found_match = True
                elif result == ii.ResultMultipleGoodMatches:
                    choices = True

                if choices:
                    if low_confidence:
                        print "Online search: Multiple low confidence matches.  Save aborted"
                        match_results.lowConfidenceMatches.append(
                            MultipleMatch(filename, matches))
                        return
                    else:
                        print "Online search: Multiple good matches.  Save aborted"
                        match_results.multipleMatches.append(
                            MultipleMatch(filename, matches))
                        return
                if low_confidence and opts.abortOnLowConfidence:
                    print "Online search: Low confidence match.  Save aborted"
                    match_results.lowConfidenceMatches.append(
                        MultipleMatch(filename, matches))
                    return
                if not found_match:
                    print "Online search: No match found.  Save aborted"
                    match_results.noMatches.append(filename)
                    return

                # we got here, so we have a single match

                # now get the particular issue data
                cv_md = actual_issue_data_fetch(matches[0], settings, opts)
                if cv_md is None:
                    match_results.fetchDataFailures.append(filename)
                    return

            md.overlay(cv_md)

        # ok, done building our metadata. time to save
        if not actual_metadata_save(ca, opts, md):
            match_results.writeFailures.append(filename)
        else:
            match_results.goodMatches.append(filename)

    elif opts.rename_file:

        msg_hdr = ""
        if batch_mode:
            msg_hdr = u"{0}: ".format(filename)

        if opts.data_style is not None:
            use_tags = has[opts.data_style]
        else:
            use_tags = False

        md = create_local_metadata(opts, ca, use_tags)

        if md.series is None:
            print msg_hdr + "Can't rename without series name"
            return

        new_ext = None  # default
        if settings.rename_extension_based_on_archive:
            if ca.isZip():
                new_ext = ".cbz"
            elif ca.isRar():
                new_ext = ".cbr"

        renamer = FileRenamer(md)
        renamer.setTemplate(settings.rename_template)
        renamer.setIssueZeroPadding(settings.rename_issue_number_padding)
        renamer.setSmartCleanup(settings.rename_use_smart_string_cleanup)

        new_name = renamer.determineName(filename, ext=new_ext)

        if new_name == os.path.basename(filename):
            print msg_hdr + "Filename is already good!"
            return

        folder = os.path.dirname(os.path.abspath(filename))
        new_abs_path = utils.unique_file(os.path.join(folder, new_name))

        suffix = ""
        if not opts.dryrun:
            # rename the file
            os.rename(filename, new_abs_path)
        else:
            suffix = " (dry-run, no change)"

        print u"renamed '{0}' -> '{1}' {2}".format(os.path.basename(filename),
                                                   new_name, suffix)

    elif opts.export_to_zip:
        msg_hdr = ""
        if batch_mode:
            msg_hdr = u"{0}: ".format(filename)

        if not ca.isRar():
            print msg_hdr + "Archive is not a RAR."
            return

        rar_file = os.path.abspath(os.path.abspath(filename))
        new_file = os.path.splitext(rar_file)[0] + ".cbz"

        if opts.abort_export_on_conflict and os.path.lexists(new_file):
            print msg_hdr + "{0} already exists in the that folder.".format(
                os.path.split(new_file)[1])
            return

        new_file = utils.unique_file(os.path.join(new_file))

        delete_success = False
        export_success = False
        if not opts.dryrun:
            if ca.exportAsZip(new_file):
                export_success = True
                if opts.delete_rar_after_export:
                    try:
                        os.unlink(rar_file)
                    except:
                        print msg_hdr + "Error deleting original RAR after export"
                        delete_success = False
                    else:
                        delete_success = True
            else:
                # last export failed, so remove the zip, if it exists
                if os.path.lexists(new_file):
                    os.remove(new_file)
        else:
            msg = msg_hdr + u"Dry-run:  Would try to create {0}".format(
                os.path.split(new_file)[1])
            if opts.delete_rar_after_export:
                msg += u" and delete orginal."
            print msg
            return

        msg = msg_hdr
        if export_success:
            msg += u"Archive exported successfully to: {0}".format(
                os.path.split(new_file)[1])
            if opts.delete_rar_after_export and delete_success:
                msg += u" (Original deleted) "
        else:
            msg += u"Archive failed to export!"

        print msg
Esempio n. 7
0
class VolumeSelectionWindow(QtGui.QDialog):

    def __init__(self, parent, series_name, issue_number, year, issue_count,
                 cover_index_list, comic_archive, settings, autoselect=False):
        super(VolumeSelectionWindow, self).__init__(parent)

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

        self.imageWidget = CoverImageWidget(
            self.imageContainer, CoverImageWidget.URLMode)
        gridlayout = QtGui.QGridLayout(self.imageContainer)
        gridlayout.addWidget(self.imageWidget)
        gridlayout.setContentsMargins(0, 0, 0, 0)

        reduceWidgetFontSize(self.teDetails, 1)
        reduceWidgetFontSize(self.twList)

        self.setWindowFlags(self.windowFlags() |
                            QtCore.Qt.WindowSystemMenuHint |
                            QtCore.Qt.WindowMaximizeButtonHint)

        self.settings = settings
        self.series_name = series_name
        self.issue_number = issue_number
        self.year = year
        self.issue_count = issue_count
        self.volume_id = 0
        self.comic_archive = comic_archive
        self.immediate_autoselect = autoselect
        self.cover_index_list = cover_index_list
        self.cv_search_results = None

        self.twList.resizeColumnsToContents()
        self.twList.currentItemChanged.connect(self.currentItemChanged)
        self.twList.cellDoubleClicked.connect(self.cellDoubleClicked)
        self.btnRequery.clicked.connect(self.requery)
        self.btnIssues.clicked.connect(self.showIssues)
        self.btnAutoSelect.clicked.connect(self.autoSelect)

        self.updateButtons()
        self.performQuery()
        self.twList.selectRow(0)

    def updateButtons(self):
        if self.cv_search_results is not None and len(
                self.cv_search_results) > 0:
            enabled = True
        else:
            enabled = False

        self.btnRequery.setEnabled(enabled)
        self.btnIssues.setEnabled(enabled)
        self.btnAutoSelect.setEnabled(enabled)
        self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(enabled)

    def requery(self,):
        self.performQuery(refresh=True)
        self.twList.selectRow(0)

    def autoSelect(self):

        if self.comic_archive is None:
            QtGui.QMessageBox.information(
                self, "Auto-Select", "You need to load a comic first!")
            return

        if self.issue_number is None or self.issue_number == "":
            QtGui.QMessageBox.information(
                self,
                "Auto-Select",
                "Can't auto-select without an issue number (yet!)")
            return

        self.iddialog = IDProgressWindow(self)
        self.iddialog.setModal(True)
        self.iddialog.rejected.connect(self.identifyCancel)
        self.iddialog.show()

        self.ii = IssueIdentifier(self.comic_archive, self.settings)

        md = GenericMetadata()
        md.series = self.series_name
        md.issue = self.issue_number
        md.year = self.year
        md.issueCount = self.issue_count

        self.ii.setAdditionalMetadata(md)
        self.ii.onlyUseAdditionalMetaData = True

        self.ii.cover_page_index = int(self.cover_index_list[0])

        self.id_thread = IdentifyThread(self.ii)
        self.id_thread.identifyComplete.connect(self.identifyComplete)
        self.id_thread.identifyLogMsg.connect(self.logIDOutput)
        self.id_thread.identifyProgress.connect(self.identifyProgress)

        self.id_thread.start()

        self.iddialog.exec_()

    def logIDOutput(self, text):
        print unicode(text),
        self.iddialog.textEdit.ensureCursorVisible()
        self.iddialog.textEdit.insertPlainText(text)

    def identifyProgress(self, cur, total):
        self.iddialog.progressBar.setMaximum(total)
        self.iddialog.progressBar.setValue(cur)

    def identifyCancel(self):
        self.ii.cancel = True

    def identifyComplete(self):

        matches = self.ii.match_list
        result = self.ii.search_result
        match_index = 0

        found_match = None
        choices = False
        if result == self.ii.ResultNoMatches:
            QtGui.QMessageBox.information(
                self, "Auto-Select Result", " No matches found :-(")
        elif result == self.ii.ResultFoundMatchButBadCoverScore:
            QtGui.QMessageBox.information(
                self,
                "Auto-Select Result",
                " Found a match, but cover doesn't seem the same.  Verify before commiting!")
            found_match = matches[0]
        elif result == self.ii.ResultFoundMatchButNotFirstPage:
            QtGui.QMessageBox.information(
                self,
                "Auto-Select Result",
                " Found a match, but not with the first page of the archive.")
            found_match = matches[0]
        elif result == self.ii.ResultMultipleMatchesWithBadImageScores:
            QtGui.QMessageBox.information(
                self,
                "Auto-Select Result",
                " Found some possibilities, but no confidence. Proceed manually.")
            choices = True
        elif result == self.ii.ResultOneGoodMatch:
            found_match = matches[0]
        elif result == self.ii.ResultMultipleGoodMatches:
            QtGui.QMessageBox.information(
                self,
                "Auto-Select Result",
                " Found multiple likely matches.  Please select.")
            choices = True

        if choices:
            selector = MatchSelectionWindow(self, matches, self.comic_archive)
            selector.setModal(True)
            selector.exec_()
            if selector.result():
                # we should now have a list index
                found_match = selector.currentMatch()

        if found_match is not None:
            self.iddialog.accept()

            self.volume_id = found_match['volume_id']
            self.issue_number = found_match['issue_number']
            self.selectByID()
            self.showIssues()

    def showIssues(self):
        selector = IssueSelectionWindow(
            self, self.settings, self.volume_id, self.issue_number)
        title = ""
        for record in self.cv_search_results:
            if record['id'] == self.volume_id:
                title = record['name']
                title += " (" + unicode(record['start_year']) + ")"
                title += " - "
                break

        selector.setWindowTitle(title + "Select Issue")
        selector.setModal(True)
        selector.exec_()
        if selector.result():
            # we should now have a volume ID
            self.issue_number = selector.issue_number
            self.accept()
        return

    def selectByID(self):
        for r in range(0, self.twList.rowCount()):
            volume_id, b = self.twList.item(
                r, 0).data(QtCore.Qt.UserRole).toInt()
            if (volume_id == self.volume_id):
                self.twList.selectRow(r)
                break

    def performQuery(self, refresh=False):

        self.progdialog = QtGui.QProgressDialog(
            "Searching Online", "Cancel", 0, 100, self)
        self.progdialog.setWindowTitle("Online Search")
        self.progdialog.canceled.connect(self.searchCanceled)
        self.progdialog.setModal(True)

        self.search_thread = SearchThread(self.series_name, refresh)
        self.search_thread.searchComplete.connect(self.searchComplete)
        self.search_thread.progressUpdate.connect(self.searchProgressUpdate)
        self.search_thread.start()

        # QtCore.QCoreApplication.processEvents()
        self.progdialog.exec_()

    def searchCanceled(self):
        print("query cancelled")
        self.search_thread.searchComplete.disconnect(self.searchComplete)
        self.search_thread.progressUpdate.disconnect(self.searchProgressUpdate)
        self.progdialog.canceled.disconnect(self.searchCanceled)
        self.progdialog.reject()
        QtCore.QTimer.singleShot(200, self.closeMe)

    def closeMe(self):
        print("closeme")
        self.reject()

    def searchProgressUpdate(self, current, total):
        self.progdialog.setMaximum(total)
        self.progdialog.setValue(current)

    def searchComplete(self):
        self.progdialog.accept()
        if self.search_thread.cv_error:
            if self.search_thread.error_code == ComicVineTalkerException.RateLimit:
                QtGui.QMessageBox.critical(
                    self,
                    self.tr("Comic Vine Error"),
                    ComicVineTalker.getRateLimitMessage())
            else:
                QtGui.QMessageBox.critical(
                    self,
                    self.tr("Network Issue"),
                    self.tr("Could not connect to Comic Vine to search for series!"))
            return

        self.cv_search_results = self.search_thread.cv_search_results
        self.updateButtons()

        self.twList.setSortingEnabled(False)

        while self.twList.rowCount() > 0:
            self.twList.removeRow(0)

        row = 0
        for record in self.cv_search_results:
            self.twList.insertRow(row)

            item_text = record['name']
            item = QtGui.QTableWidgetItem(item_text)
            item.setData(QtCore.Qt.ToolTipRole, item_text)
            item.setData(QtCore.Qt.UserRole, record['id'])
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.twList.setItem(row, 0, item)

            item_text = str(record['start_year'])
            item = QtGui.QTableWidgetItem(item_text)
            item.setData(QtCore.Qt.ToolTipRole, item_text)
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.twList.setItem(row, 1, item)

            item_text = record['count_of_issues']
            item = QtGui.QTableWidgetItem(item_text)
            item.setData(QtCore.Qt.ToolTipRole, item_text)
            item.setData(QtCore.Qt.DisplayRole, record['count_of_issues'])
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.twList.setItem(row, 2, item)

            if record['publisher'] is not None:
                item_text = record['publisher']['name']
                item.setData(QtCore.Qt.ToolTipRole, item_text)
                item = QtGui.QTableWidgetItem(item_text)
                item.setFlags(
                    QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
                self.twList.setItem(row, 3, item)

            row += 1

        self.twList.resizeColumnsToContents()
        self.twList.setSortingEnabled(True)
        self.twList.sortItems(2, QtCore.Qt.DescendingOrder)
        self.twList.selectRow(0)
        self.twList.resizeColumnsToContents()

        if len(self.cv_search_results) == 0:
            QtCore.QCoreApplication.processEvents()
            QtGui.QMessageBox.information(
                self, "Search Result", "No matches found!")

        if self.immediate_autoselect and len(self.cv_search_results) > 0:
            # defer the immediate autoselect so this dialog has time to pop up
            QtCore.QCoreApplication.processEvents()
            QtCore.QTimer.singleShot(10, self.doImmediateAutoselect)

    def doImmediateAutoselect(self):
        self.immediate_autoselect = False
        self.autoSelect()

    def cellDoubleClicked(self, r, c):
        self.showIssues()

    def currentItemChanged(self, curr, prev):

        if curr is None:
            return
        if prev is not None and prev.row() == curr.row():
            return

        self.volume_id, b = self.twList.item(
            curr.row(), 0).data(QtCore.Qt.UserRole).toInt()

        # list selection was changed, update the info on the volume
        for record in self.cv_search_results:
            if record['id'] == self.volume_id:
                if record['description'] is None:
                    self.teDetails.setText("")
                else:
                    self.teDetails.setText(record['description'])
                self.imageWidget.setURL(record['image']['super_url'])
                break
class VolumeSelectionWindow(QtGui.QDialog):
    def __init__(self,
                 parent,
                 series_name,
                 issue_number,
                 year,
                 issue_count,
                 cover_index_list,
                 comic_archive,
                 settings,
                 autoselect=False):
        super(VolumeSelectionWindow, self).__init__(parent)

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

        self.imageWidget = CoverImageWidget(self.imageContainer,
                                            CoverImageWidget.URLMode)
        gridlayout = QtGui.QGridLayout(self.imageContainer)
        gridlayout.addWidget(self.imageWidget)
        gridlayout.setContentsMargins(0, 0, 0, 0)

        reduceWidgetFontSize(self.teDetails, 1)
        reduceWidgetFontSize(self.twList)

        self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowSystemMenuHint
                            | QtCore.Qt.WindowMaximizeButtonHint)

        self.settings = settings
        self.series_name = series_name
        self.issue_number = issue_number
        self.year = year
        self.issue_count = issue_count
        self.volume_id = 0
        self.comic_archive = comic_archive
        self.immediate_autoselect = autoselect
        self.cover_index_list = cover_index_list
        self.cv_search_results = None

        self.twList.resizeColumnsToContents()
        self.twList.currentItemChanged.connect(self.currentItemChanged)
        self.twList.cellDoubleClicked.connect(self.cellDoubleClicked)
        self.btnRequery.clicked.connect(self.requery)
        self.btnIssues.clicked.connect(self.showIssues)
        self.btnAutoSelect.clicked.connect(self.autoSelect)

        self.updateButtons()
        self.performQuery()
        self.twList.selectRow(0)

    def updateButtons(self):
        if self.cv_search_results is not None and len(
                self.cv_search_results) > 0:
            enabled = True
        else:
            enabled = False

        self.btnRequery.setEnabled(enabled)
        self.btnIssues.setEnabled(enabled)
        self.btnAutoSelect.setEnabled(enabled)
        self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(enabled)

    def requery(self, ):
        self.performQuery(refresh=True)
        self.twList.selectRow(0)

    def autoSelect(self):

        if self.comic_archive is None:
            QtGui.QMessageBox.information(self, "Auto-Select",
                                          "You need to load a comic first!")
            return

        if self.issue_number is None or self.issue_number == "":
            QtGui.QMessageBox.information(
                self, "Auto-Select",
                "Can't auto-select without an issue number (yet!)")
            return

        self.iddialog = IDProgressWindow(self)
        self.iddialog.setModal(True)
        self.iddialog.rejected.connect(self.identifyCancel)
        self.iddialog.show()

        self.ii = IssueIdentifier(self.comic_archive, self.settings)

        md = GenericMetadata()
        md.series = self.series_name
        md.issue = self.issue_number
        md.year = self.year
        md.issueCount = self.issue_count

        self.ii.setAdditionalMetadata(md)
        self.ii.onlyUseAdditionalMetaData = True

        self.ii.cover_page_index = int(self.cover_index_list[0])

        self.id_thread = IdentifyThread(self.ii)
        self.id_thread.identifyComplete.connect(self.identifyComplete)
        self.id_thread.identifyLogMsg.connect(self.logIDOutput)
        self.id_thread.identifyProgress.connect(self.identifyProgress)

        self.id_thread.start()

        self.iddialog.exec_()

    def logIDOutput(self, text):
        print unicode(text),
        self.iddialog.textEdit.ensureCursorVisible()
        self.iddialog.textEdit.insertPlainText(text)

    def identifyProgress(self, cur, total):
        self.iddialog.progressBar.setMaximum(total)
        self.iddialog.progressBar.setValue(cur)

    def identifyCancel(self):
        self.ii.cancel = True

    def identifyComplete(self):

        matches = self.ii.match_list
        result = self.ii.search_result
        match_index = 0

        found_match = None
        choices = False
        if result == self.ii.ResultNoMatches:
            QtGui.QMessageBox.information(self, "Auto-Select Result",
                                          " No matches found :-(")
        elif result == self.ii.ResultFoundMatchButBadCoverScore:
            QtGui.QMessageBox.information(
                self, "Auto-Select Result",
                " Found a match, but cover doesn't seem the same.  Verify before commiting!"
            )
            found_match = matches[0]
        elif result == self.ii.ResultFoundMatchButNotFirstPage:
            QtGui.QMessageBox.information(
                self, "Auto-Select Result",
                " Found a match, but not with the first page of the archive.")
            found_match = matches[0]
        elif result == self.ii.ResultMultipleMatchesWithBadImageScores:
            QtGui.QMessageBox.information(
                self, "Auto-Select Result",
                " Found some possibilities, but no confidence. Proceed manually."
            )
            choices = True
        elif result == self.ii.ResultOneGoodMatch:
            found_match = matches[0]
        elif result == self.ii.ResultMultipleGoodMatches:
            QtGui.QMessageBox.information(
                self, "Auto-Select Result",
                " Found multiple likely matches.  Please select.")
            choices = True

        if choices:
            selector = MatchSelectionWindow(self, matches, self.comic_archive)
            selector.setModal(True)
            selector.exec_()
            if selector.result():
                # we should now have a list index
                found_match = selector.currentMatch()

        if found_match is not None:
            self.iddialog.accept()

            self.volume_id = found_match['volume_id']
            self.issue_number = found_match['issue_number']
            self.selectByID()
            self.showIssues()

    def showIssues(self):
        selector = IssueSelectionWindow(self, self.settings, self.volume_id,
                                        self.issue_number)
        title = ""
        for record in self.cv_search_results:
            if record['id'] == self.volume_id:
                title = record['name']
                title += " (" + unicode(record['start_year']) + ")"
                title += " - "
                break

        selector.setWindowTitle(title + "Select Issue")
        selector.setModal(True)
        selector.exec_()
        if selector.result():
            # we should now have a volume ID
            self.issue_number = selector.issue_number
            self.accept()
        return

    def selectByID(self):
        for r in range(0, self.twList.rowCount()):
            volume_id, b = self.twList.item(r, 0).data(
                QtCore.Qt.UserRole).toInt()
            if (volume_id == self.volume_id):
                self.twList.selectRow(r)
                break

    def performQuery(self, refresh=False):

        self.progdialog = QtGui.QProgressDialog("Searching Online", "Cancel",
                                                0, 100, self)
        self.progdialog.setWindowTitle("Online Search")
        self.progdialog.canceled.connect(self.searchCanceled)
        self.progdialog.setModal(True)

        self.search_thread = SearchThread(self.series_name, refresh)
        self.search_thread.searchComplete.connect(self.searchComplete)
        self.search_thread.progressUpdate.connect(self.searchProgressUpdate)
        self.search_thread.start()

        # QtCore.QCoreApplication.processEvents()
        self.progdialog.exec_()

    def searchCanceled(self):
        print("query cancelled")
        self.search_thread.searchComplete.disconnect(self.searchComplete)
        self.search_thread.progressUpdate.disconnect(self.searchProgressUpdate)
        self.progdialog.canceled.disconnect(self.searchCanceled)
        self.progdialog.reject()
        QtCore.QTimer.singleShot(200, self.closeMe)

    def closeMe(self):
        print("closeme")
        self.reject()

    def searchProgressUpdate(self, current, total):
        self.progdialog.setMaximum(total)
        self.progdialog.setValue(current)

    def searchComplete(self):
        self.progdialog.accept()
        if self.search_thread.cv_error:
            if self.search_thread.error_code == ComicVineTalkerException.RateLimit:
                QtGui.QMessageBox.critical(
                    self, self.tr("Comic Vine Error"),
                    ComicVineTalker.getRateLimitMessage())
            else:
                QtGui.QMessageBox.critical(
                    self, self.tr("Network Issue"),
                    self.tr(
                        "Could not connect to Comic Vine to search for series!"
                    ))
            return

        self.cv_search_results = self.search_thread.cv_search_results
        self.updateButtons()

        self.twList.setSortingEnabled(False)

        while self.twList.rowCount() > 0:
            self.twList.removeRow(0)

        row = 0
        for record in self.cv_search_results:
            self.twList.insertRow(row)

            item_text = record['name']
            item = QtGui.QTableWidgetItem(item_text)
            item.setData(QtCore.Qt.ToolTipRole, item_text)
            item.setData(QtCore.Qt.UserRole, record['id'])
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.twList.setItem(row, 0, item)

            item_text = str(record['start_year'])
            item = QtGui.QTableWidgetItem(item_text)
            item.setData(QtCore.Qt.ToolTipRole, item_text)
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.twList.setItem(row, 1, item)

            item_text = record['count_of_issues']
            item = QtGui.QTableWidgetItem(item_text)
            item.setData(QtCore.Qt.ToolTipRole, item_text)
            item.setData(QtCore.Qt.DisplayRole, record['count_of_issues'])
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.twList.setItem(row, 2, item)

            if record['publisher'] is not None:
                item_text = record['publisher']['name']
                item.setData(QtCore.Qt.ToolTipRole, item_text)
                item = QtGui.QTableWidgetItem(item_text)
                item.setFlags(QtCore.Qt.ItemIsSelectable
                              | QtCore.Qt.ItemIsEnabled)
                self.twList.setItem(row, 3, item)

            row += 1

        self.twList.resizeColumnsToContents()
        self.twList.setSortingEnabled(True)
        self.twList.sortItems(2, QtCore.Qt.DescendingOrder)
        self.twList.selectRow(0)
        self.twList.resizeColumnsToContents()

        if len(self.cv_search_results) == 0:
            QtCore.QCoreApplication.processEvents()
            QtGui.QMessageBox.information(self, "Search Result",
                                          "No matches found!")

        if self.immediate_autoselect and len(self.cv_search_results) > 0:
            # defer the immediate autoselect so this dialog has time to pop up
            QtCore.QCoreApplication.processEvents()
            QtCore.QTimer.singleShot(10, self.doImmediateAutoselect)

    def doImmediateAutoselect(self):
        self.immediate_autoselect = False
        self.autoSelect()

    def cellDoubleClicked(self, r, c):
        self.showIssues()

    def currentItemChanged(self, curr, prev):

        if curr is None:
            return
        if prev is not None and prev.row() == curr.row():
            return

        self.volume_id, b = self.twList.item(curr.row(), 0).data(
            QtCore.Qt.UserRole).toInt()

        # list selection was changed, update the info on the volume
        for record in self.cv_search_results:
            if record['id'] == self.volume_id:
                if record['description'] is None:
                    self.teDetails.setText("")
                else:
                    self.teDetails.setText(record['description'])
                self.imageWidget.setURL(record['image']['super_url'])
                break