Coverage for Popup.py: 0%

172 statements  

« prev     ^ index     » next       coverage.py v7.6.3, created at 2024-10-14 11:07 +0000

1#!/usr/bin/env python 

2# -*- coding: utf-8 -*- 

3"""Popup.py 

4 

5Popup windows for the HUD. 

6""" 

7 

8from __future__ import division 

9# Copyright 2011-2012, Ray E. Barker 

10# 

11# This program is free software; you can redistribute it and/or modify 

12# it under the terms of the GNU General Public License as published by 

13# the Free Software Foundation; either version 3 of the License, or 

14# (at your option) any later version. 

15# 

16# This program is distributed in the hope that it will be useful, 

17# but WITHOUT ANY WARRANTY; without even the implied warranty of 

18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

19# GNU General Public License for more details. 

20# 

21# You should have received a copy of the GNU General Public License 

22# along with this program; if not, write to the Free Software 

23# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

24 

25######################################################################## 

26 

27# to do 

28 

29# Standard Library modules 

30 

31from past.utils import old_div 

32import logging 

33 

34 

35import ctypes 

36 

37try: 

38 from AppKit import NSView, NSWindowAbove 

39except ImportError: 

40 NSView = None 

41 

42from PyQt5.QtGui import QCursor 

43from PyQt5.QtCore import Qt 

44from PyQt5.QtWidgets import QGridLayout, QLabel, QVBoxLayout, QWidget 

45 

46# FreePokerTools modules 

47import Stats 

48 

49# logging has been set up in fpdb.py or HUD_main.py, use their settings: 

50log = logging.getLogger("hud") 

51 

52 

53class Popup(QWidget): 

54 def __init__( 

55 self, seat=None, stat_dict=None, win=None, pop=None, hand_instance=None, config=None, parent_popup=None 

56 ): 

57 super(Popup, self).__init__( 

58 parent_popup or win, Qt.Window | Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus 

59 ) 

60 self.seat = seat 

61 self.stat_dict = stat_dict 

62 self.win = win 

63 self.pop = pop 

64 self.hand_instance = hand_instance 

65 self.config = config 

66 self.parent_popup = parent_popup # parent's instance only used if this popup is a child of another popup 

67 self.submenu_count = 0 # used to keep track of active submenus - only one at once allowed 

68 

69 self.create() 

70 self.show() 

71 # child popups are positioned at the mouse pointer and must be killed if 

72 # the parent is killed 

73 parent = parent_popup or win 

74 if config.os_family == "Mac" and NSView is not None: 

75 selfwinid = self.effectiveWinId() 

76 selfcvp = ctypes.c_void_p(int(selfwinid)) 

77 selfview = NSView(c_void_p=selfcvp) 

78 parentwinid = parent.effectiveWinId() 

79 parentcvp = ctypes.c_void_p(int(parentwinid)) 

80 parentview = NSView(c_void_p=parentcvp) 

81 parentview.window().addChildWindow_ordered_(selfview.window(), NSWindowAbove) 

82 else: 

83 self.windowHandle().setTransientParent(self.parent().windowHandle()) 

84 parent.destroyed.connect(self.destroy) 

85 self.move(QCursor.pos()) 

86 

87 # Every popup window needs one of these 

88 def mousePressEvent(self, event): 

89 """Handle button clicks on the popup window.""" 

90 # Any button click gets rid of popup. 

91 self.destroy_pop() 

92 

93 def create(self): 

94 # popup_count is used by Aux_hud to prevent multiple active popups per player 

95 # do not increment count if this popup is a child of another popup 

96 if self.parent_popup: 

97 self.parent_popup.submenu_count += 1 

98 else: 

99 self.win.popup_count += 1 

100 

101 def destroy_pop(self): 

102 if self.parent_popup: 

103 self.parent_popup.submenu_count -= 1 

104 else: 

105 self.win.popup_count -= 1 

106 self.destroy() 

107 

108 

109class default(Popup): 

110 def create(self): 

111 super(default, self).create() 

112 player_id = None 

113 for id in list(self.stat_dict.keys()): 

114 if self.seat == self.stat_dict[id]["seat"]: 

115 player_id = id 

116 if player_id is None: 

117 self.destroy_pop() 

118 

119 self.lab = QLabel() 

120 self.setLayout(QVBoxLayout()) 

121 self.layout().addWidget(self.lab) 

122 

123 text, tip_text = "", "" 

124 for stat in self.pop.pu_stats: 

125 number = Stats.do_stat(self.stat_dict, player=int(player_id), stat=stat, hand_instance=self.hand_instance) 

126 if number: 

127 text += number[3] + "\n" 

128 tip_text += number[5] + " " + number[4] + "\n" 

129 else: 

130 text += "xxx" + "\n" 

131 tip_text += "xxx" + " " + "xxx" + "\n" 

132 

133 # trim final \n 

134 tip_text = tip_text[:-1] 

135 text = text[:-1] 

136 

137 self.lab.setText(text) 

138 Stats.do_tip(self.lab, tip_text) 

139 

140 

141class Submenu(Popup): 

142 # fixme refactor this class, too much repeat code 

143 def create(self): 

144 super(Submenu, self).create() 

145 

146 player_id = None 

147 for id in list(self.stat_dict.keys()): 

148 if self.seat == self.stat_dict[id]["seat"]: 

149 player_id = id 

150 if player_id is None: 

151 self.destroy_pop() 

152 

153 number_of_items = len(self.pop.pu_stats) 

154 if number_of_items < 1: 

155 self.destroy_pop() 

156 

157 self.grid = QGridLayout() 

158 self.grid.setContentsMargins(0, 0, 0, 0) 

159 self.grid.setSpacing(0) 

160 self.setLayout(self.grid) 

161 

162 grid_line = {} 

163 row = 1 

164 

165 for stat, submenu_to_run in self.pop.pu_stats_submenu: 

166 grid_line[row] = {} 

167 grid_line[row]["lab"] = QLabel() 

168 

169 number = Stats.do_stat(self.stat_dict, player=int(player_id), stat=stat, hand_instance=self.hand_instance) 

170 if number: 

171 grid_line[row]["text"] = number[3] 

172 grid_line[row]["lab"].setText(number[3]) 

173 Stats.do_tip(grid_line[row]["lab"], number[5] + " " + number[4]) 

174 else: 

175 grid_line[row]["text"] = stat 

176 grid_line[row]["lab"].setText(stat) 

177 

178 if row == 1: 

179 # put an "x" close label onto the popup, invert bg/fg 

180 # the window can also be closed by clicking on any non-menu label 

181 # but this "x" is added incase the menu is entirely non-menu labels 

182 

183 xlab = QLabel("x") 

184 xlab.setStyleSheet("background:%s;color:%s;" % (self.win.aw.fgcolor, self.win.aw.bgcolor)) 

185 grid_line[row]["x"] = xlab 

186 self.grid.addWidget(grid_line[row]["x"], row - 1, 2) 

187 

188 if submenu_to_run: 

189 lab = QLabel(">") 

190 grid_line[row]["arrow_object"] = lab 

191 lab.submenu = submenu_to_run 

192 grid_line[row]["lab"].submenu = submenu_to_run 

193 if row == 1: 

194 self.grid.addWidget(grid_line[row]["arrow_object"], row - 1, 1) 

195 else: 

196 self.grid.addWidget(grid_line[row]["arrow_object"], row - 1, 1, 1, 2) 

197 

198 self.grid.addWidget(grid_line[row]["lab"], row - 1, 0) 

199 

200 row += 1 

201 

202 def mousePressEvent(self, event): 

203 widget = self.childAt(event.pos()) 

204 submenu = "_destroy" 

205 if hasattr(widget, "submenu"): 

206 submenu = widget.submenu 

207 if submenu == "_destroy": 

208 self.destroy_pop() 

209 return 

210 if self.submenu_count < 1: # only 1 popup allowed to be open at this level 

211 popup_factory( 

212 self.seat, 

213 self.stat_dict, 

214 self.win, 

215 self.config.popup_windows[submenu], 

216 self.hand_instance, 

217 self.config, 

218 self, 

219 ) 

220 

221 

222class Multicol(Popup): 

223 # like a default, but will flow into columns of 16 items 

224 # use "blank" items if the default flowing affects readability 

225 

226 def create(self): 

227 super(Multicol, self).create() 

228 

229 player_id = None 

230 for id in list(self.stat_dict.keys()): 

231 if self.seat == self.stat_dict[id]["seat"]: 

232 player_id = id 

233 if player_id is None: 

234 self.destroy_pop() 

235 

236 number_of_items = len(self.pop.pu_stats) 

237 if number_of_items < 1: 

238 self.destroy_pop() 

239 

240 number_of_cols = old_div(number_of_items, 16) 

241 if number_of_cols % 16: 

242 number_of_cols += 1 

243 

244 number_per_col = old_div(number_of_items, float(number_of_cols)) 

245 

246 # if number_per_col != round((number_of_items / float(number_of_cols)),0): 

247 # number_per_col += 1 

248 # number_per_col = int(number_per_col) 

249 number_per_col = 16 

250 

251 self.grid = QGridLayout() 

252 self.setLayout(self.grid) 

253 self.grid.setHorizontalSpacing(5) 

254 

255 col_index, row_index = 0, 0 

256 text, tip_text = {}, {} 

257 for i in range(number_of_cols): 

258 text[i], tip_text[i] = "", "" 

259 

260 for stat in self.pop.pu_stats: 

261 number = Stats.do_stat(self.stat_dict, player=int(player_id), stat=stat, hand_instance=self.hand_instance) 

262 if number: 

263 text[col_index] += number[3] + "\n" 

264 tip_text[col_index] += number[5] + " " + number[4] + "\n" 

265 else: 

266 text[col_index] += stat + "\n" 

267 tip_text[col_index] += stat + "\n" 

268 

269 row_index += 1 

270 if row_index >= number_per_col: 

271 col_index += 1 

272 row_index = 0 

273 

274 if row_index > 0: 

275 for i in range(number_per_col - row_index): 

276 # pad final column with blank lines 

277 text[col_index] += "\n" 

278 

279 for i in text: 

280 contentlab = QLabel(text[i][:-1]) 

281 Stats.do_tip(contentlab, tip_text[i][:-1]) 

282 self.grid.addWidget(contentlab, 0, int(i)) 

283 

284 

285def popup_factory(seat=None, stat_dict=None, win=None, pop=None, hand_instance=None, config=None, parent_popup=None): 

286 # a factory function to discover the base type of the popup 

287 # and to return a class instance of the correct popup 

288 # getattr looksup the class reference in this module 

289 

290 class_to_return = getattr(__import__(__name__), pop.pu_class) 

291 popup_instance = class_to_return(seat, stat_dict, win, pop, hand_instance, config, parent_popup) 

292 

293 return popup_instance