Coverage for Popup.py: 0%
172 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 -*-
3"""Popup.py
5Popup windows for the HUD.
6"""
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
25########################################################################
27# to do
29# Standard Library modules
31from past.utils import old_div
32import logging
35import ctypes
37try:
38 from AppKit import NSView, NSWindowAbove
39except ImportError:
40 NSView = None
42from PyQt5.QtGui import QCursor
43from PyQt5.QtCore import Qt
44from PyQt5.QtWidgets import QGridLayout, QLabel, QVBoxLayout, QWidget
46# FreePokerTools modules
47import Stats
49# logging has been set up in fpdb.py or HUD_main.py, use their settings:
50log = logging.getLogger("hud")
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
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())
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()
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
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()
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()
119 self.lab = QLabel()
120 self.setLayout(QVBoxLayout())
121 self.layout().addWidget(self.lab)
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"
133 # trim final \n
134 tip_text = tip_text[:-1]
135 text = text[:-1]
137 self.lab.setText(text)
138 Stats.do_tip(self.lab, tip_text)
141class Submenu(Popup):
142 # fixme refactor this class, too much repeat code
143 def create(self):
144 super(Submenu, self).create()
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()
153 number_of_items = len(self.pop.pu_stats)
154 if number_of_items < 1:
155 self.destroy_pop()
157 self.grid = QGridLayout()
158 self.grid.setContentsMargins(0, 0, 0, 0)
159 self.grid.setSpacing(0)
160 self.setLayout(self.grid)
162 grid_line = {}
163 row = 1
165 for stat, submenu_to_run in self.pop.pu_stats_submenu:
166 grid_line[row] = {}
167 grid_line[row]["lab"] = QLabel()
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)
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
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)
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)
198 self.grid.addWidget(grid_line[row]["lab"], row - 1, 0)
200 row += 1
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 )
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
226 def create(self):
227 super(Multicol, self).create()
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()
236 number_of_items = len(self.pop.pu_stats)
237 if number_of_items < 1:
238 self.destroy_pop()
240 number_of_cols = old_div(number_of_items, 16)
241 if number_of_cols % 16:
242 number_of_cols += 1
244 number_per_col = old_div(number_of_items, float(number_of_cols))
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
251 self.grid = QGridLayout()
252 self.setLayout(self.grid)
253 self.grid.setHorizontalSpacing(5)
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] = "", ""
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"
269 row_index += 1
270 if row_index >= number_per_col:
271 col_index += 1
272 row_index = 0
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"
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))
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
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)
293 return popup_instance