Reworked GUI to be more space friendlty.

- Added compression ability for nw executables
- Added tabs to navigate options
- Added file menu with recent files and keyboard shortcuts
- Added a status bar for displaying information about fields
This commit is contained in:
Joey Payne 2015-04-21 08:02:19 -06:00
commit 17532053c9
21 changed files with 1215 additions and 113 deletions

0
build_windows.bat Normal file → Executable file
View file

View file

@ -5,7 +5,9 @@ from pycns import save_icns
from pepy.pe import PEFile from pepy.pe import PEFile
import urllib2 import urllib2
import platform
import re import re
import time
import sys import sys
import os import os
import glob import glob
@ -36,6 +38,11 @@ inside_packed_exe = getattr(sys, 'frozen', '')
CWD = os.getcwd() CWD = os.getcwd()
def get_file(path):
parts = path.split('/')
independent_path = os.path.join(CWD, *parts)
return independent_path
TEMP_DIR = get_temp_dir() TEMP_DIR = get_temp_dir()
DEFAULT_DOWNLOAD_PATH = os.path.join(CWD, DEFAULT_DOWNLOAD_PATH = os.path.join(CWD,
'files', 'files',
@ -99,6 +106,7 @@ class Setting(object):
self.filter = kwargs.pop('filter', '.*') self.filter = kwargs.pop('filter', '.*')
self.filter_action = kwargs.pop('filter_action', 'None') self.filter_action = kwargs.pop('filter_action', 'None')
self.check_action = kwargs.pop('check_action', 'None') self.check_action = kwargs.pop('check_action', 'None')
self.action = kwargs.pop('action', None)
self.set_extra_attributes_from_keyword_args(**kwargs) self.set_extra_attributes_from_keyword_args(**kwargs)
@ -309,9 +317,13 @@ class CommandBase(object):
for setting_group, setting_group_dict in sgroup_items: for setting_group, setting_group_dict in sgroup_items:
settings['setting_groups'].append(settings[setting_group]) settings['setting_groups'].append(settings[setting_group])
self._setting_items = (config['setting_groups'].items() +
[('export_settings', config['export_settings'])] +
[('compression', config['compression'])])
config.pop('setting_groups') config.pop('setting_groups')
config.pop('export_settings') config.pop('export_settings')
config.pop('compression') config.pop('compression')
self._setting_items += config.items()
for key, val in config.items(): for key, val in config.items():
settings[key] = val settings[key] = val
@ -450,7 +462,8 @@ class CommandBase(object):
dl_export_items = (self.settings['download_settings'].items() + dl_export_items = (self.settings['download_settings'].items() +
self.settings['export_settings'].items() + self.settings['export_settings'].items() +
self.settings['compression'].items()) self.settings['compression'].items() +
self.settings['web2exe_settings'].items())
for setting_name, setting in dl_export_items: for setting_name, setting in dl_export_items:
if setting.value is not None: if setting.value is not None:
dic['webexe_settings'][setting_name] = setting.value dic['webexe_settings'][setting_name] = setting.value
@ -513,6 +526,8 @@ class CommandBase(object):
if setting.type == 'list': if setting.type == 'list':
val_str = self.convert_val_to_str(new_dic[item]) val_str = self.convert_val_to_str(new_dic[item])
setting.value = val_str setting.value = val_str
if setting.type == 'range':
setting.value = new_dic[item]
if isinstance(new_dic[item], dict): if isinstance(new_dic[item], dict):
stack.append((item, new_dic[item])) stack.append((item, new_dic[item]))
return setting_list return setting_list
@ -678,7 +693,7 @@ class CommandBase(object):
if windows: if windows:
self.replace_icon_in_exe(nw_path) self.replace_icon_in_exe(nw_path)
#self.compress_nw(nw_path) self.compress_nw(nw_path)
dest_binary_path = os.path.join(export_dest, dest_binary_path = os.path.join(export_dest,
self.project_name() + self.project_name() +
@ -709,15 +724,29 @@ class CommandBase(object):
def compress_nw(self, nw_path): def compress_nw(self, nw_path):
compression = self.get_setting('nw_compression_level') compression = self.get_setting('nw_compression_level')
upx_bin = os.path.join('files', 'compressors', 'upx-linux-x64') comp_dict = {'Darwin64bit': get_file('files/compressors/upx-mac'),
cmd = '{upx_bin} --lzma -{comp_level} -o test {path}'.format(upx_bin=upx_bin, 'Darwin32bit': get_file('files/compressors/upx-mac'),
comp_level=compression.value, 'Linux64bit': get_file('files/compressors/upx-linux-x64'),
path=nw_path) 'Linux32bit': get_file('files/compressors/upx-linux-x32'),
print cmd 'Windows64bit': get_file('files/compressors/upx-win.exe'),
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 'Windows32bit': get_file('files/compressors/upx-win.exe')
stderr=subprocess.PIPE, shell=True) }
output, err = proc.communicate()
print err, output plat = platform.system()+platform.architecture()[0]
upx_version = comp_dict.get(plat, None)
if upx_version is not None:
upx_bin = os.path.join('files', 'compressors', upx_version)
os.chmod(upx_bin, 0755)
cmd = [upx_bin, '--lzma', '-{}'.format(compression.value), str(nw_path)]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
self.progress_text = '\nCompressing files'
while proc.poll() is None:
self.progress_text += '.'
time.sleep(5)
output, err = proc.communicate()
def copy_files_to_project_folder(self): def copy_files_to_project_folder(self):
old_dir = CWD old_dir = CWD

BIN
files/compressors/upx-linux-x32 Executable file

Binary file not shown.

BIN
files/compressors/upx-linux-x64 Executable file

Binary file not shown.

BIN
files/compressors/upx-mac Executable file

Binary file not shown.

BIN
files/compressors/upx-win.exe Executable file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
id="SVGRoot"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="app_settings.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="2.5341245"
inkscape:cy="6.1584452"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4143">
<linearGradient
inkscape:collect="always"
id="linearGradient4772">
<stop
style="stop-color:#d3d3d3;stop-opacity:1;"
offset="0"
id="stop4774" />
<stop
style="stop-color:#d3d3d3;stop-opacity:0;"
offset="1"
id="stop4776" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4730">
<stop
style="stop-color:#3d3d3e;stop-opacity:1;"
offset="0"
id="stop4732" />
<stop
style="stop-color:#3d3d3e;stop-opacity:0;"
offset="1"
id="stop4734" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4730"
id="linearGradient4736"
x1="13.593119"
y1="13.064024"
x2="-124.15217"
y2="-100.05997"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0439827,0,0,1.0439827,-0.33554965,-0.28661264)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4772"
id="linearGradient4780"
x1="6.4024119"
y1="3.2154982"
x2="46.513737"
y2="26.952219"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4772"
id="linearGradient4826"
gradientUnits="userSpaceOnUse"
x1="6.4024119"
y1="3.2154982"
x2="46.513737"
y2="26.952219"
gradientTransform="matrix(0.94762762,0.21358123,-0.21358123,0.94762762,2.5055978,-1.2401189)" />
</defs>
<metadata
id="metadata4146">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<rect
style="opacity:1;fill:url(#linearGradient4736);fill-opacity:1;stroke:none;stroke-width:62.59950638;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4700"
width="14.126391"
height="13.637024"
x="0.93680429"
y="1.181488"
ry="2.055341" />
<path
style="opacity:1;fill:url(#linearGradient4826);fill-opacity:1;stroke:none;stroke-width:53.80522919;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
clip-path="none"
d="M 7.9398486,2.1449285 C 5.5056259,2.1703938 7.8595712,2.981495 5.7642049,4.2206599 3.6688388,5.4598248 4.0944274,3.0051573 2.8993696,5.1259886 1.7043117,7.24682 3.5834863,5.611655 3.6089516,8.0458778 3.6344164,10.480101 1.7213755,8.886713 2.9605405,10.982079 c 1.2391648,2.095366 0.7623552,-0.350899 2.8831866,0.844158 2.1208313,1.195059 -0.2157595,2.054299 2.2184632,2.028833 2.4342227,-0.02546 0.078238,-0.834526 2.1736047,-2.073692 2.095366,-1.239164 1.669777,1.215503 2.864835,-0.905328 C 14.295688,8.7552183 12.416513,10.388344 12.391048,7.9541215 12.365583,5.5198987 14.278624,7.1153253 13.03946,5.0199591 11.800294,2.9245929 12.277104,5.3708591 10.156273,4.1758012 8.0354415,2.9807433 10.374072,2.1194634 7.9398486,2.1449285 Z m 0.061171,3.6417054 A 2.2146216,2.2146216 0 0 1 10.215405,8.0010191 2.2146216,2.2146216 0 0 1 8.0010195,10.215404 2.2146216,2.2146216 0 0 1 5.7866343,8.0010191 2.2146216,2.2146216 0 0 1 8.0010195,5.7866339 Z"
id="path4738"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:export-filename="/home/joey/Projects/Web2Executable/files/images/compress_settings.png"
sodipodi:docname="compress_settings.svg"
inkscape:version="0.91+devel r"
version="1.1"
id="SVGRoot"
viewBox="0 0 16 16"
height="16px"
width="16px">
<sodipodi:namedview
inkscape:grid-bbox="true"
inkscape:window-maximized="1"
inkscape:window-y="24"
inkscape:window-x="65"
inkscape:window-height="1056"
inkscape:window-width="1855"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="10.205154"
inkscape:cx="0.67126005"
inkscape:zoom="11.313709"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base" />
<defs
id="defs4143">
<linearGradient
id="linearGradient4772"
inkscape:collect="always">
<stop
id="stop4774"
offset="0"
style="stop-color:#d3d3d3;stop-opacity:1;" />
<stop
id="stop4776"
offset="1"
style="stop-color:#d3d3d3;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient4730"
inkscape:collect="always">
<stop
id="stop4732"
offset="0"
style="stop-color:#3d3d3e;stop-opacity:1;" />
<stop
id="stop4734"
offset="1"
style="stop-color:#3d3d3e;stop-opacity:0;" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1.0439827,0,0,1.0439827,-0.33554965,-0.28661264)"
gradientUnits="userSpaceOnUse"
y2="-100.05997"
x2="-124.15217"
y1="13.064024"
x1="13.593119"
id="linearGradient4736"
xlink:href="#linearGradient4730"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="26.952219"
x2="46.513737"
y1="3.2154982"
x1="6.4024119"
id="linearGradient4780"
xlink:href="#linearGradient4772"
inkscape:collect="always" />
<linearGradient
gradientTransform="matrix(0.7582309,0.17089402,-0.17089402,0.7582309,3.6731782,16.025256)"
y2="26.952219"
x2="46.513737"
y1="3.2154982"
x1="6.4024119"
gradientUnits="userSpaceOnUse"
id="linearGradient4826"
xlink:href="#linearGradient4772"
inkscape:collect="always" />
</defs>
<metadata
id="metadata4146">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
ry="2.055341"
y="1.181488"
x="0.93680429"
height="13.637024"
width="14.126391"
id="rect4700"
style="opacity:1;fill:url(#linearGradient4736);fill-opacity:1;stroke:none;stroke-width:62.59950638;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4738"
d="m 13.858968,7.2410286 c 0.923129,1.5171458 -0.809369,0.042891 -1.540816,1.3316276 -0.980653,1.7278148 2.098544,1.3308325 -0.302351,2.5199508 C 9.0597011,12.556709 11.153629,10.383417 7.8692271,10.358548 4.5984606,10.333783 6.4471116,12.533426 3.6678994,11.025787 1.4254964,9.8093494 4.4235492,10.248531 3.6341638,8.5169358 3.0465331,7.2279098 1.1881231,8.669562 2.2540087,7.1764557 3.0486014,6.0633786 3.1026251,7.1356548 4.7654177,6.1688201 6.0957901,5.3952705 4.079129,5.5396116 5.9214856,5.1486519 c 1.6502939,-0.350203 0.3038643,0.2183737 2.2102407,0.226777 1.9110007,0.00842 0.619542,-0.5722369 2.2379197,-0.2078126 1.814684,0.4086285 -0.202138,0.2456624 1.054453,1.0339594 1.576394,0.9889173 1.748209,-0.08906 2.434869,1.0394529 0,0 0,0 0,0 M 10.229006,7.208623 C 10.098503,6.6073751 9.138078,6.177246 8.0683525,6.1771923 6.9986232,6.177246 6.0096606,6.6073751 5.8392676,7.2086231 c -0.1971591,0.6966797 0.751854,1.3481626 2.1501436,1.3482548 1.398296,-9.22e-5 2.3905318,-0.6515752 2.2395948,-1.3482548 0,0 0,-10e-8 0,-10e-8"
clip-path="none"
style="opacity:1;fill:url(#linearGradient4826);fill-opacity:1;stroke:none;stroke-width:43.05149841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

View file

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:export-filename="/home/joey/Projects/Web2Executable/files/images/download_settings.png"
sodipodi:docname="download_settings.svg"
inkscape:version="0.91+devel r"
version="1.1"
id="SVGRoot"
viewBox="0 0 16 16"
height="16px"
width="16px">
<sodipodi:namedview
inkscape:grid-bbox="true"
inkscape:window-maximized="1"
inkscape:window-y="24"
inkscape:window-x="65"
inkscape:window-height="1056"
inkscape:window-width="1855"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="10.750147"
inkscape:cx="2.0955227"
inkscape:zoom="22.627418"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base" />
<defs
id="defs4143">
<linearGradient
inkscape:collect="always"
id="linearGradient4155">
<stop
style="stop-color:#4a89dc;stop-opacity:1;"
offset="0"
id="stop4157" />
<stop
style="stop-color:#5d9cec;stop-opacity:1"
offset="1"
id="stop4159" />
</linearGradient>
<linearGradient
id="linearGradient4772"
inkscape:collect="always">
<stop
id="stop4774"
offset="0"
style="stop-color:#d3d3d3;stop-opacity:1;" />
<stop
id="stop4776"
offset="1"
style="stop-color:#d3d3d3;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient4730"
inkscape:collect="always">
<stop
id="stop4732"
offset="0"
style="stop-color:#3d3d3e;stop-opacity:1;" />
<stop
id="stop4734"
offset="1"
style="stop-color:#3d3d3e;stop-opacity:0;" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1.0439827,0,0,1.0439827,-0.33554965,-0.28661264)"
gradientUnits="userSpaceOnUse"
y2="-100.05997"
x2="-124.15217"
y1="13.064024"
x1="13.593119"
id="linearGradient4736"
xlink:href="#linearGradient4730"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="26.952219"
x2="46.513737"
y1="3.2154982"
x1="6.4024119"
id="linearGradient4780"
xlink:href="#linearGradient4772"
inkscape:collect="always" />
<linearGradient
gradientTransform="matrix(0.7582309,0.17089402,-0.17089402,0.7582309,3.5847899,16.799843)"
y2="26.952219"
x2="46.513737"
y1="3.2154982"
x1="6.4024119"
gradientUnits="userSpaceOnUse"
id="linearGradient4826"
xlink:href="#linearGradient4772"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4155"
id="linearGradient4161"
x1="13.189182"
y1="14.049465"
x2="3.2565863"
y2="1.3619654"
gradientUnits="userSpaceOnUse" />
</defs>
<metadata
id="metadata4146">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
ry="2.055341"
y="1.181488"
x="0.93680429"
height="13.637024"
width="14.126391"
id="rect4700"
style="opacity:1;fill:url(#linearGradient4736);fill-opacity:1;stroke:none;stroke-width:62.59950638;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4738"
d="m 13.77058,8.0156159 c 0.923129,1.5171455 -0.809369,0.042891 -1.540816,1.3316275 -0.980653,1.7278146 2.098544,1.3308326 -0.302351,2.5199506 C 8.9713128,13.331296 11.065241,11.158004 7.7808388,11.133135 4.5100723,11.10837 6.3587233,13.308013 3.5795111,11.800374 1.3371081,10.583936 4.3351609,11.023118 3.5457755,9.2915231 2.9581448,8.0024971 1.0997348,9.4441494 2.1656204,7.951043 2.9602131,6.8379659 3.0142368,7.9102421 4.6770294,6.9434074 6.0074018,6.1698578 3.9907407,6.3141989 5.8330973,5.9232392 c 1.6502939,-0.350203 0.3038643,0.2183737 2.2102407,0.226777 1.9110007,0.00842 0.619542,-0.5722369 2.23792,-0.2078126 1.814684,0.4086285 -0.202138,0.2456624 1.054453,1.0339594 1.576394,0.9889173 1.748209,-0.08906 2.434869,1.0394529 0,0 0,0 0,0 M 10.140618,7.9832103 C 10.010115,7.3819624 9.0496897,6.9518333 7.9799642,6.9517796 6.9102349,6.9518333 5.9212723,7.3819624 5.7508793,7.9832104 5.5537202,8.6798901 6.5027333,9.331373 7.9010229,9.3314652 9.2993189,9.331373 10.291555,8.67989 10.140618,7.9832104 c 0,0 0,-1e-7 0,-1e-7"
clip-path="none"
style="opacity:1;fill:url(#linearGradient4826);fill-opacity:1;stroke:none;stroke-width:43.05149841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient4161);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.01137726px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 9.1814569,2.2041468 C 8.1196871,2.9367735 7.2499098,2.8659711 6.1660764,9.6370096 l -2.3683598,0 3.8100016,4.4702294 4.1971408,-4.4702294 -2.2596157,0 C 9.5270521,8.6213252 9.649399,4.2097051 11.194086,1.8198522 c 0,0 -0.946091,-0.093675 -2.0126291,0.3842946 z"
id="path4138"
inkscape:export-xdpi="10.238106"
inkscape:export-ydpi="10.238106"
sodipodi:nodetypes="cccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

View file

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
id="SVGRoot"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="export_settings.svg"
inkscape:export-filename="/home/joey/Projects/Web2Executable/files/images/export_settings.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="-2.4708373"
inkscape:cy="8.933887"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4143">
<linearGradient
inkscape:collect="always"
id="linearGradient4886">
<stop
style="stop-color:#37b39b;stop-opacity:1"
offset="0"
id="stop4888" />
<stop
style="stop-color:#48cfad;stop-opacity:1"
offset="1"
id="stop4890" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4772">
<stop
style="stop-color:#d3d3d3;stop-opacity:1;"
offset="0"
id="stop4774" />
<stop
style="stop-color:#d3d3d3;stop-opacity:0;"
offset="1"
id="stop4776" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4730">
<stop
style="stop-color:#3d3d3e;stop-opacity:1;"
offset="0"
id="stop4732" />
<stop
style="stop-color:#3d3d3e;stop-opacity:0;"
offset="1"
id="stop4734" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4730"
id="linearGradient4736"
x1="13.593119"
y1="13.064024"
x2="-124.15217"
y2="-100.05997"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0439827,0,0,1.0439827,-0.33554965,-0.28661264)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4772"
id="linearGradient4780"
x1="6.4024119"
y1="3.2154982"
x2="46.513737"
y2="26.952219"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4772"
id="linearGradient4826"
gradientUnits="userSpaceOnUse"
x1="6.4024119"
y1="3.2154982"
x2="46.513737"
y2="26.952219"
gradientTransform="matrix(0.94762762,0.21358123,-0.21358123,0.94762762,2.5055978,-1.2401189)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4886"
id="linearGradient4894"
gradientUnits="userSpaceOnUse"
x1="10.783379"
y1="10.696699"
x2="-0.57452416"
y2="-2.1638048"
gradientTransform="matrix(1.0841182,0,0,1.0841182,-0.9286483,-0.27436275)" />
</defs>
<metadata
id="metadata4146">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<rect
style="opacity:1;fill:url(#linearGradient4736);fill-opacity:1;stroke:none;stroke-width:62.59950638;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4700"
width="14.126391"
height="13.637024"
x="0.93680429"
y="1.181488"
ry="2.055341" />
<path
style="opacity:1;fill:url(#linearGradient4826);fill-opacity:1;stroke:none;stroke-width:53.80522919;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
clip-path="none"
d="M 7.9398486,2.1449285 C 5.5056259,2.1703938 7.8595712,2.981495 5.7642049,4.2206599 3.6688388,5.4598248 4.0944274,3.0051573 2.8993696,5.1259886 1.7043117,7.24682 3.5834863,5.611655 3.6089516,8.0458778 3.6344164,10.480101 1.7213755,8.886713 2.9605405,10.982079 c 1.2391648,2.095366 0.7623552,-0.350899 2.8831866,0.844158 2.1208313,1.195059 -0.2157595,2.054299 2.2184632,2.028833 2.4342227,-0.02546 0.078238,-0.834526 2.1736047,-2.073692 2.095366,-1.239164 1.669777,1.215503 2.864835,-0.905328 C 14.295688,8.7552183 12.416513,10.388344 12.391048,7.9541215 12.365583,5.5198987 14.278624,7.1153253 13.03946,5.0199591 11.800294,2.9245929 12.277104,5.3708591 10.156273,4.1758012 8.0354415,2.9807433 10.374072,2.1194634 7.9398486,2.1449285 Z m 0.061171,3.6417054 A 2.2146216,2.2146216 0 0 1 10.215405,8.0010191 2.2146216,2.2146216 0 0 1 8.0010195,10.215404 2.2146216,2.2146216 0 0 1 5.7866343,8.0010191 2.2146216,2.2146216 0 0 1 8.0010195,5.7866339 Z"
id="path4738"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient4894);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.01325854px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 10.842376,1.5529067 -3.9731557,4.1877913 1.7972428,0 c 0.00322,1.3669134 -0.3877342,7.24255 -7.3094525,7.874669 0,0 10.4402554,3.350629 11.6434674,-7.874669 l 1.743314,0 -3.901416,-4.1877913 z"
id="path4138-0"
inkscape:export-xdpi="10.238106"
inkscape:export-ydpi="10.238106" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
files/images/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

84
files/images/warning.svg Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
id="SVGRoot"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="warning.svg"
inkscape:export-filename="/home/joey/Projects/Web2Executable/files/images/warning.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="-15.835665"
inkscape:cy="6.3038239"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4183" />
<metadata
id="metadata4186">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<g
id="g4217"
transform="translate(-0.00532229,-0.01899142)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3336"
d="m 8.1447354,2.7412884 5.6732056,10.5552146 -11.6252444,0 z"
style="fill:#d03436;fill-opacity:1;fill-rule:evenodd;stroke:#d03436;stroke-width:3.5687921;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="0.94282585"
cy="12.731531"
cx="8.1741886"
id="path4147"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.0342989;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
ry="1.028775"
y="3.4383595"
x="7.2482905"
height="7.5717845"
width="1.8517954"
id="rect4168"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.12858665;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

View file

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
id="SVGRoot"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="window_settings.svg"
inkscape:export-filename="/home/joey/Projects/Web2Executable/files/images/window_settings.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="-42.943793"
inkscape:cy="12.800391"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4143">
<linearGradient
inkscape:collect="always"
id="linearGradient4772">
<stop
style="stop-color:#d3d3d3;stop-opacity:1;"
offset="0"
id="stop4774" />
<stop
style="stop-color:#d3d3d3;stop-opacity:0;"
offset="1"
id="stop4776" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4730">
<stop
style="stop-color:#3d3d3e;stop-opacity:1;"
offset="0"
id="stop4732" />
<stop
style="stop-color:#3d3d3e;stop-opacity:0;"
offset="1"
id="stop4734" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4730"
id="linearGradient4736"
x1="13.593119"
y1="13.064024"
x2="-124.15217"
y2="-100.05997"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0439827,0,0,1.0439827,-0.33554965,-0.28661264)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4772"
id="linearGradient4780"
x1="6.4024119"
y1="3.2154982"
x2="46.513737"
y2="26.952219"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4772"
id="linearGradient4826"
gradientUnits="userSpaceOnUse"
x1="6.4024119"
y1="3.2154982"
x2="46.513737"
y2="26.952219"
gradientTransform="matrix(0.72672638,0.16379336,-0.16379336,0.72672638,5.421581,2.5440104)" />
</defs>
<metadata
id="metadata4146">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<rect
style="opacity:1;fill:url(#linearGradient4736);fill-opacity:1;stroke:none;stroke-width:62.59950638;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4700"
width="14.126391"
height="13.637024"
x="0.93680429"
y="1.181488"
ry="2.055341" />
<path
style="opacity:1;fill:url(#linearGradient4826);fill-opacity:1;stroke:none;stroke-width:41.26270676;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
clip-path="none"
d="M 9.5890549,5.1399702 C 7.7222732,5.1594993 9.5274909,5.7815249 7.920575,6.7318284 6.3136591,7.6821319 6.6400389,5.7996713 5.7235607,7.4261161 4.8070825,9.0525611 6.2482031,7.798569 6.2677322,9.6653507 6.2872609,11.532133 4.8201685,10.310179 5.7704721,11.917095 c 0.9503034,1.606916 0.5846427,-0.269101 2.2110877,0.647376 1.6264448,0.916479 -0.1654639,1.575422 1.7013177,1.555893 1.8667815,-0.01953 0.06,-0.63999 1.6669165,-1.590295 1.606915,-0.950302 1.280535,0.932158 2.197013,-0.694287 C 14.463286,10.209337 13.022165,11.461765 13.002636,9.5949837 12.983107,7.728202 14.450199,8.9517191 13.499897,7.3448032 12.549593,5.7378873 12.915254,7.6139049 11.288809,6.6974267 9.6623642,5.7809484 11.455837,5.1204413 9.5890549,5.1399702 Z m 0.046911,2.7927884 A 1.6983717,1.6983717 0 0 1 11.334157,9.630949 1.6983717,1.6983717 0 0 1 9.6359663,11.329139 1.6983717,1.6983717 0 0 1 7.9377758,9.630949 1.6983717,1.6983717 0 0 1 9.6359663,7.9327586 Z"
id="path4738"
inkscape:connector-curvature="0" />
<circle
style="opacity:1;fill:#da4453;fill-opacity:1;stroke:none;stroke-width:77.15126038;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4855"
cx="3.1991758"
cy="3.1535499"
r="1.0519673" />
<circle
r="1.0519673"
cy="3.1535499"
cx="6.0991936"
id="circle4857"
style="opacity:1;fill:#f6bb42;fill-opacity:1;stroke:none;stroke-width:77.15126038;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="opacity:1;fill:#8cc152;fill-opacity:1;stroke:none;stroke-width:77.15126038;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle4859"
cx="9.0296631"
cy="3.1535499"
r="1.0519673" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -108,6 +108,11 @@ linux_64_dir_prefix = 'node-webkit-v{}-linux-x64'
default_value=False default_value=False
type='check' type='check'
[[web2exe_settings]]
[[[export_dir]]]
default_value=''
type='string'
[[window_settings]] [[window_settings]]
[[[title]]] [[[title]]]
default_value='' default_value=''
@ -116,15 +121,18 @@ linux_64_dir_prefix = 'node-webkit-v{}-linux-x64'
display_name='Window Icon' display_name='Window Icon'
default_value='' default_value=''
type='file' type='file'
action='set_window_icon'
file_types='*.png *.jpg *.jpeg' file_types='*.png *.jpg *.jpeg'
[[[mac_icon]]] [[[mac_icon]]]
default_value='' default_value=''
type='file' type='file'
action='set_mac_icon'
file_types='*.png *.jpg *.jpeg *.icns' file_types='*.png *.jpg *.jpeg *.icns'
description='This icon to be displayed for the Mac Application. Defaults to Window Icon' description='This icon to be displayed for the Mac Application. Defaults to Window Icon'
[[[exe_icon]]] [[[exe_icon]]]
default_value='' default_value=''
type='file' type='file'
action='set_exe_icon'
file_types='*.png *.jpg *.jpeg' file_types='*.png *.jpg *.jpeg'
description='This icon to be displayed for the windows exe of the app. Defaults to Window icon.' description='This icon to be displayed for the windows exe of the app. Defaults to Window icon.'
[[[width]]] [[[width]]]
@ -323,10 +331,12 @@ linux_64_dir_prefix = 'node-webkit-v{}-linux-x64'
[compression] [compression]
[[nw_compression_level]] [[nw_compression_level]]
display_name='NW Compression' display_name='Compression Level'
default_value=5 default_value=0
min=0
max=9
type='range' type='range'
description='Compression to be applied to the executable\'s node webkit binary. 0 is no compression, 9 is maximum. They all use lzma.' description='Compression to be applied to the executable\'s nwjs binary. 0 is no compression, 9 is maximum. They all use lzma.'
[order] [order]
@ -342,6 +352,7 @@ linux_64_dir_prefix = 'node-webkit-v{}-linux-x64'
'kiosk', 'kiosk_emulation', 'transparent']""" 'kiosk', 'kiosk_emulation', 'transparent']"""
export_setting_order = """['windows-x32', 'windows-x64', 'mac-x32', 'mac-x64', 'linux-x64', 'linux-x32']""" export_setting_order = """['windows-x32', 'windows-x64', 'mac-x32', 'mac-x64', 'linux-x64', 'linux-x32']"""
compression_setting_order = """['nw_compression_level']"""
download_setting_order = """['nw_version', 'download_dir', download_setting_order = """['nw_version', 'download_dir',
'force_download']""" 'force_download']"""

0
image_tool_build.bat Normal file → Executable file
View file

458
main.py
View file

@ -1,6 +1,6 @@
from utils import log, open_folder_in_explorer from utils import log, open_folder_in_explorer
__gui_version__ = "v0.2.0b" __gui_version__ = "v0.2.1b"
import os import os
import re import re
@ -8,12 +8,14 @@ import glob
import sys import sys
from PySide import QtGui, QtCore from PySide import QtGui, QtCore
from PySide.QtGui import QApplication from PySide.QtGui import QApplication, QHBoxLayout, QVBoxLayout
from PySide.QtNetwork import QHttp from PySide.QtNetwork import QHttp
from PySide.QtCore import QUrl, QFile, QIODevice, QCoreApplication from PySide.QtCore import QUrl, QFile, QIODevice, QCoreApplication
from command_line import CWD, CommandBase, logger from command_line import CommandBase, logger, get_file
MAX_RECENT = 10
class Validator(QtGui.QRegExpValidator): class Validator(QtGui.QRegExpValidator):
@ -45,15 +47,104 @@ class BackgroundThread(QtCore.QThread):
func() func()
class MainWindow(QtGui.QWidget, CommandBase): class MainWindow(QtGui.QMainWindow, CommandBase):
def update_nw_versions(self, button): def update_nw_versions(self, button):
self.get_versions_in_background() self.get_versions_in_background()
def load_recent_projects(self):
files = []
history_file = get_file('files/recent_files.txt')
with open(history_file, 'a+') as f:
for line in f:
line = line.strip()
if line and os.path.exists(line):
files.append(line)
files.reverse()
return files
def load_last_project_path(self):
proj_path = ''
proj_file = get_file('files/last_project_path.txt')
with open(proj_file, 'a+') as f:
proj_path = f.read().strip()
if not proj_path:
proj_path = QtCore.QDir.currentPath()
return proj_path
def save_project_path(self, path):
proj_file = get_file('files/last_project_path.txt')
with open(proj_file, 'w+') as f:
f.write(path)
def save_recent_project(self, proj):
recent_file_path = get_file('files/recent_files.txt')
max_length = MAX_RECENT
recent_files = open(recent_file_path, 'a+').read().split('\n')
try:
recent_files.remove(proj)
except ValueError:
pass
recent_files.append(proj)
with open(recent_file_path, 'w+') as f:
for recent_file in recent_files[-max_length:]:
if recent_file and os.path.exists(recent_file):
f.write(recent_file+'\n')
def update_recent_files(self):
previous_files = self.load_recent_projects()
self.recent_separator.setVisible(len(previous_files) > 0)
for i in xrange(len(previous_files)):
text = '{} - {}'.format(i+1, os.path.basename(previous_files[i]))
action = self.recent_file_actions[i]
action.setText(text)
action.setData(previous_files[i])
action.setVisible(True)
def __init__(self, width, height, app, parent=None): def __init__(self, width, height, app, parent=None):
super(MainWindow, self).__init__(parent) super(MainWindow, self).__init__(parent)
CommandBase.__init__(self) CommandBase.__init__(self)
self.icon_style = 'width:48px;height:48px;background-color:white;border-radius:5px;border:1px solid rgb(50,50,50);'
self.last_project_dir = self.load_last_project_path()
status_bar = QtGui.QStatusBar()
self.setStatusBar(status_bar)
self.project_path = ''
self.project_menu = self.menuBar().addMenu('File')
browse_action = QtGui.QAction('Open Project', self.project_menu,
shortcut=QtGui.QKeySequence.Open,
statusTip='Open an existing or new project.',
triggered=self.browse_dir)
self.project_menu.addAction(browse_action)
self.project_menu.addSeparator()
self.recent_file_actions = []
for i in xrange(MAX_RECENT):
if i == 9:
key = 0
else:
key = i+1
action = QtGui.QAction(self, visible=False, triggered=self.open_recent_file,
shortcut=QtGui.QKeySequence('Ctrl+{}'.format(key)))
self.recent_file_actions.append(action)
self.project_menu.addAction(action)
self.recent_separator = self.project_menu.addSeparator()
self.update_recent_files()
exit_action = QtGui.QAction('Exit', self.project_menu)
exit_action.triggered.connect(QtGui.qApp.closeAllWindows)
self.project_menu.addAction(exit_action)
self.logger = logger self.logger = logger
self.gui_app = app self.gui_app = app
@ -62,8 +153,7 @@ class MainWindow(QtGui.QWidget, CommandBase):
self.options_enabled = False self.options_enabled = False
self.output_package_json = True self.output_package_json = True
self.setWindowIcon(QtGui.QIcon(os.path.join(CWD, 'files', self.setWindowIcon(QtGui.QIcon(get_file('files/images/icon.png')))
'images', 'icon.png')))
self.update_json = False self.update_json = False
self.setup_nw_versions() self.setup_nw_versions()
@ -82,10 +172,15 @@ class MainWindow(QtGui.QWidget, CommandBase):
self.setWindowTitle("Web2Executable {}".format(__gui_version__)) self.setWindowTitle("Web2Executable {}".format(__gui_version__))
self.update_nw_versions(None) self.update_nw_versions(None)
def open_recent_file(self):
action = self.sender()
if action:
self.load_project(action.data())
def setup_nw_versions(self): def setup_nw_versions(self):
nw_version = self.get_setting('nw_version') nw_version = self.get_setting('nw_version')
try: try:
f = open(os.path.join(CWD, 'files', 'nw-versions.txt')) f = open(get_file('files/nw-versions.txt'))
for line in f: for line in f:
nw_version.values.append(line.strip()) nw_version.values.append(line.strip())
except IOError: except IOError:
@ -93,28 +188,48 @@ class MainWindow(QtGui.QWidget, CommandBase):
def create_application_layout(self): def create_application_layout(self):
self.main_layout = QtGui.QVBoxLayout() self.main_layout = QtGui.QVBoxLayout()
self.tab_widget = QtGui.QTabWidget()
self.main_layout.setContentsMargins(10, 5, 10, 5) self.main_layout.setContentsMargins(10, 5, 10, 5)
self.create_layout_widgets() self.create_layout_widgets()
self.addWidgets_to_main_layout() self.addWidgets_to_main_layout()
self.setLayout(self.main_layout) w = QtGui.QWidget()
w.setLayout(self.main_layout)
self.setCentralWidget(w)
def create_layout_widgets(self): def create_layout_widgets(self):
self.download_bar_widget = self.create_download_bar() self.download_bar_widget = self.create_download_bar()
self.app_settings_widget = self.create_application_settings() self.app_settings_widget = self.create_application_settings()
self.comp_settings_widget = self.create_compression_settings()
self.win_settings_widget = self.create_window_settings() self.win_settings_widget = self.create_window_settings()
self.ex_settings_widget = self.create_export_settings() self.ex_settings_widget = self.create_export_settings()
self.dl_settings_widget = self.create_download_settings() self.dl_settings_widget = self.create_download_settings()
self.directory_chooser_widget = self.create_directory_choose() self.directory_chooser_widget = self.create_directory_choose()
def addWidgets_to_main_layout(self): def addWidgets_to_main_layout(self):
self.warning_settings_icon = QtGui.QIcon(get_file('files/images/warning.png'))
self.app_settings_icon = QtGui.QIcon(get_file('files/images/app_settings.png'))
self.win_settings_icon = QtGui.QIcon(get_file('files/images/window_settings.png'))
self.ex_settings_icon = QtGui.QIcon(get_file('files/images/export_settings.png'))
self.comp_settings_icon = QtGui.QIcon(get_file('files/images/compress_settings.png'))
self.download_settings_icon = QtGui.QIcon(get_file('files/images/download_settings.png'))
self.tab_icons = [self.app_settings_icon,
self.win_settings_icon,
self.ex_settings_icon,
self.comp_settings_icon,
self.download_settings_icon]
self.main_layout.addWidget(self.directory_chooser_widget) self.main_layout.addWidget(self.directory_chooser_widget)
self.main_layout.addWidget(self.app_settings_widget) self.tab_widget.addTab(self.app_settings_widget, self.app_settings_icon, 'App Settings')
self.main_layout.addWidget(self.win_settings_widget) self.tab_widget.addTab(self.win_settings_widget, self.win_settings_icon, 'Window Settings')
self.main_layout.addWidget(self.ex_settings_widget) self.tab_widget.addTab(self.ex_settings_widget, self.ex_settings_icon, 'Export Settings')
self.main_layout.addWidget(self.dl_settings_widget) self.tab_widget.addTab(self.comp_settings_widget, self.comp_settings_icon, 'Compression Settings')
self.tab_widget.addTab(self.dl_settings_widget, self.download_settings_icon, 'Download Settings')
self.main_layout.addWidget(self.tab_widget)
self.main_layout.addLayout(self.download_bar_widget) self.main_layout.addLayout(self.download_bar_widget)
def option_settings_enabled(self, is_enabled): def option_settings_enabled(self, is_enabled):
@ -122,6 +237,7 @@ class MainWindow(QtGui.QWidget, CommandBase):
self.app_settings_widget.setEnabled(is_enabled) self.app_settings_widget.setEnabled(is_enabled)
self.win_settings_widget.setEnabled(is_enabled) self.win_settings_widget.setEnabled(is_enabled)
self.ex_settings_widget.setEnabled(is_enabled) self.ex_settings_widget.setEnabled(is_enabled)
self.comp_settings_widget.setEnabled(is_enabled)
self.dl_settings_widget.setEnabled(is_enabled) self.dl_settings_widget.setEnabled(is_enabled)
self.options_enabled = is_enabled self.options_enabled = is_enabled
@ -168,23 +284,22 @@ class MainWindow(QtGui.QWidget, CommandBase):
self.option_settings_enabled(True) self.option_settings_enabled(True)
self.directory_chooser_widget.setEnabled(True) self.directory_chooser_widget.setEnabled(True)
def get_tab_index_for_setting_name(self, name):
options_dict = {'app_settings': 0,
'webkit_settings': 0,
'window_settings': 1,
'export_settings': 2,
'compression': 3,
'download_settings': 4}
for setting_group_name, setting_group in self._setting_items:
if name in setting_group:
return options_dict.get(setting_group_name, None)
def required_settings_filled(self, ignore_options=False): def required_settings_filled(self, ignore_options=False):
if not self.options_enabled and not ignore_options: if not self.options_enabled and not ignore_options:
return False return False
proj_dir = self.project_dir() red_border = 'QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}'
out_dir = self.output_dir()
valid_proj_dirs = False
if proj_dir and out_dir:
if os.path.exists(proj_dir):
valid_proj_dirs = True
self.input_line.setStyleSheet('')
self.input_line.setToolTip('')
else:
self.input_line.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}')
self.input_line.setToolTip('The project directory does not exist.')
settings_valid = True settings_valid = True
for sgroup in self.settings['setting_groups']: for sgroup in self.settings['setting_groups']:
@ -196,8 +311,10 @@ class MainWindow(QtGui.QWidget, CommandBase):
settings_valid = False settings_valid = False
widget = self.find_child_by_name(setting.name) widget = self.find_child_by_name(setting.name)
if widget is not None: if widget is not None:
widget.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}') widget.setStyleSheet(red_border)
widget.setToolTip('This setting is required.') widget.setToolTip('This setting is required.')
tab = self.get_tab_index_for_setting_name(setting.name)
self.tab_widget.setTabIcon(tab, self.warning_settings_icon)
if (setting.type == 'file' and if (setting.type == 'file' and
setting.value and setting.value and
@ -206,8 +323,10 @@ class MainWindow(QtGui.QWidget, CommandBase):
settings_valid = False settings_valid = False
widget = self.find_child_by_name(setting.name) widget = self.find_child_by_name(setting.name)
if widget is not None: if widget is not None:
widget.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}') widget.setStyleSheet(red_border)
widget.setToolTip('The file "{}" does not exist.'.format(os.path.join(self.project_dir(),setting.value))) widget.setToolTip('The file "{}" does not exist.'.format(os.path.join(self.project_dir(),setting.value)))
tab = self.get_tab_index_for_setting_name(setting.name)
self.tab_widget.setTabIcon(tab, self.warning_settings_icon)
if (setting.type == 'folder' and if (setting.type == 'folder' and
setting.value and setting.value and
@ -215,12 +334,17 @@ class MainWindow(QtGui.QWidget, CommandBase):
settings_valid = False settings_valid = False
widget = self.find_child_by_name(setting.name) widget = self.find_child_by_name(setting.name)
if widget is not None: if widget is not None:
widget.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}') widget.setStyleSheet(red_border)
widget.setToolTip('The folder "{}" does not exist'.format(os.path.join(self.project_dir(), setting.value))) widget.setToolTip('The folder "{}" does not exist'.format(os.path.join(self.project_dir(), setting.value)))
tab = self.get_tab_index_for_setting_name(setting.name)
self.tab_widget.setTabIcon(tab, self.warning_settings_icon)
if settings_valid: if settings_valid:
widget = self.find_child_by_name(setting.name) widget = self.find_child_by_name(setting.name)
widget.setStyleSheet('') if widget is not None:
widget.setToolTip('') widget.setStyleSheet('')
widget.setToolTip('')
tab = self.get_tab_index_for_setting_name(setting.name)
self.tab_widget.setTabIcon(tab, self.tab_icons[tab])
export_chosen = False export_chosen = False
for setting_name, setting in self.settings['export_settings'].items(): for setting_name, setting in self.settings['export_settings'].items():
@ -233,21 +357,30 @@ class MainWindow(QtGui.QWidget, CommandBase):
if widget is not None: if widget is not None:
widget.setStyleSheet('QCheckBox{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}') widget.setStyleSheet('QCheckBox{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}')
widget.setToolTip('At least one of these options should be selected.') widget.setToolTip('At least one of these options should be selected.')
tab = self.get_tab_index_for_setting_name(setting.name)
self.tab_widget.setTabIcon(tab, self.warning_settings_icon)
else: else:
widget = self.find_child_by_name(setting.name) widget = self.find_child_by_name(setting.name)
widget.setStyleSheet('') if widget is not None:
widget.setToolTip('') widget.setStyleSheet('')
widget.setToolTip('')
tab = self.get_tab_index_for_setting_name(setting.name)
self.tab_widget.setTabIcon(tab, self.tab_icons[tab])
return export_chosen and valid_proj_dirs and settings_valid return export_chosen and settings_valid
def project_dir(self): def project_dir(self):
return self.project_path
if hasattr(self, 'input_line'): if hasattr(self, 'input_line'):
return self.input_line.text() return self.input_line.text()
return '' return ''
def output_dir(self): def output_dir(self):
if hasattr(self, 'output_line'): if hasattr(self, 'output_line'):
return self.output_line.text() if os.path.isabs(self.output_line.text()):
return self.output_line.text()
else:
return os.path.join(self.project_dir(), self.output_line.text())
return '' return ''
def create_download_bar(self): def create_download_bar(self):
@ -278,6 +411,7 @@ class MainWindow(QtGui.QWidget, CommandBase):
open_export_button.setEnabled(False) open_export_button.setEnabled(False)
open_export_button.setIcon(QtGui.QIcon(os.path.join('files', 'images', 'folder_open.png'))) open_export_button.setIcon(QtGui.QIcon(os.path.join('files', 'images', 'folder_open.png')))
open_export_button.setToolTip('Open Export Folder') open_export_button.setToolTip('Open Export Folder')
open_export_button.setStatusTip('Open Export Folder')
open_export_button.setMaximumWidth(30) open_export_button.setMaximumWidth(30)
open_export_button.setMaximumHeight(30) open_export_button.setMaximumHeight(30)
@ -481,45 +615,103 @@ class MainWindow(QtGui.QWidget, CommandBase):
# Download the file. # Download the file.
self.http_get_id = self.http.get(path, self.out_file) self.http_get_id = self.http.get(path, self.out_file)
def create_icon_box(self, name, text):
style = 'width:48px;height:48px;background-color:white;border-radius:5px;border:1px solid rgb(50,50,50);'
icon_label = QtGui.QLabel()
icon_label.setStyleSheet(style)
icon_label.setMaximumWidth(48)
icon_label.setMinimumWidth(48)
icon_label.setMaximumHeight(48)
icon_label.setMinimumHeight(48)
setattr(self, name, icon_label)
icon_text = QtGui.QLabel(text)
icon_text.setStyleSheet('font-size:10px;')
icon_text.setAlignment(QtCore.Qt.AlignCenter)
vbox = QVBoxLayout()
vbox.setAlignment(QtCore.Qt.AlignCenter)
vbox.addWidget(icon_label)
vbox.addWidget(icon_text)
vbox.setContentsMargins(0, 0, 0, 0)
w = QtGui.QWidget()
w.setLayout(vbox)
w.setMaximumWidth(70)
return w
def create_directory_choose(self): def create_directory_choose(self):
group_box = QtGui.QGroupBox("Choose Your Web Project") group_box = QtGui.QGroupBox('An awesome web project called:')
input_layout = QtGui.QHBoxLayout() title_hbox = QHBoxLayout()
title_hbox.setContentsMargins(10, 10, 10, 10)
input_label = QtGui.QLabel('Project Directory:') win_icon = self.create_icon_box('window_icon', 'Window Icon')
self.input_line = QtGui.QLineEdit() exe_icon = self.create_icon_box('exe_icon', 'Exe Icon')
self.input_line.textChanged.connect(self.project_path_changed) mac_icon = self.create_icon_box('mac_icon', 'Mac Icon')
input_button = QtGui.QPushButton('...')
input_button.clicked.connect(self.browse_dir)
input_layout.addWidget(input_label) self.title_label = QtGui.QLabel('TBD')
input_layout.addWidget(self.input_line) self.title_label.setStyleSheet('font-size:20px; font-weight:bold;')
input_layout.addWidget(input_button) title_hbox.addWidget(self.title_label)
title_hbox.addWidget(QtGui.QLabel())
output_layout = QtGui.QHBoxLayout() title_hbox.addWidget(win_icon)
title_hbox.addWidget(exe_icon)
output_label = QtGui.QLabel('Output Directory:') title_hbox.addWidget(mac_icon)
self.output_line = QtGui.QLineEdit()
self.output_line.textChanged.connect(self.project_path_changed)
output_button = QtGui.QPushButton('...')
output_button.clicked.connect(self.browse_out_dir)
output_layout.addWidget(output_label)
output_layout.addWidget(self.output_line)
output_layout.addWidget(output_button)
vlayout = QtGui.QVBoxLayout() vlayout = QtGui.QVBoxLayout()
vlayout.setSpacing(5) vlayout.setSpacing(5)
vlayout.setContentsMargins(10, 5, 10, 5) vlayout.setContentsMargins(10, 5, 10, 5)
vlayout.addLayout(input_layout) vlayout.addLayout(title_hbox)
vlayout.addLayout(output_layout) #vlayout.addLayout(input_layout)
#vlayout.addLayout(output_layout)
group_box.setLayout(vlayout) group_box.setLayout(vlayout)
return group_box return group_box
def set_window_icon(self):
icon_setting = self.get_setting('icon')
mac_icon_setting = self.get_setting('mac_icon')
exe_icon_setting = self.get_setting('exe_icon')
self.set_icon(icon_setting.value, self.window_icon)
if not mac_icon_setting.value:
self.set_icon(icon_setting.value, self.mac_icon)
if not exe_icon_setting.value:
self.set_icon(icon_setting.value, self.exe_icon)
def set_exe_icon(self):
icon_setting = self.get_setting('exe_icon')
self.set_icon(icon_setting.value, self.exe_icon)
def set_mac_icon(self):
icon_setting = self.get_setting('mac_icon')
self.set_icon(icon_setting.value, self.mac_icon)
def set_icon(self, icon_path, icon):
if icon_path:
icon_path = os.path.join(self.project_dir(), icon_path)
if os.path.exists(icon_path):
if icon_path.endswith('.icns'):
#image = QtGui.QImage.fromData(make_thumbnail(icon_path,48), 'png')
return
image = QtGui.QImage(icon_path)
if image.width() >= image.height():
image = image.scaledToWidth(48,
QtCore.Qt.SmoothTransformation)
else:
image = image.scaledToHeight(48,
QtCore.Qt.SmoothTransformation)
icon.setPixmap(QtGui.QPixmap.fromImage(image))
icon.setStyleSheet('')
else:
icon.setPixmap(None)
icon.setStyleSheet(self.icon_style)
else:
icon.setStyleSheet(self.icon_style)
def call_with_object(self, name, obj, *args, **kwargs): def call_with_object(self, name, obj, *args, **kwargs):
"""Allows arguments to be passed to click events""" """Allows arguments to be passed to click events"""
def call(*cargs, **ckwargs): def call(*cargs, **ckwargs):
@ -544,51 +736,67 @@ class MainWindow(QtGui.QWidget, CommandBase):
return self.find_child_by_name('app_name').text() return self.find_child_by_name('app_name').text()
def browse_dir(self): def browse_dir(self):
self.update_json = False directory = QtGui.QFileDialog.getExistingDirectory(self, 'Find Project Directory',
directory = QtGui.QFileDialog.getExistingDirectory(self, "Find Project Directory", self.project_dir() or self.last_project_dir)
self.project_dir() or QtCore.QDir.currentPath())
if directory: if directory:
self.reset_settings() self.load_project(directory)
self.input_line.setText(directory)
self.output_line.setText(os.path.join(directory, 'output'))
proj_name = os.path.basename(directory) def load_project(self, directory):
self.update_json = False
self.project_path = directory
self.save_recent_project(directory)
self.save_project_path(directory)
self.update_recent_files()
self.reset_settings()
#self.input_line.setText(directory)
setting_input = self.find_child_by_name('main')
files = (glob.glob(os.path.join(directory, 'index.html')) +
glob.glob(os.path.join(directory, 'index.php')) +
glob.glob(os.path.join(directory, 'index.htm')))
if not setting_input.text():
if files:
setting_input.setText(files[0].replace(self.project_dir() + os.path.sep, ''))
app_name_input = self.find_child_by_name('app_name') proj_name = os.path.basename(directory)
name_input = self.find_child_by_name('name') self.title_label.setText(proj_name)
name_setting = self.get_setting('name')
title_input = self.find_child_by_name('title')
if not name_input.text(): setting_input = self.find_child_by_name('main')
name_input.setText(name_setting.filter_name(proj_name)) files = (glob.glob(os.path.join(directory, 'index.html')) +
glob.glob(os.path.join(directory, 'index.php')) +
glob.glob(os.path.join(directory, 'index.htm')))
if not setting_input.text():
if files:
setting_input.setText(files[0].replace(self.project_dir() + os.path.sep, ''))
if not app_name_input.text(): app_name_input = self.find_child_by_name('app_name')
app_name_input.setText(proj_name) name_input = self.find_child_by_name('name')
name_setting = self.get_setting('name')
title_input = self.find_child_by_name('title')
if not title_input.text(): if not name_input.text():
title_input.setText(proj_name) name_input.setText(name_setting.filter_name(proj_name))
self.load_package_json() if not app_name_input.text():
self.open_export_button.setEnabled(True) app_name_input.setText(proj_name)
self.update_json = True
if not title_input.text():
title_input.setText(proj_name)
self.load_package_json()
default_dir = 'output'
export_dir_setting = self.get_setting('export_dir')
default_dir = export_dir_setting.value or default_dir
self.output_line.setText(default_dir)
self.set_window_icon()
self.open_export_button.setEnabled(True)
self.update_json = True
def browse_out_dir(self): def browse_out_dir(self):
self.update_json = False self.update_json = False
directory = QtGui.QFileDialog.getExistingDirectory(self, "Choose Output Directory", directory = QtGui.QFileDialog.getExistingDirectory(self, "Choose Output Directory",
(self.output_line.text() or (self.output_line.text() or
self.project_dir() or self.project_dir() or
QtCore.QDir.currentPath())) self.last_project_dir))
if directory: if directory:
self.output_line.setText(directory)
self.update_json = True self.update_json = True
self.output_line.setText(directory)
def get_file(self, obj, text_obj, setting, *args, **kwargs): def get_file(self, obj, text_obj, setting, *args, **kwargs):
file_path, _ = QtGui.QFileDialog.getOpenFileName(self, 'Choose File', file_path, _ = QtGui.QFileDialog.getOpenFileName(self, 'Choose File',
@ -612,12 +820,22 @@ class MainWindow(QtGui.QWidget, CommandBase):
setting.last_value = folder setting.last_value = folder
def create_application_settings(self): def create_application_settings(self):
group_box = QtGui.QGroupBox("Application Settings") group_box = QtGui.QWidget()
vlayout = self.create_layout(self.settings['order']['application_setting_order'], cols=4) vlayout = self.create_layout(self.settings['order']['application_setting_order'], cols=3)
group_box.setLayout(vlayout) group_box.setLayout(vlayout)
return group_box return group_box
def create_compression_settings(self):
group_box = QtGui.QWidget()
vlayout = self.create_layout(self.settings['order']['compression_setting_order'], cols=3)
warning_label = QtGui.QLabel('Note: When using compression (greater than 0) it will decrease the executable size,\nbut will increase the startup time when running it.')
vbox = QtGui.QVBoxLayout()
vbox.addLayout(vlayout)
vbox.addWidget(warning_label)
group_box.setLayout(vbox)
return group_box
def create_setting(self, name): def create_setting(self, name):
setting = self.get_setting(name) setting = self.get_setting(name)
if setting.type == 'string': if setting.type == 'string':
@ -634,30 +852,50 @@ class MainWindow(QtGui.QWidget, CommandBase):
return self.create_range_setting(name) return self.create_range_setting(name)
def create_window_settings(self): def create_window_settings(self):
group_box = QtGui.QGroupBox("Window Settings") group_box = QtGui.QWidget()
vlayout = self.create_layout(self.settings['order']['window_setting_order'], cols=4) vlayout = self.create_layout(self.settings['order']['window_setting_order'], cols=3)
group_box.setLayout(vlayout) group_box.setLayout(vlayout)
return group_box return group_box
def create_export_settings(self): def create_export_settings(self):
group_box = QtGui.QGroupBox("Export Settings") group_box = QtGui.QWidget()
vlayout = self.create_layout(self.settings['order']['export_setting_order'], cols=4) vlayout = self.create_layout(self.settings['order']['export_setting_order'], cols=4)
group_box.setLayout(vlayout) output_layout = QtGui.QHBoxLayout()
output_label = QtGui.QLabel('Output Directory:')
self.output_line = QtGui.QLineEdit()
self.output_line.textChanged.connect(self.call_with_object('setting_changed',
self.output_line, self.get_setting('export_dir')))
self.output_line.textChanged.connect(self.project_path_changed)
self.output_line.setStatusTip('The output directory relative to the project directory.')
output_button = QtGui.QPushButton('...')
output_button.clicked.connect(self.browse_out_dir)
output_layout.addWidget(output_label)
output_layout.addWidget(self.output_line)
output_layout.addWidget(output_button)
vbox = QtGui.QVBoxLayout()
vbox.addLayout(vlayout)
vbox.addLayout(output_layout)
group_box.setLayout(vbox)
return group_box return group_box
def create_download_settings(self): def create_download_settings(self):
group_box = QtGui.QGroupBox("Download Settings") group_box = QtGui.QWidget()
vlayout = self.create_layout(self.settings['order']['download_setting_order'], 2) vlayout = self.create_layout(self.settings['order']['download_setting_order'], cols=1)
group_box.setLayout(vlayout) group_box.setLayout(vlayout)
return group_box return group_box
def create_layout(self, settings, cols=3): def create_layout(self, settings, cols=3):
glayout = QtGui.QGridLayout() glayout = QtGui.QGridLayout()
glayout.setContentsMargins(10, 5, 10, 5) glayout.setContentsMargins(10, 15, 10, 5)
glayout.setAlignment(QtCore.Qt.AlignTop)
glayout.setSpacing(10) glayout.setSpacing(10)
glayout.setHorizontalSpacing(20)
col = 0 col = 0
row = 0 row = 0
@ -671,6 +909,7 @@ class MainWindow(QtGui.QWidget, CommandBase):
display_name += '*' display_name += '*'
setting_label = QtGui.QLabel(display_name) setting_label = QtGui.QLabel(display_name)
setting_label.setToolTip(setting.description) setting_label.setToolTip(setting.description)
setting_label.setStatusTip(setting.description)
glayout.addWidget(setting_label, row, col) glayout.addWidget(setting_label, row, col)
glayout.addLayout(self.create_setting(setting_name), glayout.addLayout(self.create_setting(setting_name),
row, col+1) row, col+1)
@ -691,6 +930,8 @@ class MainWindow(QtGui.QWidget, CommandBase):
text, setting)) text, setting))
if setting.value: if setting.value:
text.setText(str(setting.value)) text.setText(str(setting.value))
text.setStatusTip(setting.description)
text.setToolTip(setting.description)
hlayout.addWidget(text) hlayout.addWidget(text)
@ -713,6 +954,8 @@ class MainWindow(QtGui.QWidget, CommandBase):
if setting.value: if setting.value:
text.setText(str(setting.value)) text.setText(str(setting.value))
text.setStatusTip(setting.description)
text.setToolTip(setting.description)
text.textChanged.connect(self.call_with_object('setting_changed', text.textChanged.connect(self.call_with_object('setting_changed',
text, setting)) text, setting))
@ -739,6 +982,8 @@ class MainWindow(QtGui.QWidget, CommandBase):
if setting.value: if setting.value:
text.setText(str(setting.value)) text.setText(str(setting.value))
text.setStatusTip(setting.description)
text.setToolTip(setting.description)
text.textChanged.connect(self.call_with_object('setting_changed', text.textChanged.connect(self.call_with_object('setting_changed',
text, setting)) text, setting))
@ -752,6 +997,8 @@ class MainWindow(QtGui.QWidget, CommandBase):
for sgroup in self.settings['setting_groups']: for sgroup in self.settings['setting_groups']:
for setting in sgroup.values(): for setting in sgroup.values():
widget = self.find_child_by_name(setting.name) widget = self.find_child_by_name(setting.name)
if widget is None:
continue
if (setting.type == 'string' or if (setting.type == 'string' or
setting.type == 'file' or setting.type == 'file' or
@ -813,7 +1060,7 @@ class MainWindow(QtGui.QWidget, CommandBase):
if (setting.type == 'string' or if (setting.type == 'string' or
setting.type == 'file' or setting.type == 'file' or
setting.type == 'folder'): setting.type == 'folder'):
setting.value = obj.text() setting.value = args[0]
elif setting.type == 'check': elif setting.type == 'check':
setting.value = obj.isChecked() setting.value = obj.isChecked()
check_action = setting.check_action check_action = setting.check_action
@ -824,6 +1071,11 @@ class MainWindow(QtGui.QWidget, CommandBase):
elif setting.type == 'range': elif setting.type == 'range':
setting.value = obj.value() setting.value = obj.value()
if setting.action is not None:
action = getattr(self, setting.action, None)
if callable(action):
action()
if self.update_json: if self.update_json:
json_file = os.path.join(self.project_dir(), 'package.json') json_file = os.path.join(self.project_dir(), 'package.json')
@ -854,6 +1106,8 @@ class MainWindow(QtGui.QWidget, CommandBase):
check.clicked.connect(self.call_with_object('setting_changed', check.clicked.connect(self.call_with_object('setting_changed',
check, setting)) check, setting))
check.setChecked(setting.value) check.setChecked(setting.value)
check.setStatusTip(setting.description)
check.setToolTip(setting.description)
hlayout.addWidget(check) hlayout.addWidget(check)
@ -877,6 +1131,9 @@ class MainWindow(QtGui.QWidget, CommandBase):
combo.editTextChanged.connect(self.call_with_object('setting_changed', combo.editTextChanged.connect(self.call_with_object('setting_changed',
combo, setting)) combo, setting))
combo.setStatusTip(setting.description)
combo.setToolTip(setting.description)
for val in setting.values: for val in setting.values:
combo.addItem(val) combo.addItem(val)
@ -884,6 +1141,7 @@ class MainWindow(QtGui.QWidget, CommandBase):
if default_index != -1: if default_index != -1:
combo.setCurrentIndex(default_index) combo.setCurrentIndex(default_index)
hlayout.addWidget(QtGui.QLabel())
hlayout.addWidget(combo) hlayout.addWidget(combo)
if button: if button:
hlayout.addWidget(button) hlayout.addWidget(button)
@ -901,12 +1159,14 @@ class MainWindow(QtGui.QWidget, CommandBase):
button.clicked.connect(lambda: setting.button_callback(button)) button.clicked.connect(lambda: setting.button_callback(button))
slider = QtGui.QSlider(QtCore.Qt.Orientation.Horizontal) slider = QtGui.QSlider(QtCore.Qt.Orientation.Horizontal)
slider.setRange(0, 9) slider.setRange(setting.min, setting.max)
slider.valueChanged.connect(self.call_with_object('setting_changed', slider.valueChanged.connect(self.call_with_object('setting_changed',
slider, setting)) slider, setting))
slider.setObjectName(setting.name) slider.setObjectName(setting.name)
slider.setValue(setting.default_value) slider.setValue(setting.default_value)
slider.setStatusTip(setting.description)
slider.setToolTip(setting.description)
range_label = QtGui.QLabel(str(setting.default_value)) range_label = QtGui.QLabel(str(setting.default_value))
range_label.setMaximumWidth(30) range_label.setMaximumWidth(30)
@ -961,7 +1221,7 @@ if __name__ == '__main__':
QCoreApplication.setOrganizationName("SimplyPixelated") QCoreApplication.setOrganizationName("SimplyPixelated")
QCoreApplication.setOrganizationDomain("simplypixelated.com") QCoreApplication.setOrganizationDomain("simplypixelated.com")
frame = MainWindow(1000, 500, app) frame = MainWindow(800, 500, app)
frame.show_and_raise() frame.show_and_raise()
sys.exit(app.exec_()) sys.exit(app.exec_())