Dup Ver Goto 📝

sleepqt

PT2/lang/python/qt/pyside6/examples does not exist
To
156 lines, 378 words, 3444 chars Page 'sleepqt' does not exist.
#!/usr/bin/env python
import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtNetwork import *
import time
from threading import Thread
from datetime import datetime

def parse_time(x):
  a = x.split(":")
  if len(a) < 2 or len(a) > 3:
    raise ValueError("Time should be in the format hh:mm or hh:mm:ss")
  if len(a) == 2:
    h,m = map(int,a)
    s = 0
  else:
    h,m,s = map(int,a)
  return (h,m,s)

def fmtime(x):
  h,s = divmod(x,3600)
  m,s = divmod(s,60)
  return f"{h:02d}:{m:02d}:{s:02d}"

def clamp(x,a,b):
  return max(min(x,b),a)

class Countdown(QWidget):
  def handleUdp(self):
    app.quit()

  def __init__(self,t0):
    super().__init__()

    # so we can kill via sending UDP to 2000, e.g.
    # echo hello | nc -u -w1 localhost 2000

    self.udpSocket = QUdpSocket()
    self.udpSocket.readyRead.connect(self.handleUdp)
    try:
      if not self.udpSocket.bind(QHostAddress.Any,2000):
        raise Exception("Address bind failed")
    except Exception:
      print(f"Failed to bind UDP port 2000")
      exit(1)
      app.quit()

    m = 100
    self.t0 = t0
    scr = QGuiApplication.primaryScreen()
    geom = scr.geometry()
    sh = geom.height()
    sw = geom.width()

    x = m
    y = m
    w = sw-2*m
    h = sh-2*m
    self.w = w
    self.h = h

    # size and position – possibly necessary to recompute, resize and move depending on hud contents
    self.resize(w,h)
    self.move(x,y)
    #self.resize(600,600)

    # attributes for display
    self.fontname = "Optima"
    self.fontsize = 200
    self.font = QFont(self.fontname,self.fontsize)
    self.color = QColor(100,255,100)
    self.ocolor = Qt.black
    self.pen = QPen(self.ocolor,16)

    self.content = "Countdown"

    # window attributes
    self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
    self.setAttribute(Qt.WA_TranslucentBackground)
    self.n = 60

    self.timer = QTimer(self)
    self.timer.setInterval(1000)
    self.timer.timeout.connect(self.ping)

    self.ping()

  def go(self):
    self.show()
    self.timer.start()

  def ping(self):
    t = int(datetime.now().timestamp())
    dt = self.t0 - t
    if dt < 0:
      app.quit()
    self.content = fmtime(dt)
    self.update()

  def paintEvent(self,event):
    with QPainter(self) as p:
      text = self.content
      metrics = QFontMetrics(self.font)
      tw = metrics.horizontalAdvance(text)
      x = (self.w-tw)/2
      h = metrics.height()
      sh = self.h
      dh = (sh-h)/2
      y = dh+h

      path = QPainterPath()
      path.addText(x,y,self.font,str(text))

      # draw twice so that the black outline is _behind_ the fill
      p.setPen(self.pen)
      p.drawPath(path)
      p.setBrush(self.color)
      p.setPen(Qt.NoPen)
      p.drawPath(path)

  def mousePressEvent(self,e):
    self.hide()
    super().mousePressEvent(e)

  def finish(self):
    app.quit()

def compute_secs_until(x):
  h,m,s = parse_time(x)
  now = datetime.now()
  h1 = now.hour
  m1 = now.minute
  s1 = now.second
  secs = 3600*h+60*m+s
  secs1 = 3600*h1+60*m1+s1
  dt = secs - secs1
  if dt < 0:
    dt += 24*3600
  return dt

args = sys.argv[1:]

if len(args) == 0:
  print(f"sleepyqt target-time(h:m:s)")
  exit(1)
dt = compute_secs_until(args[0])
t = int(datetime.now().timestamp())
t0 = t+dt
app = QApplication([])
win = Countdown(t0)
win.go()
exit(app.exec())