Ironpython in visual studio 2019 - python

I have been struggling to create a button that loads the file using IronPython in Visual studio 2019. The console window pops up for 1 sec and disappears.
import wpf
clr.AddReference('IronPython.Wpf') #Add a reference for the ' System.Windows.Forms' namespace and etc..
clr.AddReference('System.IO')
clr.AddReference('Systemm.Drawing')
clr.AddReference('System.Reflection')
clr.AddReference('System.Threading')
clr.AddReference('System.Windows.Forms')
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'WpfApplication1.xaml')
def Button_Click(self, sender, e):
#Folder path of variables
FOLDER_PATH = r'C:\\Users\\Desktop\\waveform1' #Back slash will be treated as escape character
# Define a funhction to print out the file name
# Input parameter will be dir
def listDir(dir):
fileNames = os.listdir(dir)
for fileName in fileNames:
print('File Name: ' +fileName)
print('Folder Path: ' + os.path.abspath(os.path.join(dir,fileName)))
if __name__ == '__main__':
Application().Run(MyWindow())

Just use if __name__ == '__main__': outside off your class
import wpf
clr.AddReference('IronPython.Wpf') #Add a reference for the ' System.Windows.Forms' namespace and etc..
clr.AddReference('System.IO')
clr.AddReference('Systemm.Drawing')
clr.AddReference('System.Reflection')
clr.AddReference('System.Threading')
clr.AddReference('System.Windows.Forms')
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'WpfApplication1.xaml')
def Button_Click(self, sender, e):
#Folder path of variables
FOLDER_PATH = r'C:\\Users\\Desktop\\waveform1' #Back slash will be treated as escape character
# Define a funhction to print out the file name
# Input parameter will be dir
def listDir(dir):
fileNames = os.listdir(dir)
for fileName in fileNames:
print('File Name: ' +fileName)
print('Folder Path: ' + os.path.abspath(os.path.join(dir,fileName)))
if __name__ == '__main__':
Application().Run(MyWindow())
I give Some example
import wpf
import FlippingGame
from System.Windows import Application, Window, Visibility
from System.Windows.Media import Brushes
class WpfSampleWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'PyWpfSample.xaml')
self.game = FlippingGame.FlippingGame()
def flipButton_Click(self, sender, e):
wager = self._getWager()
if not wager:
return
guess = "H" if self.guessHeadsButton.IsChecked else "T"
won, toss = self.game.flip(guess, wager)
self._showToss(won, toss)
self._showBankroll()
self._maybeEndGame()
def Window_Loaded(self, sender, e):
self._showBankroll()
def _getWager(self):
try:
wager = int(self.wagerBox.Text)
except ValueError as v:
self.wagerBox.Foreground = Brushes.Red
self._showError("Wager must be a number.")
return
else:
self._hideError()
self.wagerBox.Foreground = Brushes.Black
if wager < 1:
self.wagerBox.Foreground = Brushes.Red
self._showError("Wager must be at least 1 credit.")
return
if wager > self.game.bankroll:
self.wagerBox.Foreground = Brushes.Red
self._showError("Wager cannot be more than your bankroll.")
return
return wager
def _showError(self, error):
self.errorLabel.Content = error
self.errorLabel.Visibility = Visibility.Visible
def _hideError(self):
self.errorLabel.Visibility = Visibility.Collapsed
def _showToss(self, won, toss):
self.resultLabel.Content = toss
self.resultLabel.Foreground = Brushes.Green if won else Brushes.Red
def _showBankroll(self):
self.bankrollLabel.Content = str(self.game.bankroll)
def _maybeEndGame(self):
if self.game.bankroll <= 0:
self._showToss(False, 'X')
self.flipButton.IsEnabled = False
self.wagerBox.IsEnabled = False
self.guessHeadsButton.IsEnabled = False
self.guessTailsButton.IsEnabled = False
def wagerBox_GotFocus(self, sender, e):
sender.Foreground = Brushes.Black
if __name__ == '__main__':
Application().Run(WpfSampleWindow())

Related

My code can't find the file

I have written a program that has to execute a file and draw it in turtle.
But when I try to call a fdl filename it cant find it.
import turtle
#I start out making the basic turtle commands
def lt (turtle, n):
turtle.lt(n)
def fd (turtle, n):
turtle.fd(n)
def bk (turtle, n):
turtle.bk(n)
def rt (turtle, n):
turtle.rt(n)
#Then i create a class that makes it possible to create a set of rules
class Rule(object):
#Here the rule based on a description string is initialized like ("F -> F L F L")
def __init__(self,repr):
#This is where the left and right part of the rule in "F -> F L F L" comes in
self.left, self.right = [a.strip() for a in repr.split("->")]
if self.left is None or self.right is None:
print("Invalid rule description!")
#Now i use the same princip like i did in task6. the Apply function
def apply_rule_on_elements(self,element):
return [self._apply_rule_for_element (element) for element in elements]
#This is a helper function that only works on one element at a time
def _apply_rule_for_element (self,element):
if element == self.left:
return self.right.split()
return element
#Here is a very simple helper function, handy in some cases
#This allows one to perform assignment multiple values og grouping
def split_command(command, *args):
return command, args
#Now i make a command class that wraps the execution of a given command
class Command(object):
def __init__(self,command):
#the name and number of arguments for the given command
self.name,self.args = split_command(*command.split())
def execute(self,turtle,length):
if self.name == "lt":
lt(turtle,int(self.args[0]))
elif self.name == "scale":
length[0] = length[0]*float(self.args[0])
elif self.name == "fd":
fd(turtle,length[0])
elif self.name == "bk":
bk(turtle,length[0])
elif self.name == "rt":
rt(turtle,int(self.args[0]))
elif self.name == "nop":
pass
#Here i write the main Fractal class
class Fractal(object):
def __init__(self):
#Initial and current state
self.state = []
#Rules associated with the current fractal
self.rules = []
#Commands associated with the current fractal
self.commands = {}
#since values are immutable and passed by value, I use an array (passed by reference value)
#to allow the modification of the variable
self.length = [0]
#The current depth
self.depth = 0
#Executes the command associated w/ the current states stored in the fractal
def execute_commands(self,turtle,states):
for state in states:
self.commands[state].execute(turtle,self.length)
#Flattens a list
def _flatten(self,l):
flattened_list = []
for element in l:
flattened_list.extend(element)
return flattened_list
#Here i compute the fractal, which does that actual iteration work
#It returns the state of the fractal after the computation
def compute(self):
current_depth = self.depth
current_state = self.state
while self.depth !=0:
current_state=self.compute_next_state(current_state)
self.depth-=1
return current_state
def _compute_next_state(self,state):
for rule in self.rules:
state = rule.apply_rule_on_elements(state)
return self._flatten(state)
#This parses the fdl file, creates a fractal and set it up with the values
#read in the fdl file
def read_fdl(filename):
import os
f = Fractal()
if os.path.exists(filename):
lines = open(filename).readlines()
for line in lines:
if not len(line.strip())==0:
name,arguments = split_command(*line.strip().split())
if name == "start":
f.state = arguments
elif name == "rule":
f.rules.append(Rule("".join(arguments)))
elif name =="length":
f.length = [int(arguments[0])]
elif name == "depth":
f.depth = int(arguments[0])
elif name == "cmd":
f.commands[arguments[0]] = Command("".join (arguments[1:]))
else:
print("File does not exist")
#no check is made, to see if we have a fractal that was completely initialized
return f
import sys
import turtle
if len(sys.argv)>1:
f=read_fdl(sys.argv[1])
f.execute_commands(turtle,f.compute())
read_fdl("sierpinski")
The message I get is "File does not exist", but it does.
No, it doesn't exist - at least not in the current directory and without an extension.
Try adding the right directory and extension to the name "sierpinski"
Given that this is an fdl (fractal definition language) file, try:
read_fdl("sierpinski.fdl")

Preset Variable with Pickle

import time
from random import randint
import pickle
MaTC = 1
MaTC = pickle.dump(MaTC, open("MaTCFile.txt", "wb"))
AnTC = 2
AnTC = pickle.dump(AnTC, open("AnTCFile.txt", "wb"))
AuTC = 3
AuTC = pickle.dump(AuTC, open("AuTCFile.txt", "wb"))
AlTC = 3
AlTC = pickle.dump(AlTC, open("AlTCFile.txt", "wb"))
JaTC = 3
JaTC = pickle.dump(JaTC, open("JaTCFile.txt", "wb"))
print("Hello Jacob")
time.sleep(1)
print("Choose an option!")
print("(1) Selecting Cleaners")
print("(2) Edit Cleaning Information")
print("(3) Reserved")
MenuChoice = input(": ")
if MenuChoice == "1":
print("Selecting Cleaner Function")
elif MenuChoice == "2":
print("(1) Check cleaning info")
print("(2) Enter New Cleaning info")
InfoSelect = input(": ")
if InfoSelect == "2":
Mare = { "Mares Times Cleaned": MaTC}
Andre = { "Andres Times Cleaned": AnTC}
Al = { "Als Times Cleaned": AlTC}
Austin = { "Austins Times Cleaned": AuTC}
Jacob = { "Jacobs Times Cleaned": JaTC}
pickle.dump( Mare, open ("MaresFile.txt", "wb"))
pickle.dump( Jacob, open ("JacobsFile.txt", "wb"))
pickle.dump( Andre, open ("AndresFile.txt", "wb"))
pickle.dump( Austin,open ("AustinsFile.txt", "wb"))
pickle.dump( Al, open ("AlsFile.txt", "wb"))
print(Mare)
print(Austin)
print(Jacob)
print(Andre)
print(Al)
Okay so basically what I am trying to achieve is have the MaTC, AnTC, AuTC, AlTC, and JaTC Variables be preset as 1, 2, 3, 3, and 3 at the first time running the program. But when I want to add 2 to say MaTC making it 3, When I start the program again I want it to = 3 on startup. I just started python a few days ago, I would love the feedback!
Use exceptions to handle the case where the file does not exist (i.e. first run of the program)
try:
f = open("MaTCFile.dat", "rb") # Pickle is not a .txt format
MaTC = pickle.load(f)
except IOError:
# Initialise default value
MaTC = 1
I would also be inclined to store all the variables in a single file using a dict:
default_data = {
"MaTC": 1, "AnTC": 2, # ... etc.
as this would make the program more manageable.
Here is a refactored version of your program. It uses the pickle module and demonstrates usage of pickletools, zlib, and a few other module. Hopefully, the code will help you further along in writing your program. One subject that you probably will want to research in the future is that of databases.
import os
import pickle
import pickletools
import sys
import zlib
SETTINGS_FILE = 'settings.sav'
def main():
"""Present the user with a cleaning application."""
settings = load_settings(SETTINGS_FILE)
print('Hello, Jacob!')
while True:
if show_menu(settings,
select_cleaners,
edit_cleaning_information,
reserved,
close_program):
break
settings.save(SETTINGS_FILE)
def load_settings(path):
"""Create the settings schema and load them from file is possible."""
settings = Namespace(mares=Parameter(1, is_positive_int),
andres=Parameter(2, is_positive_int),
austin=Parameter(3, is_positive_int),
al=Parameter(3, is_positive_int),
jacob=Parameter(3, is_positive_int))
if os.path.isfile(path):
settings.load(path)
return settings
def is_positive_int(value):
"""Ensure that the value is valid for the settings."""
return isinstance(value, int) and value >= 0
def show_menu(context, *args):
"""Help display a menu to the user."""
for option, function in enumerate(args, 1):
print(option, '-', function.__doc__)
while True:
number = get_int('Please enter an option: ') - 1
if 0 <= number < len(args):
return args[number](context)
else:
print('Your number was out of range.')
def get_int(prompt):
"""Get a valid number from the user."""
while True:
try:
text = input(prompt)
except EOFError:
sys.exit()
else:
try:
return int(text)
except ValueError:
print('You did not enter an integer.')
def select_cleaners(context):
"""Choose this to select your cleaner."""
print('Selecting Cleaning Function')
def edit_cleaning_information(context):
"""You can edit the cleaning information."""
show_menu(context, check_cleaning_info, enter_new_cleaning_info)
def reserved(context):
"""This is reserved for future use."""
print('NOT AVAILABLE')
def close_program(context):
"""Close the program."""
return True
def check_cleaning_info(context):
"""Show all cleaning info."""
print('Mares:', context.mares)
print('Andres:', context.andres)
print('Austin:', context.austin)
print('Al:', context.al)
print('Jacob:', context.jacob)
def enter_new_cleaning_info(context):
"""Enter in additional cleaning information."""
while True:
name = input('Who needs cleaning info adjusted? ').capitalize()
if name == 'Mares':
context.mares += get_int('Add to Mares: ')
elif name == 'Andres':
context.andres += get_int('Add to Andres: ')
elif name == 'Austin':
context.austin += get_int('Add to Austin: ')
elif name == 'Al':
context.al += get_int('Add to Al: ')
elif name == 'Jacob':
context.jacob += get_int('Add to Jacob: ')
else:
continue
break
###############################################################################
class _Settings:
"""_Settings(*args, **kwargs) -> _Settings instance"""
#staticmethod
def _save(path, obj):
"""Save an object to the specified path."""
data = zlib.compress(pickletools.optimize(pickle.dumps(obj)), 9)
with open(path, 'wb') as file:
file.write(data)
#staticmethod
def _load(path):
"""Load an object from the specified path."""
with open(path, 'rb') as file:
data = file.read()
return pickle.loads(zlib.decompress(data))
class Namespace(_Settings):
"""Namespace(**schema) -> Namespace instance"""
def __init__(self, **schema):
"""Initialize the Namespace instance with a schema definition."""
self.__original, self.__dynamic, self.__static, self.__owner = \
{}, {}, {}, None
for name, value in schema.items():
if isinstance(value, _Settings):
if isinstance(value, Namespace):
if value.__owner is not None:
raise ValueError(repr(name) + 'has an owner!')
value.__owner = self
self.__original[name] = value
else:
raise TypeError(repr(name) + ' has bad type!')
def __setattr__(self, name, value):
"""Set a named Parameter with a given value to be validated."""
if name in {'_Namespace__original',
'_Namespace__dynamic',
'_Namespace__static',
'_Namespace__owner',
'state'}:
super().__setattr__(name, value)
elif '.' in name:
head, tail = name.split('.', 1)
self[head][tail] = value
else:
attr = self.__original.get(name)
if not isinstance(attr, Parameter):
raise AttributeError(name)
attr.validate(value)
if value == attr.value:
self.__dynamic.pop(name, None)
else:
self.__dynamic[name] = value
def __getattr__(self, name):
"""Get a Namespace or Parameter value by its original name."""
if '.' in name:
head, tail = name.split('.', 1)
return self[head][tail]
if name in self.__dynamic:
return self.__dynamic[name]
attr = self.__original.get(name)
if isinstance(attr, Namespace):
return attr
if isinstance(attr, Parameter):
return attr.value
raise AttributeError(name)
__setitem__ = __setattr__
__getitem__ = __getattr__
def save(self, path):
"""Save the state of the entire Namespace tree structure."""
if isinstance(self.__owner, Namespace):
self.__owner.save(path)
else:
self._save(path, {Namespace: self.state})
def load(self, path):
"""Load the state of the entire Namespace tree structure."""
if isinstance(self.__owner, Namespace):
self.__owner.load(path)
else:
self.state = self._load(path)[Namespace]
def __get_state(self):
"""Get the state of this Namespace and any child Namespaces."""
state = {}
for name, types in self.__static.items():
box = state.setdefault(name, {})
for type_, value in types.items():
box[type_] = value.state if type_ is Namespace else value
for name, value in self.__original.items():
box = state.setdefault(name, {})
if name in self.__dynamic:
value = self.__dynamic[name]
elif isinstance(value, Parameter):
value = value.value
else:
box[Namespace] = value.state
continue
box.setdefault(Parameter, {})[type(value)] = value
return state
def __set_state(self, state):
"""Set the state of this Namespace and any child Namespaces."""
dispatch = {Namespace: self.__set_namespace,
Parameter: self.__set_parameter}
for name, box in state.items():
for type_, value in box.items():
dispatch[type_](name, value)
def __set_namespace(self, name, state):
"""Set the state of a child Namespace."""
attr = self.__original.get(name)
if not isinstance(attr, Namespace):
attr = self.__static.setdefault(name, {})[Namespace] = Namespace()
attr.state = state
def __set_parameter(self, name, state):
"""Set the state of a child Parameter."""
attr = self.__original.get(name)
for type_, value in state.items():
if isinstance(attr, Parameter):
try:
attr.validate(value)
except TypeError:
pass
else:
if value == attr.value:
self.__dynamic.pop(name, None)
else:
self.__dynamic[name] = value
continue
if not isinstance(value, type_):
raise TypeError(repr(name) + ' has bad type!')
self.__static.setdefault(name, {}).setdefault(
Parameter, {})[type_] = value
state = property(__get_state, __set_state, doc='Namespace state property.')
class Parameter(_Settings):
"""Parameter(value, validator=lambda value: True) -> Parameter instance"""
def __init__(self, value, validator=lambda value: True):
"""Initialize the Parameter instance with a value to validate."""
self.__value, self.__validator = value, validator
self.validate(value)
def validate(self, value):
"""Check that value has same type and passes validator."""
if not isinstance(value, type(self.value)):
raise TypeError('Value has a different type!')
if not self.__validator(value):
raise ValueError('Validator failed the value!')
#property
def value(self):
"""Parameter value property."""
return self.__value
###############################################################################
if __name__ == '__main__':
main()

Get all subclasses defined in several python modules

I got 2 python files implement test repository factory pattern:
testrepository.py
class TestRepository(object):
def __init__(self):
pass
def generate(self, username, password):
pass
def update(self):
pass
class RepositoryFactory(object):
factories = {}
def add_repo(identification, repo_factory):
RepositoryFactory.factories[identification] = repo_factory
add_repo = staticmethod(add_repo)
def create_repo(identification, server, dirpath, reponame):
if identification not in RepositoryFactory.factories:
RepositoryFactory.factories[identification] = \
eval(identification + '.Factory()')
return RepositoryFactory.factories[identification].create(server, dirpath, reponame)
create_repo = staticmethod(create_repo)
gitrepository.py
from testrepository import TestRepository, RepositoryFactory
class GitRepository(TestRepository):
def __init__(self, server, dirpath, reponame):
super(GitRepository, self).__init__()
self.server = server
self.dirpath = dirpath
self.reponame = reponame
self.username = None
self.password = None
self.fullPath = path.join(self.dirpath, self.reponame)
def generate(self, username, password):
pass
def update(self):
pass
class Factory(object):
#staticmethod
def create(server, dirpath, reponame):
return GitRepository(server=server, dirpath=dirpath, reponame=reponame)
if __name__ == '__main__':
repo_type = TestRepository.__subclasses__().pop().__name__
repo = RepositoryFactory.create_repo(repo_type,
server='localhost',
dirpath='/home/user/git',
reponame='repo')
repo.generate(username='test', password='test')
repo.update()
Problem is repo_type = TestRepository.__subclasses__() in example above is empty, if I put all classes in one file it works:
>>> print TestRepository.__subclasses__()
[<class '__main__.GitRepository'>]
so question is how to fetch all subclasses from several python modules?

shout-python segmentation fault how can I fix this?

I'm attempting to create a source for icecast2/shoutcast. But after compiling everything I've run into a segmentation error. After further debugging with gdb I was given a more detailed error.
I do not know c of any kind so I'm not sure what to make of this error
Program received signal SIGSEGV, Segmentation fault.
send_mp3 (self=0x988eb0, buff = 0xa5c154 "" at mp3.c:175175 mp3.c: No such file or directory.
I thought maybe it was the loop using to much resources. But no matter how much I set time.sleep() I still got the same result.
import random
import shout
from pyModules import db
from pyModules import error
import ID3
import time
import sys
import glob
class Audio(object):
def __init__(self):
self.count = 0
self.nbuf = 0
self.buf = 0
self.shout = shout.Shout()
self.db = db.database()
self.songs = self.load()
def load(self):
return glob.glob("%s*%s" % (self.config('directory'), self.config('ext')))
def start(self):
self.running = True
self.shout.host = self.config('host')
self.shout.port = self.config('port')
self.shout.mount = self.config('mount')
self.shout.protocol = self.config('protocol')
self.shout.user = self.config('user')
self.shout.password = self.config('password')
self.shout.name = self.config('name')
self.shout.format = self.config('format')
self.shout.genre = self.config('genre')
self.shout.url = self.config('url')
self.shout.public = self.config('public')
self.shout.description = self.config('description')
self.songs = self.load()
self.shout.open()
def cShuffle(self):
sh = self.getSettings(1, key='shuffle')
if sh == 1:
random.shuffle(self.songs)
def cNext(self):
n = self.getSettings(1, key='setSong')
if n == 1:
self.stop()
self.db.setNext(0)
self.Change()
def cPrev(self):
p = self.getSettings(1, key='prevSong')
if p == 1:
self.stop()
if self.count == 0:
self.count -= 1
self.db.setPrev(0)
self.Change()
else:
self.count -= 2
self.Change()
def cReload(self):
r = self.getSettings(1, key='reload')
if r == 1:
self.songs = self.load()
def check(self):
self.cShuffle()
self.cNext()
self.cPrev()
self.cReload()
def getSettings(self, mode=0, key=None):
return self.db.getSettings(mode, key)
def config(self, value):
return self.db.config(value)
def getTitle(self, File, mode=0):
try:
song = ID3.ID3(File)
title = song["TITLE"]
except:
title = "unknown"
title = title.replace("'", "")
if mode == 0:
self.db.setSongTitle(title)
return title
elif mode == 1:
self.db.setNextSongTitle(title)
return title
elif mode == 2:
self.db.setPrevSongTitle(title)
def sendBlankFile(self):
File = open('/home/radio/AudioServer/bin/blank.mp3').read()
self.shout.send(File)
def stop(self):
self.buf = 0
self.nbuf = 0
self.running = 0
self.sendBlankFile()
def Change(self):
self.stop()
if len(self.songs) >= self.count: self.count = 0
else: self.count += 1
song = self.songs[self.count]
psong = self.songs[self.count - 1]
nsong = self.songs[self.count + 1]
self.getTitle(song, mode=0)
self.getTitle(nsong, mode=1)
self.getTitle(psong, mode=2)
self.play()
def play(self):
song = open(self.songs[self.count])
cs = self.songs[self.count]
self.shout.set_metadata({'song': self.getTitle(cs)})
total = 0
st = time.time()
self.nbuf = song.read(4096)
while self.running:
self.check()
self.buf = self.nbuf
self.nbuf = song.read(4096)
self.buf = self.nbuf
total = total + len(self.buf)
if len(self.buf) == 0:
self.running = False
self.Change()
self.shout.send(self.buf)
self.shout.sync()
if __name__ == "__main__":
Server = Audio()
default = Server.config('default')
Server.db.clear(default)
Server.start()
The issue was indeed a compile problem of libshout as cox pointed out. But it only worked in debian 7 and not ubuntu 12. I think the reason why is because I did not install libogg in ubuntu I only installed vorbis which I thought was the same thing. I also installed mp3 codecs just in case.

How do I find the cursor position clicked within a Cell of a Gtk IconView?

What I am attempting to-do is to find out if I've clicked in a specific position of a cell in a Gtk Iconview (blue-box on the picture)
During my current investigation if this is possible I've found out that I can get the cursor position via either of two methods:
method 1: add the POINTER_MOTION_MASK so that you can detect where on the IconView the current cursor is
i.e.
self.iconview.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
self.iconview.connect("motion-notify-event", self.on_pointer_motion)
Thus the current cursor position and cell can be found as:
def on_pointer_motion(self, widget, event):
path= self.get_path_at_pos(event.x, event.y)
method 2: connect to the "button-press-event"
self.iconview.connect("button-press-event", self.on_mouse_click)
def on_mouse_click(self, widget, event):
path= self.get_path_at_pos(event.x, event.y)
What I need though is to determine if event.x and event.y can be tied to a specific area within the cell as shown in blue on the picture.
I've looked at the unofficial reference material for GtkCellArea, GtkCellAreaBox and GtkIconView but I dont see an obvious event/function to help with this.
Can anyone give me any pointers in the right direction to take with solving this task?
I'm using Python 2.7 & GTK+ 3.2 as my development environment, but I'm additionally targeting python 3+ as well as all versions of GTK later than GTK+ 3.2
It's quite easy.
Below is Playlist.py, from one of my open source PyGObject projects.
Connect button-press-event signal of GtkIconVIew, and check event type.iconview.get_path_at_pos(...) will return path. path might be None or the position of to selected cell, depending on cursor position.
The project can be found here, https://github.com/LiuLang/babystory
# Copyright (C) 2013 LiuLang <gsushzhsosgsu#gmail.com>
# Use of this source code is governed by GPLv3 license that can be found
# in http://www.gnu.org/licenses/gpl-3.0.html
from gi.repository import GdkPixbuf
from gi.repository import Gdk
from gi.repository import Gtk
import json
import random
from babystory.Cache import Cache
from babystory import Config
from babystory import Net
from babystory import Utils
from babystory import Widgets
_ = Config._
TITLE, SIZE, DURATION, URL, CATEGORY = list(range(5))
def song_row_to_dict(song_row):
song = {
'Title': song_row[TITLE],
'Size': song_row[SIZE],
'Duration': song_row[DURATION],
'Url': song_row[URL],
'Category': song_row[CATEGORY],
}
return song
class Playlist(Gtk.Box):
def __init__(self, app):
self.app = app
super().__init__()
self.curr_playing = None
self.prev_playing = None
self.next_playing = None
self.control_box = Gtk.Box()
self.pack_start(self.control_box, False, False, 0)
paned = Gtk.Paned()
self.pack_start(paned, True, True, 0)
left_window = Gtk.ScrolledWindow()
paned.add1(left_window)
paned.child_set_property(left_window, 'resize', True)
# icon, id, title,
self.left_liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, int, str)
self.left_iconview = Gtk.IconView(model=self.left_liststore)
self.left_iconview.set_pixbuf_column(0)
self.left_iconview.set_text_column(2)
self.left_iconview.props.item_width = 130
if Gtk.MINOR_VERSION > 6:
self.left_iconview.props.activate_on_single_click = True
self.left_iconview.connect('button-press-event',
self.on_left_iconview_button_pressed)
left_window.add(self.left_iconview)
self.left_menu = Gtk.Menu()
self.left_menu_cache = Gtk.MenuItem(_('Cache'))
self.left_menu_cache.connect('activate',
self.on_left_menu_cache_activated)
self.left_menu.append(self.left_menu_cache)
sep = Gtk.SeparatorMenuItem()
self.left_menu.append(sep)
self.left_menu_delete = Gtk.MenuItem(_('Delete'))
self.left_menu_delete.connect('activate',
self.on_left_menu_delete_activated)
self.left_menu.append(self.left_menu_delete)
self.right_window = Gtk.ScrolledWindow()
paned.add2(self.right_window)
paned.child_set_property(self.right_window, 'resize', True)
# title, size, duration, url, category
self.right_liststore = Gtk.ListStore(str, str, str, str, str)
self.right_treeview = Gtk.TreeView(model=self.right_liststore)
self.right_treeview.props.headers_visible = False
self.right_window.add(self.right_treeview)
self.right_treeview.connect('row_activated',
self.on_right_treeview_row_activated)
title_cell = Gtk.CellRendererText()
title_col = Widgets.ExpandedTreeViewColumn(_('Title'), title_cell,
text=TITLE)
self.right_treeview.append_column(title_col)
size_cell = Gtk.CellRendererText()
size_col = Gtk.TreeViewColumn(_('Size'), size_cell, text=SIZE)
self.right_treeview.append_column(size_col)
duration_cell = Gtk.CellRendererText()
duration_col = Gtk.TreeViewColumn(_('Duration'), duration_cell,
text=DURATION)
self.right_treeview.append_column(duration_col)
def after_init(self):
self.playlist = Config.load_playlist()
self.left_liststore.append([self.app.theme['default-icon'], -1,
'All Categories'])
for cat_id in self.playlist:
self.show_category(cat_id)
# signal handlers starts
def do_destroy(self):
Config.dump_playlist(self.playlist)
def on_left_iconview_button_pressed(self, iconview, event):
if event.type != Gdk.EventType.BUTTON_PRESS:
return False
path = iconview.get_path_at_pos(event.x, event.y)
if path is None:
iconview.unselect_all()
if event.button == Gdk.BUTTON_PRIMARY:
if path is not None:
self.on_left_iconview_item_activated(iconview, path)
return True
elif event.button == Gdk.BUTTON_SECONDARY:
self.on_left_iconview_popup_menu(iconview, path, event)
return True
return False
def on_left_iconview_popup_menu(self, iconview, path, event):
self.left_menu.path = path
if path is not None:
self.on_left_iconview_item_activated(iconview, path)
self.left_menu_delete.set_label(_('Delete'))
self.left_menu_cache.set_label(_('Cache'))
else:
self.left_menu_delete.set_label(_('Delete All'))
self.left_menu_cache.set_label(_('Cache All'))
self.left_menu.show_all()
self.left_menu.popup(None, None, None, None,
event.button, event.time)
def on_left_iconview_item_activated(self, iconview, path):
self.left_iconview.select_path(path)
model = self.left_iconview.get_model()
pix, cat_id, title = model[path]
self.curr_category = {'Pix': pix, 'Id': cat_id, 'Title': title, }
self.right_liststore.clear()
self.right_window.get_vadjustment().set_value(0)
if cat_id != -1:
self.append_song_to_liststore(cat_id)
return
for cat_id in self.playlist:
self.append_song_to_liststore(cat_id)
def on_left_menu_delete_activated(self, menu_item):
path = self.left_menu.path
if path is None or int(str(path)) == 0:
while len(self.playlist) > 0:
cat_id = self.playlist[len(self.playlist) - 1]
self.remove_category(cat_id)
return
icon, cat_id, title = self.left_liststore[path]
self.remove_category(cat_id)
def on_left_menu_cache_activated(self, menu_item):
path = self.left_menu.path
if path is None:
_path = Gtk.TreePath(0)
self.left_iconview.select_path(_path)
self.on_left_iconview_item_activated(self.left_iconview, _path)
self.cache_job = Cache(self.app)
self.cache_job.run()
self.cache_job.destroy()
def on_right_treeview_row_activated(self, treeview, path, column):
self.play_song_at(int(str(path)))
# signal handlers ends
#
def show_category(self, cat_id):
category = self.app.categories.category_list[str(cat_id)]
image_path = Net.get_image(category['IconUrl'])
if image_path:
pix = GdkPixbuf.Pixbuf.new_from_file(image_path)
else:
pix = self.app.theme['default-icon']
self.left_liststore.append([pix, category['Id'], category['Title']])
def append_category(self, cat_id):
if cat_id in self.playlist:
return
self.playlist.append(cat_id)
self.show_category(cat_id)
def remove_category(self, cat_id):
if cat_id == -1:
return
index = self.playlist.index(cat_id)
path = Gtk.TreePath(index + 1)
_iter = self.left_liststore.get_iter(path)
self.left_liststore.remove(_iter)
self.playlist.remove(cat_id)
def append_song_to_liststore(self, cat_id):
songs_wrap = Net.get_songs(cat_id)
if songs_wrap is None:
return
songs = songs_wrap['Items']
category = self.get_category_title(cat_id)
print('category:', category)
for song in songs:
self.right_liststore.append([
song['Title'],
Utils.print_size(song['Size']),
Utils.print_duration(song['Duration']),
song['Url'],
category,
])
def get_prev_song(self, repeat=False, shuffle=False):
song_nums = len(self.right_liststore)
if song_nums == 0:
return None
path = self.curr_playing
if path == 0:
if repeat:
path = song_nums - 1
else:
path = 0
else:
path = path - 1
self.prev_playing = path
return self.get_song_from_index(self.prev_playing)
def get_next_song(self, repeat=False, shuffle=False):
song_nums = len(self.right_liststore)
if song_nums == 0:
return None
path = self.curr_playing
if shuffle:
path = random.randint(0, song_nums-1)
elif path == song_nums - 1:
if repeat is False:
self.next_playing = None
return None
path = 0
else:
path = path + 1
self.next_playing = path
print(self.curr_playing, self.prev_playing, self.next_playing)
return self.get_song_from_index(self.next_playing)
def play_prev_song(self, repeat=False, shuffle=False):
if self.prev_playing is None:
song = self.get_prev_song(repeat=repeat, shuffle=shuffle)
if song is None:
return
self.curr_playing = self.prev_playing
self.prev_playing = None
self.play_song()
def play_song(self):
selection = self.right_treeview.get_selection()
path = Gtk.TreePath(self.curr_playing)
selection.select_path(path)
song = self.get_song_from_index(self.curr_playing)
self.app.player.load(song)
def play_song_at(self, pos):
print('play song at:', pos)
self.curr_playing = pos
self.play_song()
def play_next_song(self, repeat=False, shuffle=False):
if self.next_playing is None:
song = self.get_next_song(repeat=repeat, shuffle=shuffle)
if song is None:
return
self.curr_playing = self.next_playing
self.next_playing = None
self.play_song()
def get_song_from_index(self, index):
row = self.right_liststore[index]
song = song_row_to_dict(row)
return song
def get_category_title(self, cat_id):
return self.app.categories.category_list[str(cat_id)]['Title']
def activate_iconview_item_with_cat_id(self, cat_id):
i = 0
for cate in self.left_liststore:
if cate[1] == cat_id:
break
i += 1
path = Gtk.TreePath(i)
self.on_left_iconview_item_activated(self.left_iconview, path)

Categories