checkpoint. nearing completion of GUI

This commit is contained in:
Brennen Raimer
2019-04-19 20:12:57 -04:00
parent fb5131e480
commit 32c32306d6
3 changed files with 127 additions and 20 deletions

View File

@@ -1,135 +1,174 @@
{
"Portable Apps Platform": {
"page": "https://portableapps.com/download",
"category":"",
"xpath": "//*[@id=\"node-58089\"]/div/div[1]/div/div/div/div/a"
},
"Git": {
"page": "https://git-scm.com/download/win",
"category": "programming.tools.source code management",
"xpath": "//*[@id=\"main\"]/div/p[6]/strong/a"
},
"GitExtensions": {
"page": "https://github.com/gitextensions/gitextensions/releases/latest",
"category": "programming.tools.source code management",
"depends on": "programming.source code management.Git",
"xpath": "/html/body/div[4]/div/div/div[2]/div[1]/div[2]/div/div[2]/details/ul/li[1]/a",
"search": "GitExtensions-(\\d|\\.)+-Mono\\.zip$"
},
"WinPython": {
"page": "https://sourceforge.net/projects/winpython/",
"category": "programming.languages.python",
"xpath": "//*[@id=\"pg_project\"]/div[5]/div[2]/div[1]/div/section/div[2]/div[3]/a[1]"
},
"MSYS2": {
"page": "http://www.msys2.org/",
"Category": "programming.languages.C/C++",
"xpath": "//*[@id=\"downloads\"]/div[1]/a[2]"
},
"Java JDK": {
"page": "http://jdk.java.net/11/",
"page": "http://jdk.java.net/",
"category": "programming.languages.java",
"xpath": "",
"search": ""
},
"SublimeText": {
"page": "https://www.sublimetext.com/3",
"category": "programming.tools.text editors and integrated development environments",
"xpath": "//*[@id=\"dl_win_64\"]/a[2]",
"search": "Sublime\\sText\\sBuild\\s(\\d|\\.)+\\sx64\\.zip$"
},
"Atom": {
"page": "https://github.com/atom/atom/releases/latest",
"category": "programming.tools.text editors and integrated development environments",
"xpath": "/html/body/div[4]/div/div/div[2]/div[1]/div[2]/div/div[2]/details/ul/li[11]/a",
"search": "atom-x64-windows\\.zip$"
},
".NET Core SDK": {
"page": "https://www.microsoft.com/net/download/dotnet-core/",
"category": "programming.languages.C#",
"xpath": "",
"search": ""
},
"Node.js": {
"page": "https://nodejs.org/en/",
"category": "programming.languages.javascript",
"xpath": "",
"search": ""
},
"Google Chrome": {
"page": "https://portableapps.com/apps/internet/google_chrome_portable",
"category": "web.browsers",
"xpath": "//*[@id=\"node-57731\"]/div/div[1]/div/div/div/a"
},
"Mozilla Firefox": {
"page": "https://portableapps.com/apps/internet/firefox_portable",
"category": "web.browsers",
"xpath": "//*[@id=\"node-58088\"]/div/div[1]/div/div/div/a"
},
"Cherrytree": {
"page": "https://portableapps.com/apps/office/cherrytree-portable",
"category": "office.notes",
"xpath": "//*[@id=\"node-58652\"]/div/div[1]/div/div/div/a"
},
"KeepNote": {
"page": "https://portableapps.com/apps/office/keepnote-portable",
"category": "office.notes",
"xpath": "//*[@id=\"node-58966\"]/div/div[1]/div/div/div/a"
},
"LibreOffice": {
"page": "https://portableapps.com/apps/office/libreoffice_portable",
"category": "office.suite",
"xpath": "//*[@id=\"node-54208\"]/div/div[1]/div/div/div[1]/a"
},
"RedNotebook": {
"page": "https://portableapps.com/apps/office/rednotebook_portable",
"category": "office.notes",
"xpath": "//*[@id=\"node-58725\"]/div/div[1]/div/div/div/a"
},
"Filezilla": {
"page": "https://portableapps.com/apps/internet/filezilla_portable",
"category": "web.file transfer",
"xpath": "//*[@id=\"node-57960\"]/div/div[1]/div/div/div/a"
},
"WinSCP": {
"page": "https://portableapps.com/apps/internet/winscp_portable",
"category": "web.file transfer",
"xpath": "//*[@id=\"node-58447\"]/div/div[1]/div/div/div/a"
},
"Cppcheck": {
"page": "https://portableapps.com/apps/development/cppcheck-portable",
"category": "programming.languages.C/C++",
"xpath": "//*[@id=\"node-58057\"]/div/div[1]/div/div/div/a"
},
"Frhed": {
"page": "https://portableapps.com/apps/development/frhed_portable",
"category": "programming.tools",
"xpath": "//*[@id=\"node-58921\"]/div/div[1]/div/div/div/a"
},
"Geany": {
"page": "https://portableapps.com/apps/development/geany_portable",
"category": "programming.tools.text editors and integrated development environments",
"xpath": "//*[@id=\"node-58428\"]/div/div[1]/div/div/div/a"
},
"gVim": {
"page": "https://portableapps.com/apps/development/gvim_portable",
"category": "programming.tools.text editors and integrated development environments",
"xpath": "//*[@id=\"node-58871\"]/div/div[1]/div/div/div/a"
},
"Notepad++": {
"page": "https://portableapps.com/apps/development/notepadpp_portable",
"category": "programming.tools.text editors and integrated development environments",
"xpath": "//*[@id=\"node-57991\"]/div/div[1]/div/div/div/a"
},
"Peazip": {
"page": "https://portableapps.com/apps/utilities/peazip_portable",
"category": "utlities.archiving",
"xpath": "//*[@id=\"node-58441\"]/div/div[1]/div/div/div/a"
},
"7-Zip": {
"page": "https://portableapps.com/apps/utilities/7-zip_portable",
"category": "utlities.archiving",
"xpath": "//*[@id=\"node-57727\"]/div/div[1]/div/div/div/a"
},
"CubicExplorer": {
"page": "https://portableapps.com/apps/utilities/cubicexplorer_portable",
"category": "utilities.file browsers",
"xpath": "//*[@id=\"node-58914\"]/div/div[1]/div/div/div/a"
},
"Explorer++": {
"page": "https://portableapps.com/apps/utilities/explorerplusplus_portable",
"category": "utilities.file browsers",
"xpath": "//*[@id=\"node-58851\"]/div/div[1]/div/div/div/a"
},
"WinMerge": {
"page": "https://portableapps.com/apps/utilities/winmerge_portable",
"category": "programming.tools.file comparison",
"xpath": "//*[@id=\"node-58807\"]/div/div[1]/div/div/div/a"
},
"Command Prompt Portable": {
"page": "https://portableapps.com/apps/utilities/command_prompt_portable",
"category": "utilities.terminals",
"xpath": "//*[@id=\"node-58853\"]/div/div[1]/div/div/div/a"
},
"Console": {
"page": "https://portableapps.com/apps/utilities/console_portable",
"category": "utilities.terminals",
"xpath": "//*[@id=\"node-58901\"]/div/div[1]/div/div/div/a"
},
"KiTTY": {
"page": "https://portableapps.com/apps/internet/kitty-portable",
"category": "utilities.terminals.remote",
"xpath": "//*[@id=\"node-57811\"]/div/div[1]/div/div/div/a"
},
"PuTTY": {
"page": "https://portableapps.com/apps/internet/putty_portable",
"category": "utilities.terminals.remote",
"xpath": "//*[@id=\"node-58621\"]/div/div[1]/div/div/div/a"
},
"Microsoft Visual Studio Code": {
"page": "https://code.visualstudio.com/docs/?dv=win64user",
"category": "programming.tools.text editors and integrated development environments",
"xpath": "//*[@id=\"direct-link\"]"
}
}

View File

@@ -6,9 +6,10 @@ import webbrowser
import zipfile
from pathlib import Path
from queue import Queue
import json
import psutil
from PyQt5 import QtCore, QtGui, QtWebEngineWidgets, QtWidgets
from PyQt5 import QtCore, QtGui, QtNetwork, QtWebEngineWidgets, QtWidgets
from PyQt5.uic import loadUi
try:
@@ -24,16 +25,20 @@ class InstallerWizard(QtWidgets.QWizard):
def __init__(self, parent=None):
super().__init__(parent)
loadUi(Path(__file__).parent / "installer_wizard.ui", baseinstance=self)
self.button(QtWidgets.QWizard.NextButton).clicked.connect(self._requirements_check)
#self.button(QtWidgets.QWizard.NextButton).clicked.connect(self._requirements_check)
self.intro_page.validatePage = self._requirements_check
self.currentIdChanged.connect
self.intro.anchorClicked.connect(self._link_clicked)
self.license.anchorClicked.connect(self._link_clicked)
self.install_location.setValidator(Location_Validator(parent=self))
self.location_page.registerField("Location*", self.install_location)
self.browse_button.clicked.connect(self._link_clicked)
self.browse_button.clicked.connect(self._select_location)
#Change button text on license page
self.license_page.setButtonText(QtWidgets.QWizard.NextButton, "Agree")
self.license_page.setButtonText(QtWidgets.QWizard.CancelButton, "Decline")
self._network_manager = QtNetwork.QNetworkAccessManager(parent=QtWidgets.QApplication.instance())
self._thread_pool = QtCore.QThreadPool.globalInstance()
self._project_page=Path("https://github.com/norweeg/portable-computing-tookit-installer/")
def _link_clicked(self, address):
"""Receives anchorClicked signal from the intro or license text browsers and opens the address in an external web browser.
@@ -45,9 +50,9 @@ class InstallerWizard(QtWidgets.QWizard):
try:
webbrowser.open(address.toString())
except webbrowser.Error as e:
message=QtWidgets.QMessageBox(icon=QtWidgets.QMessageBox.Critical,parent=self,text="Unable to launch external browser")
message.setDetailedText(str(e))
message.show()
self._display_error("Unable to launch external browser",e)
except Exception as e:
self._display_error("An error has occurred",e)
def _select_location(self):
"""Opens a QFileDialog in either the root of the most-recently connected non-network, non-cd drive or the user's home directory,
@@ -67,21 +72,69 @@ class InstallerWizard(QtWidgets.QWizard):
selected_location = QtWidgets.QFileDialog.getExistingDirectory(parent=self,caption="Select Location",
directory=str(dialog_location),
options=(QtWidgets.QFileDialog.ShowDirsOnly))
self.__window.install_location.clear()
self.__window.install_location.insert(selected_location)
self.install_location.clear()
self.install_location.insert(selected_location)
def _requirements_check(self):
"""Checks that the minimum system requirements are met. Opens error message and resets the wizard if they are not.
Minimum Requirements: Windows 7 or greater (64-bit)
"""
process_dialog = QtWidgets.QProgressDialog("Checking System Requirements...", str(), 0, 100, self, QtCore.Qt.Dialog)
process_dialog.setAutoClose(True)
process_dialog.setAutoReset(True)
process_dialog.setCancelButton(None)
if self._network_manager.networkAccessible():
request = QtNetwork.QNetworkRequest(QtCore.QUrl("https://www.gnu.org/licenses/gpl-3.0-standalone.html"))
request.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute, QtNetwork.QNetworkRequest.AlwaysNetwork)
reply = self._network_manager.get(request)
reply.downloadProgress.connect(lambda received, total: process_dialog.setMaximum(total))
reply.downloadProgress.connect(lambda received, total: process_dialog.setValue(received))
process_dialog.show()
else:
self._display_error("This installer requires an active internet connection, but you do not appear to be online")
return False
if not platform.system() == 'Windows' or int(platform.release()) < 7:
QtWidgets.QMessageBox(icon=QtWidgets.QMessageBox.Critical,parent=self,text="This toolkit requires Microsoft Windows 7 or newer").show()
self.restart()
reply.abort()
process_dialog.cancel()
self._display_error("This toolkit requires Microsoft Windows 7 or newer")
return False
elif not platform.machine() == 'AMD64':
QtWidgets.QMessageBox(icon=QtWidgets.QMessageBox.Critical,parent=self,text='''Parts of this toolkit require a 64-bit processor.
Please open an issue on Github or Gitlab if you absolutely need it all 32-bit''').show()
self.restart()
reply.abort()
process_dialog.cancel()
self._display_error("Parts of this toolkit require a 64-bit processor. Please open an issue on Github if you absolutely need it all 32-bit")\
.buttonClicked.connect(lambda: webbrowser.open_new_tab(self._project_page/"issues"))
return False
else:
return True
while reply.isRunning():
QtWidgets.QApplication.instance().processEvents()
QtCore.QThread.currentThread().msleep(100)
if not reply.error():
self.license.setHtml(bytearray(reply.readAll()).decode("utf-8"))
return True
else:
self._display_error(f"Encountered a {QtCore.QMetaEnum.valueToKey(reply.error())} while testing Internet connectivity")
return False
def _display_error(self, message, exception = None):
message=QtWidgets.QMessageBox(icon=QtWidgets.QMessageBox.Critical,parent=self,text=message)
if exception:
message.setDetailedText(str(exception))
message.show()
return message
def _load_tools(self):
request = QtNetwork.QNetworkRequest(QtCore.QUrl(f"{self._project_page}/blob/master/resources/supported_tools.json"))
reply = self._network_manager.get(request)
while reply.isRunning():
QtWidgets.QApplication.instance().processEvents()
QtCore.QThread.currentThread().msleep(100)
if not reply.error():
try:
self.tools = json.loads(reply.readAll())
except json.JSONDecodeError as e:
self._display_error(f"Unable to decode {request.url.toString()}", e)
else:
self._display_error(f"Encountered a {QtCore.QMetaEnum.valueToKey(reply.error())} error while loading supported tools")
return False

View File

@@ -56,7 +56,20 @@
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e; background-color:#ffffff;&quot;&gt;The portable computing toolkit installer sets up and combines the &lt;/span&gt;&lt;a href=&quot;https://portableapps.com/&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; text-decoration: underline; color:#0366d6; background-color:#ffffff;&quot;&gt;PortableApps.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e; background-color:#ffffff;&quot;&gt; framework with various tools for writing code. The goal of this project is to provide a platform for anyone who has computing needs but does not own their on PC to be able to have a private workspace on public/shared computers.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; font-family:'Segoe UI, sans-serif'; color:#24292e; background-color:transparent;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; font-weight:600;&quot;&gt;Requirements:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; background-color:transparent;&quot; style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e;&quot;&gt;A PC runninging Windows 7 (64-bit) or later&lt;/span&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif';&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot; background-color:transparent;&quot; style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e;&quot;&gt;An &lt;/span&gt;&lt;a href=&quot;https://lifehacker.com/how-to-erase-and-format-a-hard-drive-1525128357&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; text-decoration: underline; color:#0366d6;&quot;&gt;NTFS-Formatted&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e;&quot;&gt; USB storage device&lt;/span&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif';&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot; background-color:transparent;&quot; style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e;&quot;&gt;An active Internet connection&lt;/span&gt; &lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; font-weight:600;&quot;&gt;Contributing and bug reporting:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif';&quot;&gt;Source code for this installer is available on &lt;/span&gt;&lt;a href=&quot;https://github.com/norweeg/portable-computing-tookit-installer&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; text-decoration: underline; color:#0000ff;&quot;&gt;Github&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif';&quot;&gt;. This installer was originally a learning exercise for myself to learn python, so I welcome you to help improve it!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif';&quot;&gt;This installer scrapes the web for the URLs to the installers for the software. I don't have control over the homepages of the tools in this toolkit, so if they fail to download, it's likely that the download page has changed and this tool needs to be updated to reflect those changes. If you find the installer is unable to download one of the tools, please &lt;/span&gt;&lt;a href=&quot;https://github.com/norweeg/portable-computing-tookit-installer/issues&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;open an issue&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif';&quot;&gt; on &lt;/span&gt;Github&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e; background-color:#ffffff;&quot;&gt;This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; font-family:'Segoe UI, sans-serif'; color:#24292e; background-color:#ffffff;&quot;&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;span style=&quot; background-color:transparent;&quot;&gt;Copyright © 2019 &lt;/span&gt;&lt;a href=&quot;https://github.com/norweeg&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Brennen Raimer&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:115%; background-color:transparent;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:100%; background-color:transparent;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
@@ -81,10 +94,12 @@ p, li { white-space: pre-wrap; }
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTextBrowser" name="license">
<property name="source">
<url>
<string>qrc:/resources/license.html</string>
</url>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openLinks">
<bool>false</bool>