import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QCheckBox, QPushButton from PyQt5.QtCore import Qt, QRect, QPoint from PyQt5.QtGui import QPainter, QPen, QColor, QFont from ctypes import windll HANDLE_SIZE = 10 # Size of the resize handle squares LABEL_HEIGHT = 20 # Height of the label area above the rectangle class Region: def __init__(self, x, y, w, h, label="Region", color=QColor(0, 0, 255)): self.x = x self.y = y self.w = w self.h = h self.label = label self.color = color def rect(self): return QRect(self.x, self.y, self.w, self.h) def label_rect(self): """The rectangle representing the label area.""" return QRect(self.x, self.y - LABEL_HEIGHT, self.w, LABEL_HEIGHT) def resize_handles(self): """Calculate the positions of the resize handles.""" return [ QRect(self.x - HANDLE_SIZE // 2, self.y - HANDLE_SIZE // 2, HANDLE_SIZE, HANDLE_SIZE), # Top-left QRect(self.x + self.w - HANDLE_SIZE // 2, self.y - HANDLE_SIZE // 2, HANDLE_SIZE, HANDLE_SIZE), # Top-right QRect(self.x - HANDLE_SIZE // 2, self.y + self.h - HANDLE_SIZE // 2, HANDLE_SIZE, HANDLE_SIZE), # Bottom-left QRect(self.x + self.w - HANDLE_SIZE // 2, self.y + self.h - HANDLE_SIZE // 2, HANDLE_SIZE, HANDLE_SIZE), # Bottom-right ] class OverlayCanvas(QWidget): """ A canvas to draw, resize, and interact with rectangular regions. """ def __init__(self, regions, parent=None): super().__init__(parent) self.regions = regions self.edit_mode = False self.selected_region = None self.selected_handle = None # Track which handle is being dragged self.drag_offset = QPoint() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) for region in self.regions: # Draw the rectangle pen = QPen(region.color) pen.setWidth(3) painter.setPen(pen) painter.drawRect(region.x, region.y, region.w, region.h) # Draw the label above the rectangle painter.setFont(QFont("Arial", 12, QFont.Bold)) painter.setPen(region.color) painter.drawText(region.x + 5, region.y - 5, region.label) # Draw resize handles if in edit mode if self.edit_mode: for handle in region.resize_handles(): painter.fillRect(handle, region.color) def mousePressEvent(self, event): if not self.edit_mode: return # Ignore clicks if not in edit mode if event.button() == Qt.LeftButton: for region in reversed(self.regions): # Check regions from topmost to bottommost # Check if a resize handle is clicked for i, handle in enumerate(region.resize_handles()): if handle.contains(event.pos()): self.selected_region = region self.selected_handle = i return # Check if the label area is clicked (for dragging) if region.label_rect().contains(event.pos()): self.selected_region = region self.selected_handle = None # No resize handle, just dragging the rectangle self.drag_offset = event.pos() - QPoint(region.x, region.y) return # Check if the main rectangle is clicked (fallback for dragging) if region.rect().contains(event.pos()): self.selected_region = region self.selected_handle = None self.drag_offset = event.pos() - QPoint(region.x, region.y) return def mouseMoveEvent(self, event): if not self.edit_mode or self.selected_region is None: return if self.selected_handle is None: # Dragging the entire rectangle self.selected_region.x = event.x() - self.drag_offset.x() self.selected_region.y = event.y() - self.drag_offset.y() else: # Resizing the rectangle if self.selected_handle == 0: # Top-left self.selected_region.w += self.selected_region.x - event.x() self.selected_region.h += self.selected_region.y - event.y() self.selected_region.x = event.x() self.selected_region.y = event.y() elif self.selected_handle == 1: # Top-right self.selected_region.w = event.x() - self.selected_region.x self.selected_region.h += self.selected_region.y - event.y() self.selected_region.y = event.y() elif self.selected_handle == 2: # Bottom-left self.selected_region.w += self.selected_region.x - event.x() self.selected_region.h = event.y() - self.selected_region.y self.selected_region.x = event.x() elif self.selected_handle == 3: # Bottom-right self.selected_region.w = event.x() - self.selected_region.x self.selected_region.h = event.y() - self.selected_region.y # Prevent negative width/height self.selected_region.w = max(self.selected_region.w, 10) self.selected_region.h = max(self.selected_region.h, 10) self.update() # Trigger a repaint def mouseReleaseEvent(self, event): if not self.edit_mode: return if event.button() == Qt.LeftButton: self.selected_region = None self.selected_handle = None # Deselect handle class BorealisOverlay(QWidget): def __init__(self): super().__init__() # Set window properties to cover the full screen screen_geometry = QApplication.primaryScreen().geometry() self.setGeometry(screen_geometry) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_TranslucentBackground, True) # Transparent background # Use Win32 API to keep the window on top hwnd = self.winId().__int__() windll.user32.SetWindowPos(hwnd, -1, 0, 0, 0, 0, 0x0001 | 0x0002) # Create regions to draw and interact with self.regions = [ Region(200, 200, 150, 50, label="Region 01"), Region(400, 300, 200, 80, label="Region 02"), ] # Create canvas and attach to window self.canvas = OverlayCanvas(self.regions, self) self.canvas.setGeometry(self.rect()) # Match the canvas size to the full window # Add title, Edit Mode UI, and close button self.init_ui() def init_ui(self): """Initialize UI components.""" # Title label self.title_label = QLabel("Borealis Overlay", self) self.title_label.setStyleSheet("QLabel { color: white; font-size: 18px; font-weight: bold; }") self.title_label.move(10, 5) # Edit mode checkbox self.mode_toggle = QCheckBox("Edit Mode", self) self.mode_toggle.setStyleSheet("QCheckBox { color: white; }") self.mode_toggle.move(10, 30) self.mode_toggle.stateChanged.connect(self.toggle_edit_mode) # Close button self.close_button = QPushButton("Close", self) self.close_button.setStyleSheet( "QPushButton { background-color: #40E0D0; color: white; font-weight: bold; border-radius: 5px; }" ) # Turquoise color self.close_button.move(10, 60) # Place it below the Edit Mode checkbox self.close_button.clicked.connect(self.close) def toggle_edit_mode(self, state): """Enable or disable edit mode for dragging and resizing rectangles.""" editing = (state == 2) self.canvas.edit_mode = editing # Pass the state to the canvas print(f"Borealis Overlay Edit Mode: {'ON' if editing else 'OFF'}") # Debugging output def main(): app = QApplication(sys.argv) window = BorealisOverlay() window.setWindowTitle("Borealis Overlay") # Set application window title window.show() # Explicitly show the window sys.exit(app.exec_()) if __name__ == "__main__": main()