Init
This commit is contained in:
parent
5a846d328d
commit
cdd0e4070d
15 changed files with 864 additions and 0 deletions
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
config.json
|
||||
__pycache__/
|
||||
update/
|
||||
build/
|
||||
*.spec
|
||||
*.bin
|
||||
*.build
|
||||
dist
|
||||
data/config.json
|
||||
*.dist
|
||||
*.onefile-build
|
||||
downloaded_files/
|
||||
my_app_github/
|
||||
my_app_gitlab/
|
||||
data-backup/
|
3
build.bat
Executable file
3
build.bat
Executable file
|
@ -0,0 +1,3 @@
|
|||
nuitka3 ./src/main.py --clean-cache=all --onefile --run --output-dir=./build --enable-plugin=tk-inter
|
||||
:: --clean-cache=all --disable-console --windows-icon-from-ico=./data/icon.ico
|
||||
pause
|
2
build.sh
Executable file
2
build.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
nuitka3 ./src/main.py --linux-onefile-icon=./data/icon.png --onefile --output-dir=./build --run
|
||||
#--disable-console --linux-icon=./data/icon.png --output-dir=./build --clean-cache=all #--include-plugin-directory=./src/ --run --disable-console --linux-icon=./data/icon.png --output-dir=./build #--clean-cache=all --recompile-c-only #--windows-icon-from-ico=./data/icon.ico --disable-console --linux-icon=./data/icon.png --onefile --output-dir=./build
|
34
dwnld.sh
Executable file
34
dwnld.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
display_usage() {
|
||||
echo "Downloads all of a SourceForge project's files."
|
||||
echo -e "\nUsage: ./sourceforge-file-download.sh [project name]\n"
|
||||
}
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
display_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
project=$1
|
||||
echo "Downloading $project's files"
|
||||
|
||||
# download all the pages on which direct download links are
|
||||
# be nice, sleep a second
|
||||
wget -w 1 -np -m -A download https://sourceforge.net/projects/$project/files/
|
||||
|
||||
# find the files (ignore "latest" link, that should be included as another URL already)
|
||||
find sourceforge.net/ | sed "s#.*${project}/files/##" | grep download$ | grep -v "latest/download" | sed -e "s#^#https://master.dl.sourceforge.net/project/${project}/#" -e "s#/download#?viasf=1#" > urllist
|
||||
|
||||
# download each of the extracted URLs, put into $projectname/
|
||||
while read url; do wget --content-disposition -x -nH --cut-dirs=1 "${url}"; done < urllist
|
||||
|
||||
# remove ?viasf=1 suffix
|
||||
find . -name '*?viasf=1' -print0 | xargs -0 rename --verbose "?viasf=1" ""
|
||||
|
||||
# remove temporary files, unless you want to keep them for some reason
|
||||
rm -ri sourceforge.net/
|
||||
rm -i urllist
|
||||
|
29
install-linux.sh
Executable file
29
install-linux.sh
Executable file
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
# This script installs required dependencies on Linux
|
||||
|
||||
# Update package lists and install Python3
|
||||
sudo apt update -y
|
||||
sudo apt install python3 -y
|
||||
|
||||
# Install Python3 pip
|
||||
sudo apt install python3-pip -y
|
||||
|
||||
# Install GTK4 package
|
||||
sudo apt install libgtk-4-dev -y
|
||||
|
||||
# Install PatchELF for Nuitka (if needed)
|
||||
sudo apt install patchelf -y
|
||||
|
||||
# Install Nuitka
|
||||
pip3 install nuitka
|
||||
|
||||
# Install additional Python packages
|
||||
pip3 install requests
|
||||
sudo apt install libgirepository1.0-dev -y
|
||||
sudo apt install python3-cairo-dev -y
|
||||
pip3 install PyGObject # Install PyGObject for Gtk support
|
||||
pip3 install pillow # Install Pillow for image manipulation
|
||||
pip3 install setuptools # Install setuptools for packaging
|
||||
|
||||
# Install ccache for faster re-compiling
|
||||
sudo apt install ccache -y
|
13
install-windows.txt
Executable file
13
install-windows.txt
Executable file
|
@ -0,0 +1,13 @@
|
|||
# install msys2
|
||||
|
||||
# update msys2
|
||||
|
||||
# install python && pip in msys2
|
||||
|
||||
# install GTK4 according to GTK website
|
||||
|
||||
# install nuitka (in msys2)
|
||||
|
||||
# add python (usually: C:\msys2\bin) to system variable PATH
|
||||
|
||||
# restart computer, and if done well you should be able to build and run this app
|
3
run.bat
Normal file
3
run.bat
Normal file
|
@ -0,0 +1,3 @@
|
|||
python3 ./src/main.py
|
||||
:: --clean-cache=all --disable-console --windows-icon-from-ico=./data/icon.ico
|
||||
pause
|
1
run.sh
Executable file
1
run.sh
Executable file
|
@ -0,0 +1 @@
|
|||
python3 ./src/main.py
|
29
src/donwload_sourceforege.py
Normal file
29
src/donwload_sourceforege.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
# not exactly ideal solution
|
||||
|
||||
def download_from_sourceforge(api_url, file_path):
|
||||
response = requests.get(api_url, stream=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
total_size = int(response.headers.get('content-length', 0))
|
||||
block_size = 1024 # 1 KB
|
||||
progress_bar = tqdm(total=total_size, unit='B', unit_scale=True)
|
||||
|
||||
with open(file_path, 'wb') as file:
|
||||
for data in response.iter_content(block_size):
|
||||
progress_bar.update(len(data))
|
||||
file.write(data)
|
||||
|
||||
progress_bar.close()
|
||||
|
||||
print("Download completed successfully.")
|
||||
else:
|
||||
print(f"Failed to download. Status code: {response.status_code}")
|
||||
|
||||
# Example usage with the provided link
|
||||
sourceforge_api_url = "https://downloads.sourceforge.net/project/sevenzip/7-Zip/19.00/7z1900-x64.exe"
|
||||
download_path = "7z1900-x64.exe"
|
||||
|
||||
download_from_sourceforge(sourceforge_api_url, download_path)
|
80
src/download_github.py
Normal file
80
src/download_github.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
import os
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
def fetch_release_version(url):
|
||||
try:
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
return response.json()['tag_name']
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching release version: {str(e)}")
|
||||
return None
|
||||
|
||||
def download_from_github(url, destination, progress_bar, version):
|
||||
# Get the latest release information
|
||||
api_url = f"{url}/releases/latest"
|
||||
response = requests.get(api_url)
|
||||
response.raise_for_status()
|
||||
release_info = response.json()
|
||||
|
||||
latest_version = release_info["tag_name"]
|
||||
|
||||
# Check if the latest version is different from the current version
|
||||
if latest_version != version:
|
||||
# Get the asset URL for the first asset in the release (you may modify this based on your needs)
|
||||
asset_url = release_info["assets"][0]["browser_download_url"]
|
||||
|
||||
# Download the asset with a progress bar
|
||||
response = requests.get(asset_url, stream=True)
|
||||
response.raise_for_status()
|
||||
|
||||
# Calculate the total file size for the progress bar
|
||||
total_size = int(response.headers.get('content-length', 0))
|
||||
|
||||
# Create the destination directory if it doesn't exist
|
||||
os.makedirs(destination, exist_ok=True)
|
||||
|
||||
# Define the file path for the downloaded asset
|
||||
file_path = os.path.join(destination, os.path.basename(asset_url))
|
||||
|
||||
with open(file_path, 'wb') as file, tqdm(
|
||||
desc="Downloading",
|
||||
total=total_size,
|
||||
unit="B",
|
||||
unit_scale=True,
|
||||
unit_divisor=1024,
|
||||
disable=not progress_bar,
|
||||
) as bar:
|
||||
for data in response.iter_content(chunk_size=1024):
|
||||
bar.update(len(data))
|
||||
file.write(data)
|
||||
|
||||
print("Download complete.")
|
||||
return latest_version
|
||||
else:
|
||||
print("You already have the latest version.")
|
||||
return version
|
||||
|
||||
def download_from_url(url, destination, progress_bar, version):
|
||||
if "github.com" in url:
|
||||
return download_from_github(url, destination, progress_bar, version)
|
||||
elif "sourceforge.net" in url:
|
||||
return download_from_sourceforge(url, destination, progress_bar)
|
||||
elif "gitlab.com" in url:
|
||||
return download_from_gitlab(url, destination, progress_bar)
|
||||
elif "gitea.com" in url:
|
||||
return download_from_gitea(url, destination, progress_bar)
|
||||
else:
|
||||
print("Unsupported platform")
|
||||
return None
|
||||
|
||||
#######################
|
||||
|
||||
# # Example usage:
|
||||
# github_url = "https://api.github.com/repos/emoacht/Monitorian"
|
||||
# destination_folder = "./downloaded_files"
|
||||
# current_version = "v1.0.0"
|
||||
|
||||
# new_version = download_from_github(github_url, destination_folder, True, current_version)
|
||||
# print(f"Updated to version: {new_version}")
|
119
src/download_gitlab.py
Normal file
119
src/download_gitlab.py
Normal file
|
@ -0,0 +1,119 @@
|
|||
import requests
|
||||
from tqdm import tqdm
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
def download_release_from_gitlab(api_url, project_id, token, destination, progress_bar, version):
|
||||
# Get the latest release information
|
||||
response = requests.get(f"{api_url}/projects/{project_id}/releases", headers={"PRIVATE-TOKEN": token})
|
||||
response.raise_for_status()
|
||||
|
||||
releases = response.json()
|
||||
|
||||
# Check if there are any releases
|
||||
if not releases:
|
||||
return None
|
||||
|
||||
# Assuming releases are sorted by creation date, so the latest release is the first one
|
||||
latest_release = releases[0]
|
||||
latest_version = latest_release["tag_name"]
|
||||
|
||||
# Check if the latest version is different from the current version
|
||||
if latest_version != version:
|
||||
# Get the asset URL for the first asset in the release (you may modify this based on your needs)
|
||||
asset_url = latest_release["assets"]["sources"][0]["url"]
|
||||
|
||||
# Download the asset with a progress bar
|
||||
response = requests.get(asset_url, stream=True, headers={"PRIVATE-TOKEN": token})
|
||||
response.raise_for_status()
|
||||
|
||||
# Calculate the total file size for the progress bar
|
||||
total_size = int(response.headers.get('content-length', 0))
|
||||
|
||||
# Create the destination directory if it doesn't exist
|
||||
os.makedirs(destination, exist_ok=True)
|
||||
|
||||
# Define the file path for the downloaded asset
|
||||
file_path = os.path.join(destination, os.path.basename(asset_url))
|
||||
|
||||
with open(file_path, 'wb') as file, tqdm(
|
||||
desc="Downloading",
|
||||
total=total_size,
|
||||
unit="B",
|
||||
unit_scale=True,
|
||||
unit_divisor=1024,
|
||||
disable=not progress_bar,
|
||||
) as bar:
|
||||
for data in response.iter_content(chunk_size=1024):
|
||||
bar.update(len(data))
|
||||
file.write(data)
|
||||
|
||||
print("Download complete.")
|
||||
return latest_version
|
||||
else:
|
||||
print("You already have the latest version.")
|
||||
return version
|
||||
|
||||
def download_source_from_gitlab(api_url, project_id, token, destination, progress_bar):
|
||||
# Construct the source code repository URL based on the project ID
|
||||
repository_url = f"{api_url}/projects/{project_id}/repository/archive.zip"
|
||||
|
||||
# Download the source code as a ZIP file
|
||||
response = requests.get(repository_url, stream=True, headers={"PRIVATE-TOKEN": token})
|
||||
response.raise_for_status()
|
||||
|
||||
# Create the destination directory if it doesn't exist
|
||||
os.makedirs(destination, exist_ok=True)
|
||||
|
||||
# Define the file path for the downloaded ZIP file
|
||||
zip_file_path = os.path.join(destination, "source_code.zip")
|
||||
|
||||
with open(zip_file_path, 'wb') as file, tqdm(
|
||||
desc="Downloading Source Code",
|
||||
unit="B",
|
||||
unit_scale=True,
|
||||
unit_divisor=1024,
|
||||
disable=not progress_bar,
|
||||
) as bar:
|
||||
for data in response.iter_content(chunk_size=1024):
|
||||
bar.update(len(data))
|
||||
file.write(data)
|
||||
|
||||
print("Download complete.")
|
||||
|
||||
# Extract the ZIP file
|
||||
extract_folder = os.path.join(destination, "source_code")
|
||||
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(extract_folder)
|
||||
|
||||
# Remove the ZIP file
|
||||
os.remove(zip_file_path)
|
||||
|
||||
return extract_folder
|
||||
|
||||
def download_and_update(api_url, project_id, private_token, destination_folder, progress_bar, current_version):
|
||||
try:
|
||||
new_version = download_release_from_gitlab(api_url, project_id, private_token, destination_folder, progress_bar, current_version)
|
||||
if new_version:
|
||||
print(f"Updated to version: {new_version}")
|
||||
else:
|
||||
print("No releases found. Downloading source code instead.")
|
||||
source_code_folder = download_source_from_gitlab(api_url, project_id, private_token, destination_folder, progress_bar)
|
||||
print(f"Source code downloaded to: {source_code_folder}")
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if e.response.status_code == 404:
|
||||
print("No releases found. Downloading source code instead.")
|
||||
source_code_folder = download_source_from_gitlab(api_url, project_id, private_token, destination_folder, progress_bar)
|
||||
print(f"Source code downloaded to: {source_code_folder}")
|
||||
else:
|
||||
raise # Re-raise the exception if it's not a 404 error
|
||||
|
||||
# #######################################
|
||||
# # Example usage:
|
||||
# gitlab_api_url = "https://gitlab.com/api/v4"
|
||||
# project_id = 5774889 # Use the project ID directly
|
||||
# private_token = "" # No private token needed for public projects
|
||||
# destination_folder = "./downloaded_files"
|
||||
# current_version = "v1.0.0"
|
||||
|
||||
# download_and_update(gitlab_api_url, project_id, private_token, destination_folder, True, current_version)
|
71
src/download_main.py
Normal file
71
src/download_main.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
import os
|
||||
from tqdm import tqdm # You might need to install this package using pip if not already installed
|
||||
|
||||
import json
|
||||
import json_main
|
||||
import download_gitlab
|
||||
import download_github
|
||||
|
||||
data_location = "./data/"
|
||||
|
||||
# Ensure that the directory structure exists, once again
|
||||
if not os.path.exists(data_location):
|
||||
os.makedirs(data_location)
|
||||
|
||||
# Check if config.json exists and create it with default values if not
|
||||
if not os.path.isfile(data_location+"config.json"):
|
||||
default_data = {
|
||||
"first_run": "false",
|
||||
"packages": []
|
||||
}
|
||||
with open(data_location+"config.json", "w") as json_file:
|
||||
json.dump(default_data, json_file, indent=4)
|
||||
|
||||
# Placeholder functions for SourceForge and Gitea
|
||||
def download_from_sourceforge(url, destination, progress_bar, version):
|
||||
# Placeholder function for downloading from SourceForge
|
||||
print("Sourceforge not supported yet")
|
||||
|
||||
def download_from_gitea(api_url, project_id, token, destination, progress_bar, version):
|
||||
# Placeholder function for downloading from Gitea
|
||||
print("Gita not supported, yet")
|
||||
|
||||
# Function to install all packages
|
||||
def install_all_packages(progress_bar, progress_label):
|
||||
try:
|
||||
with open(data_location+"config.json", 'r') as file:
|
||||
data = json.load(file)
|
||||
packages = data.get("packages", [])
|
||||
total_packages = len(packages)
|
||||
|
||||
for index, package in enumerate(packages, start=1):
|
||||
app_name, app_data = package.popitem()
|
||||
source_info = app_data.get("source", {})
|
||||
source_type = source_info.get("source_type", "")
|
||||
version = app_data.get("version", "")
|
||||
|
||||
try:
|
||||
progress_label.set_text(f"Downloading {app_name}")
|
||||
progress_value = index / total_packages/2
|
||||
progress_bar.set_fraction(progress_value)
|
||||
|
||||
if source_type == "github":
|
||||
download_github.download_from_github(source_info["github_url"], app_name, tqdm, version)
|
||||
elif source_type == "gitlab":
|
||||
download_gitlab.download_and_update(source_info["gitlab_api_url"], source_info["project_id"],
|
||||
source_info["private_token"], app_name, tqdm, version)
|
||||
# Add other source types as needed
|
||||
else:
|
||||
progress_label.set_text(f"Unsupported source type for {app_name}: {source_type}")
|
||||
print(f"Unsupported source type for {app_name}: {source_type}")
|
||||
except Exception as e:
|
||||
progress_label.set_text(f"Error processing {app_name}: {e}")
|
||||
print(f"Error processing {app_name}: {e}")
|
||||
except FileNotFoundError:
|
||||
progress_label.set_text(f"Config file not found.")
|
||||
print("Config file not found.")
|
||||
|
||||
|
||||
# Check if the script is executed directly
|
||||
if __name__ == "__main__":
|
||||
install_all_packages()
|
212
src/gui_main.py
Normal file
212
src/gui_main.py
Normal file
|
@ -0,0 +1,212 @@
|
|||
import gi
|
||||
gi.require_version('Gtk', '4.0')
|
||||
from gi.repository import Gtk, Gio, GLib, GdkPixbuf
|
||||
import threading
|
||||
|
||||
import download_main
|
||||
|
||||
number_of_tabs = 4
|
||||
|
||||
class InstallerGUI:
|
||||
def __init__(self):
|
||||
self.app = Gtk.Application(application_id="org.example.customizableapp",
|
||||
flags=Gio.ApplicationFlags.FLAGS_NONE)
|
||||
self.app.connect("activate", self.activate)
|
||||
|
||||
def run(self):
|
||||
self.app.run()
|
||||
|
||||
def activate(self, app):
|
||||
app_window = MainWindow(application=app)
|
||||
app_window.present()
|
||||
|
||||
class UpdaterGUI(Gtk.Box):
|
||||
def __init__(self):
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
||||
|
||||
# Create a progress bar and a label
|
||||
self.progress_bar = Gtk.ProgressBar()
|
||||
self.progress_label = Gtk.Label()
|
||||
|
||||
# # Set up the layout
|
||||
# logo_path = "./data/icon.png"
|
||||
# logo_pixbuf = GdkPixbuf.Pixbuf.new_from_file(logo_path)
|
||||
# logo_image = Gtk.Image.new_from_pixbuf(logo_pixbuf)
|
||||
|
||||
# self.append(logo_image)
|
||||
self.append(self.progress_bar)
|
||||
self.append(self.progress_label)
|
||||
|
||||
# Connect to the "realize" signal to run the function when the widget becomes visible
|
||||
self.connect("realize", self.on_realize)
|
||||
|
||||
def on_realize(self, widget):
|
||||
# Run the install_all_packages function in a separate thread when the widget becomes visible
|
||||
threading.Thread(target=self.run_installation).start()
|
||||
|
||||
def run_installation(self):
|
||||
# Pass the progress bar and label to the install_all_packages function
|
||||
download_main.install_all_packages(self.progress_bar, self.progress_label)
|
||||
# Glib.idle_add() ?
|
||||
|
||||
|
||||
class CustomizationTab(Gtk.Box):
|
||||
def __init__(self, button_box):
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
self.create_ui(button_box)
|
||||
|
||||
def create_ui(self, button_box):
|
||||
# Add elements for customization tab in the future
|
||||
|
||||
# Add back and next buttons at the bottom
|
||||
self.bottom_buttons(button_box)
|
||||
|
||||
def bottom_buttons(self, button_box):
|
||||
self.append(Gtk.Box(hexpand=True, vexpand=True)) # Expandable empty box to push buttons to the bottom
|
||||
self.append(button_box)
|
||||
|
||||
class MainWindow(Gtk.ApplicationWindow):
|
||||
def __init__(self, application, **kwargs):
|
||||
super().__init__(application=application, **kwargs)
|
||||
|
||||
# # Set Adwaita theme
|
||||
# settings = Gtk.Settings.get_default()
|
||||
# settings.set_property("gtk-application-prefer-dark-theme", True)
|
||||
# settings.set_property("gtk-theme-name", "Adwaita")
|
||||
|
||||
self.set_default_size(600, 400)
|
||||
self.set_title("Spitfire Installer Nightly")
|
||||
|
||||
self.child_names = ["Main", "Customization", "Tab 2", "Tab 3", "Tab 4","UpdaterGUI"]
|
||||
|
||||
self.stack = Gtk.Stack(transition_type=Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
||||
self.stack.set_transition_duration(1000) # Set the duration of the transition in milliseconds
|
||||
|
||||
# Create a HeaderBar
|
||||
header_bar = Gtk.HeaderBar()
|
||||
header_bar.set_show_title_buttons(True)
|
||||
self.set_titlebar(header_bar)
|
||||
|
||||
# First tab
|
||||
self.add_first_tab()
|
||||
|
||||
# Second tab (Customization tab)
|
||||
button_box = self.create_button_box(0)
|
||||
self.customization_tab = CustomizationTab(button_box)
|
||||
self.stack.add_titled(self.customization_tab, "Customization", "Customization")
|
||||
|
||||
# Third to Fifth tabs (empty for now)
|
||||
for i in range(3):
|
||||
self.add_tab(i + 1)
|
||||
|
||||
# Last tab (Installer tab)
|
||||
self.updater_tab = UpdaterGUI()
|
||||
self.stack.add_titled(self.updater_tab, "UpdaterGUI", "UpdaterGUI")
|
||||
|
||||
self.set_child(self.stack)
|
||||
|
||||
self.show()
|
||||
|
||||
def create_button_box(self, current_tab):
|
||||
button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
|
||||
left_button = Gtk.Button(label="Back")
|
||||
left_button.connect("clicked", self.on_back_clicked)
|
||||
|
||||
right_button = Gtk.Button(label="Next")
|
||||
right_button.connect("clicked", self.on_next_clicked)
|
||||
|
||||
label = Gtk.Label(label=f"{current_tab + 1} / {number_of_tabs}") # Display current tab number
|
||||
label.set_halign(Gtk.Align.CENTER) # Center-align the label
|
||||
|
||||
# Add an empty box to act as a flexible space
|
||||
button_box.append(Gtk.Box(hexpand=True))
|
||||
|
||||
# Add left button, label, and right button to the button box
|
||||
button_box.append(left_button)
|
||||
button_box.append(label)
|
||||
button_box.append(right_button)
|
||||
|
||||
return button_box
|
||||
|
||||
def add_first_tab(self):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
self.stack.add_titled(box, "Main", "Main")
|
||||
|
||||
label = Gtk.Label(label=f"\nThis is an experimental (Nightly) build.")
|
||||
box.append(label)
|
||||
|
||||
empty_space = Gtk.Box(vexpand=True)
|
||||
box.append(empty_space) # Expandable empty box to push buttons to the bottom
|
||||
|
||||
skip_button = Gtk.Button(label="Install")
|
||||
skip_button.connect("clicked", self.on_skip_clicked)
|
||||
box.append(skip_button) # Use append to add child widgets
|
||||
|
||||
customize_button = Gtk.Button(label="Customize")
|
||||
customize_button.connect("clicked", self.on_next_clicked)
|
||||
box.append(customize_button) # Use append to add child widget
|
||||
|
||||
empty_space = Gtk.Box(vexpand=True)
|
||||
box.append(empty_space) # Expandable empty box to push buttons to the bottom
|
||||
|
||||
def add_tab(self, current_tab):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
self.stack.add_titled(box, f"Tab {current_tab + 1}", f"Tab {current_tab + 1}")
|
||||
|
||||
# Add back and next buttons at the bottom
|
||||
self.bottom_buttons(box, current_tab)
|
||||
|
||||
def bottom_buttons(self, box, current_tab):
|
||||
button_box = self.create_button_box(current_tab)
|
||||
box.append(Gtk.Box(hexpand=True, vexpand=True)) # Expandable empty box to push buttons to the bottom
|
||||
box.append(button_box)
|
||||
|
||||
def on_skip_clicked(self, button):
|
||||
current_page_name = "UpdaterGUI"
|
||||
current_page_index = self.child_names.index(current_page_name)
|
||||
next_page_index = number_of_tabs+1
|
||||
|
||||
if next_page_index < len(self.child_names):
|
||||
next_page_name = self.child_names[next_page_index]
|
||||
next_page = self.stack.get_child_by_name(next_page_name)
|
||||
self.stack.set_visible_child(next_page)
|
||||
|
||||
def on_next_clicked(self, button):
|
||||
current_page_name = self.stack.get_visible_child_name()
|
||||
current_page_index = self.child_names.index(current_page_name)
|
||||
next_page_index = current_page_index + 1
|
||||
|
||||
if next_page_index < len(self.child_names):
|
||||
next_page_name = self.child_names[next_page_index]
|
||||
next_page = self.stack.get_child_by_name(next_page_name)
|
||||
self.stack.set_visible_child(next_page)
|
||||
|
||||
def on_back_clicked(self, button):
|
||||
current_page_name = self.stack.get_visible_child_name()
|
||||
current_page_index = self.child_names.index(current_page_name)
|
||||
prev_page_index = current_page_index - 1
|
||||
|
||||
if prev_page_index >= 0:
|
||||
prev_page_name = self.child_names[prev_page_index]
|
||||
prev_page = self.stack.get_child_by_name(prev_page_name)
|
||||
self.stack.set_visible_child(prev_page)
|
||||
|
||||
def update_logo_and_title(self, page_name):
|
||||
# Update title label text
|
||||
self.title_label.set_label(page_name)
|
||||
|
||||
# Update logo image based on the page name
|
||||
logo_path = f"./data/{page_name.lower()}_icon.png" # Assuming you have different icons for each page
|
||||
logo_pixbuf = GdkPixbuf.Pixbuf.new_from_file(logo_path)
|
||||
self.logo_and_title_box.get_children()[0].set_from_pixbuf(logo_pixbuf)
|
||||
|
||||
# Make the MainWindow class callable as a function
|
||||
def run_installer():
|
||||
app = Gtk.Application(application_id="org.example.customizableapp",
|
||||
flags=Gio.ApplicationFlags.FLAGS_NONE)
|
||||
app.connect("activate", lambda app: MainWindow(application=app))
|
||||
app.run()
|
||||
|
||||
# # Run the installer when this script is executed directly
|
||||
# if __name__ == "__main__":
|
||||
# run_installer()
|
110
src/json_main.py
Normal file
110
src/json_main.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
data_location = "./data/config.json"
|
||||
|
||||
def save_first_run(var):
|
||||
with open(data_location, "r") as json_file:
|
||||
data = json.load(json_file)
|
||||
data["first_run"] = var
|
||||
with open(data_location, "w") as json_file:
|
||||
json.dump(data, json_file, indent=4)
|
||||
|
||||
|
||||
def get_first_run():
|
||||
with open(data_location, "r") as json_file:
|
||||
data = json.load(json_file)
|
||||
return data["first_run"]
|
||||
|
||||
# Save variable app to .json file with version, source, and source_type as variables
|
||||
def save_package(version, app, source_type, source_info, package_type):
|
||||
try:
|
||||
with open(data_location, 'r') as file:
|
||||
data = json.load(file)
|
||||
except FileNotFoundError:
|
||||
# If the file doesn't exist, create an empty dictionary
|
||||
data = {"packages": []}
|
||||
|
||||
# Create or update the category for the given app
|
||||
app_data = {
|
||||
"version": version,
|
||||
"source": {
|
||||
"source_type": source_type,
|
||||
**source_info
|
||||
},
|
||||
"state": "not installed",
|
||||
"type": package_type
|
||||
}
|
||||
|
||||
data["packages"].append({app: app_data})
|
||||
|
||||
with open(data_location, 'w') as file:
|
||||
json.dump(data, file, indent=2)
|
||||
|
||||
# This function will get the package information for the given app.
|
||||
# If the app is not in .json, return an empty dictionary.
|
||||
def get_package(app):
|
||||
try:
|
||||
with open(data_location, 'r') as file:
|
||||
data = json.load(file)
|
||||
for package in data.get("packages", []):
|
||||
if app in package:
|
||||
return package[app]
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
# ######################
|
||||
# # save package test
|
||||
|
||||
# # Example usage:
|
||||
# # Define source information for GitHub
|
||||
# github_source_info = {
|
||||
# "github_url": "https://api.github.com/repos/emoacht/Monitorian"
|
||||
# }
|
||||
|
||||
# # Define source information for GitLab
|
||||
# gitlab_source_info = {
|
||||
# "gitlab_api_url": "https://gitlab.com/api/v4",
|
||||
# "project_id": 5774889,
|
||||
# "private_token": "" # No private token needed for public projects
|
||||
# }
|
||||
|
||||
# # Define source information for Gitea
|
||||
# gitea_source_info = {
|
||||
# # Add gitea-specific information here
|
||||
# }
|
||||
|
||||
# # Define source information for SourceForge
|
||||
# sourceforge_source_info = {
|
||||
# # Add sourceforge-specific information here
|
||||
# }
|
||||
|
||||
# # Save package information for GitHub
|
||||
# save_package("1.0", "my_app_github", "github", github_source_info, "addon")
|
||||
|
||||
# # Save package information for GitLab
|
||||
# save_package("1.0", "my_app_gitlab", "gitlab", gitlab_source_info, "skin")
|
||||
|
||||
# # Save package information for Gitea
|
||||
# save_package("1.0", "my_app_gitea", "gitea", gitea_source_info, "config")
|
||||
|
||||
# # Save package information for SourceForge
|
||||
# save_package("1.0", "my_app_sourceforge", "sourceforge", sourceforge_source_info, "panel")
|
||||
|
||||
|
||||
# #########################
|
||||
# # get package test
|
||||
|
||||
# # Get package information for GitHub
|
||||
# package_info = get_package("my_app_github")
|
||||
|
||||
# # Example of accessing package information
|
||||
# if package_info:
|
||||
# print(f"Your package version is: {package_info['version']}")
|
||||
# print(f"Your package source type is: {package_info['source']['source_type']}")
|
||||
# print(f"Your package state is: {package_info['state']}")
|
||||
# print(f"Your package type is: {package_info['type']}")
|
||||
# else:
|
||||
# print("Package not found.")
|
143
src/main.py
Normal file
143
src/main.py
Normal file
|
@ -0,0 +1,143 @@
|
|||
import sys
|
||||
|
||||
if sys.platform == 'win32':
|
||||
import os
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from urllib.request import urlopen
|
||||
import zipfile
|
||||
import certifi
|
||||
import ssl
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
def get_temp_folder():
|
||||
# Get the current user's temporary directory
|
||||
temp_dir = tempfile.gettempdir()
|
||||
|
||||
# Create a subdirectory inside the temporary directory
|
||||
user_temp_folder = os.path.join(temp_dir, 'my_temp_folder')
|
||||
|
||||
# Create the directory if it doesn't exist
|
||||
if not os.path.exists(user_temp_folder):
|
||||
os.makedirs(user_temp_folder)
|
||||
|
||||
return user_temp_folder
|
||||
|
||||
def download_file(url, destination, progress_callback=None):
|
||||
context = ssl.create_default_context(cafile=certifi.where())
|
||||
|
||||
with urlopen(url, context=context) as response, open(destination, 'wb') as out_file:
|
||||
total_size = int(response.headers.get('content-length', 0))
|
||||
block_size = 1024
|
||||
current_size = 0
|
||||
while True:
|
||||
buffer = response.read(block_size)
|
||||
if not buffer:
|
||||
break
|
||||
out_file.write(buffer)
|
||||
current_size += len(buffer)
|
||||
if progress_callback:
|
||||
progress_callback(current_size, total_size)
|
||||
|
||||
def extract_zip(zip_file, extract_path):
|
||||
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
|
||||
zip_ref.extractall(extract_path)
|
||||
|
||||
def download_gtk_dlls(download_path, dll_url, dll_files, progress_callback=None):
|
||||
|
||||
for dll_file in dll_files:
|
||||
file_url = dll_url + dll_file
|
||||
|
||||
# Check if the file already exists, if not, download it
|
||||
if not os.path.exists(os.path.join(download_path, dll_file)):
|
||||
download_file(file_url, os.path.join(download_path, dll_file), progress_callback)
|
||||
|
||||
# Check if the downloaded file is a zip file, extract it, and remove the zip file
|
||||
if dll_file.endswith('.zip'):
|
||||
extract_path = os.path.join(download_path, dll_file.replace('.zip', ''))
|
||||
extract_zip(os.path.join(download_path, dll_file), extract_path)
|
||||
os.remove(os.path.join(download_path, dll_file))
|
||||
|
||||
def set_path_variable(download_path):
|
||||
|
||||
current = subprocess.run("echo %Path%", stdout=subprocess.PIPE, shell=True, text=True)
|
||||
|
||||
output_string = str(current.stdout).strip() + ';' + download_path
|
||||
|
||||
# Split the output_string into individual elements
|
||||
elements = output_string.split(';')
|
||||
|
||||
# Remove duplicates
|
||||
unique_elements = list(set(elements))
|
||||
|
||||
# Join the unique elements back together
|
||||
output_string_unique = ';'.join(unique_elements)
|
||||
|
||||
# Refresh the system environment variables
|
||||
subprocess.run("SETX Path " + output_string_unique, shell=True)
|
||||
|
||||
print(f"Added PATH: {output_string_unique}")
|
||||
|
||||
def main():
|
||||
# Skips entier program if is a different system than windows
|
||||
if sys.platform != 'win32':
|
||||
from gui_main import run_installer
|
||||
run_installer()
|
||||
return
|
||||
|
||||
# Replace this with the desired download path
|
||||
download_path = get_temp_folder()
|
||||
|
||||
dll_url = 'https://downloads.sourceforge.net/project/spitfire-browser/nightly/components/GTK4/'
|
||||
|
||||
# Check if all required files are already present
|
||||
dll_files = [
|
||||
'libs.zip'
|
||||
# Add more files as needed
|
||||
]
|
||||
|
||||
all_files_exist = all(os.path.exists(os.path.join(download_path, filename)) for filename in dll_files)
|
||||
|
||||
if not all_files_exist:
|
||||
# Create a simple GUI window if files are not present
|
||||
root = tk.Tk()
|
||||
root.title("Preparing for first start")
|
||||
root.geometry("300x100")
|
||||
|
||||
progress_var = tk.DoubleVar()
|
||||
progress = ttk.Progressbar(root, variable=progress_var, length=200)
|
||||
progress.grid(row=0, column=0, padx=20, pady=20)
|
||||
|
||||
def update_progress_bar(current_size, total_size):
|
||||
progress_value = (current_size / total_size) * 100
|
||||
progress_var.set(progress_value)
|
||||
root.update_idletasks()
|
||||
|
||||
def start_download():
|
||||
# Download GTK4 DLLs if they are not already present
|
||||
download_gtk_dlls(download_path, dll_url, dll_files, update_progress_bar)
|
||||
|
||||
# Set PATH variable and refresh environment variables
|
||||
if sys.platform == 'win32':
|
||||
set_path_variable(download_path)
|
||||
|
||||
# Destroy the GUI window
|
||||
root.destroy()
|
||||
|
||||
# Run your main application function
|
||||
from gui_main import run_installer
|
||||
run_installer()
|
||||
|
||||
# Schedule the start_download function to run after 100 milliseconds
|
||||
root.after(100, start_download)
|
||||
|
||||
# Start the Tkinter event loop
|
||||
root.mainloop()
|
||||
else:
|
||||
# Run installer directly if all files are present
|
||||
from gui_main import run_installer
|
||||
run_installer()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in a new issue