def op(self, verb): '''Do operation on game.''' game = self.sources[self.game] if self.operation == False and \ ask.askyesno('%s game?' % verb, 'Are you sure you want to %s %s?' % (verb.lower(), self.name(self.game)), icon='warning', default='no'): self.operation = 0 self.lastpercent = 0 self.button('move', False) for i in (self.ltype, self.rtype): i.unbind('<Return>') #Disallow refreshing during operation if verb != 'Delete': self.copy(self.srclib, self.dstlib, self.game) if verb == 'Move': self.title('Deleting original files', 100) if verb != 'Copy': self.delete(self.srclib, self.game) self.title() for lib, lab, lis, bar in ((self.llib, self.llab, self.llis, self.lbar), (self.llib, self.llab, self.llis, self.lbar)): capacity, used, free = shutil.disk_usage(lib['path']) lib['capacity'] = capacity lib['used'] = used lib['free'] = free self.canvas(bar, capacity, [ (bgcolor, 0, capacity),(usedcolor, 0, used)]) updateitem(lab, '%s (%s free)' % (sm.bytesize(capacity), sm.bytesize(free))) names = [self.name(ID) for ID in lib['games']] updateitem(lis, sorted(names, key = lambda x: x.lower().replace('the ','').replace('a ',''))) self.operation = False self.button() #Reset movement self.ltype.bind('<Return>', lambda e: thread(self.getlibrary,'l')) self.rtype.bind('<Return>', lambda e: thread(self.getlibrary,'r')) #Reällow refresh
def clean(self, event=None): inp = self.path.get() path = sm.getpath(inp) if not path: print("Can't find library at path '%s'" % inp) self.button.config(state='active', text='Library not find') return None self.button.config(text='Cleaning...', state='disabled') path = os.path.join(path, 'steamapps', 'common') deletedsize, deletedcount = removeredists(path) if deletedcount: update = '%s (%s files) saved' % (sm.bytesize(deletedsize), deletedcount) print(path + ': ' + update) self.button.config(state='active', text=update) else: print('No redundant files found in ' + path) self.button.config(state='active', text='Already clean :D')
def displaygame(self, side, ID): if 'l' in side: lib = self.llib dstlib = self.rlib srclab = self.llab dstlab = self.rlab srcnam = 'left' dstnam = 'right' srcbar = self.lbar dstbar = self.rbar else: lib = self.rlib dstlib = self.llib srclab = self.rlab dstlab = self.llab srcbar = self.rbar dstbar = self.lbar srcnam = 'right' dstnam = 'left' game = self.sources[ID] if lib['games'][ID]: # The size in bytes, or FALSE if not provided size = lib['games'][ID] sizeestimate = False else: size = game['size'] # Steam's provided size; may be incorrect sizeestimate = True def sizeget(): self.updatesize(lib, ID) self.displaygame(side, ID) thread(sizeget) # Immediately set off to get size if ID in self.names: name = self.names[ID] else: name = game['name'] if len(name) > 50: name = name[:50] + '...' #Truncate name for display if dstlib: needed = size - dstlib['free'] #Bytes needed on other drive else: needed = 1 #Update canvas for own game showing space taken self.canvas(srcbar, lib['capacity'],[ (bgcolor,0,lib['capacity']),(usedcolor, 0, lib['used']), (ohnecolor, lib['used'] - size, lib['used']) ]) if needed < 0: #Can move to destination drive self.srclib = lib self.dstlib = dstlib if not self.operation: self.button() #Allow movement to other library if sizeestimate: updateitem(self.info, '%s (%s side)\nSize: %s? – ID: %s' % ( name, srcnam, sm.bytesize(size), ID)) bg = bgcolor_ #Paler color to indicate unsureness else: updateitem(self.info, '%s (%s side)\nSize: %s – ID: %s' % ( name, srcnam, sm.bytesize(size), ID)) bg = bgcolor self.canvas(dstbar, dstlib['capacity'],[ (bg, 0, dstlib['capacity']), (usedcolor, 0, dstlib['used']), (withcolor, dstlib['used'], dstlib['used'] + size) ]) else: self.button('move', False) #Disallow movement buttons if sizeestimate: updateitem(self.info, '%s\nSize: %s? – %s more needed – ID: %s' % ( name, sm.bytesize(size), sm.bytesize(needed), ID)) else: updateitem(self.info, '%s\nSize: %s – %s more needed – ID: %s' % ( name, sm.bytesize(size), sm.bytesize(needed), ID)) self.canvas(dstbar, dstlib['capacity'],[ (ohnecolor, 0, dstlib['capacity']), (usedcolor, 0, dstlib['used']) ])
def getlibrary(self, side): '''Fetches library of given side ('l' or 'r')''' updateitem(self.info, 'No game selected. Double-click one from either library.') side, inp, lab, lis, bar = ( ('left', self.ltype, self.llab, self.llis, self.lbar), ('right', self.rtype, self.rlab, self.rlis, self.rbar))[side == 'r'] self.title('Finding %s library' % side) path = sm.getpath(inp.get()) if path: updateitem(inp, path) gamespath = os.path.join(path, 'steamapps') self.title('Scanning %s library' % side) capacity, used, free = shutil.disk_usage(path) games = {} # List of library's game IDs. for i in os.listdir(gamespath): if not (i.endswith('.acf') and i.startswith('appmanifest_')): continue ID = i[12:-4] downloaded = None if not ID in self.sources: acfpath = os.path.join(gamespath, i) with open(acfpath) as f: f = f.readlines() for line in f: if 'buildid' in line: # if it is "0", it is not downloaded downloaded = re.findall('"buildid"\s+"(.+)"', line)[0] elif 'installdir' in line: gamepath = re.findall('"installdir"\s+"(.+)"', line)[0] elif 'name' in line: name = re.findall('"name"\s+"(.+)"', line)[0] elif 'SizeOnDisk' in line: size = int(re.findall('"SizeOnDisk"\s+"(.+)"', line)[0]) if downloaded != '0': self.sources[ID] = {'name': name, 'path': gamepath, 'size': size} games[ID] = False else: games[ID] = False lib = {'capacity': capacity, 'free': free, 'used': used, 'games': games, 'path': gamespath} self.canvas(bar, capacity, [ (bgcolor, 0, capacity),(usedcolor, 0, used)]) updateitem(lab, '%s (%s free)' % (sm.bytesize(capacity), sm.bytesize(free))) names = [self.name(ID) for ID in games] updateitem(lis, sorted(names, key = lambda x: x.lower().replace('the ','').replace('a ',''))) else: lib = False updateitem(lab, 'No drive found') updateitem(lis, defaultlist) self.canvas(bar, 1, [(bgcolor,0,1)]) if side == 'right': self.rlib = lib else: self.llib = lib if lib: sm.thread(self.updatesizes, side) #Set process off to calculate sizes self.title() # Clear title