Skip to content

docs: add comprehensive JSDoc documentation to all Python modules #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions GetDataV2.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
"""
GetDataV2.py - Screen Capture and Window Management Module

This module provides functionality for capturing screen data from Windows applications,
managing window handles, and retrieving process information. It's designed to work
with the Porda AI application for intelligent screen monitoring and object detection.

@author Abdullah
@version 2.0
@since 2024
"""

import win32gui
import win32ui
import win32con
Expand All @@ -9,6 +21,13 @@
import time

def get_process_name(hwnd):
"""
Retrieves the process name from a window handle using win32api.

@param {int} hwnd - Window handle to get process name for
@returns {str|None} Process name if successful, None if failed
@throws {Exception} When unable to access process information
"""
try:
_, pid = win32process.GetWindowThreadProcessId(hwnd)
handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, pid)
Expand All @@ -21,6 +40,13 @@ def get_process_name(hwnd):


def get_process_name2(hwnd):
"""
Retrieves the process name from a window handle using psutil.

@param {int} hwnd - Window handle to get process name for
@returns {str|None} Process name if successful, None if failed
@throws {psutil.NoSuchProcess} When process no longer exists
"""
_, pid = win32process.GetWindowThreadProcessId(hwnd)
try:
process_name = psutil.Process(pid).name()
Expand All @@ -30,6 +56,12 @@ def get_process_name2(hwnd):


def get_hwnds_for_pid(pid):
"""
Gets all window handles associated with a specific process ID.

@param {int} pid - Process ID to find windows for
@returns {list} List of window handles for the given process ID
"""
def callback(hwnd, hwnds):
#if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
_, found_pid = win32process.GetWindowThreadProcessId(hwnd)
Expand All @@ -41,6 +73,12 @@ def callback(hwnd, hwnds):
return hwnds

def get_hwnd_by_process_name(process_name):
"""
Finds window handles by process name.

@param {str} process_name - Name of the process to find windows for
@returns {list} List of window handles for the given process name
"""
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == process_name:
hwnds = get_hwnds_for_pid(proc.pid)
Expand All @@ -49,8 +87,21 @@ def get_hwnd_by_process_name(process_name):
return [] # Return an empty list if process not found

class FoundWindow(Exception):
"""
Custom exception raised when a window is found during enumeration.

@extends {Exception}
"""
pass

def get_hwnds_for_pid_first_hwnd(pid):
"""
Gets the first visible and enabled window handle for a specific process ID.

@param {int} pid - Process ID to find window for
@returns {list} List containing the first found window handle
@throws {FoundWindow} When a suitable window is found (caught internally)
"""
def callback(hwnd, hwnds):
if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
if win32gui.GetParent(hwnd) == 0:
Expand All @@ -70,6 +121,12 @@ def callback(hwnd, hwnds):
return hwnds

def get_hwnd_by_process_name_first_hwnd(process_name):
"""
Finds the first window handle for a given process name.

@param {str} process_name - Name of the process to find window for
@returns {list} List containing the first found window handle
"""
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == process_name:
hwnds = get_hwnds_for_pid_first_hwnd(proc.pid)
Expand All @@ -79,6 +136,21 @@ def get_hwnd_by_process_name_first_hwnd(process_name):


def GetScreenData(self):
"""
Captures screen data from the currently active window or specified windows.

This function handles window detection, screen capture, and returns image data
along with window position and size information. It supports various detection
modes including all windows, included windows only, and specific window detection.

@param {object} self - Main window instance containing detection settings
@returns {tuple} (image, x, y, height, width, status) where:
- image: numpy array of captured screen data
- x, y: window position coordinates
- height, width: window dimensions
- status: 1 for success, None for failure
@throws {Exception} When window capture fails
"""
not_empt=False

try:
Expand Down
39 changes: 39 additions & 0 deletions ProjectStructure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
## Project Structure

```
Porda-AI/
├── main.py # Main application entry point
├── GetDataV2.py # Screen capture and window management
├── SetupPordaApp.py # Application setup and configuration
├── settings/
│ ├── SettingsValue.py # Settings management
│ ├── message.py # Message and notification system
│ ├── startup.py # Startup configuration
│ ├── settingscss2.py # UI styling
│ ├── doc.py # Documentation content
│ ├── ga4_porda.py # Google Analytics tracking
│ ├── EngineSetting.py # Detection engine configuration
│ └── Settings.py # Main settings interface
├── model/ # Neural network model files
├── readme-assets/ # Documentation assets
└── context.md # This documentation file
```

## Key Features Documented

### Core Functionality
- **Screen Capture**: Real-time screen capture with window filtering
- **Object Detection**: AI-powered object detection using YOLO models
- **Overlay System**: Dynamic overlay drawing for detected objects
- **Settings Management**: Comprehensive settings interface
- **System Tray Integration**: System tray icon with context menu
- **Keyboard Shortcuts**: Configurable hotkeys for various actions
- **CPU Monitoring**: Automatic detection stopping based on CPU usage

### Technical Components
- **PyQt5 GUI Framework**: Main application interface
- **OpenCV**: Computer vision and image processing
- **Windows API**: Screen capture and window management
- **Neural Networks**: YOLO-based object detection
- **OpenCL**: GPU acceleration support
- **Google Analytics**: Usage tracking and analytics
108 changes: 102 additions & 6 deletions SetupPordaApp.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
"""
SetupPordaApp.py - Application Setup and Configuration Module

This module handles the initial setup and configuration of the Porda AI application.
It manages application directories, model loading, logging setup, registry modifications,
and various utility functions for the application lifecycle.

@author Abdullah
@version 1.0
@since 2024
"""

import logging
import os
import sys
Expand All @@ -22,6 +34,18 @@
#"Normal": "00000002",

def set_priority_in_registry(exe_path, priority_hex):
"""
Sets the CPU priority for an executable in the Windows registry.

This function modifies the Windows registry to set the CPU priority class
for a specific executable file. It requires administrative privileges.

@param {str} exe_path - Path to the executable file
@param {str} priority_hex - Hexadecimal priority value (e.g., "00000003" for High)
@returns {bool} True if successful, False otherwise
@throws {OSError} When registry operations fail
@throws {PermissionError} When administrative privileges are required
"""
try:
# Open the key for the specified application
key_path = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options"
Expand Down Expand Up @@ -56,11 +80,21 @@ def set_priority_in_registry(exe_path, priority_hex):

from settings import SettingsValue

FEEDBACK_MESSAGE = "Please Check The latest Version. Could You Please Give us a Feedback? Please Donate us 01823170383 (bkash/nagad/whatsapp). লেটেস্ট ভার্সন চেক করুন। অত্যান্ত ব্যয়বহুল এই প্রজেক্টটিকে এগিয়ে নিতে দয়া করে দান করুন"
FEEDBACK_MESSAGE = "Please Check The latest Version. Could You Please Give us a Feedback? Please Donate us 01823170383 (bkash/nagad/whatsapp). লেটেস্ট ভার্সন চেক করুন। অত্যান্ত ব্যয়বহুল এই প্রজেক্টটিকে এগিয়ে নিতে দয়া করে দান করুন"
FEEDBACK_URL = "https://forms.gle/yQk4yesWcuv65Ruw7"

DONATION_REMINDER = "Please Donate Us so that we can Improve it more, 01823170383 (bkash/nagad/whatsapp)"

def check_validity():
"""
Checks application validity and shows feedback reminder.

This function checks if the application should show a feedback/donation
reminder based on the last message shown date. If more than 15 days have
passed, it shows the feedback message and opens the feedback URL.

@returns {bool} True if validity check passes, False if reminder was shown
"""
now_time = date.today()
settings = SettingsValue.load_settings()

Expand Down Expand Up @@ -91,7 +125,17 @@ def check_validity():
return True

import psutil

def isAppOpend():
"""
Checks if the Porda AI application is already running.

This function scans all running processes to check if multiple instances
of the Porda AI application are running. It returns True if more than
2 instances are found.

@returns {bool} True if multiple instances are running, False otherwise
"""
app_name = "PordaAi"
app_count=0
for proc in psutil.process_iter(['pid', 'name']):
Expand All @@ -109,8 +153,14 @@ def isAppOpend():

#==========================================================================================
def PordaAppDir():
"""It located exactly where the app (.exe) is located"""

"""
Gets the directory where the application executable is located.

This function returns the path to the directory containing the application
executable, whether running as a frozen executable or as a Python script.

@returns {str} Path to the application directory
"""
path = ""
if getattr(sys, 'frozen', False):
path = os.path.dirname(sys.executable)
Expand All @@ -120,8 +170,15 @@ def PordaAppDir():
return str(path)

def PordaInternalFileDir():
"""It locates the files which was integrated when executable in py installer, """
"""
Gets the directory containing internal application files.

This function returns the path to the directory containing files that were
integrated when the executable was created with PyInstaller, or the current
script directory when running as a Python script.

@returns {str} Path to the internal files directory
"""
dir_path = ""
if getattr(sys, 'frozen', False):
dir_path = sys._MEIPASS
Expand All @@ -133,6 +190,19 @@ def PordaInternalFileDir():
#============= ================ ========================= ====================== ================ =====

def app_initial_setup():
"""
Performs initial setup for the Porda AI application.

This function creates necessary directories, sets up logging, and determines
which model files to use (external or internal). It handles the complete
initialization process for the application.

@returns {tuple} (CONFIG, WEIGHTS, internal_dir) where:
- CONFIG: Path to the model configuration file
- WEIGHTS: Path to the model weights file
- internal_dir: Path to internal application directory
@throws {Exception} When setup process fails
"""
try:
app_dir = PordaAppDir()
# creating dir for porda ai
Expand Down Expand Up @@ -223,6 +293,16 @@ def app_initial_setup():
return CONFIG , WEIGHTS, internal_dir

def log_setup(app_dir, porda_app_dir_name):
"""
Sets up logging configuration for the application.

This function creates the log directory, sets up logging configuration,
and configures unhandled exception logging. It also manages log file
cleanup to prevent excessive disk usage.

@param {str} app_dir - Application directory path
@param {str} porda_app_dir_name - Name of the Porda AI application directory
"""
# Creating log folder if not exist
log_folder_path = os.path.join(app_dir, porda_app_dir_name, "Error-log")
os.makedirs(log_folder_path, exist_ok=True)
Expand Down Expand Up @@ -258,8 +338,16 @@ def log_unhandled_exception(exc_type, exc_value, exc_traceback):
sys.excepthook = log_unhandled_exception


#This keep last 7 log files
def delete_old_logs_based_on_file_count(log_folder_path, files_to_keep):
"""
Deletes old log files based on file count, keeping the most recent ones.

This function keeps only the specified number of most recent log files
and deletes older ones to manage disk space usage.

@param {str} log_folder_path - Path to the log folder
@param {int} files_to_keep - Number of most recent log files to keep
"""
log_files = [f for f in os.listdir(log_folder_path) if f.startswith("Error_") and f.endswith(".log")]

# Sort log files based on the date in the file name
Expand All @@ -275,8 +363,16 @@ def delete_old_logs_based_on_file_count(log_folder_path, files_to_keep):
except Exception as e:
logging.error(f"Error while deleting old log file: {e}")

#This keeps last files based on date, Delete log files older than 7 days
def delete_old_logs_based_on_date(log_folder_path, days_to_keep):
"""
Deletes log files older than the specified number of days.

This function removes log files that are older than the specified number
of days to manage disk space usage.

@param {str} log_folder_path - Path to the log folder
@param {int} days_to_keep - Number of days to keep log files
"""
today_date = datetime.now()
for file_name in os.listdir(log_folder_path):
file_path = os.path.join(log_folder_path, file_name)
Expand Down
Loading