diff --git a/.gitignore b/.gitignore index f414fc8..4d9c1b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +app.ini +debug.ini + .venv-* __pycache__/ *.py[cod] diff --git a/_freeze.py b/_freeze.py new file mode 100644 index 0000000..1b2d77c --- /dev/null +++ b/_freeze.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# FIXME: Get py2exe working for Windows builds (since it produces a single EXE). + +import sys +from cx_Freeze import setup , Executable + +from constants import * + +# --------------------------------------------------------------------- + +# initialize +extra_files = [ + "resources/app.ico" +] +build_options = { + "packages": [ "os" ] , + "excludes": [ "tkinter" ] , + "include_files": extra_files , +} + +# freeze the application +# FIXME! set the app icon +target = Executable( + "main.py" , + base = "Win32GUI" if sys.platform == "win32" else None , + targetName = "asl_cards.exe" if sys.platform == "win32" else "asl_cards" , +) +setup( + name = APP_NAME , + version = APP_VERSION , + description = APP_DESCRIPTION , + options = { + APP_NAME: build_options + } , + executables = [ target ] +) diff --git a/constants.py b/constants.py new file mode 100755 index 0000000..db47598 --- /dev/null +++ b/constants.py @@ -0,0 +1,11 @@ +APP_VENDOR = "Pacman Ghost" +APP_HOME_URL = "https://github.com/pacman-ghost" +APP_NAME = "ASL Cards" +APP_VERSION = "v0.1" +APP_DESCRIPTION = "ASL Cards viewer." + +# settings file +MAINWINDOW_POSITION = "MainWindow/position" +MAINWINDOW_SIZE = "MainWindow/size" +# +CONFIRM_EXIT = "Settings/ConfirmExit" diff --git a/freeze.sh b/freeze.sh new file mode 100755 index 0000000..833eb0f --- /dev/null +++ b/freeze.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# initialize +BASE_DIR=$(readlink -f "`dirname "$0"`") +RELEASE_FILENAME="/tmp/asl_cards.tar.gz" + +# freeze the application +cd "$BASE_DIR" +rm -rf build +python _freeze.py build +if [ $? -ne 0 ] ; then + echo "ERROR: Freeze failed." + exit $? +fi + +# create the release +cd build/exe.linux-x86_64-3.6 +tar cfz "$RELEASE_FILENAME" . +echo +echo "Created release:" +ls -lh "$RELEASE_FILENAME" | sed -e "s/^/ /" + +# clean up +rm -rf "$BASE_DIR/build" diff --git a/globals.py b/globals.py new file mode 100644 index 0000000..c8e2207 --- /dev/null +++ b/globals.py @@ -0,0 +1,7 @@ +# who we are, and where we live +base_dir = None +app_name = None + +# application settings +app_settings = None +debug_settings = None diff --git a/main.py b/main.py new file mode 100755 index 0000000..4784017 --- /dev/null +++ b/main.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import sys +import os +import getopt + +from PyQt5.QtCore import QSettings , QDir +from PyQt5.QtWidgets import QApplication + +from constants import * +import globals + +# --------------------------------------------------------------------- + +def do_main( args ) : + + # initialize + QApplication.setOrganizationName( APP_VENDOR ) + QApplication.setOrganizationDomain( APP_HOME_URL ) + QApplication.setApplicationName( APP_NAME ) + + # initialize + globals.base_dir , app_name = os.path.split( + os.path.abspath( sys.executable if hasattr(sys,"frozen") else __file__ ) + ) + globals.app_name = os.path.splitext( app_name )[ 0 ] + + # parse the command-line arguments + settings_fname = None + opts , args = getopt.getopt( args[1:] , "c:h?" , ["config=","help"] ) + for opt,val in opts : + if opt in ["-c","--config"] : + settings_fname = val + elif opt in ["-h","--help","-?"] : + print_help() + else : + raise RuntimeError( "Unknown argument: {}".format( opt ) ) + if not settings_fname : + # try to locate the settings file + settings_fname = os.path.join( globals.base_dir , globals.app_name+".ini" ) + if not os.path.isfile( settings_fname ) : + settings_fname = os.path.split(settings_fname)[ 1 ] + if sys.platform != "win32" : + settings_fname = "." + settings_fname + settings_fname = os.path.join( QDir.homePath() , settings_fname ) + + # load our settings + globals.app_settings = QSettings( settings_fname , QSettings.IniFormat ) + fname = os.path.join( os.path.split(settings_fname)[0] , "debug.ini" ) + globals.debug_settings = QSettings( fname , QSettings.IniFormat ) + + # do main processing + app = QApplication( sys.argv ) + import main_window + main_window = main_window.MainWindow() + main_window.show() + return app.exec_() + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +def print_help() : + print( "{} {{options}}".format( os.path.split(sys.argv[0])[1] ) ) # FIXME! frozen? + print( " {}".format( APP_DESCRIPTION ) ) + print() + print( " -c --config Config file." ) + sys.exit() + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +if __name__ == "__main__" : + sys.exit( do_main( sys.argv ) ) diff --git a/main_window.py b/main_window.py new file mode 100755 index 0000000..fd94b03 --- /dev/null +++ b/main_window.py @@ -0,0 +1,44 @@ +import sys +import os + +from PyQt5.QtCore import Qt , QPoint , QSize +from PyQt5.QtWidgets import QMainWindow +from PyQt5.QtWidgets import QMessageBox +from PyQt5.QtGui import QIcon + +from constants import * +import globals + +# --------------------------------------------------------------------- + +class MainWindow( QMainWindow ) : + + def __init__( self ) : + super().__init__() + # initialize the window + self.setWindowTitle( APP_NAME ) + self.setWindowIcon( QIcon("resources/app.ico") ) + # load the window settings + self.resize( globals.app_settings.value( MAINWINDOW_SIZE , QSize(500,300) ) ) + self.move( globals.app_settings.value( MAINWINDOW_POSITION , QPoint(200,200) ) ) + + def closeEvent( self , evt ) : + """Handle window close.""" + # confirm the close + if globals.app_settings.value( CONFIRM_EXIT , True , type=bool ) : + rc = QMessageBox.question( self , "Confirm close" , + "Do you want to the close the program?" , + QMessageBox.Ok | QMessageBox.Cancel , + QMessageBox.Cancel + ) + if rc != QMessageBox.Ok : + evt.ignore() + # save the window settings + # FIXME! handle fullscreen + globals.app_settings.setValue( MAINWINDOW_POSITION , self.pos() ) + globals.app_settings.setValue( MAINWINDOW_SIZE , self.size() ) + + def keyPressEvent( self , evt ) : + """Handle key-presses.""" + if evt.key() == Qt.Key_Escape and globals.debug_settings.value("Debug/AllowEscapeToClose",type=bool) : + self.close() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ccccc6f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +# python == 3.6.1 + +# NOTE: There are additional requirements for the asl_cards module (see its requirements.txt). +PyQt5 == 5.8.2 +cx-Freeze == 5.0.1 diff --git a/resources/app.ico b/resources/app.ico new file mode 100755 index 0000000..c3e3649 Binary files /dev/null and b/resources/app.ico differ