import wx
import string
import ConfigParser
import sys
from btconfig import BTConfig
from os.path import join,dirname,exists
from threading import Thread
if sys.platform == "win32":
win32_flag = True
else:
win32_flag = False
if win32_flag:
from webbrowser import open_new
else:
from leoxv import open_new
#entry flags
NEWENTRY = 0
SAVEENTRY = 1
REMOVEENTRY = 2
class SearchPopup(wx.Frame):
def __init__(self, parent, btconfig, images, srch_visflag):
wx.Frame.__init__(self, parent, -1, _("Torrent Search"), pos = wx.DefaultPosition, size = (500,180), style = wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP )
self.search_file = join(btconfig['path'], "search.ini")
self.srch_visflag = srch_visflag
self.images = images
self.keys = None
self.search_entries = []
self.multi = False
if self.srch_visflag != None:
self.srch_visflag.set()
self.LoadURLs()
self.CentreOnScreen()
self.panel = wx.Panel(self, -1)
framesizer = wx.BoxSizer(wx.VERTICAL)
box = wx.StaticBox(self.panel, -1, "Search")
boxsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
colsizer = wx.FlexGridSizer(1, 1, 0, 0)
colsizer.AddGrowableRow(0)
colsizer.AddGrowableCol(0)
doublesizer = wx.FlexGridSizer(1, 3, 3, 2)
doublesizer.AddGrowableRow(0)
doublesizer.AddGrowableCol(2)
splitsizer = wx.FlexGridSizer(2, 1, 3, 2)
splitsizer.AddGrowableRow(0)
splitsizer.AddGrowableRow(1)
splitsizer.AddGrowableCol(0)
self.multilist = wx.ListBox(self.panel, -1, choices=[], style = wx.LB_MULTIPLE)
doublesizer.Add(self.multilist, 0, wx.ALL|wx.EXPAND|wx.FIXED_MINSIZE, 2)
self.multilist.Hide() #hidden by default
self.singlelist = wx.ListBox(self.panel, -1, choices=[])
self.singlelist.Bind(wx.EVT_LISTBOX, self.OnListBox, self.singlelist)
doublesizer.Add(self.singlelist, 0, wx.ALL|wx.EXPAND|wx.FIXED_MINSIZE, 2)
self.listbox = self.singlelist #single search is default
self.search = SearchPanel(self.panel, self.OnToggleSettings, self.GetSearchData, self.SetMultiple)
splitsizer.Add(self.search, 1, wx.EXPAND, 0)
self.settings = SettingsPanel(self.panel, btconfig, self.OnToggleSettings, self.populate, self.editlist)
self.settings.Hide() #hidden by default
splitsizer.Add(self.settings, 1, wx.EXPAND, 0)
doublesizer.Add(splitsizer, 1, wx.EXPAND, 0)
colsizer.Add(doublesizer, 1, wx.EXPAND, 0)
boxsizer.Add(colsizer, 1, wx.EXPAND, 0)
self.panel.SetAutoLayout(True)
self.panel.SetSizer(boxsizer)
boxsizer.Fit(self.panel)
boxsizer.SetSizeHints(self.panel)
framesizer.Add(self.panel, 1, wx.EXPAND, 0)
self.SetAutoLayout(True)
self.SetSizer(framesizer)
self.Layout()
#wx.EVT_CLOSE(self, self.CleanUp)
self.Bind(wx.EVT_CLOSE, self.CleanUp, self)
self.populate()
if images != None:
self.SetIcon(images.GetImage('rufus.ico'))
self.Show()
#hides/shows the search settings/config panel
def OnToggleSettings(self, event):
self.SetMultiple(False)
self.search.check1.SetValue(False)
if self.settings.IsShown():
self.settings.Hide()
self.search.Show()
self.panel.Layout()
else:
self.search.Hide()
self.settings.Show()
self.panel.Layout()
def SaveURLs(self):
print 'Saving Search URLs'
try:
cp = ConfigParser.ConfigParser()
cp.add_section('SEARCH')
i = 0
for item in self.search_entries:
cp.set('SEARCH', str(i), item)
i = i+1
file = open(self.search_file, 'w')
cp.write(file)
file.close()
except IOError, e:
print "ERROR: writing to search ini -", str(e)
except:
print "ERROR: writing to search ini"
def LoadURLs(self):
if exists(self.search_file):
print 'Loading Search URLs'
try:
cp = ConfigParser.ConfigParser()
file = open(self.search_file, 'r')
cp.readfp(file)
items = cp.items('SEARCH')
for key, param in items:
param = eval(param)
self.search_entries.append(param)
file.close()
self.search_entries.sort(lambda u, v: cmp(u[0].lower(), v[0].lower()) or cmp(u[0], v[0]))
except IOError, e:
print "ERROR: accessing search.ini - ", str(e)
except (ConfigParser.MissingSectionHeaderError, ConfigParser.NoSectionError), e:
print "ERROR: processing search.ini - ", str(e)
def editlist(self, entry, optype):
if optype == NEWENTRY: #New entry
self.listbox.DeselectAll()
elif optype == SAVEENTRY: #save entry
key = self.listbox.GetSelection()
if key != -1 and entry[0] != '':
self.search_entries.pop(key)
self.search_entries.append(entry)
elif entry[0] != '':
self.search_entries.append(entry)
elif optype == REMOVEENTRY: #remove entry
key = self.listbox.GetSelection()
if key != -1:
self.search_entries.pop(key)
self.search_entries.sort(lambda u, v: cmp(u[0].lower(), v[0].lower()) or cmp(u[0], v[0])) #sort list
self.SaveURLs()
self.listbox.DeselectAll()
self.settings.UpdateFields(None)
self.populate()
def OnListBox (self, event):
if self.settings.IsShown():
self.settings.UpdateFields(self.search_entries[self.listbox.GetSelection()])
def GetSearchData (self, searchstr):
def makeURL(item, searchstr):
searchstr = string.replace(searchstr, " ",item[2])
try:
if item[3] != '':
searchstr = item[3]+searchstr
except IndexError:
pass
try:
if item[4] != '':
searchstr = searchstr+item[4]
except IndexError:
pass
return item[1] + searchstr
if searchstr != '':
if self.multi:
print "multi search", self.listbox.GetSelections()
for i in self.listbox.GetSelections():
url = makeURL(self.search_entries[i], searchstr)
Thread(target = self._OpenUrl, args = [url]).start()
else:
if self.listbox.GetSelection() != -1:
url = makeURL(self.search_entries[self.listbox.GetSelection()], searchstr)
Thread(target = self._OpenUrl, args = [url]).start()
def _OpenUrl(self, url):
try:
open_new(url)
except:
pass
def SetMultiple(self, value):
if value:
self.singlelist.Hide()
self.multilist.Show()
self.listbox = self.multilist
else:
self.multilist.Hide()
self.singlelist.Show()
self.listbox = self.singlelist
self.multi = value
self.populate()
self.panel.Layout()
self.listbox.DeselectAll()
def populate(self):
self.search_choices = []
self.listbox.Clear()
for param in self.search_entries:
self.search_choices.append(param[0])
self.listbox.Set(self.search_choices)
def CleanUp (self, event):
if self.srch_visflag != None:
self.srch_visflag.clear()
self.Destroy()
class SearchPanel(wx.Panel):
def __init__(self, parent, togglefunc, searchfunc, multifunc):
wx.Panel.__init__(self, parent, -1)
self.togglefunc = togglefunc
self.searchfunc = searchfunc
self.setmulti = multifunc
searchsizer = wx.FlexGridSizer(4, 2, 3, 2)
searchsizer.AddGrowableRow(2)
searchsizer.AddGrowableCol(1)
self.edit1 = wx.TextCtrl(self, -1, "", size=(200, 21))
searchsizer.Add(self.edit1, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
btn = wx.Button(self, -1, _("Find"))
searchsizer.Add(btn, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_BUTTON, self.OnFind, btn)
self.check1 = wx.CheckBox(self, -1, _("Search using multiple browser windows"))
searchsizer.Add(self.check1, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.check1)
searchsizer.Add((-1,-1)) #spacer
searchsizer.Add((-1,-1)) #spacer
searchsizer.Add((-1,-1)) #spacer
searchsizer.Add((-1,-1)) #spacer
btn = wx.Button(self, -1, _("Settings..."))
searchsizer.Add(btn, 0, wx.ALL|wx.ALIGN_RIGHT|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_BUTTON, self.togglefunc, btn)
self.SetAutoLayout(True)
self.SetSizer(searchsizer)
searchsizer.Fit(self)
searchsizer.SetSizeHints(self)
def OnCheck (self, event=None):
self.setmulti(self.check1.GetValue())
def OnFind (self, event):
self.searchfunc(self.edit1.GetValue())
class SettingsPanel(wx.Panel):
def __init__(self, parent, btconfig, togglefunc, populatefunc, editfunc):
wx.Panel.__init__(self, parent, -1)
self.togglefunc = togglefunc
self.populate = populatefunc
self.editlist = editfunc
self.name = ''
self.link = ''
self.delimiter = ''
self.prefix = ''
self.suffix = ''
self.newcount = 0
doublesizer = wx.FlexGridSizer(2, 1, 0, 0)
doublesizer.AddGrowableRow(0)
doublesizer.AddGrowableCol(0)
buttsizer = wx.FlexGridSizer(1, 6, 0, 0)
buttsizer.AddGrowableCol(3)
settingsizer = wx.FlexGridSizer(4, 2, 3, 2)
settingsizer.AddGrowableCol(1)
prefixsizer = wx.FlexGridSizer(1, 3, 0, 0)
prefixsizer.AddGrowableCol(1)
namesizer = wx.FlexGridSizer(1, 3, 0, 0)
namesizer.AddGrowableCol(0)
lbl = wx.StaticText(self, -1, _("Name:"))
settingsizer.Add(lbl, 0, wx.ALL|wx.ALIGN_RIGHT|wx.FIXED_MINSIZE, 3)
self.edit1 = wx.TextCtrl(self, -1, "", size=(150,-1))
namesizer.Add(self.edit1, 0, wx.FIXED_MINSIZE, 0)
self.edit1.Disable()
lbl = wx.StaticText(self, -1, _("Delimiter:"))
namesizer.Add(lbl, 0, wx.ALL|wx.FIXED_MINSIZE, 3)
self.edit2 = wx.TextCtrl(self, -1, "", size=(60,-1))
namesizer.Add(self.edit2, 0, wx.FIXED_MINSIZE, 0)
self.edit2.Disable()
settingsizer.Add(namesizer, 1, wx.EXPAND, 4)
lbl = wx.StaticText(self, -1, _("URL:"))
settingsizer.Add(lbl, 0, wx.ALL|wx.ALIGN_RIGHT|wx.FIXED_MINSIZE, 3)
self.edit3 = wx.TextCtrl(self, -1, "", size=(300,21))
settingsizer.Add(self.edit3, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
self.edit3.Disable()
lbl = wx.StaticText(self, -1, _("Prefix:"))
settingsizer.Add(lbl, 0, wx.ALL|wx.ALIGN_RIGHT|wx.FIXED_MINSIZE, 3)
self.edit4 = wx.TextCtrl(self, -1, "")
prefixsizer.Add(self.edit4, 0, wx.FIXED_MINSIZE, 0)
self.edit4.Disable()
lbl = wx.StaticText(self, -1, _("Suffix:"))
prefixsizer.Add(lbl, 0, wx.ALL|wx.ALIGN_RIGHT|wx.FIXED_MINSIZE, 3)
self.edit5 = wx.TextCtrl(self, -1, "")
prefixsizer.Add(self.edit5, 0, wx.FIXED_MINSIZE, 0)
self.edit5.Disable()
settingsizer.Add(prefixsizer, 1, wx.EXPAND, 0)
doublesizer.Add(settingsizer, 1, wx.EXPAND, 0)
btn = wx.Button(self, -1, _("New"))
buttsizer.Add(btn, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_BUTTON, self.OnNewEntry, btn)
self.svbtn = wx.Button(self, -1, _("Save"))
buttsizer.Add(self.svbtn, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_BUTTON, self.OnSaveEntry, self.svbtn)
self.svbtn.Disable()
self.rmbtn = wx.Button(self, -1, _("Remove"))
buttsizer.Add(self.rmbtn, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_BUTTON, self.OnRemoveEntry, self.rmbtn)
self.rmbtn.Disable()
buttsizer.Add((-1,-1)) #spacer
btn = wx.Button(self, -1, _("<- Back"))
buttsizer.Add(btn, 0, wx.ALL|wx.FIXED_MINSIZE, 2)
self.Bind(wx.EVT_BUTTON, self.togglefunc, btn)
doublesizer.Add(buttsizer, 1, wx.EXPAND, 0)
self.SetAutoLayout(True)
self.SetSizer(doublesizer)
doublesizer.Fit(self)
doublesizer.SetSizeHints(self)
def UpdateFields(self, entry):
if entry == None:
#disable save/remove buttons and other fields/values if nothing is selected
self.rmbtn.Disable()
self.svbtn.Disable()
self.name = ''
self.link = ''
self.delimiter = ''
self.prefix = ''
self.suffix = ''
self.edit1.SetValue(self.name)
self.edit2.SetValue(self.delimiter)
self.edit3.SetValue(self.link)
self.edit4.SetValue(self.prefix)
self.edit5.SetValue(self.suffix)
self.edit1.Disable()
self.edit2.Disable()
self.edit3.Disable()
self.edit4.Disable()
self.edit5.Disable()
else:
#re-enable buttons
self.rmbtn.Enable()
self.svbtn.Enable()
#needed for comparison on newentry
self.name = entry[0]
self.delimiter = entry[2]
self.link = entry[1]
try:
self.prefix = entry[3]
self.suffix = entry[4]
except IndexError:
self.suffix = ''
self.prefix = ''
#re-enable text entry
self.edit1.Enable()
self.edit2.Enable()
self.edit3.Enable()
self.edit4.Enable()
self.edit5.Enable()
self.edit1.SetValue(self.name)
self.edit2.SetValue(self.delimiter)
self.edit3.SetValue(self.link)
self.edit4.SetValue(self.prefix)
self.edit5.SetValue(self.suffix)
def CheckOK(self):
if self.edit1.GetValue() != self.name or self.edit2.GetValue() != self.delimiter or self.edit3.GetValue() != self.link or self.edit4.GetValue() != self.prefix or self.edit5.GetValue() != self.suffix:
dlg = wx.MessageDialog(self, _("You have not saved the changes to the current serach item...\nDo you want to create a new search item anyway?"),
_("Save current changes?"), wx.YES_NO | wx.ICON_QUESTION)
dlgresult = dlg.ShowModal()
dlg.Destroy()
if dlgresult != wx.ID_YES:
return False
return True #default
def OnNewEntry(self, event):
if self.CheckOK():
self.newcount += 1
blank_entry = ['New'+str(self.newcount), 'http://', '+', '', '']
self.editlist(None, optype = NEWENTRY)
self.UpdateFields(blank_entry)
def OnSaveEntry(self, event):
param = [self.edit1.GetValue(), self.edit3.GetValue(), self.edit2.GetValue(), self.edit4.GetValue(), self.edit5.GetValue()]
self.editlist(param, optype = SAVEENTRY)
def OnRemoveEntry(self, event):
self.editlist(None, optype = REMOVEENTRY)
if __name__ == "__main__":
_ = lambda x: x # needed for gettext
app = wx.PySimpleApp()
frame = SearchPopup(None, BTConfig(), None, None)
app.SetTopWindow(frame)
app.MainLoop()
|