Coverage for GuiAutoImport.py: 0%

233 statements  

« 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 

4 

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 

26 

27import Importer 

28from optparse import OptionParser 

29import Configuration 

30 

31import interlocks 

32 

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") 

37 

38if os.name == "nt": 

39 import win32console 

40 

41 

42def to_raw(string): 

43 return rf"{string}" 

44 

45 

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 

55 

56 self.input_settings = {} 

57 self.pipe_to_hud = None 

58 

59 self.importer = Importer.Importer(self, self.settings, self.config, self.sql) 

60 

61 self.importer.setCallHud(True) 

62 self.importer.setQuiet(False) 

63 self.importer.setHandCount(0) 

64 self.importer.setMode("auto") 

65 

66 self.server = settings["db-host"] 

67 self.user = settings["db-user"] 

68 self.password = settings["db-password"] 

69 self.database = settings["db-databaseName"] 

70 

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 

78 

79 def setupGui(self): 

80 self.setLayout(QVBoxLayout()) 

81 

82 hbox = QHBoxLayout() 

83 

84 self.intervalLabel = QLabel(("Time between imports in seconds:")) 

85 

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) 

91 

92 hbox = QHBoxLayout() 

93 vbox1 = QVBoxLayout() 

94 vbox2 = QVBoxLayout() 

95 hbox.addLayout(vbox1) 

96 hbox.addLayout(vbox2) 

97 self.layout().addLayout(hbox) 

98 

99 self.addSites(vbox1, vbox2) 

100 

101 self.textview = QTextEdit() 

102 self.textview.setReadOnly(True) 

103 

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) 

109 

110 self.addText(("Auto Import Ready.")) 

111 

112 def addText(self, text): 

113 self.textview.moveCursor(QTextCursor.End) 

114 self.textview.insertPlainText(text) 

115 

116 # end of GuiAutoImport.__init__ 

117 

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() 

125 

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 

133 

134 # end def GuiAutoImport.browseClicked 

135 

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 

144 

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")) 

150 

151 return False 

152 

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 

168 

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 

178 

179 def startClicked(self): 

180 """runs when user clicks start on auto import tab""" 

181 

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. 

185 

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. 

191 

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 

234 

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 ) 

252 

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) 

269 

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) 

286 

287 # end def GuiAutoImport.startClicked 

288 

289 def get_vbox(self): 

290 """returns the vbox of this thread""" 

291 return self.mainVBox 

292 

293 # end def get_vbox 

294 

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) 

301 

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) 

308 

309 browseButton = QPushButton(("Browse...")) 

310 browseButton.hackdata = [(site, type)] + [dirPath] 

311 browseButton.clicked.connect(self.browseClicked) # , [(site,type)] + [dirPath]) 

312 hbox2.addWidget(browseButton) 

313 

314 label = QLabel("filter:") 

315 hbox2.addWidget(label) 

316 

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) 

323 

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) 

332 

333 params = self.config.get_site_parameters(site) 

334 paths = self.config.get_default_paths(site) 

335 

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"]] 

347 

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)) 

365 

366 

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() 

371 

372 config = Configuration.Config() 

373 

374 settings = {} 

375 if os.name == "nt": 

376 settings["os"] = "windows" 

377 else: 

378 settings["os"] = "linuxmac" 

379 

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:]) 

385 

386 if options.gui is True: 

387 from PyQt5.QtWidgets import QApplication, QMainWindow 

388 

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)