Skip to content

Commit 3475322

Browse files
committed
Complete APP readme, package release script, final changes
The app tutorial has been written in depth, with accompanying images for illustration. A release script has been written by bundling the source code into a ZIP and generating the EXE using Pyinstaller. And that marks the end of v1!
1 parent d8a164b commit 3475322

32 files changed

+286
-12
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
testing/test_outputs/
33
*.so
44
docs/_*
5-
dist/
5+
dist/
6+
release/

APP.md

+170-6
Large diffs are not rendered by default.

app_images/batch_add_panorama_id.PNG

25.6 KB
Loading

app_images/batch_after_adding.PNG

44.4 KB
Loading

app_images/batch_after_settings.PNG

48 KB
Loading

app_images/batch_blank.PNG

37.9 KB
Loading

app_images/batch_edit.PNG

27.7 KB
Loading

app_images/batch_filled.PNG

65.1 KB
Loading

app_images/batch_finish.PNG

61.9 KB
Loading

app_images/downloading_panorama.PNG

13.8 KB
Loading

app_images/live_blank.PNG

57.4 KB
Loading

app_images/live_filled.PNG

58.8 KB
Loading

app_images/live_fixed_intervals.PNG

30.6 KB
Loading

app_images/live_keybind.PNG

25.7 KB
Loading

app_images/live_log.PNG

133 KB
Loading

app_images/live_start.PNG

95.6 KB
Loading

app_images/panorama_id_blank.PNG

28.3 KB
Loading

app_images/panorama_id_filled.PNG

49.3 KB
Loading
24.9 KB
Loading
29 KB
Loading
531 KB
Loading
590 KB
Loading

app_images/save_panorama.PNG

2.2 MB
Loading

app_images/save_url.PNG

1.28 MB
Loading

app_images/url_blank.PNG

24.9 KB
Loading

app_images/url_filled.PNG

33.2 KB
Loading

package_release.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""Entire release creation - including source code and EXE."""
2+
import os
3+
import pathlib
4+
import shutil
5+
import subprocess
6+
7+
8+
FOLDER = pathlib.Path(__file__).parent
9+
RELEASE_FOLDER = FOLDER / "release"
10+
if RELEASE_FOLDER.is_dir():
11+
shutil.rmtree(RELEASE_FOLDER)
12+
RELEASE_FOLDER.mkdir()
13+
14+
CODE_PACKAGE_FOLDER = RELEASE_FOLDER / "code"
15+
CODE_PACKAGE_ZIP = RELEASE_FOLDER / "code"
16+
17+
ICON = FOLDER / "src" / "gui" / "bin" / "icon.ico"
18+
START_SCRIPT = FOLDER / "run_app.py"
19+
20+
PATHS = (
21+
FOLDER / "src",
22+
FOLDER / "src" / "gui"
23+
)
24+
BINARIES = {
25+
FOLDER / "src" / "gui" / "cpp" / "conversion.so": "src/gui/cpp",
26+
FOLDER / "src" / "gui" / "cpp" / "foreground.so": "src/gui/cpp",
27+
}
28+
ADDITIONAL_DATA = {
29+
FOLDER / "src" / "gui" / "bin": "src/gui/bin/"
30+
}
31+
OUTPUT_EXE_NAME = RELEASE_FOLDER / "streetviewimagedownloader.exe"
32+
33+
34+
def package_code() -> None:
35+
"""Packages source, ready to run."""
36+
CODE_PACKAGE_FOLDER.mkdir()
37+
shutil.copy(START_SCRIPT, CODE_PACKAGE_FOLDER / START_SCRIPT.name)
38+
# Copy source folder.
39+
shutil.copytree(FOLDER / "src", CODE_PACKAGE_FOLDER / "src")
40+
# Delete all pycaches.
41+
for path in (CODE_PACKAGE_FOLDER / "src").rglob("__pycache__"):
42+
shutil.rmtree(path)
43+
# Make zip file.
44+
shutil.make_archive(CODE_PACKAGE_ZIP, "zip", CODE_PACKAGE_FOLDER)
45+
# Delete copied source folder.
46+
shutil.rmtree(CODE_PACKAGE_FOLDER)
47+
48+
49+
def package_exe() -> None:
50+
"""Packages standalone EXE, ready to run."""
51+
# Build command parts.
52+
command_parts = [
53+
"pyinstaller", str(START_SCRIPT), "--noconfirm", "--onefile",
54+
"--windowed", "--icon", str(ICON)]
55+
for binary_src, binary_dest in BINARIES.items():
56+
command_parts.append("--add-binary")
57+
command_parts.append(f"{binary_src};{binary_dest}")
58+
for path in PATHS:
59+
command_parts.append("--paths")
60+
command_parts.append(str(path))
61+
for add_data_src, add_data_dest in ADDITIONAL_DATA.items():
62+
command_parts.append("--add-data")
63+
command_parts.append(f"{add_data_src};{add_data_dest}")
64+
# Run Pyinstaller.
65+
os.chdir(RELEASE_FOLDER)
66+
subprocess.run(command_parts)
67+
# Renames output EXE.
68+
output_exe = RELEASE_FOLDER / "dist" / f"{START_SCRIPT.stem}.exe"
69+
output_exe.rename(OUTPUT_EXE_NAME)
70+
# Deletes Pyinstaller files and folders.
71+
(RELEASE_FOLDER / "dist").rmdir()
72+
shutil.rmtree(RELEASE_FOLDER / "build")
73+
(RELEASE_FOLDER / f"{START_SCRIPT.stem}.spec").unlink(True)
74+
75+
76+
def main() -> None:
77+
package_code()
78+
package_exe()
79+
80+
81+
if __name__ == "__main__":
82+
main()

run_app.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""Runs the Street View Image Download app."""
2+
import pathlib
3+
import sys
4+
5+
6+
if hasattr(sys, "_MEIPASS"):
7+
FOLDER = pathlib.Path(sys._MEIPASS) / "src"
8+
else:
9+
FOLDER = pathlib.Path(__file__).parent / "src"
10+
11+
sys.path.append(str(FOLDER))
12+
sys.path.append(str(FOLDER / "gui"))
13+
14+
from gui.main import main
15+
16+
17+
if __name__ == "__main__":
18+
main()

src/gui/__init__.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
from ctypes import windll
44

55

6-
sys.path.append(str(pathlib.Path(__file__).parent.parent))
7-
sys.path.append(str(pathlib.Path(__file__).parent))
6+
if hasattr(sys, "_MEIPASS"):
7+
sys.path.append(f"{sys._MEIPASS}/src")
8+
else:
9+
sys.path.append(str(pathlib.Path(__file__).parent.parent))
810

911
# Make GUI DPI aware - significant GUI quality improvement.
1012
windll.shcore.SetProcessDpiAwareness(True)

src/gui/_utils.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
"""Utilities for the GUI."""
22
import ctypes
33
import pathlib
4+
import sys
45
import tkinter as tk
56
from tkinter.font import Font
67

78
import pyglet
89

910

10-
BIN_FOLDER = pathlib.Path(__file__).parent / "bin"
11-
CPP_FOLDER = pathlib.Path(__file__).parent / "cpp"
11+
if hasattr(sys, "_MEIPASS"):
12+
GUI_FOLDER = pathlib.Path(sys._MEIPASS) / "src" / "gui"
13+
else:
14+
GUI_FOLDER = pathlib.Path(__file__).parent
15+
BIN_FOLDER = GUI_FOLDER / "bin"
16+
CPP_FOLDER = GUI_FOLDER / "cpp"
1217
CPP_FOREGROUND_PID_LIBRARY = CPP_FOLDER / "foreground.so"
1318
CPP_CONVERSION_LIBRARY = CPP_FOLDER / "conversion.so"
1419

1520
# Load Inter font downloaded online.
1621
pyglet.font.add_file(str(BIN_FOLDER / "Inter.ttf"))
22+
ICON_FILE = BIN_FOLDER / "icon.ico"
1723

1824

1925
RED = "#ff0000"

src/gui/bin/icon.ico

4.19 KB
Binary file not shown.

src/gui/main.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import panorama_id
1010
import rendering
1111
import url
12-
from _utils import inter, BUTTON_COLOURS, bool_to_state
12+
from _utils import inter, BUTTON_COLOURS, bool_to_state, ICON_FILE
1313

1414

1515
TITLE = "Street View Image Downloader"
@@ -100,6 +100,7 @@ def __init__(self, master: MainMenu) -> None:
100100
def main() -> None:
101101
"""Main procedure of the program."""
102102
root = tk.Tk()
103+
root.iconbitmap(ICON_FILE)
103104
main_menu = MainMenu(root)
104105
main_menu.pack()
105106
root.mainloop()

0 commit comments

Comments
 (0)