I have a TreeView with QtGui.QFileSystemModel to render file system folders.
My TreeView has a checkbox and checks & uncheck working fine. I want to pre-select all checkboxes on UI Load.
please suggest how to make default selected checkbox for TreeView.
My Model code is:-
class CheckableDirModel(QtGui.QFileSystemModel):
def __init__(self, resultFormats, parent=None):
QtGui.QFileSystemModel.__init__(self, None)
filters = QStringList()
#import ipdb;ipdb.set_trace()
filters.append('*.odb')
resultFormats = resultFormats.split(',')
for resultFormat in resultFormats:
filters.append('*.' + resultFormat)
self.setNameFilters(filters)
#set to False to hide files that match the filter
self.setNameFilterDisables(True)
self.checks = {}
self.selectedFiles = set()
#self.b1 = QCheckBox("SPM_CAE_DATA")
#self.b1.setChecked(True)
#Show the particular formate ('.pages') file into result set for the checked folder
def addFile(self,path1):
# import ipdb;ipd b.set_trace()
files = glob.iglob(os.path.join(str(path1), "*.pages"))#size= os.path.getsize(fp)
for file in files:
print(file)
if os.path.isfile(file):
#print(file)
Formate.append(file)
shutil.copy2(file, reportpath + '/../Particular_Formate')
#print(Formate)
#treeView1 = TreeView(reportpath)
#Show the file greater than 250 MB into list
def addFilegt250mb(self,path1):
# import ipdb;ipd b.set_trace()
global listview1
for root, dirs, files in os.walk(str(path1), topdown=False):
for name in files:
f = os.path.join(root, name)
if os.path.isfile(f):#if os.path.isfile(f)
if os.path.getsize(f) >= 0:
greaterSize.append(f)
print(name)
shutil.copy2(f, reportpath+ '/../Particular_Formate_size')
#print(greaterSize)
#remove the File, When uncheck the Folder
def deleteFile(self,path2):
for root, dirs, files in os.walk(str(path2), topdown=False):
for name in files:
f = os.path.join(root, name)
if name == ".DS_Store" :
pass
else:
if os.path.getsize(f) >=0 :
greaterSize.remove(f)
for x in Formate:
if x == f :
Formate.remove(x)
#Formate.remove(f)
self.deletSize(name)
self.deletFormate(name)
#print(greaterSize)
#print(Formate)
#remove the file size greater then 250 MB , When Folder is uncheck
def deletSize(self,name) :
folder = reportpath +'/../Particular_Formate_size'
for the_file in os.listdir(folder):
file_path = os.path.join(folder, the_file)
if the_file == name :
try:
if os.path.isfile(file_path):
os.unlink(file_path)
#elif os.path.isdir(file_path): shutil.rmtree(file_path)
except Exception as e:
print(e)
#print(greaterSize)
#Renove the particular formate file
def deletFormate(self,name) :
folder = reportpath + '/../Particular_Formate'
for the_file in os.listdir(folder):
file_path = os.path.join(folder, the_file)
if the_file == name :
try:
if os.path.isfile(file_path):
os.unlink(file_path)
#import ipdb;ipdb.set_trace()
#elif os.path.isdir(file_path): shutil.rmtree(file_path)
except Exception as e:
print(e)
def data(self, index, role=QtCore.Qt.DisplayRole):
if role != QtCore.Qt.CheckStateRole:
return QtGui.QFileSystemModel.data(self, index, role)
else:
if index.column() == 0:
return self.checkState(index)
def flags(self, index):
if (index.column() == 0):
return QtGui.QFileSystemModel.flags(self, index) | QtCore.Qt.ItemIsUserCheckable
else:
return QtGui.QFileSystemModel.flags(self, index)
def checkState(self, index):
if index in self.checks:
return self.checks[index]
else:
return QtCore.Qt.Unchecked
def setData(self, index, value, role):
if (role == QtCore.Qt.CheckStateRole and index.column() == 0):
# print(QtGui.QFileSystemModel.filePath(self, index))
self.checks[index] = value
if QtGui.QFileSystemModel.filePath(self, index) in self.selectedFiles:
self.selectedFiles.remove(QtGui.QFileSystemModel.filePath(self, index))
path2=QtGui.QFileSystemModel.filePath(self, index)
self.deleteFile(path2)
else:
path1 =QtGui.QFileSystemModel.filePath(self, index)
self.addFile(path1)
self.addFilegt250mb(path1)
self.selectedFiles.add(QtGui.QFileSystemModel.filePath(self, index))
self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
return True
return QtGui.QFileSystemModel.setData(self, index, value, role)
Source Code
i tried to use different combination for Checkbox pre-selection but couldn't successed.
There is a method setCheckState that takes a bool
self.b1 = QCheckBox("SPM_CAE_DATA")
self.b1.setCheckState(True)
Related
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())
So I'm using testdome's public questions to practice python and one of them is this path problem. I can only get 50% on the solution and I can't figure out why. I can't even create a test of my own that fails.
class Path:
def __init__(self, path):
self.current_path = path
def cd(self, new_path):
new_path_list = new_path.split('/')
for item in new_path_list:
if item == '':
self.current_path = '/'
elif item == '..':
self.current_path = self.current_path[:-2]
else:
self.current_path = self.current_path + '/' + item
if '//' in self.current_path:
self.current_path = self.current_path.replace('//','/')
Edit: Updated code based on first response. Still 50% though.
Thanks everyone for the help.
At a guess, where you have
for item in new_path_list:
if new_path_list[0] == '':
what you meant was
for item in new_path_list:
if item == '':
Edit: I thought I'd try it myself; here's how I did it (scores 100%):
# https://www.testdome.com/questions/python/path/8735
ROOT = "/"
DIV = "/"
PREV = ".."
class Path:
def __init__(self, path):
self.dirs = []
self.cd(path)
#property
def current_path(self):
return str(self)
def cd(self, path):
if path.startswith(ROOT):
# absolute path - start from the beginning
self.dirs = []
path = path[len(ROOT):]
# follow relative path
for dir in path.split(DIV):
if dir == PREV:
self.dirs.pop()
else:
self.dirs.append(dir)
def __str__(self):
return ROOT + DIV.join(self.dirs)
path = Path('/a/b/c/d')
path.cd('../x')
print(path.current_path)
root='/'
div='/'
parent='..'
class Path:
def __init__(self, path):
self.current_path = path
self.current = path.split('/')
def cd(self, new_path):
if new_path[0]=='/':
self.current_path= "/"
self.current= ['']
new_path_list = new_path.split('/')
for item in new_path_list:
if item != '' :
if item == parent:
self.current.pop()
else:
self.current.append(item)
self.current_path = div.join(self.current)
path = Path('/a/b/')
path.cd('../x')
path.cd('/a/b')
print(path.current_path)
I just started learning Python recently, thanks for ppl who replied above which are really helpful for newbie!
I created my own 100% resolution, share it here to be another reference for any newbie like me :
class Path:
def __init__(self, path):
self.current_path = path
def cd(self, new_path):
PREV = '..'
DIV = '/'
#c_list = ['', 'a', 'b', 'c', 'd']
c_list = self.current_path.split(DIV)
#n_list = ['..', 'x']
n_list = new_path.split(DIV)
for item in n_list:
if item == PREV:
#delete the last item in list
del c_list[-1]
else:
c_list.append(item)
#add "/" before each item in the list and printout as string
self.current_path = "/".join(c_list)
return self.current_path
path = Path('/a/b/c/d')
path.cd('../x')
print(path.current_path)
Same, same, but different...
class Path:
def __init__(self, path):
self.current_path = path
def cd(self, new_path):
if new_path[0] == '/':
self.current_path = new_path
else:
for part in new_path.split('/'):
if part == '..':
self.current_path = '/'.join((self.current_path.split('/')[:-1]))
else:
self.current_path = self.current_path + '/' + part
Here's my code, the intention of which is to crawl a given folder and look for .md and .pdf files, and build a tree-like structure which describes it.
I'm probably really overthinking it, so I could really use a second set of eyes on this.
class Resource_Item:
def __init__(self, name=None, stub=None, path=None, parent=None, html_file_location=None, documents=[], children=[]):
self.name = name
self.stub = stub
self.path = path
self.parent = parent
self.html_file_location = html_file_location
self.documents = documents
self.children = children
def add_child(self, c):
self.children.append(c)
def to_json(self):
o = {
'name' : self.name,
'stub' : self.stub,
'path' : self.path,
'parent' : self.parent,
'html_file_location' : self.html_file_location,
'documents' : self.documents,
'children' : [c.to_json() for c in self.children] } #len(self.children)
return json.dumps(o)
def walk_dir(root, parent = None):
"""
>>> walk_dir("./test_docs/folder containing pdfs/").documents
['dummy_pdf 2.pdf', 'dummy_pdf 3.pdf', 'dummy_pdf 4.pdf', 'dummy_pdf.pdf']
>>> len(walk_dir("./test_docs/folder containing pdfs/").children)
0
>>> walk_dir("./test_docs/folder containing markdown and pdfs/").stub is None
False
>>> walk_dir("./test_docs/folder containing markdown and pdfs/").children
['dummy_pdf 2.pdf', 'dummy_pdf 3.pdf', 'dummy_pdf 4.pdf', 'dummy_pdf.pdf']
"""
file_or_folder_name_no_ext = os.path.splitext(os.path.basename(root))[0]
entry = Resource_Item( name=file_or_folder_name_no_ext, parent=parent, path=os.path.abspath(root) )
for item in os.listdir(root):
path = os.path.join(os.path.abspath(root), item)
if os.path.isfile(path):
if item.endswith(".pdf"):
entry.documents.append(item)
elif item.endswith(".md"):
entry.stub = read_markdown_file_as_html(path)
elif os.path.isdir(path):
if dir_contains_pdf(path):
print('found a path to contain PDFs: "'+str(path)+'"')
entry.add_child(walk_dir(path)) # broken!
#entry.add_child(path)
return entry
What appears to be happening is that on the entry.add_child(walk_dir(path)) line, walk_dir doesn't properly create a new instance of Resource_Item, since my testing shows that Resource_Item.children gets populated with all the pdfs in that file tree, not just those in the immediate folder.
As for my supporting functions, I'm pretty sure they work properly, but here they are for completeness:
def dir_contains_pdf(root):
"""
>>> dir_contains_pdf("./test_docs/folder containing pdfs/")
True
>>> dir_contains_pdf("./test_docs/folder containing nothing/")
False
>>> dir_contains_pdf("./test_docs/folder containing folders, markdown, and pdf/")
True
>>> dir_contains_pdf("./test_docs/folder containing markdown and pdfs/")
True
"""
root = os.path.abspath(root)
for item in os.listdir(root):
item_path = os.path.join(root, item)
if os.path.isfile(item_path):
if item.endswith(".pdf"):
return True
elif os.path.isdir(item_path):
if dir_contains_pdf(item_path):
return True
return False
def read_markdown_file_as_html(markdown_filename):
f = open(markdown_filename, 'r')
markdown_content = f.read()
return markdown.markdown(markdown_content)
As another view of how this recursion should be working, I built this other program in the same style to confirm that it works, and it does work properly, so I'm guessing the issue has to do with how I'm using the Python file API:
class Item:
def __init__(self, n=None):
self.n = n
self.children = []
def add_child(self, c):
self.children.append(c)
def to_o(self):
o = { 'n' : self.n, 'children' : [c.to_o() for c in self.children] }
return o
def bad(count):
item = Item(n=count)
print('count : '+str(count))
if count > 100 or count == 0:
return item
elif (count-1) % 2 == 0:
print(str(count) + ' is odd')
item.add_child(bad(count*3))
elif count % 2 == 0:
print(str(count) + ' is even')
item.add_child(bad(count/2))
return item
import json
print(json.dumps(bad(7).to_o()))
I'm trying to find the next file by natural sorting with a depth variable but am facing some problems.
the folder structure is following:
tests/
------test1/
-----------test2/
----------------...
----------------30.jpg
----------------31.jpg
-----------test3/
----------------...
----------------30.jpg
----------------31.jpg
-----------1.jpg
------1.jpg
I want to reach the next or the item before my current item, iterating over them with the forward and backward function.
Getting items on the same level is working currently, also to get one on the max depth level.
For example I want to get with the backwards function on
path=tests/test1/test2/1.jpg
the result
tests/test1/1.jpg
but with
path=tests/test1/test3/1.jpg
the result
tests/test1/test2/31.jpg
obviously reversed results same with the forward functions.
My current problem is finding the next file on the next level without repeating myself and building a loop, iterating through the folders worked completely fine so far, but I'm currently completely stuck on this one.
My current code so far:
import os
import re
import wx
class PathSelect(wx.App):
"""
path select application
"""
def __init__(self):
"""
initializing function
:return:
"""
super(PathSelect, self).__init__()
#staticmethod
def ask_path():
"""
ask for our starting path
:return:
"""
wildcard = ("Image Files (*.*)|*.jpeg;*.jpg;*.png;*.bmp|"
"Joint Photographic Experts Group (*.jpeg;*.jpg)|*.jpeg;*.jpg|"
"Portable Network Graphics (*.png)|*.png|"
"Bitmap (*.bmp)|*.bmp|"
"All files (*.*)|*.*")
dialog = wx.FileDialog(None, "Choose a file", os.getcwd(), "", wildcard, wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if dialog.ShowModal() == wx.ID_OK:
return dialog.GetPath()
dialog.Destroy()
class PathingAlgorithm(object):
"""
our pathing algorithm
"""
def __init__(self, depth=1):
"""
initializing function
:return:
"""
self.depth = depth
self.image_path = ""
#staticmethod
def natural_sort(current_list):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(current_list, key=alphanum_key)
def current(self):
"""
return the current path or ask for the path
:return:
"""
if not self.image_path:
self.image_path = PathSelect.ask_path()
if self.image_path:
return self.image_path
def backward(self, path="", depth=0, ghost=False):
"""
return path for the previous picture
:param path:
:param depth:
:param ghost:
:return:
"""
# max recursion case, break our function here
if self.depth < depth:
return None
depth += 1
if path == "":
path = self.image_path
folder = os.path.dirname(path)
file_name = os.path.basename(path)
folder_content = self.natural_sort(os.listdir(folder))
file_index = folder_content.index(file_name)
if file_index == 0:
path = self.backward(folder, depth, ghost)
# handle max depth case
if path is None:
return None
# get in the same level of the foldertree again if possible
for x in xrange(depth):
path_list = os.listdir(path)
if path_list:
path = os.path.join(path, self.natural_sort(path_list)[len(path_list) - 1])
else:
path = os.path.join(folder, folder_content[folder_content.index(file_name) - 1])
if not ghost:
self.image_path = path
return path
def forward(self, path="", depth=0, ghost=False):
"""
return path for the next picture
:param path:
:param depth:
:return:
"""
depth += 1
# max recursion case, break our function here
if self.depth < depth:
return None
# on start use current path, on recursion skip this
if path == "":
path = self.image_path
folder = os.path.dirname(path)
file_name = os.path.basename(path)
if os.path.isfile(os.path.join(folder, file_name)):
folders = os.listdir(folder)
else:
folders = [name for name in os.listdir(folder) if os.path.isdir(os.path.join(folder, name))]
folder_content = self.natural_sort(folders)
file_index = folder_content.index(file_name)
if file_index == len(folder_content) - 1:
if self.depth - 1 < depth:
files = [name for name in os.listdir(folder) if os.path.isfile(os.path.join(folder, name))]
if files:
return os.path.join(folder, files[0])
path = self.forward(folder, depth, ghost)
# handle max depth case
if path is None:
return None
# get in the same level of the foldertree again if possible
for x in xrange(depth):
if not os.path.isfile(path):
file_list = os.listdir(path)
if file_list:
path = os.path.join(path, self.natural_sort(file_list)[0])
else:
path = os.path.join(folder, folder_content[folder_content.index(file_name) + 1])
if not ghost:
self.image_path = path
return path
if __name__ == "__main__":
app = wx.App()
app.MainLoop()
ps = PathingAlgorithm(depth=3)
# print ps.current()
# print ps.backward(ghost=True)
# print ps.forward(ghost=True)
print ps.forward(
path='../tests/test1/test2/31.jpg',
ghost=True,
)
thanks for any help in advance
I was too focused on the recursive function, solving it over a sorted file tree was the solution, currently not the best performance is the depth is too big and it wants to get all files, but good enough for my case
def get_file_tree(self, path):
"""
return a natural sorted file tree and the index of your original file
:param path:
:return:
"""
if not os.path.exists(path):
return None
filename = os.path.basename(path)
basepath = os.path.abspath(os.path.dirname(path))
for _ in xrange(self.depth):
path = os.path.abspath(os.path.join(basepath, os.pardir))
# list all files
configfiles = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(path)
for f in fnmatch.filter(files, '*')]
# use natural sort for the tree
configfiles = self.natural_sort(configfiles)
original_path = os.path.join(basepath, filename)
original_index = configfiles.index(original_path)
return configfiles, original_index
def backward(self, path="", ghost=False):
"""
get the next file of our current or defined path
:param path:
:param ghost:
:return:
"""
if path == "":
path = self.image_path
path = os.path.abspath(path)
configfiles, original_index = self.get_file_tree(path)
# if file was non existant or the index was 0 return None
if original_index is None or original_index == 0:
return None
new_path = configfiles[original_index - 1]
if new_path.count("\\") > path.count("\\"):
return None
if not ghost:
self.image_path = new_path
return new_path
def forward(self, path="", ghost=False):
"""
get the next file of our current or defined path
:param path:
:param ghost:
:return:
"""
if path == "":
path = self.image_path
path = os.path.abspath(path)
configfiles, original_index = self.get_file_tree(path)
# if file was non existant or was the last file, return None
if original_index is None or len(configfiles) <= original_index + 1:
return None
new_path = configfiles[original_index + 1]
if not ghost:
self.image_path = new_path
return new_path
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)