2 # -*- coding: utf-8 -*-
4 #Copyright 2008-2011 Steffen Schaumburg
5 #This program is free software: you can redistribute it and/or modify
6 #it under the terms of the GNU Affero General Public License as published by
7 #the Free Software Foundation, version 3 of the License.
9 #This program is distributed in the hope that it will be useful,
10 #but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 #GNU General Public License for more details.
14 #You should have received a copy of the GNU Affero General Public License
15 #along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #In the "official" distribution you can find the license in agpl-3.0.txt.
19 _
= L10n
.get_translation()
34 # logging has been set up in fpdb.py or HUD_main.py, use their settings:
35 log
= logging
.getLogger("importer")
39 from optparse
import OptionParser
47 class GuiAutoImport (threading
.Thread
):
48 def __init__(self
, settings
, config
, sql
= None, parent
= None, cli
= False):
50 self
.settings
= settings
55 imp
= self
.config
.get_import_parameters()
57 self
.input_settings
= {}
58 self
.pipe_to_hud
= None
60 self
.importer
= fpdb_import
.Importer(self
, self
.settings
, self
.config
, self
.sql
)
61 self
.importer
.setCallHud(True)
62 self
.importer
.setQuiet(False)
63 self
.importer
.setFailOnError(False)
64 self
.importer
.setHandCount(0)
66 self
.server
= settings
['db-host']
67 self
.user
= settings
['db-user']
68 self
.password
= settings
['db-password']
69 self
.database
= settings
['db-databaseName']
74 # TODO: Separate the code that grabs the directories from config
75 # Separate the calls to the Importer API
76 # Create a timer interface that doesn't rely on GTK
80 self
.mainVBox
= gtk
.VBox(False,1)
82 hbox
= gtk
.HBox(True, 0) # contains 2 equal vboxes
83 self
.mainVBox
.pack_start(hbox
, False, False, 0)
85 vbox1
= gtk
.VBox(True, 0)
86 hbox
.pack_start(vbox1
, True, True, 0)
87 vbox2
= gtk
.VBox(True, 0)
88 hbox
.pack_start(vbox2
, True, True, 0)
90 self
.intervalLabel
= gtk
.Label(_("Time between imports in seconds:"))
91 self
.intervalLabel
.set_alignment(xalign
=1.0, yalign
=0.5)
92 vbox1
.pack_start(self
.intervalLabel
, False, True, 0)
94 hbox
= gtk
.HBox(False, 0)
95 vbox2
.pack_start(hbox
, False, True, 0)
96 self
.intervalEntry
= gtk
.Entry()
97 self
.intervalEntry
.set_text(str(self
.config
.get_import_parameters().get("interval")))
98 hbox
.pack_start(self
.intervalEntry
, False, False, 0)
100 hbox
.pack_start(lbl1
, expand
=False, fill
=True)
103 vbox1
.pack_start(lbl
, expand
=False, fill
=True)
105 vbox2
.pack_start(lbl
, expand
=False, fill
=True)
107 self
.addSites(vbox1
, vbox2
)
108 self
.textbuffer
= gtk
.TextBuffer()
109 self
.textview
= gtk
.TextView(self
.textbuffer
)
111 hbox
= gtk
.HBox(False, 0)
112 self
.mainVBox
.pack_start(hbox
, expand
=True, padding
=3)
114 hbox
= gtk
.HBox(False, 0)
115 self
.mainVBox
.pack_start(hbox
, expand
=False, padding
=3)
118 hbox
.pack_start(lbl1
, expand
=True, fill
=False)
120 self
.doAutoImportBool
= False
121 self
.startButton
= gtk
.ToggleButton(_("Start _Auto Import"))
122 self
.startButton
.connect("clicked", self
.startClicked
, "start clicked")
123 hbox
.pack_start(self
.startButton
, expand
=False, fill
=False)
125 self
.DetectButton
= gtk
.Button(_("Detect Directories"))
126 self
.DetectButton
.connect("clicked", self
.detect_hh_dirs
, "detect")
127 #hbox.pack_start(self.DetectButton, expand=False, fill=False)
131 hbox
.pack_start(lbl2
, expand
=True, fill
=False)
133 hbox
= gtk
.HBox(False, 0)
136 self
.mainVBox
.pack_start(hbox
, expand
=True, padding
=3)
138 scrolledwindow
= gtk
.ScrolledWindow()
139 scrolledwindow
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_AUTOMATIC
)
140 self
.mainVBox
.pack_end(scrolledwindow
, expand
=True)
141 scrolledwindow
.add(self
.textview
)
143 self
.mainVBox
.show_all()
144 self
.addText(_("Auto Import Ready."))
146 def addText(self
, text
):
147 end_iter
= self
.textbuffer
.get_end_iter()
148 self
.textbuffer
.insert(end_iter
, text
)
149 self
.textview
.scroll_to_mark(self
.textbuffer
.get_insert(), 0)
152 #end of GuiAutoImport.__init__
153 def browseClicked(self
, widget
, data
):
154 """runs when user clicks one of the browse buttons in the auto import tab"""
155 current_path
=data
[1].get_text()
157 dia_chooser
= gtk
.FileChooserDialog(title
=_("Please choose the path that you want to Auto Import"),
158 action
=gtk
.FILE_CHOOSER_ACTION_SELECT_FOLDER
,
159 buttons
=(gtk
.STOCK_CANCEL
,gtk
.RESPONSE_CANCEL
,gtk
.STOCK_OPEN
,gtk
.RESPONSE_OK
))
160 #dia_chooser.set_current_folder(pathname)
161 dia_chooser
.set_filename(current_path
)
162 #dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import
163 dia_chooser
.set_destroy_with_parent(True)
164 dia_chooser
.set_transient_for(self
.parent
)
166 response
= dia_chooser
.run()
167 if response
== gtk
.RESPONSE_OK
:
168 #print dia_chooser.get_filename(), 'selected'
169 data
[1].set_text(dia_chooser
.get_filename())
170 self
.input_settings
[data
[0]][0] = dia_chooser
.get_filename()
171 elif response
== gtk
.RESPONSE_CANCEL
:
172 #print 'Closed, no files selected'
174 dia_chooser
.destroy()
175 #end def GuiAutoImport.browseClicked
178 """Callback for timer to do an import iteration."""
179 if self
.doAutoImportBool
:
180 self
.startButton
.set_label(_(u
'_Auto Import Running'))
181 self
.importer
.runUpdated()
183 #sys.stdout.write(".")
185 gobject
.timeout_add(1000, self
.reset_startbutton
)
189 def reset_startbutton(self
):
190 if self
.pipe_to_hud
is not None:
191 self
.startButton
.set_label(_(u
'Stop _Auto Import'))
193 self
.startButton
.set_label(_(u
'Start _Auto Import'))
197 def detect_hh_dirs(self
, widget
, data
):
198 """Attempt to find user hand history directories for enabled sites"""
199 the_sites
= self
.config
.get_supported_sites()
200 for site
in the_sites
:
201 params
= self
.config
.get_site_parameters(site
)
202 if params
['enabled'] == True:
203 print (_("DEBUG:") + " " + _("Detecting hand history directory for site: '%s'") % site
)
204 if os
.name
== 'posix':
205 if self
.posix_detect_hh_dirs(site
):
206 #data[1].set_text(dia_chooser.get_filename())
207 self
.input_settings
[site
][0]
209 elif os
.name
== 'nt':
213 def posix_detect_hh_dirs(self
, site
):
215 'PokerStars': '~/.wine/drive_c/Program Files/PokerStars/HandHistory',
217 if site
== 'PokerStars':
218 directory
= os
.path
.expanduser(defaults
[site
])
219 for file in [file for file in os
.listdir(directory
) if not file in [".",".."]]:
223 def startClicked(self
, widget
, data
):
224 """runs when user clicks start on auto import tab"""
226 # Check to see if we have an open file handle to the HUD and open one if we do not.
227 # bufsize = 1 means unbuffered
228 # We need to close this file handle sometime.
230 # TODO: Allow for importing from multiple dirs - REB 29AUG2008
231 # As presently written this function does nothing if there is already a pipe open.
232 # That is not correct. It should open another dir for importing while piping the
233 # results to the same pipe. This means that self.path should be a a list of dirs
236 if data
== "autostart" or (widget
== self
.startButton
and self
.startButton
.get_active()):
237 self
.startButton
.set_active(True)
238 # - Does the lock acquisition need to be more sophisticated for multiple dirs?
239 # (see comment above about what to do if pipe already open)
240 # - Ideally we want to release the lock if the auto-import is killed by some
241 # kind of exception - is this possible?
242 if self
.settings
['global_lock'].acquire(wait
=False, source
="AutoImport"): # returns false immediately if lock not acquired
243 self
.addText("\n" + _("Global lock taken ... Auto Import Started.")+"\n")
244 self
.doAutoImportBool
= True
245 self
.startButton
.set_label(_(u
'Stop _Auto Import'))
246 while gtk
.events_pending(): # change the label NOW don't wait for the pipe to open
247 gtk
.main_iteration(False)
248 if self
.pipe_to_hud
is None:
249 if self
.config
.install_method
== "exe": # if py2exe, run hud_main.exe
250 path
= self
.config
.fpdb_program_path
251 command
= "HUD_main.exe"
253 elif os
.name
== 'nt':
254 path
= sys
.path
[0].replace('\\','\\\\')
255 if win32console
.GetConsoleWindow() == 0:
256 command
= 'pythonw "'+path
+'\\HUD_main.pyw" ' + self
.settings
['cl_options']
258 command
= 'python "'+path
+'\\HUD_main.pyw" ' + self
.settings
['cl_options']
261 command
= os
.path
.join(sys
.path
[0], 'HUD_main.pyw')
262 command
= [command
, ] + string
.split(self
.settings
['cl_options'])
265 print _("opening pipe to HUD")
267 if self
.config
.install_method
== "exe" or (os
.name
== "nt" and win32console
.GetConsoleWindow()) == 0:
268 self
.pipe_to_hud
= subprocess
.Popen(command
, bufsize
=bs
,
269 stdin
=subprocess
.PIPE
,
270 stdout
=subprocess
.PIPE
, # needed for pythonw / py2exe
271 stderr
=subprocess
.PIPE
, # needed for pythonw / py2exe
272 universal_newlines
=True
275 self
.pipe_to_hud
= subprocess
.Popen(command
, bufsize
=bs
, stdin
=subprocess
.PIPE
, universal_newlines
=True)
277 err
= traceback
.extract_tb(sys
.exc_info()[2])[-1]
278 #self.addText( "\n*** GuiAutoImport Error opening pipe: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]))
279 self
.addText("\n" + _("*** GuiAutoImport Error opening pipe:") + " " + traceback
.format_exc() )
281 for site
in self
.input_settings
:
282 self
.importer
.addImportDirectory(self
.input_settings
[site
][0], True, site
, self
.input_settings
[site
][1])
283 self
.addText("\n * Add "+ site
+ " import directory "+ str(self
.input_settings
[site
][0]))
285 interval
= int(self
.intervalEntry
.get_text())
286 if self
.importtimer
!= 0:
287 gobject
.source_remove(self
.importtimer
)
288 self
.importtimer
= gobject
.timeout_add(interval
* 1000, self
.do_import
)
291 self
.addText(_("\nAuto Import aborted - global lock not available"))
293 gobject
.source_remove(self
.importtimer
)
294 self
.settings
['global_lock'].release()
295 self
.doAutoImportBool
= False # do_import will return this and stop the gobject callback timer
296 self
.addText(_("\nStopping Auto Import - global lock released."))
297 if self
.pipe_to_hud
.poll() is not None:
298 self
.addText(_("\n * Stop Auto Import: HUD already terminated"))
300 self
.pipe_to_hud
.terminate()
301 #print >>self.pipe_to_hud.stdin, "\n"
302 # self.pipe_to_hud.communicate('\n') # waits for process to terminate
303 self
.pipe_to_hud
= None
304 self
.startButton
.set_label(_(u
' Start _Auto Import '))
306 #end def GuiAutoImport.startClicked
309 """returns the vbox of this thread"""
313 #Create the site line given required info and setup callbacks
314 #enabling and disabling sites from this interface not possible
315 #expects a box to layout the line horizontally
316 def createSiteLine(self
, hbox1
, hbox2
, site
, iconpath
, hhpath
, filter_name
, active
= True):
317 label
= gtk
.Label(_("%s auto-import:") % site
)
318 hbox1
.pack_start(label
, False, False, 3)
322 dirPath
.set_text(hhpath
)
323 hbox1
.pack_start(dirPath
, True, True, 3)
326 browseButton
=gtk
.Button(_("Browse..."))
327 browseButton
.connect("clicked", self
.browseClicked
, [site
] + [dirPath
])
328 hbox2
.pack_start(browseButton
, False, False, 3)
331 label
= gtk
.Label("%s filter:" % site
)
332 hbox2
.pack_start(label
, False, False, 3)
336 filter.set_text(filter_name
)
337 hbox2
.pack_start(filter, True, True, 3)
340 def addSites(self
, vbox1
, vbox2
):
341 the_sites
= self
.config
.get_supported_sites()
342 #log.debug("addSites: the_sites="+str(the_sites))
343 for site
in the_sites
:
344 pathHBox1
= gtk
.HBox(False, 0)
345 vbox1
.pack_start(pathHBox1
, False, True, 0)
346 pathHBox2
= gtk
.HBox(False, 0)
347 vbox2
.pack_start(pathHBox2
, False, True, 0)
349 params
= self
.config
.get_site_parameters(site
)
350 paths
= self
.config
.get_default_paths(site
)
351 self
.createSiteLine(pathHBox1
, pathHBox2
, site
, False, paths
['hud-defaultPath'], params
['converter'], params
['enabled'])
352 self
.input_settings
[site
] = [paths
['hud-defaultPath']] + [params
['converter']]
353 #log.debug("addSites: input_settings="+str(self.input_settings))
355 if __name__
== "__main__":
356 def destroy(*args
): # call back for terminating the main eventloop
360 # settings['db-host'] = "192.168.1.100"
361 # settings['db-user'] = "mythtv"
362 # settings['db-password'] = "mythtv"
363 # settings['db-databaseName'] = "fpdb"
364 # settings['hud-defaultInterval'] = 10
365 # settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic'
366 # settings['callFpdbHud'] = True
368 parser
= OptionParser()
369 parser
.add_option("-q", "--quiet", action
="store_false", dest
="gui", default
=True, help="don't start gui")
370 (options
, argv
) = parser
.parse_args()
372 config
= Configuration
.Config()
375 if os
.name
== 'nt': settings
['os'] = 'windows'
376 else: settings
['os'] = 'linuxmac'
378 settings
.update(config
.get_db_parameters())
379 settings
.update(config
.get_import_parameters())
380 settings
.update(config
.get_default_paths())
382 if(options
.gui
== True):
383 i
= GuiAutoImport(settings
, config
, None, None)
384 main_window
= gtk
.Window()
385 main_window
.connect('destroy', destroy
)
386 main_window
.add(i
.mainVBox
)
390 i
= GuiAutoImport(settings
, config
, cli
= True)