diff --git a/comictaggerlib/options.py b/comictaggerlib/options.py index 3cc619a..c9ee885 100644 --- a/comictaggerlib/options.py +++ b/comictaggerlib/options.py @@ -27,6 +27,7 @@ import ctversion import utils from genericmetadata import GenericMetadata from comicarchive import MetaDataStyle +from versionchecker import VersionChecker class Options: help_text = """ @@ -252,7 +253,7 @@ For more help visit the wiki at: http://code.google.com/p/comictagger/ if o == "--version": print "ComicTagger {0}: Copyright (c) 2012-2013 Anthony Beville".format(ctversion.version) print "Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)" - new_version = utils.getLatestVersion() + new_version = VersionChecker().getLatestVersion("", False) if new_version is not None: print "----------------------------------------" print "New version available online: {0}".format(new_version) diff --git a/comictaggerlib/settings.py b/comictaggerlib/settings.py index f5b1b75..5fc7a44 100644 --- a/comictaggerlib/settings.py +++ b/comictaggerlib/settings.py @@ -24,6 +24,7 @@ import sys import configparser import platform import codecs +import uuid import utils @@ -68,8 +69,10 @@ class ComicTaggerSettings: self.unrar_exe_path = "" self.allow_cbi_in_rar = True self.check_for_new_version = True + self.send_usage_stats = False # automatic settings + self.install_id = uuid.uuid4().hex self.last_selected_save_data_style = 0 self.last_selected_load_data_style = 0 self.last_opened_folder = "" @@ -88,6 +91,7 @@ class ComicTaggerSettings: self.ask_about_cbi_in_rar = True self.show_disclaimer = True self.dont_notify_about_this_version = "" + self.ask_about_usage_stats = True # Comic Vine settings self.use_series_start_as_volume = False @@ -175,7 +179,11 @@ class ComicTaggerSettings: self.unrar_exe_path = self.config.get( 'settings', 'unrar_exe_path' ) if self.config.has_option('settings', 'check_for_new_version'): self.check_for_new_version = self.config.getboolean( 'settings', 'check_for_new_version' ) - + if self.config.has_option('settings', 'send_usage_stats'): + self.send_usage_stats = self.config.getboolean( 'settings', 'send_usage_stats' ) + + if self.config.has_option('auto', 'install_id'): + self.install_id = self.config.get( 'auto', 'install_id' ) if self.config.has_option('auto', 'last_selected_load_data_style'): self.last_selected_load_data_style = self.config.getint( 'auto', 'last_selected_load_data_style' ) if self.config.has_option('auto', 'last_selected_save_data_style'): @@ -206,6 +214,8 @@ class ComicTaggerSettings: self.show_disclaimer = self.config.getboolean( 'dialogflags', 'show_disclaimer' ) if self.config.has_option('dialogflags', 'dont_notify_about_this_version'): self.dont_notify_about_this_version = self.config.get( 'dialogflags', 'dont_notify_about_this_version' ) + if self.config.has_option('dialogflags', 'ask_about_usage_stats'): + self.ask_about_usage_stats = self.config.getboolean( 'dialogflags', 'ask_about_usage_stats' ) if self.config.has_option('comicvine', 'use_series_start_as_volume'): self.use_series_start_as_volume = self.config.getboolean( 'comicvine', 'use_series_start_as_volume' ) @@ -244,10 +254,12 @@ class ComicTaggerSettings: self.config.set( 'settings', 'check_for_new_version', self.check_for_new_version ) self.config.set( 'settings', 'rar_exe_path', self.rar_exe_path ) self.config.set( 'settings', 'unrar_exe_path', self.unrar_exe_path ) + self.config.set( 'settings', 'send_usage_stats', self.send_usage_stats ) if not self.config.has_section( 'auto' ): self.config.add_section( 'auto' ) + self.config.set( 'auto', 'install_id', self.install_id ) self.config.set( 'auto', 'last_selected_load_data_style', self.last_selected_load_data_style ) self.config.set( 'auto', 'last_selected_save_data_style', self.last_selected_save_data_style ) self.config.set( 'auto', 'last_opened_folder', self.last_opened_folder ) @@ -270,6 +282,7 @@ class ComicTaggerSettings: self.config.set( 'dialogflags', 'ask_about_cbi_in_rar', self.ask_about_cbi_in_rar ) self.config.set( 'dialogflags', 'show_disclaimer', self.show_disclaimer ) self.config.set( 'dialogflags', 'dont_notify_about_this_version', self.dont_notify_about_this_version ) + self.config.set( 'dialogflags', 'ask_about_usage_stats', self.ask_about_usage_stats ) if not self.config.has_section( 'comicvine' ): self.config.add_section( 'comicvine' ) diff --git a/comictaggerlib/taggerwindow.py b/comictaggerlib/taggerwindow.py index a80fd5f..2c489f5 100644 --- a/comictaggerlib/taggerwindow.py +++ b/comictaggerlib/taggerwindow.py @@ -55,6 +55,7 @@ from autotagstartwindow import AutoTagStartWindow from autotagprogresswindow import AutoTagProgressWindow from autotagmatchwindow import AutoTagMatchWindow from coverimagewidget import CoverImageWidget +from versionchecker import VersionChecker import utils import ctversion @@ -204,8 +205,20 @@ class TaggerWindow( QtGui.QMainWindow): ) self.settings.show_disclaimer = not checked - if self.settings.check_for_new_version: - QtCore.QTimer.singleShot(1, self.checkLatestVersionOnline) + if self.settings.ask_about_usage_stats: + reply = QtGui.QMessageBox.question(self, + self.tr("Anonymous Stats"), + self.tr( + "Is it okay if ComicTagger occasionally sends some anonymous usage statistics? Nothing nefarious, " + "just trying to get a better idea of how the app is being used.\n\nThanks for your support!" + ), + QtGui.QMessageBox.Yes|QtGui.QMessageBox.Default, QtGui.QMessageBox.No ) + + if reply == QtGui.QMessageBox.Yes: + self.settings.send_usage_stats = True + self.settings.ask_about_usage_stats = False + + self.checkLatestVersionOnline() def sigint_handler(self, *args): # defer the actual close in the app loop thread @@ -1840,11 +1853,11 @@ class TaggerWindow( QtGui.QMainWindow): self.splitterMovedEvent( 0, 0) def checkLatestVersionOnline( self ): - - new_version = utils.getLatestVersion() - if new_version is None: - return - + self.versionChecker = VersionChecker() + self.versionChecker.versionRequestComplete.connect( self.versionCheckComplete ) + self.versionChecker.asyncGetLatestVersion( self.settings.install_id, self.settings.send_usage_stats ) + + def versionCheckComplete( self, new_version ): if ( new_version != self.version and new_version != self.settings.dont_notify_about_this_version): website = "http://code.google.com/p/comictagger" diff --git a/comictaggerlib/versionchecker.py b/comictaggerlib/versionchecker.py new file mode 100644 index 0000000..a8044db --- /dev/null +++ b/comictaggerlib/versionchecker.py @@ -0,0 +1,91 @@ +""" +Version checker +""" + +""" +Copyright 2013 Anthony Beville + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" +import sys +import os +import platform +import urllib,urllib2 +import ctversion + +try: + from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest + from PyQt4.QtCore import QUrl, pyqtSignal, QObject, QByteArray +except ImportError: + # No Qt, so define a few dummy QObjects to help us compile + class QObject(): + def __init__(self,*args): + pass + class pyqtSignal(): + def __init__(self,*args): + pass + def emit(a,b,c): + pass + +class VersionChecker(QObject): + + def getRequestUrl( self, uuid, use_stats ): + + base_url = "http://comictagger1.appspot.com/latest" + args = "" + + if use_stats: + if platform.system() == "Windows": + plat = "win" + elif platform.system() == "Linux": + plat = "lin" + elif platform.system() == "Darwin": + plat = "mac" + else: + plat = "other" + args = "?uuid={0}&platform={1}&version={2}".format(uuid, plat, ctversion.version) + if not getattr(sys, 'frozen', None): + args += "&src=T" + + return base_url+args + + def getLatestVersion( self, uuid, use_stats=True): + + try: + resp = urllib2.urlopen( self.getRequestUrl(uuid, use_stats )) + new_version = resp.read() + except Exception as e: + return None + + if new_version is None or new_version == "": + return None + return new_version.strip() + + versionRequestComplete = pyqtSignal( str ) + + def asyncGetLatestVersion( self, uuid, use_stats ): + + url = self.getRequestUrl( uuid, use_stats ) + + self.nam = QNetworkAccessManager() + self.nam.finished.connect( self.asyncGetLatestVersionComplete ) + self.nam.get(QNetworkRequest(QUrl(str(url)))) + + def asyncGetLatestVersionComplete( self, reply ): + # read in the response + new_version = str(reply.readAll()) + + if new_version is None or new_version == "": + return + + self.versionRequestComplete.emit( new_version.strip() )