| 1 |
from Tkinter import * |
|---|
| 2 |
import tkSimpleDialog, tkFileDialog |
|---|
| 3 |
import os, sys, ConfigParser |
|---|
| 4 |
|
|---|
| 5 |
class EditShare(tkSimpleDialog.Dialog): |
|---|
| 6 |
|
|---|
| 7 |
def __init__(self, parent, title=None, name='', path='', plugin='', |
|---|
| 8 |
subshares=0): |
|---|
| 9 |
self.name = name |
|---|
| 10 |
self.path = path |
|---|
| 11 |
self.plugin = StringVar() |
|---|
| 12 |
self.plugin.set(plugin) |
|---|
| 13 |
self.subshares = IntVar() |
|---|
| 14 |
self.subshares.set(subshares) |
|---|
| 15 |
tkSimpleDialog.Dialog.__init__(self, parent, title) |
|---|
| 16 |
|
|---|
| 17 |
def get_dir(self): |
|---|
| 18 |
self.e2.delete(0, END) |
|---|
| 19 |
self.e2.insert(0, os.path.normpath(tkFileDialog.askdirectory())) |
|---|
| 20 |
|
|---|
| 21 |
def sub_show(self): |
|---|
| 22 |
if self.plugin.get() == 'video': |
|---|
| 23 |
self.subbutt.grid(row=2, column=1) |
|---|
| 24 |
else: |
|---|
| 25 |
self.subbutt.grid_forget() |
|---|
| 26 |
|
|---|
| 27 |
def body(self, master): |
|---|
| 28 |
Label(master, text="Name:").grid(row=0) |
|---|
| 29 |
Label(master, text="Path:").grid(row=1) |
|---|
| 30 |
|
|---|
| 31 |
self.e1 = Entry(master) |
|---|
| 32 |
self.e2 = Entry(master) |
|---|
| 33 |
|
|---|
| 34 |
if self.name: |
|---|
| 35 |
self.e1.insert(0, self.name) |
|---|
| 36 |
if self.path: |
|---|
| 37 |
self.e2.insert(0, self.path) |
|---|
| 38 |
|
|---|
| 39 |
browse = Button(master, text="Browse", command=self.get_dir) |
|---|
| 40 |
|
|---|
| 41 |
self.e1.grid(row=0, column=1, columnspan=2, sticky=W+E) |
|---|
| 42 |
self.e2.grid(row=1, column=1, sticky=W+E) |
|---|
| 43 |
browse.grid(row=1, column=2) |
|---|
| 44 |
|
|---|
| 45 |
self.subbutt = Checkbutton(master, text='Auto subshares', |
|---|
| 46 |
variable=self.subshares) |
|---|
| 47 |
|
|---|
| 48 |
if not self.plugin.get(): |
|---|
| 49 |
self.plugin.set('video') |
|---|
| 50 |
|
|---|
| 51 |
self.sub_show() |
|---|
| 52 |
|
|---|
| 53 |
for i, name in zip(xrange(3), ('video', 'music', 'photo')): |
|---|
| 54 |
b = Radiobutton(master, text=name, variable=self.plugin, |
|---|
| 55 |
value=name, command=self.sub_show).grid(row=i, column=3) |
|---|
| 56 |
|
|---|
| 57 |
return self.e1 # initial focus |
|---|
| 58 |
|
|---|
| 59 |
def apply(self): |
|---|
| 60 |
name = self.e1.get() |
|---|
| 61 |
path = self.e2.get() |
|---|
| 62 |
self.result = name, path, self.plugin.get(), self.subshares.get() |
|---|
| 63 |
|
|---|
| 64 |
class pyTivoConfigurator(Frame): |
|---|
| 65 |
|
|---|
| 66 |
section = None |
|---|
| 67 |
|
|---|
| 68 |
def buildContainerList(self): |
|---|
| 69 |
header = Frame(self) |
|---|
| 70 |
header.pack(fill=X) |
|---|
| 71 |
Label(header, text='Shares').pack(side=LEFT) |
|---|
| 72 |
frame = Frame(self) |
|---|
| 73 |
frame.pack(fill=BOTH, expand=1) |
|---|
| 74 |
scrollbar = Scrollbar(frame, orient=VERTICAL) |
|---|
| 75 |
self.container_list = Listbox(frame, yscrollcommand=scrollbar.set) |
|---|
| 76 |
scrollbar.config(command=self.container_list.yview) |
|---|
| 77 |
scrollbar.pack(side=RIGHT, fill=Y) |
|---|
| 78 |
self.container_list.pack(side=LEFT, fill=BOTH, expand=1) |
|---|
| 79 |
self.container_list.bind("<Double-Button-1>", self.selected) |
|---|
| 80 |
|
|---|
| 81 |
def selected(self, e): |
|---|
| 82 |
if not self.container_list.curselection(): |
|---|
| 83 |
return |
|---|
| 84 |
index = self.container_list.curselection()[0] |
|---|
| 85 |
self.section = self.container_list.get(index) |
|---|
| 86 |
|
|---|
| 87 |
self.edit() |
|---|
| 88 |
|
|---|
| 89 |
def buildButtons(self): |
|---|
| 90 |
frame = Frame(self) |
|---|
| 91 |
frame.pack(fill=X) |
|---|
| 92 |
|
|---|
| 93 |
quit_button = Button(frame, text="Quit", command=self.quit) |
|---|
| 94 |
quit_button.pack(side=RIGHT) |
|---|
| 95 |
|
|---|
| 96 |
del_button = Button(frame, text='Del', command=self.delete) |
|---|
| 97 |
del_button.pack(side=RIGHT) |
|---|
| 98 |
|
|---|
| 99 |
add_button = Button(frame, text="Add", command=self.add) |
|---|
| 100 |
add_button.pack(side=RIGHT) |
|---|
| 101 |
|
|---|
| 102 |
if sys.platform == 'win32': |
|---|
| 103 |
restart_button = Button(frame, text="Restart pyTivo", |
|---|
| 104 |
command=self.restart) |
|---|
| 105 |
restart_button.pack(side=RIGHT) |
|---|
| 106 |
|
|---|
| 107 |
def add(self): |
|---|
| 108 |
share = EditShare(self, title='New Share') |
|---|
| 109 |
if share.result: |
|---|
| 110 |
sharename, path, plugin, subshares = share.result |
|---|
| 111 |
self.config.add_section(sharename) |
|---|
| 112 |
self.config.set(sharename, 'type', plugin) |
|---|
| 113 |
self.config.set(sharename, 'path', path) |
|---|
| 114 |
if subshares and plugin == 'video': |
|---|
| 115 |
self.config.set(name, 'auto_subshares', 'True') |
|---|
| 116 |
|
|---|
| 117 |
self.updateContainerList() |
|---|
| 118 |
|
|---|
| 119 |
def delete(self): |
|---|
| 120 |
if not self.container_list.curselection(): |
|---|
| 121 |
return |
|---|
| 122 |
index = self.container_list.curselection()[0] |
|---|
| 123 |
section = self.container_list.get(index) |
|---|
| 124 |
self.config.remove_section(section) |
|---|
| 125 |
self.updateContainerList() |
|---|
| 126 |
|
|---|
| 127 |
def restart(self): |
|---|
| 128 |
import win32serviceutil |
|---|
| 129 |
self.writeConfig() |
|---|
| 130 |
win32serviceutil.RestartService('pyTivo') |
|---|
| 131 |
|
|---|
| 132 |
def edit(self): |
|---|
| 133 |
if not self.section: |
|---|
| 134 |
return |
|---|
| 135 |
|
|---|
| 136 |
name = self.section |
|---|
| 137 |
path = self.config.get(name, 'path') |
|---|
| 138 |
plugin = self.config.get(name, 'type') |
|---|
| 139 |
|
|---|
| 140 |
if self.config.has_option(name, 'auto_subshares') and \ |
|---|
| 141 |
self.config.getboolean(name, 'auto_subshares'): |
|---|
| 142 |
subshares = 1 |
|---|
| 143 |
else: |
|---|
| 144 |
subshares = 0 |
|---|
| 145 |
|
|---|
| 146 |
share = EditShare(self, title='Edit Share', name=name, path=path, |
|---|
| 147 |
plugin=plugin, subshares=subshares) |
|---|
| 148 |
if share.result: |
|---|
| 149 |
name, path, plugin, subshares = share.result |
|---|
| 150 |
if name != self.section: |
|---|
| 151 |
self.config.remove_section(self.section) |
|---|
| 152 |
self.config.add_section(name) |
|---|
| 153 |
self.section = name |
|---|
| 154 |
self.config.set(name, 'type', plugin) |
|---|
| 155 |
self.config.set(name, 'path', path) |
|---|
| 156 |
if subshares and plugin == 'video': |
|---|
| 157 |
self.config.set(name, 'auto_subshares', 'True') |
|---|
| 158 |
else: |
|---|
| 159 |
self.config.remove_option(name, 'auto_subshares') |
|---|
| 160 |
|
|---|
| 161 |
self.updateContainerList() |
|---|
| 162 |
|
|---|
| 163 |
def updateContainerList(self): |
|---|
| 164 |
self.writeConfig() |
|---|
| 165 |
self.container_list.delete(0, END) |
|---|
| 166 |
for section in self.config.sections(): |
|---|
| 167 |
if not section == 'Server': |
|---|
| 168 |
self.container_list.insert(END, section) |
|---|
| 169 |
|
|---|
| 170 |
def readConfig(self): |
|---|
| 171 |
self.config = ConfigParser.ConfigParser() |
|---|
| 172 |
self.config.read(self.config_file) |
|---|
| 173 |
|
|---|
| 174 |
def writeConfig(self): |
|---|
| 175 |
self.config.write(open(self.config_file, 'w')) |
|---|
| 176 |
|
|---|
| 177 |
def __init__(self, master=None): |
|---|
| 178 |
Frame.__init__(self, master) |
|---|
| 179 |
self.master.title('pyTivoConfigurator') |
|---|
| 180 |
self.pack(fill=BOTH, expand=1) |
|---|
| 181 |
|
|---|
| 182 |
p = os.path.dirname(__file__) |
|---|
| 183 |
self.config_file = os.path.join(p, 'pyTivo.conf') |
|---|
| 184 |
|
|---|
| 185 |
self.readConfig() |
|---|
| 186 |
|
|---|
| 187 |
self.buildContainerList() |
|---|
| 188 |
self.buildButtons() |
|---|
| 189 |
|
|---|
| 190 |
self.updateContainerList() |
|---|
| 191 |
|
|---|
| 192 |
if __name__ == '__main__': |
|---|
| 193 |
root = Tk() |
|---|
| 194 |
app = pyTivoConfigurator(master=root) |
|---|
| 195 |
app.mainloop() |
|---|