feat: Add ProBackup.exe executable for Windows XP distribution.
This commit is contained in:
Binary file not shown.
@@ -4,6 +4,7 @@ import subprocess
|
||||
import platform
|
||||
import os
|
||||
import base64
|
||||
import sys
|
||||
|
||||
# Simple Secret Salt - In a real app, obfuscate this or use asymmetric keys (RSA)
|
||||
# For this level, a symmetric secret is "good enough" for basic protection.
|
||||
@@ -14,6 +15,35 @@ CREATE_NO_WINDOW = 0x08000000
|
||||
|
||||
class LicenseManager:
|
||||
@staticmethod
|
||||
def _get_base_dir():
|
||||
if getattr(sys, 'frozen', False):
|
||||
return os.path.dirname(sys.executable)
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
@staticmethod
|
||||
def _get_license_path():
|
||||
return os.path.join(LicenseManager._get_base_dir(), "license.dat")
|
||||
|
||||
@staticmethod
|
||||
def save_license(key):
|
||||
try:
|
||||
with open(LicenseManager._get_license_path(), "w") as f:
|
||||
f.write(key.strip())
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def load_license():
|
||||
path = LicenseManager._get_license_path()
|
||||
if not os.path.exists(path):
|
||||
return None
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
return f.read().strip()
|
||||
except:
|
||||
return None
|
||||
@staticmethod
|
||||
def get_motherboard_id():
|
||||
"""Gets the motherboard UUID using WMIC (Windows only)."""
|
||||
try:
|
||||
|
||||
24
main.py
24
main.py
@@ -278,8 +278,11 @@ class BackupApp(QMainWindow):
|
||||
|
||||
# Ensure sql_tools folder exists
|
||||
self.ensure_sql_tools_folder()
|
||||
self.settings = self.load_settings()
|
||||
self.trial_limit = 10 # Max uses in trial mode
|
||||
|
||||
self.load_settings()
|
||||
# Job Queue System
|
||||
self.job_queue = []
|
||||
|
||||
if self.trial_mode:
|
||||
# Check if strict limit reached immediately
|
||||
@@ -1308,9 +1311,9 @@ class BackupApp(QMainWindow):
|
||||
def scheduled_backup_wrapper(self, job_id):
|
||||
# Determine if we can run
|
||||
if self.worker and self.worker.isRunning():
|
||||
# Concurrent jobs? For now let's skip or queue?
|
||||
# Simple approach: Skip if busy.
|
||||
self.log(">>> Jadwal Skip (App Sibuk) untuk Job ID: {}".format(job_id))
|
||||
# Concurrent jobs? Queue them!
|
||||
self.log(">>> App Sibuk. Job ID {} masuk antrian.".format(job_id))
|
||||
self.job_queue.append(job_id)
|
||||
return
|
||||
|
||||
# --- Check Trial Limit ---
|
||||
@@ -1370,6 +1373,13 @@ class BackupApp(QMainWindow):
|
||||
if hasattr(self, 'run_single_btn'):
|
||||
self.run_single_btn.setEnabled(True)
|
||||
self.log(">>> Eksekusi Selesai.")
|
||||
|
||||
# Check Queue
|
||||
if self.job_queue:
|
||||
next_job_id = self.job_queue.pop(0)
|
||||
self.log(">>> Memproses antrian: Job ID {}".format(next_job_id))
|
||||
# Use QTimer to schedule it on main thread to be safe, though we are likely already on main thread slot
|
||||
QTimer.singleShot(100, lambda: self.scheduled_backup_wrapper(next_job_id))
|
||||
|
||||
def processing_error(self, error_msg):
|
||||
self.run_all_btn.setEnabled(True)
|
||||
@@ -1378,6 +1388,12 @@ class BackupApp(QMainWindow):
|
||||
if hasattr(self, 'run_single_btn'):
|
||||
self.run_single_btn.setEnabled(True)
|
||||
self.log("!!! Kesalahan Thread: {}".format(error_msg))
|
||||
|
||||
# Check Queue even on error
|
||||
if self.job_queue:
|
||||
next_job_id = self.job_queue.pop(0)
|
||||
self.log(">>> Memproses antrian (setelah error): Job ID {}".format(next_job_id))
|
||||
QTimer.singleShot(100, lambda: self.scheduled_backup_wrapper(next_job_id))
|
||||
|
||||
# --- Tray ---
|
||||
def setup_tray(self):
|
||||
|
||||
Reference in New Issue
Block a user