If anything is causing the export button not to function, the field will now be highlighted in red.
928 lines
33 KiB
Python
928 lines
33 KiB
Python
from utils import log, open_folder_in_explorer
|
|
|
|
__gui_version__ = "v0.1.17b"
|
|
|
|
import os
|
|
import re
|
|
import glob
|
|
import sys
|
|
|
|
from PySide import QtGui, QtCore
|
|
from PySide.QtGui import QApplication
|
|
from PySide.QtNetwork import QHttp
|
|
from PySide.QtCore import QUrl, QFile, QIODevice, QCoreApplication
|
|
|
|
|
|
from command_line import CWD, CommandBase
|
|
|
|
|
|
class Validator(QtGui.QRegExpValidator):
|
|
def __init__(self, regex, action, parent=None):
|
|
self.exp = regex
|
|
self.action = unicode
|
|
if hasattr(unicode, action):
|
|
self.action = getattr(unicode, action)
|
|
reg = QtCore.QRegExp(regex)
|
|
super(Validator, self).__init__(reg, parent)
|
|
|
|
def validate(self, text, pos):
|
|
result = super(Validator, self).validate(text, pos)
|
|
return result
|
|
|
|
def fixup(self, text):
|
|
return ''.join(re.findall(self.exp, self.action(unicode(text))))
|
|
|
|
|
|
class BackgroundThread(QtCore.QThread):
|
|
def __init__(self, widget, method_name, parent=None):
|
|
QtCore.QThread.__init__(self, parent)
|
|
self.widget = widget
|
|
self.method_name = method_name
|
|
|
|
def run(self):
|
|
if hasattr(self.widget, self.method_name):
|
|
func = getattr(self.widget, self.method_name)
|
|
func()
|
|
|
|
|
|
class MainWindow(QtGui.QWidget, CommandBase):
|
|
|
|
def update_nw_versions(self, button):
|
|
self.get_versions_in_background()
|
|
|
|
def __init__(self, width, height, parent=None):
|
|
super(MainWindow, self).__init__(parent)
|
|
CommandBase.__init__(self)
|
|
self.options_enabled = False
|
|
self.output_package_json = True
|
|
self.setWindowIcon(QtGui.QIcon(os.path.join(CWD, 'files',
|
|
'images', 'icon.png')))
|
|
self.update_json = False
|
|
|
|
self.setup_nw_versions()
|
|
|
|
self.thread = None
|
|
self.original_packagejson = {}
|
|
|
|
self.resize(width, height)
|
|
|
|
self.extract_error = None
|
|
|
|
self.create_application_layout()
|
|
|
|
self.option_settings_enabled(False)
|
|
|
|
self.setWindowTitle("Web2Executable {}".format(__gui_version__))
|
|
self.update_nw_versions(None)
|
|
|
|
def setup_nw_versions(self):
|
|
nw_version = self.get_setting('nw_version')
|
|
try:
|
|
f = open(os.path.join(CWD, 'files', 'nw-versions.txt'))
|
|
for line in f:
|
|
nw_version.values.append(line.strip())
|
|
except IOError:
|
|
nw_version.values.append(nw_version.default_value)
|
|
|
|
def create_application_layout(self):
|
|
self.main_layout = QtGui.QVBoxLayout()
|
|
self.main_layout.setContentsMargins(10, 5, 10, 5)
|
|
|
|
self.create_layout_widgets()
|
|
|
|
self.addWidgets_to_main_layout()
|
|
|
|
self.setLayout(self.main_layout)
|
|
|
|
def create_layout_widgets(self):
|
|
self.download_bar_widget = self.create_download_bar()
|
|
self.app_settings_widget = self.create_application_settings()
|
|
self.win_settings_widget = self.create_window_settings()
|
|
self.ex_settings_widget = self.create_export_settings()
|
|
self.dl_settings_widget = self.create_download_settings()
|
|
self.directory_chooser_widget = self.create_directory_choose()
|
|
|
|
def addWidgets_to_main_layout(self):
|
|
self.main_layout.addWidget(self.directory_chooser_widget)
|
|
self.main_layout.addWidget(self.app_settings_widget)
|
|
self.main_layout.addWidget(self.win_settings_widget)
|
|
self.main_layout.addWidget(self.ex_settings_widget)
|
|
self.main_layout.addWidget(self.dl_settings_widget)
|
|
self.main_layout.addLayout(self.download_bar_widget)
|
|
|
|
def option_settings_enabled(self, is_enabled):
|
|
self.ex_button.setEnabled(is_enabled)
|
|
self.app_settings_widget.setEnabled(is_enabled)
|
|
self.win_settings_widget.setEnabled(is_enabled)
|
|
self.ex_settings_widget.setEnabled(is_enabled)
|
|
self.dl_settings_widget.setEnabled(is_enabled)
|
|
self.options_enabled = is_enabled
|
|
|
|
def export(self, export_button, cancel_button):
|
|
self.get_files_to_download()
|
|
self.try_to_download_files()
|
|
|
|
def open_export(self, open_export_button):
|
|
open_folder_in_explorer(self.output_dir())
|
|
|
|
def try_to_download_files(self):
|
|
if self.files_to_download:
|
|
self.progress_bar.setVisible(True)
|
|
self.cancel_button.setEnabled(True)
|
|
self.disable_ui_while_working()
|
|
|
|
self.download_file_with_error_handling()
|
|
else:
|
|
# This shouldn't happen since we disable the UI if there are no
|
|
# options selected
|
|
# But in the weird event that this does happen, we are prepared!
|
|
QtGui.QMessageBox.information(self,
|
|
'Export Options Empty!',
|
|
('Please choose one of '
|
|
'the export options!'))
|
|
|
|
def selected_version(self):
|
|
return self.get_setting('nw_version').value
|
|
|
|
def enable_ui_after_error(self):
|
|
self.enable_ui()
|
|
self.progress_text = ''
|
|
self.progress_bar.setVisible(False)
|
|
self.cancel_button.setEnabled(False)
|
|
|
|
def show_error(self, exception):
|
|
QtGui.QMessageBox.information(self, 'Error!', str(exception))
|
|
|
|
def disable_ui_while_working(self):
|
|
self.option_settings_enabled(False)
|
|
self.directory_chooser_widget.setEnabled(False)
|
|
|
|
def enable_ui(self):
|
|
self.option_settings_enabled(True)
|
|
self.directory_chooser_widget.setEnabled(True)
|
|
|
|
def required_settings_filled(self, ignore_options=False):
|
|
if not self.options_enabled and not ignore_options:
|
|
return False
|
|
|
|
proj_dir = self.project_dir()
|
|
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
|
|
for sgroup in self.settings['setting_groups']:
|
|
for sname, setting in sgroup.items():
|
|
setting_path = os.path.join(self.project_dir(),
|
|
str(setting.value))
|
|
|
|
if setting.required and not setting.value:
|
|
settings_valid = False
|
|
widget = self.find_child_by_name(setting.name)
|
|
if widget is not None:
|
|
widget.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}')
|
|
widget.setToolTip('This setting is required.')
|
|
|
|
if (setting.type == 'file' and
|
|
setting.value and
|
|
not os.path.exists(setting_path)):
|
|
log(setting.value, "does not exist")
|
|
settings_valid = False
|
|
widget = self.find_child_by_name(setting.name)
|
|
if widget is not None:
|
|
widget.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}')
|
|
widget.setToolTip('The file "{}" does not exist.'.format(os.path.join(self.project_dir(),setting.value)))
|
|
|
|
if (setting.type == 'folder' and
|
|
setting.value and
|
|
not os.path.exists(setting_path)):
|
|
settings_valid = False
|
|
widget = self.find_child_by_name(setting.name)
|
|
if widget is not None:
|
|
widget.setStyleSheet('QLineEdit{border:3px solid rgba(238, 68, 83, 200); border-radius:5px;}')
|
|
widget.setToolTip('The folder "{}" does not exist'.format(os.path.join(self.project_dir(), setting.value)))
|
|
if settings_valid:
|
|
widget = self.find_child_by_name(setting.name)
|
|
widget.setStyleSheet('')
|
|
widget.setToolTip('')
|
|
|
|
export_chosen = False
|
|
for setting_name, setting in self.settings['export_settings'].items():
|
|
if setting.value:
|
|
export_chosen = True
|
|
|
|
for setting_name, setting in self.settings['export_settings'].items():
|
|
if not export_chosen:
|
|
widget = self.find_child_by_name(setting.name)
|
|
if widget is not None:
|
|
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.')
|
|
else:
|
|
widget = self.find_child_by_name(setting.name)
|
|
widget.setStyleSheet('')
|
|
widget.setToolTip('')
|
|
|
|
return export_chosen and valid_proj_dirs and settings_valid
|
|
|
|
def project_dir(self):
|
|
if hasattr(self, 'input_line'):
|
|
return self.input_line.text()
|
|
return ''
|
|
|
|
def output_dir(self):
|
|
if hasattr(self, 'output_line'):
|
|
return self.output_line.text()
|
|
return ''
|
|
|
|
def create_download_bar(self):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
vlayout = QtGui.QVBoxLayout()
|
|
vlayout.setContentsMargins(5, 5, 5, 5)
|
|
vlayout.setSpacing(5)
|
|
hlayout.setSpacing(5)
|
|
hlayout.setContentsMargins(5, 5, 5, 5)
|
|
|
|
progress_label = QtGui.QLabel('')
|
|
progress_bar = QtGui.QProgressBar()
|
|
progress_bar.setVisible(False)
|
|
progress_bar.setContentsMargins(5, 5, 5, 5)
|
|
|
|
vlayout.addWidget(progress_label)
|
|
vlayout.addWidget(progress_bar)
|
|
vlayout.addWidget(QtGui.QLabel(''))
|
|
|
|
ex_button = QtGui.QPushButton('Export')
|
|
ex_button.setEnabled(False)
|
|
|
|
cancel_button = QtGui.QPushButton('Cancel Download')
|
|
cancel_button.setEnabled(False)
|
|
|
|
open_export_button = QtGui.QPushButton()
|
|
open_export_button.setEnabled(False)
|
|
open_export_button.setIcon(QtGui.QIcon(os.path.join('files', 'images', 'folder_open.png')))
|
|
open_export_button.setToolTip('Open Export Folder')
|
|
open_export_button.setMaximumWidth(30)
|
|
open_export_button.setMaximumHeight(30)
|
|
|
|
ex_button.clicked.connect(self.call_with_object('export', ex_button, cancel_button))
|
|
cancel_button.clicked.connect(self.cancel_download)
|
|
open_export_button.clicked.connect(self.call_with_object('open_export', open_export_button))
|
|
|
|
button_box = QtGui.QDialogButtonBox()
|
|
button_box.addButton(open_export_button, QtGui.QDialogButtonBox.NoRole)
|
|
button_box.addButton(cancel_button, QtGui.QDialogButtonBox.RejectRole)
|
|
button_box.addButton(ex_button, QtGui.QDialogButtonBox.AcceptRole)
|
|
|
|
hlayout.addLayout(vlayout)
|
|
hlayout.addWidget(button_box)
|
|
|
|
self.progress_label = progress_label
|
|
self.progress_bar = progress_bar
|
|
self.cancel_button = cancel_button
|
|
self.open_export_button = open_export_button
|
|
|
|
http = QHttp(self)
|
|
http.requestFinished.connect(self.http_request_finished)
|
|
http.dataReadProgress.connect(self.update_progress_bar)
|
|
http.responseHeaderReceived.connect(self.read_response_header)
|
|
self.http = http
|
|
self.ex_button = ex_button
|
|
|
|
return hlayout
|
|
|
|
def read_response_header(self, response_header):
|
|
# Check for genuine error conditions.
|
|
if response_header.statusCode() not in (200, 300, 301, 302, 303, 307):
|
|
self.show_error('Download failed: {}.'.format(response_header.reasonPhrase()))
|
|
self.http_request_aborted = True
|
|
self.http.abort()
|
|
self.enable_ui_after_error()
|
|
|
|
def http_request_finished(self, request_id, error):
|
|
if request_id != self.http_get_id:
|
|
return
|
|
|
|
if self.http_request_aborted:
|
|
if self.out_file is not None:
|
|
self.out_file.close()
|
|
self.out_file.remove()
|
|
self.out_file = None
|
|
return
|
|
|
|
self.out_file.close()
|
|
self.http.abort()
|
|
|
|
if error:
|
|
self.out_file.remove()
|
|
self.show_error('Download failed: {}.'.format(self.http.errorString()))
|
|
self.enable_ui_after_error()
|
|
else:
|
|
self.continue_downloading_or_extract()
|
|
|
|
def continue_downloading_or_extract(self):
|
|
if self.files_to_download:
|
|
self.progress_bar.setVisible(True)
|
|
self.cancel_button.setEnabled(True)
|
|
self.disable_ui_while_working()
|
|
|
|
self.download_file_with_error_handling()
|
|
else:
|
|
self.progress_text = 'Done.'
|
|
self.cancel_button.setEnabled(False)
|
|
self.progress_bar.setVisible(False)
|
|
self.extract_files_in_background()
|
|
|
|
@property
|
|
def progress_text(self):
|
|
return self.progress_label.text()
|
|
|
|
@progress_text.setter
|
|
def progress_text(self, value):
|
|
self.progress_label.setText(str(value))
|
|
|
|
def run_in_background(self, method_name, callback):
|
|
self.thread = BackgroundThread(self, method_name)
|
|
self.thread.finished.connect(callback)
|
|
self.thread.start()
|
|
|
|
def get_versions_in_background(self):
|
|
self.ex_button.setEnabled(False)
|
|
self.run_in_background('get_versions', self.done_getting_versions)
|
|
|
|
def done_getting_versions(self):
|
|
self.ex_button.setEnabled(self.required_settings_filled())
|
|
self.progress_text = 'Done retrieving versions.'
|
|
|
|
nw_version = self.get_setting('nw_version')
|
|
combo = self.find_child_by_name(nw_version.name)
|
|
|
|
combo.clear()
|
|
combo.addItems(nw_version.values)
|
|
|
|
def make_output_files_in_background(self):
|
|
self.ex_button.setEnabled(False)
|
|
self.run_in_background('make_output_dirs', self.done_making_files)
|
|
|
|
def done_making_files(self):
|
|
self.ex_button.setEnabled(self.required_settings_filled())
|
|
self.progress_text = 'Done Exporting.'
|
|
self.enable_ui()
|
|
self.delete_files()
|
|
if self.output_err:
|
|
self.show_error(self.output_err)
|
|
self.enable_ui_after_error()
|
|
|
|
def extract_files_in_background(self):
|
|
self.progress_text = 'Extracting.'
|
|
self.ex_button.setEnabled(False)
|
|
|
|
self.run_in_background('extract_files', self.done_extracting)
|
|
|
|
def done_extracting(self):
|
|
self.ex_button.setEnabled(self.required_settings_filled())
|
|
if self.extract_error:
|
|
self.progress_text = 'Error extracting.'
|
|
self.show_error('There were one or more errors with your '
|
|
'zip/tar files. They were deleted. Please '
|
|
'try to export again.')
|
|
|
|
self.enable_ui_after_error()
|
|
|
|
else:
|
|
self.progress_text = 'Done extracting.'
|
|
self.make_output_files_in_background()
|
|
|
|
def cancel_download(self):
|
|
self.progress_text = 'Download cancelled.'
|
|
self.cancel_button.setEnabled(False)
|
|
self.http_request_aborted = True
|
|
self.http.abort()
|
|
self.enable_ui()
|
|
self.progress_bar.setValue(0)
|
|
self.progress_bar.setVisible(False)
|
|
|
|
def update_progress_bar(self, bytes_read, total_bytes):
|
|
if self.http_request_aborted:
|
|
self.progress_bar.setValue(0)
|
|
self.progress_bar.setVisible(False)
|
|
return
|
|
self.progress_bar.setMaximum(total_bytes)
|
|
self.progress_bar.setValue(bytes_read)
|
|
|
|
def download_file(self, path, setting):
|
|
version_file = self.settings['base_url'].format(self.selected_version())
|
|
|
|
location = self.get_setting('download_dir').value
|
|
|
|
versions = re.findall('v(\d+)\.(\d+)\.(\d+)', path)[0]
|
|
|
|
minor = int(versions[1])
|
|
if minor >= 12:
|
|
path = path.replace('node-webkit', 'nwjs')
|
|
|
|
self.progress_text = 'Downloading {}'.format(path.replace(version_file, ''))
|
|
|
|
url = QUrl(path)
|
|
file_name = setting.save_file_path(self.selected_version(), location)
|
|
|
|
archive_exists = QFile.exists(file_name)
|
|
|
|
#dest_files_exist = False
|
|
|
|
# for dest_file in setting.dest_files:
|
|
# dest_file_path = os.path.join('files', setting.name, dest_file)
|
|
# dest_files_exist &= QFile.exists(dest_file_path)
|
|
|
|
forced = self.get_setting('force_download').value
|
|
|
|
if archive_exists and not forced:
|
|
self.continue_downloading_or_extract()
|
|
return
|
|
|
|
self.out_file = QFile(file_name)
|
|
if not self.out_file.open(QIODevice.WriteOnly):
|
|
error = self.out_file.error().name
|
|
self.show_error('Unable to save the file {}: {}.'.format(file_name,
|
|
error))
|
|
self.out_file = None
|
|
self.enable_ui()
|
|
return
|
|
|
|
mode = QHttp.ConnectionModeHttp
|
|
port = url.port()
|
|
if port == -1:
|
|
port = 0
|
|
self.http.setHost(url.host(), mode, port)
|
|
self.http_request_aborted = False
|
|
|
|
path = QUrl.toPercentEncoding(url.path(), "!$&'()*+,;=:@/")
|
|
if path:
|
|
path = str(path)
|
|
else:
|
|
path = '/'
|
|
|
|
# Download the file.
|
|
self.http_get_id = self.http.get(path, self.out_file)
|
|
|
|
def create_directory_choose(self):
|
|
group_box = QtGui.QGroupBox("Choose Your Web Project")
|
|
|
|
input_layout = QtGui.QHBoxLayout()
|
|
|
|
input_label = QtGui.QLabel('Project Directory:')
|
|
self.input_line = QtGui.QLineEdit()
|
|
self.input_line.textChanged.connect(self.project_path_changed)
|
|
input_button = QtGui.QPushButton('...')
|
|
input_button.clicked.connect(self.browse_dir)
|
|
|
|
input_layout.addWidget(input_label)
|
|
input_layout.addWidget(self.input_line)
|
|
input_layout.addWidget(input_button)
|
|
|
|
output_layout = QtGui.QHBoxLayout()
|
|
|
|
output_label = QtGui.QLabel('Output Directory:')
|
|
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.setSpacing(5)
|
|
vlayout.setContentsMargins(10, 5, 10, 5)
|
|
|
|
vlayout.addLayout(input_layout)
|
|
vlayout.addLayout(output_layout)
|
|
|
|
group_box.setLayout(vlayout)
|
|
|
|
return group_box
|
|
|
|
def call_with_object(self, name, obj, *args, **kwargs):
|
|
"""Allows arguments to be passed to click events"""
|
|
def call(*cargs, **ckwargs):
|
|
if hasattr(self, name):
|
|
func = getattr(self, name)
|
|
kwargs.update(ckwargs)
|
|
func(obj, *(args+cargs), **kwargs)
|
|
return call
|
|
|
|
def find_child_by_name(self, name):
|
|
return self.findChild(QtCore.QObject, name)
|
|
|
|
def find_all_children(self, names):
|
|
children = []
|
|
for child in self.find_children(QtCore.QObject):
|
|
if child.object_name() in names:
|
|
children.append(child)
|
|
|
|
return children
|
|
|
|
def project_name(self):
|
|
return self.find_child_by_name('app_name').text()
|
|
|
|
def browse_dir(self):
|
|
self.update_json = False
|
|
directory = QtGui.QFileDialog.getExistingDirectory(self, "Find Project Directory",
|
|
self.project_dir() or QtCore.QDir.currentPath())
|
|
if directory:
|
|
self.reset_settings()
|
|
self.input_line.setText(directory)
|
|
self.output_line.setText(os.path.join(directory, 'output'))
|
|
|
|
proj_name = os.path.basename(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')
|
|
name_input = self.find_child_by_name('name')
|
|
name_setting = self.get_setting('name')
|
|
title_input = self.find_child_by_name('title')
|
|
|
|
if not name_input.text():
|
|
name_input.setText(name_setting.filter_name(proj_name))
|
|
|
|
if not app_name_input.text():
|
|
app_name_input.setText(proj_name)
|
|
|
|
if not title_input.text():
|
|
title_input.setText(proj_name)
|
|
|
|
self.load_package_json()
|
|
self.open_export_button.setEnabled(True)
|
|
self.update_json = True
|
|
|
|
def browse_out_dir(self):
|
|
self.update_json = False
|
|
directory = QtGui.QFileDialog.getExistingDirectory(self, "Choose Output Directory",
|
|
(self.output_line.text() or
|
|
self.project_dir() or
|
|
QtCore.QDir.currentPath()))
|
|
if directory:
|
|
self.output_line.setText(directory)
|
|
self.update_json = True
|
|
|
|
def get_file(self, obj, text_obj, setting, *args, **kwargs):
|
|
file_path, _ = QtGui.QFileDialog.getOpenFileName(self, 'Choose File',
|
|
(setting.last_value or
|
|
self.project_dir() or
|
|
QtCore.QDir.currentPath()),
|
|
setting.file_types)
|
|
if file_path:
|
|
file_path = os.path.abspath(file_path) # fixes an issue with windows paths
|
|
file_path = file_path.replace(self.project_dir()+os.path.sep, '')
|
|
text_obj.setText(file_path)
|
|
setting.last_value = file_path
|
|
|
|
def get_folder(self, obj, text_obj, setting, *args, **kwargs):
|
|
folder = QtGui.QFileDialog.getExistingDirectory(self, 'Choose Folder',
|
|
(setting.last_value or
|
|
QtCore.QDir.currentPath()))
|
|
if folder:
|
|
folder = folder.replace(self.project_dir()+os.path.sep, '')
|
|
text_obj.setText(folder)
|
|
setting.last_value = folder
|
|
|
|
def create_application_settings(self):
|
|
group_box = QtGui.QGroupBox("Application Settings")
|
|
vlayout = self.create_layout(self.settings['order']['application_setting_order'], cols=4)
|
|
|
|
group_box.setLayout(vlayout)
|
|
return group_box
|
|
|
|
def create_setting(self, name):
|
|
setting = self.get_setting(name)
|
|
if setting.type == 'string':
|
|
return self.create_text_input_setting(name)
|
|
elif setting.type == 'file':
|
|
return self.create_text_input_with_file_setting(name)
|
|
elif setting.type == 'folder':
|
|
return self.create_text_input_with_folder_setting(name)
|
|
elif setting.type == 'check':
|
|
return self.create_check_setting(name)
|
|
elif setting.type == 'list':
|
|
return self.create_list_setting(name)
|
|
elif setting.type == 'range':
|
|
return self.create_range_setting(name)
|
|
|
|
def create_window_settings(self):
|
|
group_box = QtGui.QGroupBox("Window Settings")
|
|
vlayout = self.create_layout(self.settings['order']['window_setting_order'], cols=4)
|
|
|
|
group_box.setLayout(vlayout)
|
|
return group_box
|
|
|
|
def create_export_settings(self):
|
|
group_box = QtGui.QGroupBox("Export Settings")
|
|
vlayout = self.create_layout(self.settings['order']['export_setting_order'], cols=4)
|
|
|
|
group_box.setLayout(vlayout)
|
|
return group_box
|
|
|
|
def create_download_settings(self):
|
|
group_box = QtGui.QGroupBox("Download Settings")
|
|
vlayout = self.create_layout(self.settings['order']['download_setting_order'], 2)
|
|
|
|
group_box.setLayout(vlayout)
|
|
return group_box
|
|
|
|
def create_layout(self, settings, cols=3):
|
|
glayout = QtGui.QGridLayout()
|
|
glayout.setContentsMargins(10, 5, 10, 5)
|
|
glayout.setSpacing(10)
|
|
col = 0
|
|
row = 0
|
|
|
|
for setting_name in settings:
|
|
setting = self.get_setting(setting_name)
|
|
if col >= cols*2:
|
|
row += 1
|
|
col = 0
|
|
display_name = setting.display_name+':'
|
|
if setting.required:
|
|
display_name += '*'
|
|
setting_label = QtGui.QLabel(display_name)
|
|
setting_label.setToolTip(setting.description)
|
|
glayout.addWidget(setting_label, row, col)
|
|
glayout.addLayout(self.create_setting(setting_name),
|
|
row, col+1)
|
|
col += 2
|
|
|
|
return glayout
|
|
|
|
def create_text_input_setting(self, name):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
setting = self.get_setting(name)
|
|
|
|
text = QtGui.QLineEdit()
|
|
text.setValidator(Validator(setting.filter, setting.filter_action))
|
|
text.setObjectName(setting.name)
|
|
|
|
text.textChanged.connect(self.call_with_object('setting_changed',
|
|
text, setting))
|
|
if setting.value:
|
|
text.setText(str(setting.value))
|
|
|
|
hlayout.addWidget(text)
|
|
|
|
return hlayout
|
|
|
|
def create_text_input_with_file_setting(self, name):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
setting = self.get_setting(name)
|
|
|
|
text = QtGui.QLineEdit()
|
|
text.setObjectName(setting.name)
|
|
|
|
button = QtGui.QPushButton('...')
|
|
button.setMaximumWidth(30)
|
|
button.setMaximumHeight(26)
|
|
|
|
button.clicked.connect(self.call_with_object('get_file', button,
|
|
text, setting))
|
|
|
|
if setting.value:
|
|
text.setText(str(setting.value))
|
|
|
|
text.textChanged.connect(self.call_with_object('setting_changed',
|
|
text, setting))
|
|
|
|
hlayout.addWidget(text)
|
|
hlayout.addWidget(button)
|
|
|
|
return hlayout
|
|
|
|
def create_text_input_with_folder_setting(self, name):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
setting = self.get_setting(name)
|
|
|
|
text = QtGui.QLineEdit()
|
|
text.setObjectName(setting.name)
|
|
|
|
button = QtGui.QPushButton('...')
|
|
button.setMaximumWidth(30)
|
|
button.setMaximumHeight(26)
|
|
|
|
button.clicked.connect(self.call_with_object('get_folder', button,
|
|
text, setting))
|
|
|
|
if setting.value:
|
|
text.setText(str(setting.value))
|
|
|
|
text.textChanged.connect(self.call_with_object('setting_changed',
|
|
text, setting))
|
|
|
|
hlayout.addWidget(text)
|
|
hlayout.addWidget(button)
|
|
|
|
return hlayout
|
|
|
|
def reset_settings(self):
|
|
for sgroup in self.settings['setting_groups']:
|
|
for setting in sgroup.values():
|
|
widget = self.find_child_by_name(setting.name)
|
|
|
|
if (setting.type == 'string' or
|
|
setting.type == 'file' or
|
|
setting.type == 'folder'):
|
|
old_val = ''
|
|
|
|
if setting.default_value is not None:
|
|
old_val = setting.default_value
|
|
|
|
setting.value = old_val.replace('\\', '\\\\')
|
|
widget.setText(str(old_val))
|
|
|
|
elif setting.type == 'check':
|
|
old_val = False
|
|
|
|
if setting.default_value is not None:
|
|
old_val = setting.default_value
|
|
|
|
setting.value = old_val
|
|
widget.setChecked(old_val)
|
|
|
|
elif setting.type == 'range':
|
|
old_val = 0
|
|
if setting.default_value is not None:
|
|
old_val = setting.default_value
|
|
setting.value = old_val
|
|
widget.setValue(old_val)
|
|
|
|
def setting_changed(self, obj, setting, *args, **kwargs):
|
|
if (setting.type == 'string' or
|
|
setting.type == 'file' or
|
|
setting.type == 'folder'):
|
|
setting.value = obj.text()
|
|
elif setting.type == 'check':
|
|
setting.value = obj.isChecked()
|
|
elif setting.type == 'list':
|
|
setting.value = obj.currentText()
|
|
elif setting.type == 'range':
|
|
setting.value = obj.value()
|
|
|
|
if self.update_json:
|
|
json_file = os.path.join(self.project_dir(), 'package.json')
|
|
|
|
with open(json_file, 'w+') as f:
|
|
f.write(self.generate_json())
|
|
|
|
self.ex_button.setEnabled(self.required_settings_filled())
|
|
|
|
def project_path_changed(self, text):
|
|
self.ex_button.setEnabled(self.required_settings_filled(True))
|
|
|
|
dirs_filled_out = False
|
|
if self.project_dir() and self.output_dir():
|
|
if os.path.exists(self.project_dir()):
|
|
dirs_filled_out = True
|
|
|
|
self.option_settings_enabled(dirs_filled_out)
|
|
|
|
def create_check_setting(self, name):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
setting = self.get_setting(name)
|
|
|
|
check = QtGui.QCheckBox()
|
|
|
|
check.setObjectName(setting.name)
|
|
|
|
check.clicked.connect(self.call_with_object('setting_changed',
|
|
check, setting))
|
|
check.setChecked(setting.value)
|
|
|
|
hlayout.addWidget(check)
|
|
|
|
return hlayout
|
|
|
|
def create_list_setting(self, name):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
setting = self.get_setting(name)
|
|
|
|
button = None
|
|
if setting.button:
|
|
button = QtGui.QPushButton(setting.button)
|
|
button.clicked.connect(lambda: setting.button_callback(button))
|
|
combo = QtGui.QComboBox()
|
|
|
|
combo.setObjectName(setting.name)
|
|
|
|
combo.currentIndexChanged.connect(self.call_with_object('setting_changed',
|
|
combo, setting))
|
|
combo.editTextChanged.connect(self.call_with_object('setting_changed',
|
|
combo, setting))
|
|
|
|
for val in setting.values:
|
|
combo.addItem(val)
|
|
|
|
default_index = combo.findText(setting.default_value)
|
|
if default_index != -1:
|
|
combo.setCurrentIndex(default_index)
|
|
|
|
hlayout.addWidget(combo)
|
|
if button:
|
|
hlayout.addWidget(button)
|
|
|
|
return hlayout
|
|
|
|
def create_range_setting(self, name):
|
|
hlayout = QtGui.QHBoxLayout()
|
|
|
|
setting = self.get_setting(name)
|
|
|
|
button = None
|
|
if setting.button:
|
|
button = QtGui.QPushButton(setting.button)
|
|
button.clicked.connect(lambda: setting.button_callback(button))
|
|
|
|
slider = QtGui.QSlider(QtCore.Qt.Orientation.Horizontal)
|
|
slider.setRange(0, 9)
|
|
slider.valueChanged.connect(self.call_with_object('setting_changed',
|
|
slider, setting))
|
|
|
|
slider.setObjectName(setting.name)
|
|
slider.setValue(setting.default_value)
|
|
|
|
range_label = QtGui.QLabel(str(setting.default_value))
|
|
range_label.setMaximumWidth(30)
|
|
|
|
slider.valueChanged.connect(self.call_with_object('_update_range_label',
|
|
range_label))
|
|
|
|
w = QtGui.QWidget()
|
|
whlayout = QtGui.QHBoxLayout()
|
|
whlayout.addWidget(slider)
|
|
whlayout.addWidget(range_label)
|
|
w.setLayout(whlayout)
|
|
|
|
hlayout.addWidget(w)
|
|
|
|
return hlayout
|
|
|
|
def _update_range_label(self, label, value):
|
|
label.setText(str(value))
|
|
|
|
def load_package_json(self):
|
|
setting_list = super(MainWindow, self).load_package_json()
|
|
for setting in setting_list:
|
|
setting_field = self.find_child_by_name(setting.name)
|
|
if setting_field:
|
|
if (setting.type == 'file' or
|
|
setting.type == 'string' or
|
|
setting.type == 'folder'):
|
|
val_str = self.convert_val_to_str(setting.value)
|
|
setting_field.setText(setting.filter_name(val_str))
|
|
if setting.type == 'check':
|
|
setting_field.setChecked(setting.value)
|
|
if setting.type == 'list':
|
|
val_str = self.convert_val_to_str(setting.value)
|
|
index = setting_field.findText(val_str)
|
|
if index != -1:
|
|
setting_field.setCurrentIndex(index)
|
|
if setting.type == 'range':
|
|
setting_field.setValue(setting.value)
|
|
self.ex_button.setEnabled(self.required_settings_filled())
|
|
|
|
def show_and_raise(self):
|
|
self.show()
|
|
self.raise_()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
|
|
QCoreApplication.setApplicationName("Web2Executable")
|
|
QCoreApplication.setApplicationVersion(__gui_version__)
|
|
QCoreApplication.setOrganizationName("SimplyPixelated")
|
|
QCoreApplication.setOrganizationDomain("simplypixelated.com")
|
|
|
|
frame = MainWindow(1000, 500)
|
|
frame.show_and_raise()
|
|
|
|
sys.exit(app.exec_())
|