mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
Compare commits
14 commits
2983648a4c
...
dc86d9338d
Author | SHA1 | Date | |
---|---|---|---|
|
dc86d9338d | ||
|
12ca8c5535 | ||
|
6016a6a5c1 | ||
|
300d5dca7a | ||
|
0d98da15e6 | ||
|
e5e60d3232 | ||
|
f5b1cf0eea | ||
|
a34e169031 | ||
|
e09efe375e | ||
|
1365523131 | ||
|
864e7b9b52 | ||
|
25f1b222a1 | ||
|
ad79d2429f | ||
|
11aff68af1 |
17 changed files with 129 additions and 43 deletions
|
@ -37,11 +37,16 @@ test_script:
|
|||
- appveyor DownloadFile https://sourceforge.net/projects/pysolfc/files/PySol-Music/PySol-Music-4.50/pysol-music-4.50.tar.xz/download -FileName music.tar.xz
|
||||
- 7z x music.tar.xz -so | 7z x -si -ttar
|
||||
- move pysol-music-4.50\data\music dist\data\music
|
||||
- ps: |
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$project = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/shlomif/fc-solve"
|
||||
$jobId = $project.build.jobs[0].jobId
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/fc-solve/pkg-build/fc-solve-for-pysol.zip" -OutFile fc-solve.zip
|
||||
# - ps: |
|
||||
# $apiUrl = 'https://ci.appveyor.com/api'
|
||||
# $project = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/shlomif/fc-solve"
|
||||
# $jobId = $project.build.jobs[0].jobId
|
||||
# Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/fc-solve/pkg-build/fc-solve-for-pysol.zip" -OutFile fc-solve.zip
|
||||
#
|
||||
# For reproducible builds:
|
||||
# See: https://reproducible-builds.org/ .
|
||||
- SET FC_SOLVE_VER=5.20.0
|
||||
- appveyor DownloadFile https://netix.dl.sourceforge.net/project/fc-solve/fc-solve/DO-NOT-USE--fc-solve-for-pysol/fc-solve-for-pysol--v%FC_SOLVE_VER%.zip -FileName fc-solve.zip
|
||||
- 7z x fc-solve.zip
|
||||
- move fcs-pysol dist\freecell-solver
|
||||
- 7z a -r pysol_win_dist.7z dist\
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
[[news]]
|
||||
=== News
|
||||
|
||||
* _TODO, 2020:_ There is a new stable release
|
||||
https://sourceforge.net/projects/pysolfc/files/PySolFC/PySolFC-2.8.0/[PySolFC
|
||||
v2.8.0]. New in this release:
|
||||
** Better kivy/Android support
|
||||
** Using ttk and configobj as shipped in the python dist (instead of forked versions)
|
||||
** Requiring https://pypi.org/project/attrs/[attrs] and https://pypi.org/project/pysol-cards/[pysol-cards] from PyPI
|
||||
** Added tests, bug fixes and refactorings.
|
||||
** Add the +-g+ and +--deal+ command line options.
|
||||
* _25 April, 2019:_ There is a new stable release
|
||||
https://sourceforge.net/projects/pysolfc/files/PySolFC/PySolFC-2.6.4/[PySolFC
|
||||
v2.6.4]. New in this release:
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
Prerequisites (needs root):
|
||||
|
||||
(For updated information on these subjects please consult the scripts in
|
||||
android/debian).
|
||||
|
||||
On a 'freshly installed' Ubuntu 16.04 (32bit), the following
|
||||
additional packages had to be installed:
|
||||
|
||||
|
|
|
@ -18,3 +18,17 @@ apt-get install -y \
|
|||
lld
|
||||
|
||||
update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
|
||||
|
||||
apt-get install -y --no-install-recommends \
|
||||
imagemagick \
|
||||
python3-tk \
|
||||
ccache \
|
||||
libltdl-dev
|
||||
|
||||
# set python3 as default.
|
||||
# make python alternatives selectable.
|
||||
# (debian stretch, adapt for different versions)
|
||||
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.5 2
|
||||
|
||||
|
|
|
@ -5,22 +5,27 @@ set -eux
|
|||
|
||||
. mkp4a.common
|
||||
|
||||
if [[ -d $sdkdir && -d $ndkdir ]]; then
|
||||
echo "Skipping SDK and NDK installation: SDK and NDK directories already exist."
|
||||
exit
|
||||
urlbase=https://dl.google.com/android/repository/
|
||||
|
||||
if [[ -d $ndkdir ]]; then
|
||||
echo "Skipping NDK installation: NDK directory already exists."
|
||||
else
|
||||
mkdir -p $ndkdir
|
||||
ndk_zip=android-ndk-${ndkver}-linux-x86_64.zip
|
||||
[ -a $ndk_zip ] || wget $urlbase/$ndk_zip
|
||||
unzip -d $(dirname $ndkdir) $ndk_zip
|
||||
fi
|
||||
|
||||
urlbase=https://dl.google.com/android/repository/
|
||||
tools_zip=sdk-tools-linux-4333796.zip
|
||||
ndk_zip=android-ndk-r17c-linux-x86_64.zip
|
||||
if [[ -d $sdkdir ]]; then
|
||||
echo "Skipping SDK installation: SDK directory already exists."
|
||||
else
|
||||
mkdir -p $sdkdir
|
||||
tools_zip=sdk-tools-linux-4333796.zip
|
||||
[ -a $tools_zip ] || wget $urlbase/$tools_zip
|
||||
unzip -d $sdkdir $tools_zip
|
||||
|
||||
mkdir -p $sdkdir $ndkdir
|
||||
$sdkdir/tools/bin/sdkmanager 'platforms;android-27'
|
||||
$sdkdir/tools/bin/sdkmanager 'build-tools;29.0.1'
|
||||
fi
|
||||
|
||||
[ -a $ndk_zip ] || wget $urlbase/$ndk_zip
|
||||
unzip -d $(dirname $ndkdir) $ndk_zip
|
||||
|
||||
[ -a $tools_zip ] || wget $urlbase/$tools_zip
|
||||
unzip -d $sdkdir $tools_zip
|
||||
|
||||
$sdkdir/tools/bin/sdkmanager 'platforms;android-27'
|
||||
$sdkdir/tools/bin/sdkmanager 'build-tools;29.0.1'
|
||||
|
|
|
@ -8,8 +8,11 @@ tmpdir=${HOME}/.cache/tmp-for-p4a/pysolfc/src
|
|||
cardsets_dir='PySolFC-Cardsets--Minimal-2.0.1'
|
||||
cardsets_file="${cardsets_dir}.tar.xz"
|
||||
|
||||
p4aver="2019.10.6"
|
||||
ndkver="r19c"
|
||||
|
||||
sdkdir="${HOME}/.cache/sdk-for-p4a/sdk"
|
||||
ndkdir="${HOME}/.cache/sdk-for-p4a/android-ndk-r17c"
|
||||
ndkdir="${HOME}/.cache/sdk-for-p4a/android-ndk-${ndkver}"
|
||||
pkgdir="${HOME}/.local/share/python-for-android/packages"
|
||||
|
||||
# gradle may need this.
|
||||
|
@ -27,7 +30,7 @@ p4a_options="\
|
|||
--private ${tmpdir} \
|
||||
--orientation sensor \
|
||||
--icon ${tmpdir}/data/images/icons/48x48/pysol.png \
|
||||
--presplash ${tmpdir}/data/images/icons/1024x1024/pysol.png \
|
||||
--presplash ${tmpdir}/data/images/logo-with-margin-1024.png \
|
||||
--copy-libs \
|
||||
--add-jar ${tmpdir}/support-v4-24.1.1.aar \
|
||||
--color always"
|
||||
|
|
|
@ -17,7 +17,16 @@ echo '### install p4a'
|
|||
|
||||
if [[ $# == 0 ]]
|
||||
then
|
||||
python3 -m pip install -q --user python-for-android
|
||||
if not python3 -m pip install -q --user "python-for-android==${p4aver}"
|
||||
then
|
||||
echo "obviously inside a virtualenv, so omit --user"
|
||||
if python3 -m pip install -q "python-for-android==${p4aver}"
|
||||
then
|
||||
echo "done"
|
||||
fi
|
||||
else
|
||||
echo "done"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo '### prepare source'
|
||||
|
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
@ -31,6 +31,7 @@ from kivy.base import EventLoop
|
|||
from kivy.base import stopTouchApp
|
||||
from kivy.cache import Cache
|
||||
from kivy.clock import Clock
|
||||
from kivy.config import Config
|
||||
from kivy.core.audio import SoundLoader
|
||||
from kivy.core.window import Window
|
||||
from kivy.graphics import Color
|
||||
|
@ -54,6 +55,9 @@ from kivy.utils import platform
|
|||
|
||||
from pysollib.kivy.androidperms import requestStoragePerm
|
||||
|
||||
if platform != 'android':
|
||||
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
|
||||
|
||||
# =============================================================================
|
||||
|
||||
|
||||
|
@ -713,13 +717,27 @@ class LImageItem(BoxLayout, LBase):
|
|||
# ev. noch globales cache für stacks->game und cards->stack
|
||||
# einrichten. Aber: stacks hängt vom jeweiligen spiel ab.
|
||||
|
||||
def send_event_pressed_1(self, event):
|
||||
if self.group and '<1>' in self.group.bindings:
|
||||
self.group.bindings['<1>'](event)
|
||||
def send_event_pressed_n(self, event, n):
|
||||
if self.group and n in self.group.bindings:
|
||||
self.group.bindings[n](event)
|
||||
|
||||
def send_event_pressed_double_1(self, event):
|
||||
if self.group and '<Double-1>' in self.group.bindings:
|
||||
self.group.bindings['<Double-1>'](event)
|
||||
def send_event_pressed(self, touch, event):
|
||||
|
||||
if touch.is_double_tap:
|
||||
self.send_event_pressed_n(event, '<Double-1>')
|
||||
else:
|
||||
button = 'left'
|
||||
if 'button' in touch.profile:
|
||||
button = touch.button
|
||||
if button == 'left':
|
||||
self.send_event_pressed_n(event, '<1>')
|
||||
return
|
||||
if button == 'middle':
|
||||
self.send_event_pressed_n(event, '<2>')
|
||||
return
|
||||
if button == 'right':
|
||||
self.send_event_pressed_n(event, '<3>')
|
||||
return
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
|
||||
|
@ -743,10 +761,7 @@ class LImageItem(BoxLayout, LBase):
|
|||
event.y = ppos[1]
|
||||
self.dragstart = touch.pos
|
||||
event.cardid = i
|
||||
if touch.is_double_tap:
|
||||
self.send_event_pressed_double_1(event)
|
||||
else:
|
||||
self.send_event_pressed_1(event)
|
||||
self.send_event_pressed(touch, event)
|
||||
return True
|
||||
|
||||
if self.group is not None:
|
||||
|
@ -1777,10 +1792,9 @@ class LApp(App):
|
|||
|
||||
def doSize(self, obj, val):
|
||||
mval = self.mainWindow.size
|
||||
logging.info("LApp: size changed %s - %s (%s)" % (obj, val, mval))
|
||||
# Clock.schedule_once(self.delayedRebuild, 0.01)
|
||||
Clock.schedule_once(self.makeDelayedRebuild(), 0.01)
|
||||
# self.mainWindow.rebuildContainer()
|
||||
if (val[0] != mval[0] and val[1] != mval[1]):
|
||||
logging.info("LApp: size changed %s - %s (%s)" % (obj, val, mval))
|
||||
Clock.schedule_once(self.makeDelayedRebuild(), 0.01)
|
||||
pass
|
||||
|
||||
def on_start(self):
|
||||
|
|
|
@ -93,7 +93,7 @@ def parse_option(argv):
|
|||
"sound-mod=",
|
||||
"help"])
|
||||
except getopt.GetoptError as err:
|
||||
print_err(err + "\n" + _("try %s --help for more information") %
|
||||
print_err(str(err) + "\n" + _("try %s --help for more information") %
|
||||
prog_name, 0)
|
||||
return None
|
||||
opts = {"help": False,
|
||||
|
|
|
@ -393,7 +393,6 @@ class SelectGameDialogWithPreview(MfxDialog):
|
|||
audio=self.app.audio,
|
||||
canvas=canvas,
|
||||
cardset=self.app.cardset.copy(),
|
||||
comments=self.app.comments.new(),
|
||||
gamerandom=self.app.gamerandom,
|
||||
gdb=self.app.gdb,
|
||||
gimages=self.app.gimages,
|
||||
|
|
|
@ -32,7 +32,7 @@ PACKAGE = 'PySolFC'
|
|||
TITLE = 'PySol'
|
||||
PACKAGE_URL = 'http://pysolfc.sourceforge.net/'
|
||||
|
||||
VERSION_TUPLE = (2, 6, 4)
|
||||
VERSION_TUPLE = (2, 8, 0)
|
||||
VERSION = '.'.join(map(str, VERSION_TUPLE))
|
||||
|
||||
# Tk windowing system (auto set up in init.py)
|
||||
|
|
|
@ -319,13 +319,14 @@ class SelectGameDialog(MfxDialog):
|
|||
if button == 0: # Ok or double click
|
||||
self.gameid = self.tree.selection_key
|
||||
self.tree.n_expansions = 1 # save xyview in any case
|
||||
if button == 1: # Rules
|
||||
if button == 10: # Rules
|
||||
doc = self.app.getGameRulesFilename(self.tree.selection_key)
|
||||
if not doc:
|
||||
return
|
||||
dir = os.path.join("html", "rules")
|
||||
from pysollib.help import help_html
|
||||
help_html(self.app, doc, dir, self.top)
|
||||
self.top.grab_release() # Don't want the help window appear frozen
|
||||
return
|
||||
MfxDialog.mDone(self, button)
|
||||
|
||||
|
@ -483,7 +484,6 @@ class SelectGameDialogWithPreview(SelectGameDialog):
|
|||
audio=self.app.audio,
|
||||
canvas=canvas,
|
||||
cardset=self.app.cardset.copy(),
|
||||
comments=self.app.comments.new(),
|
||||
gamerandom=self.app.gamerandom,
|
||||
gdb=self.app.gdb,
|
||||
gimages=self.app.gimages,
|
||||
|
|
|
@ -484,7 +484,6 @@ class SelectGameDialogWithPreview(SelectGameDialog):
|
|||
audio=self.app.audio,
|
||||
canvas=canvas,
|
||||
cardset=self.app.cardset.copy(),
|
||||
comments=self.app.comments.new(),
|
||||
gamerandom=self.app.gamerandom,
|
||||
gdb=self.app.gdb,
|
||||
gimages=self.app.gimages,
|
||||
|
|
|
@ -110,7 +110,7 @@ def makeToplevel(parent, title=None):
|
|||
def make_help_toplevel(app, title=None):
|
||||
# Create an independent Toplevel window.
|
||||
from pysollib.winsystems import init_root_window
|
||||
window = tkinter.Tk(className=TITLE)
|
||||
window = tkinter.Toplevel(class_=TITLE)
|
||||
init_root_window(window, app)
|
||||
return window
|
||||
|
||||
|
|
|
@ -167,5 +167,22 @@ class DataLoader:
|
|||
filename += ('.ico' if os.name == 'nt' else '.xbm')
|
||||
return self.findFile(filename, subdirs)
|
||||
|
||||
def findAllIconSizes(self, filename='pysol.png'):
|
||||
try:
|
||||
icondir = self.findDir(os.path.join('images', 'icons'))
|
||||
icons = [os.path.join(icondir, subdir, filename) for subdir in
|
||||
os.listdir(icondir)]
|
||||
except OSError:
|
||||
try:
|
||||
# pysol06.png is known to have transparent borders around it
|
||||
# which is unsuitable for a window icon
|
||||
icon_blacklist = ('pysol06.png',)
|
||||
miscdir = self.findDir(os.path.join('images', 'misc'))
|
||||
icons = [os.path.join(miscdir, f) for f in os.listdir(miscdir)
|
||||
if f not in icon_blacklist]
|
||||
except OSError:
|
||||
icons = []
|
||||
return filter(os.path.isfile, icons)
|
||||
|
||||
def findDir(self, filename, subdirs=None):
|
||||
return self.__findFile(os.path.isdir, filename, subdirs)
|
||||
|
|
|
@ -32,6 +32,7 @@ from pysollib.settings import TOOLKIT, USE_TILE
|
|||
from pysollib.settings import VERSION
|
||||
|
||||
if TOOLKIT == 'tk':
|
||||
from pysollib.ui.tktile.tkutil import loadImage
|
||||
if USE_TILE:
|
||||
from six.moves import tkinter_ttk as ttk
|
||||
|
||||
|
@ -89,6 +90,15 @@ def base_init_root_window(root, app):
|
|||
# root.wm_group(root)
|
||||
root.wm_title(TITLE + ' ' + VERSION)
|
||||
root.wm_iconname(TITLE + ' ' + VERSION)
|
||||
|
||||
if TOOLKIT == 'tk':
|
||||
icons = [loadImage(img) for img in app.dataloader.findAllIconSizes()]
|
||||
if icons:
|
||||
try:
|
||||
root.wm_iconphoto(True, *icons)
|
||||
except AttributeError:
|
||||
root.tk.call('wm', 'iconphoto', root, '-default', *icons)
|
||||
|
||||
# set minsize
|
||||
sw, sh = (root.winfo_screenwidth(), root.winfo_screenheight())
|
||||
if sw < 640 or sh < 480:
|
||||
|
|
Loading…
Add table
Reference in a new issue