Project reorganization to use with fbs

This commit is contained in:
adrienmalin 2018-09-28 15:11:21 +02:00
parent 1a308f456a
commit 67b48eeb0b
63 changed files with 316 additions and 213 deletions

5
.gitignore vendored
View File

@ -18,8 +18,7 @@ lib/
lib64/ lib64/
parts/ parts/
sdist/ sdist/
Tetris2000.build/ target/
Tetris2000.build/
var/ var/
wheels/ wheels/
*.egg-info/ *.egg-info/
@ -31,7 +30,7 @@ MANIFEST
# Usually these files are written by a python script from a template # Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it. # before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest *.manifest
#*.spec *.spec
# Installer logs # Installer logs
pip-log.txt pip-log.txt

View File

@ -1,22 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Another TETRIS® clone
Tetris Game Design by Alexey Pajitnov.
Parts of comments issued from 2009 Tetris Design Guideline
"""
import sys
from qtpy import QtWidgets
from source.game_gui import Window
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
win.frames.new_game()
sys.exit(app.exec_())

View File

@ -1,43 +0,0 @@
# -*- mode: python -*-
block_cipher = None
a = Analysis(['TETRIS2000.py'],
pathex=[],
binaries=[],
datas=[
("backgrounds/*", "backgrounds"),
("fonts/*.ttf", "fonts"),
("fonts/*.otf", "fonts"),
("icons/*.ico", "icons"),
("icons/splash_screen.png", "icons"),
("locale/*.qm", "locale"),
("musics/*.mp3", "musics"),
("sfx/*.wav", "sfx")
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=["PyQt4", "PySide", "PySide2"],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='TETRIS2000',
debug=False,
strip=False,
upx=False,
console=False,
icon='icons\icon.ico')
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=False,
name='TETRIS2000')

101
src/main/NSIS/Installer.nsi Normal file
View File

@ -0,0 +1,101 @@
!include MUI2.nsh
!include FileFunc.nsh
;--------------------------------
;Perform Machine-level install, if possible
!define MULTIUSER_EXECUTIONLEVEL Highest
;Add support for command-line args that let uninstaller know whether to
;uninstall machine- or user installation:
!define MULTIUSER_INSTALLMODE_COMMANDLINE
!include MultiUser.nsh
!include LogicLib.nsh
Function .onInit
!insertmacro MULTIUSER_INIT
;Do not use InstallDir at all so we can detect empty $InstDir!
${If} $InstDir == "" ; /D not used
${If} $MultiUser.InstallMode == "AllUsers"
StrCpy $InstDir "$PROGRAMFILES\%{app_name}"
${Else}
StrCpy $InstDir "$LOCALAPPDATA\%{app_name}"
${EndIf}
${EndIf}
FunctionEnd
Function un.onInit
!insertmacro MULTIUSER_UNINIT
FunctionEnd
;--------------------------------
;General
Name "%{app_name}"
OutFile "..\%{app_name}Setup.exe"
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
;--------------------------------
;Pages
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of %{app_name}.$\r$\n$\r$\n$\r$\nClick Next to continue."
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_CHECKED
!define MUI_FINISHPAGE_RUN_TEXT "Run %{app_name}"
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
;Installer Sections
!define UNINST_KEY \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\%{app_name}"
Section
SetOutPath "$InstDir"
File /r "..\%{app_name}\*"
WriteRegStr SHCTX "Software\%{app_name}" "" $InstDir
WriteUninstaller "$InstDir\uninstall.exe"
CreateShortCut "$SMPROGRAMS\%{app_name}.lnk" "$InstDir\%{app_name}.exe"
WriteRegStr SHCTX "${UNINST_KEY}" "DisplayName" "%{app_name}"
WriteRegStr SHCTX "${UNINST_KEY}" "UninstallString" \
"$\"$InstDir\uninstall.exe$\" /$MultiUser.InstallMode"
WriteRegStr SHCTX "${UNINST_KEY}" "QuietUninstallString" \
"$\"$InstDir\uninstall.exe$\" /$MultiUser.InstallMode /S"
WriteRegStr SHCTX "${UNINST_KEY}" "Publisher" "%{author}"
${GetSize} "$InstDir" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
WriteRegDWORD SHCTX "${UNINST_KEY}" "EstimatedSize" "$0"
SectionEnd
;--------------------------------
;Uninstaller Section
Section "Uninstall"
RMDir /r "$InstDir"
Delete "$SMPROGRAMS\%{app_name}.lnk"
DeleteRegKey /ifempty SHCTX "Software\%{app_name}"
DeleteRegKey SHCTX "${UNINST_KEY}"
SectionEnd
Function LaunchLink
!addplugindir "."
ShellExecAsUser::ShellExecAsUser "open" "$SMPROGRAMS\%{app_name}.lnk"
FunctionEnd

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

11
src/main/icons/README.md Normal file
View File

@ -0,0 +1,11 @@
![Sample app icon](linux/128.png)
This directory contains the icons that are displayed for your app. Feel free to
change them.
The difference between the icons on Mac and the other platforms is that on Mac,
they contain a ~5% transparent margin. This is because otherwise they look too
big (eg. in the Dock or in the app switcher).
You can create Icon.ico from the .png files with
[an online tool](http://icoconvert.com/Multi_Image_to_one_icon/).

View File

Before

Width:  |  Height:  |  Size: 183 B

After

Width:  |  Height:  |  Size: 183 B

View File

Before

Width:  |  Height:  |  Size: 802 B

After

Width:  |  Height:  |  Size: 802 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/main/icons/linux/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

BIN
src/main/icons/linux/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

BIN
src/main/icons/linux/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/main/icons/mac/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

BIN
src/main/icons/mac/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

BIN
src/main/icons/mac/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -3,30 +3,27 @@
import os import os
from qtpy import QtGui from PyQt5 import QtGui
# Paths # Paths
PATH = os.path.dirname(os.path.abspath(__file__)) ICON_PATH = "icons/icon.ico"
PATH = os.path.dirname(PATH) BG_IMAGE_DIR = "backgrounds"
ICON_PATH = os.path.join(PATH, "icons", "icon.ico") START_BG_IMAGE_PATH = os.path.join(BG_IMAGE_DIR, "01-spacefield_a-000.png")
BG_IMAGE_DIR = os.path.join(PATH, "backgrounds") MUSICS_DIR = "musics"
START_BG_IMAGE_NAME = "01-spacefield_a-000.png" SFX_DIR = "sfx"
MUSICS_DIR = os.path.join(PATH, "musics")
SFX_DIR = os.path.join(PATH, "sfx")
LINE_CLEAR_SFX_PATH = os.path.join(SFX_DIR, "line_clear.wav") LINE_CLEAR_SFX_PATH = os.path.join(SFX_DIR, "line_clear.wav")
TETRIS_SFX_PATH = os.path.join(SFX_DIR, "tetris.wav") TETRIS_SFX_PATH = os.path.join(SFX_DIR, "tetris.wav")
ROTATE_SFX_PATH = os.path.join(SFX_DIR, "rotate.wav") ROTATE_SFX_PATH = os.path.join(SFX_DIR, "rotate.wav")
HARD_DROP_SFX_PATH = os.path.join(SFX_DIR, "hard_drop.wav") HARD_DROP_SFX_PATH = os.path.join(SFX_DIR, "hard_drop.wav")
WALL_SFX_PATH = os.path.join(SFX_DIR, "wall.wav") WALL_SFX_PATH = os.path.join(SFX_DIR, "wall.wav")
LOCALE_PATH = os.path.join(PATH, "locale") LOCALE_PATH = "locale"
FONTS_DIR = os.path.join(PATH, "fonts") FONTS_DIR = "fonts"
STATS_FONT_PATH = os.path.join(FONTS_DIR, "PixelCaps!.otf") STATS_FONT_PATH = os.path.join(FONTS_DIR, "PixelCaps!.otf")
STATS_FONT_NAME = "PixelCaps!" STATS_FONT_NAME = "PixelCaps!"
MATRIX_FONT_PATH = os.path.join(FONTS_DIR, "maass slicer Italic.ttf") MATRIX_FONT_PATH = os.path.join(FONTS_DIR, "maass slicer Italic.ttf")
MATRIX_FONT_NAME = "Maassslicer" MATRIX_FONT_NAME = "Maassslicer"
SPLASH_SCREEN_PATH = "splashscreen/splashscreen.png"
SPLASH_SCREEN_PATH = os.path.join(PATH, "icons", "splash_screen.png")
# Coordinates and direction # Coordinates and direction
L, R, U, D = -1, 1, -1, 1 # Left, Right, Up, Down L, R, U, D = -1, 1, -1, 1 # Left, Right, Up, Down

View File

@ -7,13 +7,14 @@ import itertools
import locale import locale
import os import os
import time import time
from qtpy import QtWidgets, QtCore, QtGui, QtMultimedia from PyQt5 import QtWidgets, QtCore, QtGui, QtMultimedia
QtCore.Signal = QtCore.pyqtSignal
from . import consts import consts
from .consts import L, R, CLOCKWISE, COUNTERCLOCKWISE from consts import L, R, CLOCKWISE, COUNTERCLOCKWISE
from .__version__ import __title__, __author__, __version__ from __version__ import __title__, __author__, __version__
from .point import Point from point import Point
from .tetromino import Block, Tetromino, GhostPiece from tetromino import Block, Tetromino, GhostPiece
class Grid(QtWidgets.QWidget): class Grid(QtWidgets.QWidget):
@ -92,10 +93,10 @@ class Matrix(Grid):
drop_signal = QtCore.Signal(int) drop_signal = QtCore.Signal(int)
lock_signal = QtCore.Signal(int, str) lock_signal = QtCore.Signal(int, str)
def __init__(self, frames): def __init__(self, frames, app):
super().__init__(frames) super().__init__(frames)
self.load_sfx() self.load_sfx(app)
self.game_over = False self.game_over = False
self.text = "" self.text = ""
@ -112,17 +113,17 @@ class Matrix(Grid):
self.cells = [] self.cells = []
def load_sfx(self): def load_sfx(self, app):
self.wall_sfx = QtMultimedia.QSoundEffect(self) self.wall_sfx = QtMultimedia.QSoundEffect(self)
url = QtCore.QUrl.fromLocalFile(consts.WALL_SFX_PATH) url = QtCore.QUrl.fromLocalFile(app.get_resource(consts.WALL_SFX_PATH))
self.wall_sfx.setSource(url) self.wall_sfx.setSource(url)
self.rotate_sfx = QtMultimedia.QSoundEffect(self) self.rotate_sfx = QtMultimedia.QSoundEffect(self)
url = QtCore.QUrl.fromLocalFile(consts.ROTATE_SFX_PATH) url = QtCore.QUrl.fromLocalFile(app.get_resource(consts.ROTATE_SFX_PATH))
self.rotate_sfx.setSource(url) self.rotate_sfx.setSource(url)
self.hard_drop_sfx = QtMultimedia.QSoundEffect(self) self.hard_drop_sfx = QtMultimedia.QSoundEffect(self)
url = QtCore.QUrl.fromLocalFile(consts.HARD_DROP_SFX_PATH) url = QtCore.QUrl.fromLocalFile(app.get_resource(consts.HARD_DROP_SFX_PATH))
self.hard_drop_sfx.setSource(url) self.hard_drop_sfx.setSource(url)
def new_game(self): def new_game(self):
@ -551,12 +552,12 @@ class Stats(QtWidgets.QWidget):
temporary_text = QtCore.Signal(str) temporary_text = QtCore.Signal(str)
def __init__(self, frames): def __init__(self, frames, app):
super().__init__(frames) super().__init__(frames)
self.frames = frames self.frames = frames
self.setStyleSheet("background-color: transparent") self.setStyleSheet("background-color: transparent")
self.load_sfx() self.load_sfx(app)
self.setSizePolicy( self.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
@ -569,13 +570,13 @@ class Stats(QtWidgets.QWidget):
self.high_score = int(qsettings.value(self.tr("High score"), 0)) self.high_score = int(qsettings.value(self.tr("High score"), 0))
def load_sfx(self): def load_sfx(self, app):
self.line_clear_sfx = QtMultimedia.QSoundEffect(self) self.line_clear_sfx = QtMultimedia.QSoundEffect(self)
url = QtCore.QUrl.fromLocalFile(consts.LINE_CLEAR_SFX_PATH) url = QtCore.QUrl.fromLocalFile(app.get_resource(consts.LINE_CLEAR_SFX_PATH))
self.line_clear_sfx.setSource(url) self.line_clear_sfx.setSource(url)
self.tetris_sfx = QtMultimedia.QSoundEffect(self) self.tetris_sfx = QtMultimedia.QSoundEffect(self)
url = QtCore.QUrl.fromLocalFile(consts.TETRIS_SFX_PATH) url = QtCore.QUrl.fromLocalFile(app.get_resource(consts.TETRIS_SFX_PATH))
self.tetris_sfx.setSource(url) self.tetris_sfx.setSource(url)
def new_game(self): def new_game(self):
@ -790,8 +791,9 @@ class Frames(QtWidgets.QWidget):
Manage interactions between them. Manage interactions between them.
""" """
def __init__(self, parent): def __init__(self, parent, app):
super().__init__(parent) super().__init__(parent)
self.app = app
self.setSizePolicy( self.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
) )
@ -801,9 +803,9 @@ class Frames(QtWidgets.QWidget):
self.load_music() self.load_music()
self.hold_queue = HoldQueue(self) self.hold_queue = HoldQueue(self)
self.matrix = Matrix(self) self.matrix = Matrix(self, app)
self.next_piece = Grid(self) self.next_piece = Grid(self)
self.stats = Stats(self) self.stats = Stats(self, app)
self.next_queue = NextQueue(self) self.next_queue = NextQueue(self)
self.matrices = (self.hold_queue, self.matrix, self.next_piece) self.matrices = (self.hold_queue, self.matrix, self.next_piece)
@ -852,7 +854,7 @@ class Frames(QtWidgets.QWidget):
self.matrix.lock_signal.connect(self.stats.update_score) self.matrix.lock_signal.connect(self.stats.update_score)
self.bg_image = QtGui.QImage( self.bg_image = QtGui.QImage(
os.path.join(consts.BG_IMAGE_DIR, consts.START_BG_IMAGE_NAME) os.path.join(app.get_resource(consts.START_BG_IMAGE_PATH))
) )
self.resize_bg_image() self.resize_bg_image()
@ -860,8 +862,9 @@ class Frames(QtWidgets.QWidget):
def load_music(self): def load_music(self):
playlist = QtMultimedia.QMediaPlaylist(self) playlist = QtMultimedia.QMediaPlaylist(self)
for entry in os.scandir(consts.MUSICS_DIR): MUSICS_DIR = self.app.get_resource(consts.MUSICS_DIR)
path = os.path.join(consts.MUSICS_DIR, entry.name) for entry in os.scandir(MUSICS_DIR):
path = os.path.join(MUSICS_DIR, entry.name)
url = QtCore.QUrl.fromLocalFile(path) url = QtCore.QUrl.fromLocalFile(path)
music = QtMultimedia.QMediaContent(url) music = QtMultimedia.QMediaContent(url)
playlist.addMedia(music) playlist.addMedia(music)
@ -901,9 +904,10 @@ class Frames(QtWidgets.QWidget):
self.resize_bg_image() self.resize_bg_image()
def reset_backgrounds(self): def reset_backgrounds(self):
BG_IMAGE_DIR = self.app.get_resource(consts.BG_IMAGE_DIR)
backgrounds = tuple( backgrounds = tuple(
QtGui.QImage((os.path.join(consts.BG_IMAGE_DIR, entry.name))) QtGui.QImage((os.path.join(BG_IMAGE_DIR, entry.name)))
for entry in os.scandir(consts.BG_IMAGE_DIR) for entry in os.scandir(BG_IMAGE_DIR)
) )
self.backgrounds_cycle = itertools.cycle(backgrounds) self.backgrounds_cycle = itertools.cycle(backgrounds)
@ -1223,21 +1227,21 @@ class SettingsDialog(QtWidgets.QDialog):
class Window(QtWidgets.QMainWindow): class Window(QtWidgets.QMainWindow):
""" Main window """ """ Main window """
def __init__(self): def __init__(self, app):
splash_screen = QtWidgets.QSplashScreen( splash_screen = QtWidgets.QSplashScreen(
QtGui.QPixmap(consts.SPLASH_SCREEN_PATH) QtGui.QPixmap(app.get_resource(consts.SPLASH_SCREEN_PATH))
) )
splash_screen.show() splash_screen.show()
self.set_locale()
self.load_settings()
super().__init__() super().__init__()
self.setWindowTitle(__title__.upper()) self.setWindowTitle(__title__.upper())
self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowIcon(QtGui.QIcon(consts.ICON_PATH)) self.set_locale(app)
self.load_settings()
self.setWindowIcon(app.app_icon)
# Windows' taskbar icon # Windows' taskbar icon
try: try:
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
@ -1252,16 +1256,14 @@ class Window(QtWidgets.QMainWindow):
except ImportError: except ImportError:
pass pass
else: else:
os.environ['QT_API'] = 'pyqt5'
self.setStyleSheet(qdarkstyle.load_stylesheet_from_environment()) self.setStyleSheet(qdarkstyle.load_stylesheet_from_environment())
for font_path in consts.STATS_FONT_PATH, consts.MATRIX_FONT_PATH: for font_path in consts.STATS_FONT_PATH, consts.MATRIX_FONT_PATH:
QtGui.QFontDatabase.addApplicationFont(font_path) QtGui.QFontDatabase.addApplicationFont(app.get_resource(font_path))
self.frames = Frames(self) self.frames = Frames(self, app)
self.setCentralWidget(self.frames) self.setCentralWidget(self.frames)
self.hold_queue = self.frames.hold_queue
self.matrix = self.frames.matrix
self.stats = self.frames.stats
self.menu = self.menuBar() self.menu = self.menuBar()
@ -1278,24 +1280,28 @@ class Window(QtWidgets.QMainWindow):
splash_screen.finish(self) splash_screen.finish(self)
def set_locale(self): def show(self):
app = QtWidgets.QApplication.instance() super().show()
self.frames.new_game()
def set_locale(self, app):
qapp = QtWidgets.QApplication.instance()
# Set appropriate thounsand separator characters # Set appropriate thounsand separator characters
locale.setlocale(locale.LC_ALL, "") locale.setlocale(locale.LC_ALL, "")
# Qt # Qt
language = QtCore.QLocale.system().name()[:2] language = QtCore.QLocale.system().name()[:2]
qt_translator = QtCore.QTranslator(app) qt_translator = QtCore.QTranslator(qapp)
qt_translation_path = QtCore.QLibraryInfo.location( qt_translation_path = QtCore.QLibraryInfo.location(
QtCore.QLibraryInfo.TranslationsPath QtCore.QLibraryInfo.TranslationsPath
) )
if qt_translator.load("qt_" + language, qt_translation_path): if qt_translator.load("qt_" + language, qt_translation_path):
app.installTranslator(qt_translator) qapp.installTranslator(qt_translator)
tetris2000_translator = QtCore.QTranslator(app) tetris2000_translator = QtCore.QTranslator(qapp)
if tetris2000_translator.load(language, consts.LOCALE_PATH): if tetris2000_translator.load(language, app.get_resource(consts.LOCALE_PATH)):
app.installTranslator(tetris2000_translator) qapp.installTranslator(tetris2000_translator)
def load_settings(self): def load_settings(self):
global s global s
@ -1517,7 +1523,7 @@ Sound effects made with voc-one by Simple-Media"""
self.frames.music.stop() self.frames.music.stop()
# Save settings # Save settings
qsettings.setValue(self.tr("High score"), self.stats.high_score) qsettings.setValue(self.tr("High score"), self.frames.stats.high_score)
qsettings.setValue("WindowGeometry", self.saveGeometry()) qsettings.setValue("WindowGeometry", self.saveGeometry())
qsettings.setValue("WindowState", int(self.windowState())) qsettings.setValue("WindowState", int(self.windowState()))

25
src/main/python/main.py Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Another TETRIS® clone
Tetris Game Design by Alexey Pajitnov.
Parts of comments issued from 2009 Tetris Design Guideline
"""
from fbs_runtime.application_context import ApplicationContext
from game_gui import Window
import sys
class AppContext(ApplicationContext): # 1. Subclass ApplicationContext
def run(self): # 2. Implement run()
win = Window(self)
win.show()
return self.app.exec_() # 3. End run() with this line
if __name__ == '__main__':
appctxt = AppContext() # 4. Instantiate the subclass
exit_code = appctxt.run() # 5. Invoke run()
sys.exit(exit_code)

View File

@ -2,9 +2,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from qtpy import QtCore from PyQt5 import QtCore
from .consts import CLOCKWISE from consts import CLOCKWISE
class Point(QtCore.QPoint): class Point(QtCore.QPoint):

View File

@ -3,11 +3,11 @@
import random import random
from qtpy import QtCore, QtGui from PyQt5 import QtCore, QtGui
from . import consts import consts
from .consts import L, R, U, D, CLOCKWISE, COUNTERCLOCKWISE from consts import L, R, U, D, CLOCKWISE, COUNTERCLOCKWISE
from .point import Point from point import Point
class Block: class Block:

View File

Before

Width:  |  Height:  |  Size: 444 KiB

After

Width:  |  Height:  |  Size: 444 KiB

View File

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 291 KiB

View File

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View File

Before

Width:  |  Height:  |  Size: 945 KiB

After

Width:  |  Height:  |  Size: 945 KiB

View File

Before

Width:  |  Height:  |  Size: 456 KiB

After

Width:  |  Height:  |  Size: 456 KiB

View File

Before

Width:  |  Height:  |  Size: 549 KiB

After

Width:  |  Height:  |  Size: 549 KiB

View File

Before

Width:  |  Height:  |  Size: 754 KiB

After

Width:  |  Height:  |  Size: 754 KiB

View File

Before

Width:  |  Height:  |  Size: 642 KiB

After

Width:  |  Height:  |  Size: 642 KiB

View File

Before

Width:  |  Height:  |  Size: 377 KiB

After

Width:  |  Height:  |  Size: 377 KiB

View File

Before

Width:  |  Height:  |  Size: 526 KiB

After

Width:  |  Height:  |  Size: 526 KiB

View File

Before

Width:  |  Height:  |  Size: 669 KiB

After

Width:  |  Height:  |  Size: 669 KiB

View File

Before

Width:  |  Height:  |  Size: 597 KiB

After

Width:  |  Height:  |  Size: 597 KiB

View File

Before

Width:  |  Height:  |  Size: 800 KiB

After

Width:  |  Height:  |  Size: 800 KiB

View File

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 416 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>${app_name}</string>
<key>CFBundleDisplayName</key>
<string>${app_name}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
<string>Icon.icns</string>
<key>CFBundleIdentifier</key>
<string>${mac_bundle_identifier}</string>
<key>LSBackgroundOnly</key>
<string>0</string>
<key>CFBundleShortVersionString</key>
<string>${version}</string>
<key>CFBundleVersion</key>
<string>${version}</string>
<key>CFBundleName</key>
<string>${app_name}</string>
<!-- Enable Retina support on OS X: -->
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB