Coverage for GuiAutoImport.py: 0%
233 statements
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-15 19:33 +0000
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-15 19:33 +0000
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3from __future__ import print_function
5# import L10n
6# _ = L10n.get_translation()
7import subprocess
8import traceback
9import os
10import sys
11import logging
12from PyQt5.QtWidgets import (
13 QWidget,
14 QVBoxLayout,
15 QHBoxLayout,
16 QLabel,
17 QSpinBox,
18 QPushButton,
19 QLineEdit,
20 QTextEdit,
21 QCheckBox,
22 QFileDialog,
23)
24from PyQt5.QtCore import QTimer
25from PyQt5.QtGui import QTextCursor
27import Importer
28from optparse import OptionParser
29import Configuration
31import interlocks
33if __name__ == "__main__":
34 Configuration.set_logfile("fpdb-log.txt")
35# logging has been set up in fpdb.py or HUD_main.py, use their settings:
36log = logging.getLogger("importer")
38if os.name == "nt":
39 import win32console
42def to_raw(string):
43 return rf"{string}"
46class GuiAutoImport(QWidget):
47 def __init__(self, settings, config, sql=None, parent=None, cli=False):
48 if not cli:
49 QWidget.__init__(self, parent)
50 self.importtimer = None
51 self.settings = settings
52 self.config = config
53 self.sql = sql
54 self.parent = parent
56 self.input_settings = {}
57 self.pipe_to_hud = None
59 self.importer = Importer.Importer(self, self.settings, self.config, self.sql)
61 self.importer.setCallHud(True)
62 self.importer.setQuiet(False)
63 self.importer.setHandCount(0)
64 self.importer.setMode("auto")
66 self.server = settings["db-host"]
67 self.user = settings["db-user"]
68 self.password = settings["db-password"]
69 self.database = settings["db-databaseName"]
71 if cli is False:
72 self.setupGui()
73 else:
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
77 raise NotImplementedError
79 def setupGui(self):
80 self.setLayout(QVBoxLayout())
82 hbox = QHBoxLayout()
84 self.intervalLabel = QLabel(("Time between imports in seconds:"))
86 self.intervalEntry = QSpinBox()
87 self.intervalEntry.setValue(int(self.config.get_import_parameters().get("interval")))
88 hbox.addWidget(self.intervalLabel)
89 hbox.addWidget(self.intervalEntry)
90 self.layout().addLayout(hbox)
92 hbox = QHBoxLayout()
93 vbox1 = QVBoxLayout()
94 vbox2 = QVBoxLayout()
95 hbox.addLayout(vbox1)
96 hbox.addLayout(vbox2)
97 self.layout().addLayout(hbox)
99 self.addSites(vbox1, vbox2)
101 self.textview = QTextEdit()
102 self.textview.setReadOnly(True)
104 self.doAutoImportBool = False
105 self.startButton = QCheckBox(("Start Auto Import"))
106 self.startButton.stateChanged.connect(self.startClicked)
107 self.layout().addWidget(self.startButton)
108 self.layout().addWidget(self.textview)
110 self.addText(("Auto Import Ready."))
112 def addText(self, text):
113 self.textview.moveCursor(QTextCursor.End)
114 self.textview.insertPlainText(text)
116 # end of GuiAutoImport.__init__
118 def browseClicked(self):
119 # runs when user clicks one of the browse buttons in the auto import tab"""
120 # Browse is not valid while hud is running, so return immediately
121 if self.pipe_to_hud:
122 return
123 data = self.sender().hackdata
124 current_path = data[1].text()
126 newdir = QFileDialog.getExistingDirectory(
127 self, caption=("Please choose the path that you want to Auto Import"), directory=current_path
128 )
129 if newdir:
130 # print dia_chooser.get_filename(), 'selected'
131 data[1].setText(newdir)
132 self.input_settings[data[0]][0] = newdir
134 # end def GuiAutoImport.browseClicked
136 def do_import(self):
137 """Callback for timer to do an import iteration."""
138 if self.doAutoImportBool:
139 self.importer.autoSummaryGrab()
140 self.importer.runUpdated()
141 self.addText(".")
142 return True
143 return False
145 def reset_startbutton(self):
146 if self.pipe_to_hud is not None:
147 self.startButton.set_label(("Stop Auto Import"))
148 else:
149 self.startButton.set_label(("Start Auto Import"))
151 return False
153 def detect_hh_dirs(self, widget, data):
154 """Attempt to find user hand history directories for enabled sites"""
155 the_sites = self.config.get_supported_sites()
156 for site in the_sites:
157 params = self.config.get_site_parameters(site)
158 if params["enabled"] is True:
159 print(("DEBUG:") + " " + ("Detecting hand history directory for site: '%s'") % site)
160 if os.name == "posix":
161 if self.posix_detect_hh_dirs(site):
162 # data[1].set_text(dia_chooser.get_filename())
163 self.input_settings[(site, "hh")][0]
164 pass
165 elif os.name == "nt":
166 # Sorry
167 pass
169 def posix_detect_hh_dirs(self, site):
170 defaults = {
171 "PokerStars": "~/.wine/drive_c/Program Files/PokerStars/HandHistory",
172 }
173 if site == "PokerStars":
174 directory = os.path.expanduser(defaults[site])
175 for file in [file for file in os.listdir(directory) if file not in [".", ".."]]:
176 print(file)
177 return False
179 def startClicked(self):
180 """runs when user clicks start on auto import tab"""
182 # Check to see if we have an open file handle to the HUD and open one if we do not.
183 # bufsize = 1 means unbuffered
184 # We need to close this file handle sometime.
186 # TODO: Allow for importing from multiple dirs - REB 29AUG2008
187 # As presently written this function does nothing if there is already a pipe open.
188 # That is not correct. It should open another dir for importing while piping the
189 # results to the same pipe. This means that self.path should be a a list of dirs
190 # to watch.
192 if self.startButton.isChecked():
193 # - Does the lock acquisition need to be more sophisticated for multiple dirs?
194 # (see comment above about what to do if pipe already open)
195 # - Ideally we want to release the lock if the auto-import is killed by some
196 # kind of exception - is this possible?
197 if self.settings["global_lock"].acquire(wait=False, source="AutoImport"):
198 self.addText("\n" + ("Global lock taken ... Auto Import Started.") + "\n")
199 self.doAutoImportBool = True
200 self.intervalEntry.setEnabled(False)
201 if self.pipe_to_hud is None:
202 print("start hud- pipe_to_hud is none:")
203 try:
204 if self.config.install_method == "exe":
205 command = "HUD_main.exe"
206 bs = 0
207 elif self.config.install_method == "app":
208 base_path = sys._MEIPASS if getattr(sys, "frozen", False) else sys.path[0]
209 command = os.path.join(base_path, "HUD_main")
210 if not os.path.isfile(command):
211 raise FileNotFoundError(f"HUD_main not found at {command}")
212 bs = 1
213 elif os.name == "nt":
214 path = to_raw(sys.path[0])
215 print("start hud- path", path)
216 path2 = os.getcwd()
217 print("start hud- path2", path2)
218 if win32console.GetConsoleWindow() == 0:
219 command = 'pythonw "' + path + '\HUD_main.pyw" ' + self.settings["cl_options"]
220 print("start hud-comand1", command)
221 else:
222 command = 'python "' + path + '\HUD_main.pyw" ' + self.settings["cl_options"]
223 print("start hud-comand2", command)
224 bs = 0
225 else:
226 base_path = sys._MEIPASS if getattr(sys, "frozen", False) else sys.path[0] or os.getcwd()
227 command = os.path.join(base_path, "HUD_main.pyw")
228 if not os.path.isfile(command):
229 self.addText("\n" + ("*** %s was not found") % (command))
230 command = [
231 command,
232 ] + str.split(self.settings["cl_options"], ".")
233 bs = 1
235 print(("opening pipe to HUD"))
236 print(f"Running {command.__repr__()}")
237 if self.config.install_method == "exe" or (
238 os.name == "nt" and win32console.GetConsoleWindow() == 0
239 ):
240 self.pipe_to_hud = subprocess.Popen(
241 command,
242 bufsize=bs,
243 stdin=subprocess.PIPE,
244 stdout=subprocess.PIPE,
245 stderr=subprocess.PIPE,
246 universal_newlines=True,
247 )
248 else:
249 self.pipe_to_hud = subprocess.Popen(
250 command, bufsize=bs, stdin=subprocess.PIPE, universal_newlines=True
251 )
253 except Exception:
254 self.addText("\n" + ("*** GuiAutoImport Error opening pipe:") + " " + traceback.format_exc())
255 # TODO: log.warning() ?
256 else:
257 for site, type in self.input_settings:
258 self.importer.addImportDirectory(
259 self.input_settings[(site, type)][0], monitor=True, site=(site, type)
260 )
261 self.addText(
262 "\n * " + ("Add %s import directory %s") % (site, self.input_settings[(site, type)][0])
263 )
264 self.do_import()
265 interval = self.intervalEntry.value()
266 self.importtimer = QTimer()
267 self.importtimer.timeout.connect(self.do_import)
268 self.importtimer.start(interval * 1000)
270 else:
271 self.addText("\n" + ("Auto Import aborted.") + ("Global lock not available."))
272 else: # toggled off
273 self.doAutoImportBool = False
274 self.importtimer = None
275 self.importer.autoSummaryGrab(True)
276 self.settings["global_lock"].release()
277 self.addText("\n" + ("Stopping Auto Import.") + ("Global lock released."))
278 if self.pipe_to_hud and self.pipe_to_hud.poll() is not None:
279 self.addText("\n * " + ("Stop Auto Import") + ": " + ("HUD already terminated."))
280 else:
281 if self.pipe_to_hud:
282 self.pipe_to_hud.terminate()
283 print(self.pipe_to_hud.stdin, "\n")
284 self.pipe_to_hud = None
285 self.intervalEntry.setEnabled(True)
287 # end def GuiAutoImport.startClicked
289 def get_vbox(self):
290 """returns the vbox of this thread"""
291 return self.mainVBox
293 # end def get_vbox
295 # Create the site line given required info and setup callbacks
296 # enabling and disabling sites from this interface not possible
297 # expects a box to layout the line horizontally
298 def createSiteLine(self, hbox1, hbox2, site, iconpath, type, path, filter_name, active=True):
299 label = QLabel(("%s auto-import:") % site)
300 hbox1.addWidget(label)
302 dirPath = QLineEdit()
303 dirPath.setText(path)
304 hbox1.addWidget(dirPath)
305 # Anything typed into dirPath was never recognised (only the browse button works)
306 # so just prevent entry to avoid user confusion
307 dirPath.setReadOnly(True)
309 browseButton = QPushButton(("Browse..."))
310 browseButton.hackdata = [(site, type)] + [dirPath]
311 browseButton.clicked.connect(self.browseClicked) # , [(site,type)] + [dirPath])
312 hbox2.addWidget(browseButton)
314 label = QLabel("filter:")
315 hbox2.addWidget(label)
317 # Anything typed into filter was never recognised
318 # so just grey it out to avoid user confusion
319 filterLine = QLineEdit()
320 filterLine.setText(filter_name)
321 filterLine.setEnabled(False)
322 hbox2.addWidget(filterLine)
324 def addSites(self, vbox1, vbox2):
325 the_sites = self.config.get_supported_sites()
326 # log.debug("addSites: the_sites="+str(the_sites))
327 for site in the_sites:
328 pathHBox1 = QHBoxLayout()
329 vbox1.addLayout(pathHBox1)
330 pathHBox2 = QHBoxLayout()
331 vbox2.addLayout(pathHBox2)
333 params = self.config.get_site_parameters(site)
334 paths = self.config.get_default_paths(site)
336 self.createSiteLine(
337 pathHBox1,
338 pathHBox2,
339 site,
340 False,
341 "hh",
342 paths["hud-defaultPath"],
343 params["converter"],
344 params["enabled"],
345 )
346 self.input_settings[(site, "hh")] = [paths["hud-defaultPath"]] + [params["converter"]]
348 if "hud-defaultTSPath" in paths:
349 pathHBox1 = QHBoxLayout()
350 vbox1.addLayout(pathHBox1)
351 pathHBox2 = QHBoxLayout()
352 vbox2.addLayout(pathHBox2)
353 self.createSiteLine(
354 pathHBox1,
355 pathHBox2,
356 site,
357 False,
358 "ts",
359 paths["hud-defaultTSPath"],
360 params["summaryImporter"],
361 params["enabled"],
362 )
363 self.input_settings[(site, "ts")] = [paths["hud-defaultTSPath"]] + [params["summaryImporter"]]
364 # log.debug("addSites: input_settings="+str(self.input_settings))
367if __name__ == "__main__":
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()
374 settings = {}
375 if os.name == "nt":
376 settings["os"] = "windows"
377 else:
378 settings["os"] = "linuxmac"
380 settings.update(config.get_db_parameters())
381 settings.update(config.get_import_parameters())
382 settings.update(config.get_default_paths())
383 settings["global_lock"] = interlocks.InterProcessLock(name="fpdb_global_lock")
384 settings["cl_options"] = ".".join(sys.argv[1:])
386 if options.gui is True:
387 from PyQt5.QtWidgets import QApplication, QMainWindow
389 app = QApplication([])
390 i = GuiAutoImport(settings, config, None, None)
391 main_window = QMainWindow()
392 main_window.setCentralWidget(i)
393 main_window.show()
394 app.exec_()
395 else:
396 i = GuiAutoImport(settings, config, cli=True)