From b22ae7b89f7993f632e10e18c116f293f314575f Mon Sep 17 00:00:00 2001 From: Benjamin Dobell Date: Thu, 19 Feb 2015 03:13:56 +1100 Subject: Removed autotools and VS files, and standardised source dir naming --- heimdall-frontend/Source/Alerts.cpp | 45 - heimdall-frontend/Source/Alerts.h | 38 - heimdall-frontend/Source/FirmwareInfo.cpp | 783 ---------------- heimdall-frontend/Source/FirmwareInfo.h | 302 ------- heimdall-frontend/Source/PackageData.cpp | 66 -- heimdall-frontend/Source/PackageData.h | 77 -- heimdall-frontend/Source/Packaging.cpp | 934 -------------------- heimdall-frontend/Source/Packaging.h | 121 --- heimdall-frontend/Source/aboutform.cpp | 126 --- heimdall-frontend/Source/aboutform.h | 58 -- heimdall-frontend/Source/main.cpp | 40 - heimdall-frontend/Source/mainwindow.cpp | 1375 ----------------------------- heimdall-frontend/Source/mainwindow.h | 183 ---- 13 files changed, 4148 deletions(-) delete mode 100644 heimdall-frontend/Source/Alerts.cpp delete mode 100644 heimdall-frontend/Source/Alerts.h delete mode 100644 heimdall-frontend/Source/FirmwareInfo.cpp delete mode 100644 heimdall-frontend/Source/FirmwareInfo.h delete mode 100644 heimdall-frontend/Source/PackageData.cpp delete mode 100644 heimdall-frontend/Source/PackageData.h delete mode 100644 heimdall-frontend/Source/Packaging.cpp delete mode 100644 heimdall-frontend/Source/Packaging.h delete mode 100644 heimdall-frontend/Source/aboutform.cpp delete mode 100644 heimdall-frontend/Source/aboutform.h delete mode 100644 heimdall-frontend/Source/main.cpp delete mode 100644 heimdall-frontend/Source/mainwindow.cpp delete mode 100644 heimdall-frontend/Source/mainwindow.h (limited to 'heimdall-frontend/Source') diff --git a/heimdall-frontend/Source/Alerts.cpp b/heimdall-frontend/Source/Alerts.cpp deleted file mode 100644 index 0dfe19c..0000000 --- a/heimdall-frontend/Source/Alerts.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Qt -#include - -// Heimdall Frontend -#include "Alerts.h" - -using namespace HeimdallFrontend; - -void Alerts::DisplayError(const QString& errorMessage) -{ - QMessageBox messageBox; - messageBox.setModal(true); - messageBox.setText(errorMessage); - messageBox.setIcon(QMessageBox::Critical); - messageBox.exec(); -} - -void Alerts::DisplayWarning(const QString& warningMessage) -{ - QMessageBox messageBox; - messageBox.setModal(true); - messageBox.setText(warningMessage); - messageBox.setIcon(QMessageBox::Warning); - messageBox.exec(); -} diff --git a/heimdall-frontend/Source/Alerts.h b/heimdall-frontend/Source/Alerts.h deleted file mode 100644 index 68b9c91..0000000 --- a/heimdall-frontend/Source/Alerts.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef ALERTS_H -#define ALERTS_H - -// Qt -#include - -namespace HeimdallFrontend -{ - class Alerts - { - public: - - static void DisplayError(const QString& errorMessage); - static void DisplayWarning(const QString& warningMessage); - }; -} - -#endif diff --git a/heimdall-frontend/Source/FirmwareInfo.cpp b/heimdall-frontend/Source/FirmwareInfo.cpp deleted file mode 100644 index c01d636..0000000 --- a/heimdall-frontend/Source/FirmwareInfo.cpp +++ /dev/null @@ -1,783 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Qt -#include "QRegExp" - -// Heimdall Frontend -#include "Alerts.h" -#include "FirmwareInfo.h" -#include "Packaging.h" - -using namespace HeimdallFrontend; - -DeviceInfo::DeviceInfo() -{ -} - -DeviceInfo::DeviceInfo(const QString& manufacturer, const QString& product, const QString& name) -{ - this->manufacturer = manufacturer; - this->product = product; - this->name = name; -} - -bool DeviceInfo::ParseXml(QXmlStreamReader& xml) -{ - bool foundManufacturer = false; - bool foundProduct = false; - bool foundName = false; - - while (!xml.atEnd()) - { - QXmlStreamReader::TokenType nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "manufacturer") - { - if (foundManufacturer) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundManufacturer = true; - - manufacturer = xml.readElementText(); - } - else if (xml.name() == "product") - { - if (foundProduct) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundProduct = true; - - product = xml.readElementText(); - } - else if (xml.name() == "name") - { - if (foundName) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundName = true; - - name = xml.readElementText(); - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "device") - { - if (foundManufacturer && foundProduct && foundName) - { - return (true); - } - else - { - Alerts::DisplayError("Required elements are missing from ."); - return (false); - } - } - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - - return (false); -} - -void DeviceInfo::WriteXml(QXmlStreamWriter& xml) const -{ - xml.writeStartElement("device"); - - xml.writeStartElement("manufacturer"); - xml.writeCharacters(manufacturer); - xml.writeEndElement(); - - xml.writeStartElement("product"); - xml.writeCharacters(product); - xml.writeEndElement(); - - xml.writeStartElement("name"); - xml.writeCharacters(name); - xml.writeEndElement(); - - xml.writeEndElement(); -} - - - -PlatformInfo::PlatformInfo() -{ -} - -void PlatformInfo::Clear(void) -{ - name.clear(); - version.clear(); -} - -bool PlatformInfo::IsCleared(void) const -{ - return (name.isEmpty() && version.isEmpty()); -} - -bool PlatformInfo::ParseXml(QXmlStreamReader& xml) -{ - Clear(); - - bool foundName = false; - bool foundVersion = false; - - while (!xml.atEnd()) - { - QXmlStreamReader::TokenType nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "name") - { - if (foundName) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundName = true; - - name = xml.readElementText(); - } - else if (xml.name() == "version") - { - if (foundVersion) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundVersion = true; - - version = xml.readElementText(); - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "platform") - { - if (foundName && foundVersion) - { - return (true); - } - else - { - Alerts::DisplayError("Required elements are missing from ."); - return (false); - } - } - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - - return (false); -} - -void PlatformInfo::WriteXml(QXmlStreamWriter& xml) const -{ - xml.writeStartElement("platform"); - - xml.writeStartElement("name"); - xml.writeCharacters(name); - xml.writeEndElement(); - - xml.writeStartElement("version"); - xml.writeCharacters(version); - xml.writeEndElement(); - - xml.writeEndElement(); -} - - - -FileInfo::FileInfo() -{ -} - -FileInfo::FileInfo(unsigned int partitionId, const QString& filename) -{ - this->partitionId = partitionId; - this->filename = filename; -} - -bool FileInfo::ParseXml(QXmlStreamReader& xml) -{ - bool foundId = false; - bool foundFilename = false; - - while (!xml.atEnd()) - { - QXmlStreamReader::TokenType nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "id") - { - if (foundId) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundId = true; - - partitionId = xml.readElementText().toInt(); - } - else if (xml.name() == "filename") - { - if (foundFilename) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundFilename = true; - - filename = xml.readElementText(); - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "file") - { - if (foundId && foundFilename) - { - return (true); - } - else - { - Alerts::DisplayError("Required elements are missing from ."); - return (false); - } - } - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - - return (false); -} - -void FileInfo::WriteXml(QXmlStreamWriter& xml, const QString& filename) const -{ - xml.writeStartElement("file"); - - xml.writeStartElement("id"); - xml.writeCharacters(QString::number(partitionId)); - xml.writeEndElement(); - - xml.writeStartElement("filename"); - xml.writeCharacters(filename); - xml.writeEndElement(); - - xml.writeEndElement(); -} - - - -FirmwareInfo::FirmwareInfo() -{ - repartition = false; - noReboot = false; -} - -void FirmwareInfo::Clear(void) -{ - name = ""; - version = ""; - platformInfo.Clear(); - - developers.clear(); - url.clear(); - donateUrl.clear(); - - deviceInfos.clear(); - - pitFilename.clear(); - repartition = false; - - noReboot = false; - - fileInfos.clear(); -} - -bool FirmwareInfo::IsCleared(void) const -{ - return (name.isEmpty() && version.isEmpty() && platformInfo.IsCleared() && developers.isEmpty() && url.isEmpty() && url.isEmpty() && donateUrl.isEmpty() - && deviceInfos.isEmpty() && pitFilename.isEmpty() && !repartition && !noReboot && fileInfos.isEmpty()); -} - -bool FirmwareInfo::ParseXml(QXmlStreamReader& xml) -{ - Clear(); - - bool foundName = false; - bool foundVersion = false; - bool foundPlatform = false; - bool foundDevelopers = false; - bool foundUrl = false; - bool foundDonateUrl = false; - bool foundDevices = false; - bool foundPit = false; - bool foundRepartition = false; - bool foundNoReboot = false; - bool foundFiles = false; - - if (!xml.readNextStartElement()) - { - Alerts::DisplayError("Failed to find element."); - return (false); - } - - if (xml.name() != "firmware") - { - Alerts::DisplayError(QString("Expected element but found <%1>.").arg(xml.name().toString())); - return (false); - } - - QString formatVersionString; - formatVersionString += xml.attributes().value("version"); - - if (formatVersionString.isEmpty()) - { - Alerts::DisplayError(" is missing the version attribute."); - return (false); - } - - bool parsedVersion = false; - int formatVersion = formatVersionString.toInt(&parsedVersion); - - if (!parsedVersion) - { - Alerts::DisplayError(" contains a malformed version."); - return (false); - } - - if (formatVersion > kVersion) - { - Alerts::DisplayError("Package is for a newer version of Heimdall Frontend.\nPlease download the latest version of Heimdall Frontend."); - return (false); - } - - while (!xml.atEnd()) - { - QXmlStreamReader::TokenType nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "name") - { - if (foundName) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundName = true; - name = xml.readElementText(); - } - else if (xml.name() == "version") - { - if (foundVersion) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundVersion = true; - version = xml.readElementText(); - } - else if (xml.name() == "platform") - { - if (foundPlatform) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundPlatform = true; - - if (!platformInfo.ParseXml(xml)) - return (false); - } - else if (xml.name() == "developers") - { - if (foundDevelopers) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundDevelopers = true; - - while (!xml.atEnd()) - { - nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "name") - { - developers.append(xml.readElementText()); - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "developers") - break; - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - } - else if (xml.name() == "url") - { - if (foundUrl) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundUrl = true; - - url = xml.readElementText(); - } - else if (xml.name() == "donateurl") - { - if (foundDonateUrl) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundDonateUrl = true; - - donateUrl = xml.readElementText(); - } - else if (xml.name() == "devices") - { - if (foundDevices) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundDevices = true; - - while (!xml.atEnd()) - { - nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "device") - { - DeviceInfo deviceInfo; - - if (!deviceInfo.ParseXml(xml)) - return (false); - - deviceInfos.append(deviceInfo); - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "devices") - break; - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - } - else if (xml.name() == "pit") - { - if (foundPit) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundPit = true; - - pitFilename = xml.readElementText(); - } - else if (xml.name() == "repartition") - { - if (foundRepartition) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundRepartition = true; - - repartition = (xml.readElementText().toInt() != 0); - } - else if (xml.name() == "noreboot") - { - if (foundNoReboot) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundNoReboot = true; - - noReboot = (xml.readElementText().toInt() != 0); - } - else if (xml.name() == "files") - { - if (foundFiles) - { - Alerts::DisplayError("Found multiple elements in ."); - return (false); - } - - foundFiles = true; - - while (!xml.atEnd()) - { - nextToken = xml.readNext(); - - if (nextToken == QXmlStreamReader::StartElement) - { - if (xml.name() == "file") - { - FileInfo fileInfo; - - if (!fileInfo.ParseXml(xml)) - return (false); - - fileInfos.append(fileInfo); - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "files") - break; - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - } - else - { - Alerts::DisplayError(QString("<%1> is not a valid child of .").arg(xml.name().toString())); - return (false); - } - } - else if (nextToken == QXmlStreamReader::EndElement) - { - if (xml.name() == "firmware") - { - if (!(foundName && foundVersion && foundPlatform && foundDevelopers && foundDevices && foundPit && foundRepartition && foundNoReboot && foundFiles)) - { - Alerts::DisplayError("Required elements are missing from ."); - return (false); - } - else - { - break; - } - } - } - else - { - if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) - { - Alerts::DisplayError("Unexpected token found in ."); - return (false); - } - } - } - - // Read whitespaces at the end of the file (if there are any) - xml.readNext(); - - if (!xml.atEnd()) - { - Alerts::DisplayError("Found data after ."); - return (false); - } - - return (true); -} - -void FirmwareInfo::WriteXml(QXmlStreamWriter& xml) const -{ - xml.writeStartDocument(); - xml.writeStartElement("firmware"); - xml.writeAttribute("version", QString::number(FirmwareInfo::kVersion)); - - xml.writeStartElement("name"); - xml.writeCharacters(name); - xml.writeEndElement(); - - xml.writeStartElement("version"); - xml.writeCharacters(version); - xml.writeEndElement(); - - platformInfo.WriteXml(xml); - - xml.writeStartElement("developers"); - - for (int i = 0; i < developers.length(); i++) - { - xml.writeStartElement("name"); - xml.writeCharacters(developers[i]); - xml.writeEndElement(); - } - - xml.writeEndElement(); - - if (!url.isEmpty()) - { - xml.writeStartElement("url"); - xml.writeCharacters(url); - xml.writeEndElement(); - } - - if (!donateUrl.isEmpty()) - { - xml.writeStartElement("donateurl"); - xml.writeCharacters(donateUrl); - xml.writeEndElement(); - } - - xml.writeStartElement("devices"); - - for (int i = 0; i < deviceInfos.length(); i++) - deviceInfos[i].WriteXml(xml); - - xml.writeEndElement(); - - xml.writeStartElement("pit"); - - int lastSlash = pitFilename.lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = pitFilename.lastIndexOf('\\'); - - xml.writeCharacters(pitFilename.mid(lastSlash + 1)); - - xml.writeEndElement(); - - xml.writeStartElement("repartition"); - xml.writeCharacters((repartition) ? "1" : "0"); - xml.writeEndElement(); - - xml.writeStartElement("noreboot"); - xml.writeCharacters((noReboot) ? "1" : "0"); - xml.writeEndElement(); - - xml.writeStartElement("files"); - - for (int i = 0; i < fileInfos.length(); i++) - { - fileInfos[i].WriteXml(xml, Packaging::ClashlessFilename(fileInfos, i)); - } - - xml.writeEndElement(); - - xml.writeEndElement(); - xml.writeEndDocument(); -} diff --git a/heimdall-frontend/Source/FirmwareInfo.h b/heimdall-frontend/Source/FirmwareInfo.h deleted file mode 100644 index 8e6713e..0000000 --- a/heimdall-frontend/Source/FirmwareInfo.h +++ /dev/null @@ -1,302 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef FIRMWAREINFO_H -#define FIRMWAREINFO_H - -// Qt -#include -#include -#include - -namespace HeimdallFrontend -{ - class DeviceInfo - { - private: - - QString manufacturer; - QString product; - QString name; - - public: - - DeviceInfo(); - DeviceInfo(const QString& manufacturer, const QString& product, const QString& name); - - bool ParseXml(QXmlStreamReader& xml); - void WriteXml(QXmlStreamWriter& xml) const; - - const QString& GetManufacturer(void) const - { - return (manufacturer); - } - - void SetManufacturer(const QString& manufacturer) - { - this->manufacturer = manufacturer; - } - - const QString& GetProduct(void) const - { - return (product); - } - - void SetProduct(const QString& product) - { - this->product = product; - } - - const QString& GetName(void) const - { - return (name); - } - - void SetName(const QString& name) - { - this->name = name; - } - }; - - class PlatformInfo - { - private: - - QString name; - QString version; - - public: - - PlatformInfo(); - - void Clear(void); - bool IsCleared(void) const; - - bool ParseXml(QXmlStreamReader& xml); - void WriteXml(QXmlStreamWriter& xml) const; - - const QString& GetName(void) const - { - return (name); - } - - void SetName(const QString& name) - { - this->name = name; - } - - const QString& GetVersion(void) const - { - return (version); - } - - void SetVersion(const QString& version) - { - this->version = version; - } - }; - - class FileInfo - { - private: - - unsigned int partitionId; - QString filename; - - public: - - FileInfo(); - FileInfo(unsigned int partitionId, const QString& filename); - - bool ParseXml(QXmlStreamReader& xml); - void WriteXml(QXmlStreamWriter& xml, const QString& filename) const; - - unsigned int GetPartitionId(void) const - { - return (partitionId); - } - - void SetPartitionId(unsigned int partitionId) - { - this->partitionId = partitionId; - } - - const QString& GetFilename(void) const - { - return (filename); - } - - void SetFilename(const QString& filename) - { - this->filename = filename; - } - }; - - class FirmwareInfo - { - public: - - enum - { - kVersion = 1 - }; - - private: - - QString name; - QString version; - PlatformInfo platformInfo; - - QList developers; - QString url; - QString donateUrl; - - QList deviceInfos; - - QString pitFilename; - bool repartition; - - bool noReboot; - - QList fileInfos; - - public: - - FirmwareInfo(); - - void Clear(void); - bool IsCleared(void) const; - - bool ParseXml(QXmlStreamReader& xml); - void WriteXml(QXmlStreamWriter& xml) const; - - const QString& GetName(void) const - { - return (name); - } - - void SetName(const QString& name) - { - this->name = name; - } - - const QString& GetVersion(void) const - { - return (version); - } - - void SetVersion(const QString& version) - { - this->version = version; - } - - const PlatformInfo& GetPlatformInfo(void) const - { - return (platformInfo); - } - - PlatformInfo& GetPlatformInfo(void) - { - return (platformInfo); - } - - const QList& GetDevelopers(void) const - { - return (developers); - } - - QList& GetDevelopers(void) - { - return (developers); - } - - const QString& GetUrl(void) const - { - return (url); - } - - void SetUrl(const QString& url) - { - this->url = url; - } - - const QString& GetDonateUrl(void) const - { - return (donateUrl); - } - - void SetDonateUrl(const QString& donateUrl) - { - this->donateUrl = donateUrl; - } - - const QList& GetDeviceInfos(void) const - { - return (deviceInfos); - } - - QList& GetDeviceInfos(void) - { - return (deviceInfos); - } - - const QString& GetPitFilename(void) const - { - return (pitFilename); - } - - void SetPitFilename(const QString& pitFilename) - { - this->pitFilename = pitFilename; - } - - bool GetRepartition(void) const - { - return (repartition); - } - - void SetRepartition(bool repartition) - { - this->repartition = repartition; - } - - bool GetNoReboot(void) const - { - return (noReboot); - } - - void SetNoReboot(bool noReboot) - { - this->noReboot = noReboot; - } - - const QList& GetFileInfos(void) const - { - return (fileInfos); - } - - QList& GetFileInfos(void) - { - return (fileInfos); - } - }; -} - -#endif diff --git a/heimdall-frontend/Source/PackageData.cpp b/heimdall-frontend/Source/PackageData.cpp deleted file mode 100644 index c3689b3..0000000 --- a/heimdall-frontend/Source/PackageData.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Heimdall Frontend -#include "Alerts.h" -#include "PackageData.h" - -using namespace HeimdallFrontend; - -PackageData::PackageData() -{ -} - -PackageData::~PackageData() -{ - for (int i = 0; i < files.length(); i++) - delete files[i]; -} - -void PackageData::Clear(void) -{ - firmwareInfo.Clear(); - - for (int i = 0; i < files.length(); i++) - delete files[i]; - - files.clear(); -} - -bool PackageData::ReadFirmwareInfo(QFile *file) -{ - if (!file->open(QFile::ReadOnly)) - { - Alerts::DisplayError(QString("Failed to open file: \1%s").arg(file->fileName())); - return (false); - } - - QXmlStreamReader xml(file); - bool success = firmwareInfo.ParseXml(xml); - - file->close(); - - return (success); -} - -bool PackageData::IsCleared(void) const -{ - return (firmwareInfo.IsCleared() && files.isEmpty()); -} diff --git a/heimdall-frontend/Source/PackageData.h b/heimdall-frontend/Source/PackageData.h deleted file mode 100644 index 84f081c..0000000 --- a/heimdall-frontend/Source/PackageData.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef PACKAGEDATA_H -#define PACKAGEDATA_H - -// Qt -#include - -// Heimdall Frontend -#include "FirmwareInfo.h" - -namespace HeimdallFrontend -{ - class PackageData - { - private: - - FirmwareInfo firmwareInfo; - QList files; - - public: - - PackageData(); - ~PackageData(); - - void Clear(void); - bool ReadFirmwareInfo(QFile *file); - - bool IsCleared(void) const; - - const FirmwareInfo& GetFirmwareInfo(void) const - { - return (firmwareInfo); - } - - FirmwareInfo& GetFirmwareInfo(void) - { - return (firmwareInfo); - } - - const QList& GetFiles(void) const - { - return (files); - } - - QList& GetFiles(void) - { - return (files); - } - - // Simply clears the files list, it does delete/close any files. - void RemoveAllFiles(void) - { - files.clear(); - } - }; -} - -#endif diff --git a/heimdall-frontend/Source/Packaging.cpp b/heimdall-frontend/Source/Packaging.cpp deleted file mode 100644 index 7a27b3c..0000000 --- a/heimdall-frontend/Source/Packaging.cpp +++ /dev/null @@ -1,934 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifdef WIN32 -#pragma warning(disable : 4996) -#endif - -// C/C++ Standard Library -#include - -// zlib -#include "zlib.h" - -// Qt -#include -#include -#include - -// Heimdall Frontend -#include "Alerts.h" -#include "Packaging.h" - -using namespace HeimdallFrontend; - -const qint64 Packaging::kMaxFileSize = 8589934592ll; -const char *Packaging::ustarMagic = "ustar"; - -bool Packaging::ExtractTar(QTemporaryFile& tarFile, PackageData *packageData) -{ - TarHeader tarHeader; - - if (!tarFile.open()) - { - Alerts::DisplayError(QString("Error opening temporary TAR archive:\n%1").arg(tarFile.fileName())); - return (false); - } - - bool previousEmpty = false; - - QProgressDialog progressDialog("Extracting files...", "Cancel", 0, tarFile.size()); - progressDialog.setWindowModality(Qt::ApplicationModal); - progressDialog.setWindowTitle("Heimdall Frontend"); - - while (!tarFile.atEnd()) - { - qint64 dataRead = tarFile.read(tarHeader.buffer, TarHeader::kBlockLength); - - if (dataRead != TarHeader::kBlockLength) - { - progressDialog.close(); - Alerts::DisplayError("Package's TAR archive is malformed."); - - tarFile.close(); - - return (false); - } - - progressDialog.setValue(tarFile.pos()); - - if (progressDialog.wasCanceled()) - { - tarFile.close(); - progressDialog.close(); - - return (false); - } - - //bool ustarFormat = strcmp(tarHeader.fields.magic, ustarMagic) == 0; - bool empty = true; - - for (int i = 0; i < TarHeader::kBlockLength; i++) - { - if (tarHeader.buffer[i] != 0) - { - empty = false; - break; - } - } - - if (empty) - { - if (previousEmpty) - { - // Two empty blocks in a row means we've reached the end of the archive. - break; - } - } - else - { - int checksum = 0; - - for (char *bufferIndex = tarHeader.buffer; bufferIndex < tarHeader.fields.checksum; bufferIndex++) - checksum += static_cast(*bufferIndex); - - checksum += 8 * ' '; - checksum += static_cast(tarHeader.fields.typeFlag); - - // Both the TAR and USTAR formats have terrible documentation, it's not clear if the following code is required. - /*if (ustarFormat) - { - for (char *bufferIndex = tarHeader.fields.linkName; bufferIndex < tarHeader.fields.prefix + 155; bufferIndex++) - checksum += static_cast(*bufferIndex); - }*/ - - bool parsed = false; - - // The size field is not always null terminated, so we must create a copy and null terminate it for parsing. - char fileSizeString[13]; - memcpy(fileSizeString, tarHeader.fields.size, 12); - fileSizeString[12] = '\0'; - - qulonglong fileSize = QString(fileSizeString).toULongLong(&parsed, 8); - - if (!parsed) - { - progressDialog.close(); - Alerts::DisplayError("Tar header contained an invalid file size."); - - tarFile.close(); - - return (false); - } - - if (fileSize > 0 && tarHeader.fields.typeFlag == '0') - { - // We're working with a file. - QString filename = QString::fromUtf8(tarHeader.fields.name); - - QTemporaryFile *outputFile = new QTemporaryFile("XXXXXX-" + filename); - packageData->GetFiles().append(outputFile); - - if (!outputFile->open()) - { - progressDialog.close(); - Alerts::DisplayError(QString("Failed to open output file: \n%1").arg(outputFile->fileName())); - - tarFile.close(); - - return (false); - } - - qulonglong dataRemaining = fileSize; - char readBuffer[TarHeader::kBlockReadCount * TarHeader::kBlockLength]; - - // Copy the file contents from tarFile to outputFile - while (dataRemaining > 0) - { - qint64 fileDataToRead = (dataRemaining < TarHeader::kBlockReadCount * TarHeader::kBlockLength) - ? dataRemaining : TarHeader::kBlockReadCount * TarHeader::kBlockLength; - - qint64 dataRead = tarFile.read(readBuffer, fileDataToRead + (TarHeader::kBlockLength - fileDataToRead % TarHeader::kBlockLength) % TarHeader::kBlockLength); - - if (dataRead < fileDataToRead || dataRead % TarHeader::kBlockLength != 0) - { - progressDialog.close(); - Alerts::DisplayError("Unexpected read error whilst extracting package files."); - - tarFile.close(); - outputFile->close(); - - remove(outputFile->fileName().toStdString().c_str()); - - return (false); - } - - outputFile->write(readBuffer, fileDataToRead); - - dataRemaining -= fileDataToRead; - - progressDialog.setValue(tarFile.pos()); - - if (progressDialog.wasCanceled()) - { - tarFile.close(); - outputFile->close(); - - remove(outputFile->fileName().toStdString().c_str()); - - progressDialog.close(); - - return (false); - } - } - - outputFile->close(); - } - else - { - progressDialog.close(); - Alerts::DisplayError("Heimdall packages shouldn't contain links or directories."); - - tarFile.close(); - - return (false); - } - } - - previousEmpty = empty; - } - - progressDialog.close(); - tarFile.close(); - - return (true); -} - -bool Packaging::WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, const QString& entryFilename) -{ - TarHeader tarHeader; - memset(tarHeader.buffer, 0, TarHeader::kBlockLength); - - QFile file(filePath); - - if (!file.open(QFile::ReadOnly)) - { - Alerts::DisplayError(QString("Failed to open file: \n%1").arg(file.fileName())); - return (false); - } - - if (file.size() > Packaging::kMaxFileSize) - { - Alerts::DisplayError(QString("File is too large to be packaged:\n%1").arg(file.fileName())); - return (false); - } - - QFileInfo qtFileInfo(file); - QByteArray utfFilename; - - utfFilename = entryFilename.toUtf8(); - - if (utfFilename.length() > 100) - { - Alerts::DisplayError(QString("File name is too long:\n%1").arg(qtFileInfo.fileName())); - return (false); - } - - strcpy(tarHeader.fields.name, utfFilename.constData()); - - unsigned int mode = 0; - - QFile::Permissions permissions = file.permissions(); - - // Other - if (permissions.testFlag(QFile::ExeOther)) - mode |= TarHeader::kModeOtherExecute; - if (permissions.testFlag(QFile::WriteOther)) - mode |= TarHeader::kModeOtherWrite; - if (permissions.testFlag(QFile::ReadOther)) - mode |= TarHeader::kModeOtherRead; - - // Group - if (permissions.testFlag(QFile::ExeGroup)) - mode |= TarHeader::kModeGroupExecute; - if (permissions.testFlag(QFile::WriteGroup)) - mode |= TarHeader::kModeGroupWrite; - if (permissions.testFlag(QFile::ReadGroup)) - mode |= TarHeader::kModeGroupRead; - - // Owner - if (permissions.testFlag(QFile::ExeOwner)) - mode |= TarHeader::kModeOwnerExecute; - if (permissions.testFlag(QFile::WriteOwner)) - mode |= TarHeader::kModeOwnerWrite; - if (permissions.testFlag(QFile::ReadOwner)) - mode |= TarHeader::kModeOwnerRead; - - sprintf(tarHeader.fields.mode, "%07o", mode); - - // Owner id - uint id = qtFileInfo.ownerId(); - - if (id < 2097151) - sprintf(tarHeader.fields.userId, "%07o", id); - else - sprintf(tarHeader.fields.userId, "%07o", 0); - - // Group id - id = qtFileInfo.groupId(); - - if (id < 2097151) - sprintf(tarHeader.fields.groupId, "%07o", id); - else - sprintf(tarHeader.fields.groupId, "%07o", 0); - - // Note: We don't support base-256 encoding. Support could be added later. - sprintf(tarHeader.fields.size, "%011llo", file.size()); - sprintf(tarHeader.fields.modifiedTime, "%u", qtFileInfo.lastModified().toTime_t()); - - // Regular File - tarHeader.fields.typeFlag = '0'; - - // Calculate checksum - int checksum = 0; - memset(tarHeader.fields.checksum, ' ', 8); - - for (int i = 0; i < TarHeader::kTarHeaderLength; i++) - checksum += static_cast(tarHeader.buffer[i]); - - sprintf(tarHeader.fields.checksum, "%07o", checksum); - - // Write the header to the TAR file. - tarFile->write(tarHeader.buffer, TarHeader::kBlockLength); - - char buffer[TarHeader::kBlockWriteCount * TarHeader::kBlockLength]; - qint64 offset = 0; - - while (offset < file.size()) - { - qint64 dataRead = file.read(buffer, TarHeader::kBlockWriteCount * TarHeader::kBlockLength); - - if (tarFile->write(buffer, dataRead) != dataRead) - { - Alerts::DisplayError("Failed to write data to the temporary TAR file."); - return (false); - } - - if (dataRead % TarHeader::kBlockLength != 0) - { - int remainingBlockLength = TarHeader::kBlockLength - dataRead % TarHeader::kBlockLength; - memset(buffer, 0, remainingBlockLength); - - if (tarFile->write(buffer, remainingBlockLength) != remainingBlockLength) - { - Alerts::DisplayError("Failed to write data to the temporary TAR file."); - return (false); - } - } - - offset += dataRead; - } - - return (true); -} - -bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarFile) -{ - const QList& fileInfos = firmwareInfo.GetFileInfos(); - - QProgressDialog progressDialog("Packaging files...", "Cancel", 0, fileInfos.length() + 2); - progressDialog.setWindowModality(Qt::ApplicationModal); - progressDialog.setWindowTitle("Heimdall Frontend"); - - QTemporaryFile firmwareXmlFile("XXXXXX-firmware.xml"); - - if (!firmwareXmlFile.open()) - { - progressDialog.close(); - Alerts::DisplayError(QString("Failed to create temporary file: \n%1").arg(firmwareXmlFile.fileName())); - - return (false); - } - - QXmlStreamWriter xml(&firmwareXmlFile); - firmwareInfo.WriteXml(xml); - firmwareXmlFile.close(); - - if (!tarFile->open()) - { - progressDialog.close(); - Alerts::DisplayError(QString("Failed to open file: \n%1").arg(tarFile->fileName())); - - return (false); - } - - for (int i = 0; i < fileInfos.length(); i++) - { - // If the file was already compressed we don't compress it again. - bool skip = false; - - for (int j = 0; j < i; j++) - { - if (fileInfos[i].GetFilename() == fileInfos[j].GetFilename()) - { - skip = true; - break; - } - } - - if (skip) - { - progressDialog.setValue(i); - continue; - } - - QString filename = ClashlessFilename(fileInfos, i); - - if (filename == "firmware.xml") - { - Alerts::DisplayError("You cannot name your partition files \"firmware.xml\".\nIt is a reserved name."); - return (false); - } - - if (!WriteTarEntry(fileInfos[i].GetFilename(), tarFile, filename)) - { - tarFile->resize(0); - tarFile->close(); - - progressDialog.close(); - - return (false); - } - - progressDialog.setValue(i); - - if (progressDialog.wasCanceled()) - { - tarFile->resize(0); - tarFile->close(); - - progressDialog.close(); - - return (false); - } - } - - int lastSlash = firmwareInfo.GetPitFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = firmwareInfo.GetPitFilename().lastIndexOf('\\'); - - QString pitFilename = ClashlessFilename(fileInfos, firmwareInfo.GetPitFilename().mid(lastSlash + 1)); - - if (pitFilename == "firmware.xml") - { - Alerts::DisplayError("You cannot name your PIT file \"firmware.xml\".\nIt is a reserved name."); - return (false); - } - - if (!WriteTarEntry(firmwareInfo.GetPitFilename(), tarFile, pitFilename)) - { - tarFile->resize(0); - tarFile->close(); - - return (false); - } - - progressDialog.setValue(progressDialog.value() + 1); - - if (progressDialog.wasCanceled()) - { - tarFile->resize(0); - tarFile->close(); - - progressDialog.close(); - - return (false); - } - - if (!WriteTarEntry(firmwareXmlFile.fileName(), tarFile, "firmware.xml")) - { - tarFile->resize(0); - tarFile->close(); - - return (false); - } - - progressDialog.setValue(progressDialog.value() + 1); - progressDialog.close(); - - // Write two empty blocks to signify the end of the archive. - char emptyEntry[TarHeader::kBlockLength]; - memset(emptyEntry, 0, TarHeader::kBlockLength); - - tarFile->write(emptyEntry, TarHeader::kBlockLength); - tarFile->write(emptyEntry, TarHeader::kBlockLength); - - tarFile->close(); - - return (true); -} - -bool Packaging::ExtractPackage(const QString& packagePath, PackageData *packageData) -{ - FILE *compressedPackageFile = fopen(packagePath.toStdString().c_str(), "rb"); - - if (!compressedPackageFile) - { - Alerts::DisplayError(QString("Failed to open package:\n%1").arg(packagePath)); - return (false); - } - - fseek(compressedPackageFile, 0, SEEK_END); - quint64 compressedFileSize = ftell(compressedPackageFile); - rewind(compressedPackageFile); - - gzFile packageFile = gzdopen(fileno(compressedPackageFile), "rb"); - - QTemporaryFile outputTar("XXXXXX.tar"); - - if (!outputTar.open()) - { - Alerts::DisplayError("Failed to open temporary TAR archive."); - gzclose(packageFile); - - return (false); - } - - char buffer[kExtractBufferLength]; - int bytesRead; - quint64 totalBytesRead = 0; - - QProgressDialog progressDialog("Decompressing package...", "Cancel", 0, compressedFileSize); - progressDialog.setWindowModality(Qt::ApplicationModal); - progressDialog.setWindowTitle("Heimdall Frontend"); - - do - { - bytesRead = gzread(packageFile, buffer, kExtractBufferLength); - - if (bytesRead == -1) - { - progressDialog.close(); - Alerts::DisplayError("Error decompressing archive."); - - gzclose(packageFile); - - return (false); - } - - outputTar.write(buffer, bytesRead); - - totalBytesRead += bytesRead; - progressDialog.setValue(totalBytesRead); - - if (progressDialog.wasCanceled()) - { - gzclose(packageFile); - progressDialog.close(); - - return (false); - } - } while (bytesRead > 0); - - progressDialog.close(); - - outputTar.close(); - gzclose(packageFile); // Closes packageFile and compressedPackageFile - - if (!ExtractTar(outputTar, packageData)) - return (false); - - // Find and read firmware.xml - for (int i = 0; i < packageData->GetFiles().length(); i++) - { - QTemporaryFile *file = packageData->GetFiles()[i]; - - if (file->fileTemplate() == "XXXXXX-firmware.xml") - { - if (!packageData->ReadFirmwareInfo(file)) - { - packageData->Clear(); - return (false); - } - - return (true); - } - } - - Alerts::DisplayError("firmware.xml is missing from the package."); - return (false); -} - -bool Packaging::BuildPackage(const QString& packagePath, const FirmwareInfo& firmwareInfo) -{ - FILE *compressedPackageFile = fopen(packagePath.toStdString().c_str(), "wb"); - - if (!compressedPackageFile) - { - Alerts::DisplayError(QString("Failed to create package:\n%1").arg(packagePath)); - return (false); - } - - QTemporaryFile tar("XXXXXX.tar"); - - if (!CreateTar(firmwareInfo, &tar)) - { - fclose(compressedPackageFile); - remove(packagePath.toStdString().c_str()); - - return (false); - } - - if (!tar.open()) - { - Alerts::DisplayError(QString("Failed to open temporary file: \n%1").arg(tar.fileName())); - - fclose(compressedPackageFile); - remove(packagePath.toStdString().c_str()); - - return (false); - } - - gzFile packageFile = gzdopen(fileno(compressedPackageFile), "wb"); - - char buffer[kCompressBufferLength]; - qint64 totalBytesRead = 0; - int bytesRead; - - QProgressDialog progressDialog("Compressing package...", "Cancel", 0, tar.size()); - progressDialog.setWindowModality(Qt::ApplicationModal); - progressDialog.setWindowTitle("Heimdall Frontend"); - - do - { - bytesRead = tar.read(buffer, kCompressBufferLength); - - if (bytesRead == -1) - { - progressDialog.close(); - Alerts::DisplayError("Error reading temporary TAR file."); - - gzclose(packageFile); - remove(packagePath.toStdString().c_str()); - - return (false); - } - - if (gzwrite(packageFile, buffer, bytesRead) != bytesRead) - { - progressDialog.close(); - Alerts::DisplayError("Error compressing package."); - - gzclose(packageFile); - remove(packagePath.toStdString().c_str()); - - return (false); - } - - totalBytesRead += bytesRead; - progressDialog.setValue(totalBytesRead); - - if (progressDialog.wasCanceled()) - { - gzclose(packageFile); - remove(packagePath.toStdString().c_str()); - - progressDialog.close(); - - return (false); - } - } while (bytesRead > 0); - - progressDialog.close(); - - gzclose(packageFile); // Closes packageFile and compressedPackageFile - - return (true); -} - -QString Packaging::ClashlessFilename(const QList& fileInfos, int fileInfoIndex) -{ - int lastSlash = fileInfos[fileInfoIndex].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[fileInfoIndex].GetFilename().lastIndexOf('\\'); - - QString filename = fileInfos[fileInfoIndex].GetFilename().mid(lastSlash + 1); - unsigned int renameIndex = 0; - - // Check for name clashes - for (int i = 0; i < fileInfoIndex; i++) - { - lastSlash = fileInfos[i].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\'); - - QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1); - - // If the filenames are the same, but the files themselves aren't the same (i.e. not the same path), then rename. - if (filename == otherFilename && fileInfos[i].GetFilename() != fileInfos[fileInfoIndex].GetFilename()) - renameIndex++; - } - - if (renameIndex > 0) - { - int lastPeriodIndex = filename.lastIndexOf(QChar('.')); - QString shortFilename; - QString fileType; - - if (lastPeriodIndex >= 0) - { - shortFilename = filename.left(lastPeriodIndex); - fileType = filename.mid(lastPeriodIndex); - } - else - { - shortFilename = filename; - } - - unsigned int renameIndexOffset = 0; - bool validIndexOffset = true; - - // Before we append a rename index we must ensure it doesn't produce further collisions. - for (int i = 0; i < fileInfos.length(); i++) - { - int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\'); - - QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1); - - if (otherFilename.length() > filename.length() + 1) - { - QString trimmedOtherFilename = otherFilename.left(shortFilename.length()); - - if (shortFilename == trimmedOtherFilename) - { - lastPeriodIndex = otherFilename.lastIndexOf(QChar('.')); - QString shortOtherFilename; - - if (lastPeriodIndex >= 0) - shortOtherFilename = otherFilename.left(lastPeriodIndex); - else - shortOtherFilename = otherFilename; - - QRegExp renameExp("-[0-9]+"); - - if (renameExp.lastIndexIn(shortOtherFilename) == shortFilename.length()) - { - unsigned int trailingInteger = shortOtherFilename.mid(shortFilename.length() + 1).toUInt(&validIndexOffset); - - if (!validIndexOffset) - break; - - if (trailingInteger > renameIndexOffset) - renameIndexOffset = trailingInteger; - } - } - } - } - - if (validIndexOffset) - { - // Ensure renaming won't involve integer overflow! - if (renameIndex > static_cast(-1) - renameIndexOffset) - validIndexOffset = false; - } - - if (validIndexOffset) - { - shortFilename.append(QChar('-')); - shortFilename.append(QString::number(renameIndexOffset + renameIndex)); - - return (shortFilename + fileType); - } - else - { - // Fallback behaviour... an absolutely terrible brute force implementation! - QString filename; - QString renamePrefix; - - for (;;) - { - renamePrefix.append(QChar('+')); - - for (unsigned int i = 0; i < static_cast(-1); i++) - { - filename = shortFilename + renamePrefix + QString::number(i) + fileType; - - bool valid = true; - - for (int i = 0; i < fileInfos.length(); i++) - { - int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\'); - - if (filename == fileInfos[i].GetFilename().mid(lastSlash + 1)) - { - valid = false; - break; - } - } - - if (valid) - return (filename); - } - } - } - } - else - { - return (filename); - } -} - -QString Packaging::ClashlessFilename(const QList& fileInfos, const QString& filename) -{ - unsigned int renameIndex = 0; - - // Check for name clashes - for (int i = 0; i < fileInfos.length(); i++) - { - int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\'); - - QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1); - - if (filename == otherFilename) - renameIndex++; - } - - if (renameIndex > 0) - { - int lastPeriodIndex = filename.lastIndexOf(QChar('.')); - QString shortFilename; - QString fileType; - - if (lastPeriodIndex >= 0) - { - shortFilename = filename.left(lastPeriodIndex); - fileType = filename.mid(lastPeriodIndex); - } - else - { - shortFilename = filename; - } - - unsigned int renameIndexOffset = 0; - bool validIndexOffset = true; - - // Before we append a rename index we must ensure it doesn't produce further collisions. - for (int i = 0; i < fileInfos.length(); i++) - { - int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\'); - - QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1); - - if (otherFilename.length() > filename.length() + 1) - { - QString trimmedOtherFilename = otherFilename.left(filename.length()); - - if (filename == trimmedOtherFilename) - { - lastPeriodIndex = otherFilename.lastIndexOf(QChar('.')); - QString shortOtherFilename; - - if (lastPeriodIndex >= 0) - shortOtherFilename = otherFilename.left(lastPeriodIndex); - else - shortOtherFilename = otherFilename; - - QRegExp renameExp("-[0-9]+"); - - if (renameExp.lastIndexIn(shortOtherFilename) == shortFilename.length()) - { - unsigned int trailingInteger = shortOtherFilename.mid(shortFilename.length() + 1).toUInt(&validIndexOffset); - - if (!validIndexOffset) - break; - - if (trailingInteger > renameIndexOffset) - renameIndexOffset = trailingInteger; - } - } - } - } - - if (validIndexOffset) - { - // Ensure renaming won't involve integer overflow! - if (renameIndex > static_cast(-1) - renameIndexOffset) - validIndexOffset = false; - } - - if (validIndexOffset) - { - shortFilename.append(QChar('-')); - shortFilename.append(QString::number(renameIndexOffset + renameIndex)); - - return (shortFilename + fileType); - } - else - { - // Fallback behaviour, brute-force/semi-random. - bool valid; - QString filename; - - do - { - valid = true; - - filename = shortFilename + "-"; - for (int i = 0; i < 8; i++) - filename.append(QChar(qrand() % ('Z' - 'A' + 1) + 'A')); - - for (int i = 0; i < fileInfos.length(); i++) - { - int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/'); - - if (lastSlash < 0) - lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\'); - - if (filename == fileInfos[i].GetFilename().mid(lastSlash + 1)) - { - valid = false; - break; - } - } - } while (!valid); - - return (filename); - } - } - else - { - return (filename); - } -} diff --git a/heimdall-frontend/Source/Packaging.h b/heimdall-frontend/Source/Packaging.h deleted file mode 100644 index 8ba83f7..0000000 --- a/heimdall-frontend/Source/Packaging.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef PACKAGING_H -#define PACKAGING_H - -// Qt -#include -#include -#include - -// Heimdall Frontend -#include "PackageData.h" - -namespace HeimdallFrontend -{ - union TarHeader - { - enum - { - kBlockLength = 512, - kBlockReadCount = 8, - kBlockWriteCount = 8, - - kTarHeaderLength = 257, - kUstarHeaderLength = 500, - }; - - enum - { - kModeOtherExecute = 1, - kModeOtherWrite = 1 << 1, - kModeOtherRead = 1 << 2, - - kModeGroupExecute = 1 << 3, - kModeGroupWrite = 1 << 4, - kModeGroupRead = 1 << 5, - - kModeOwnerExecute = 1 << 6, - kModeOwnerWrite = 1 << 7, - kModeOwnerRead = 1 << 8, - - kModeReserved = 2 << 9, - kModeSetGid = 2 << 10, - kModeSetUid = 2 << 11 - }; - - struct - { - char name[100]; - char mode[8]; - char userId[8]; - char groupId[8]; - char size[12]; - char modifiedTime[12]; - char checksum[8]; - char typeFlag; - char linkName[100]; - char magic[6]; - char version[2]; - char userName[32]; - char groupName[32]; - char devMajor[8]; - char devMinor[8]; - char prefix[155]; - } fields; - - char buffer[kBlockLength]; - }; - - class Packaging - { - public: - - // Would definitely prefer to use an enum but VC++ and GCC give conflicting warnings about C++0x or type overflow. - static const qint64 kMaxFileSize; - - private: - - enum - { - kExtractBufferLength = 262144, - kCompressBufferLength = 262144 - }; - - // TODO: Add support for sparse files to both methods? - static bool ExtractTar(QTemporaryFile& tarFile, PackageData *packageData); - - static bool WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, const QString& entryFilename); - static bool CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarFile); // Uses original TAR format. - - public: - - static const char *ustarMagic; - - static bool ExtractPackage(const QString& packagePath, PackageData *packageData); - static bool BuildPackage(const QString& packagePath, const FirmwareInfo& firmwareInfo); - - static QString ClashlessFilename(const QList& fileInfos, int fileInfoIndex); - static QString ClashlessFilename(const QList& fileInfos, const QString& filename); - }; -} - -#endif diff --git a/heimdall-frontend/Source/aboutform.cpp b/heimdall-frontend/Source/aboutform.cpp deleted file mode 100644 index fbb3fb1..0000000 --- a/heimdall-frontend/Source/aboutform.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Qt -#include -#include - -// Heimdall Frontend -#include "aboutform.h" - -#include - -#define UNUSED(x) (void)(x) - -using namespace HeimdallFrontend; - -AboutForm::AboutForm(QWidget *parent) : QWidget(parent) -{ - setupUi(this); - - // Heimdall Command Line - QObject::connect(&heimdallProcess, SIGNAL(readyRead()), this, SLOT(HandleHeimdallStdout())); - QObject::connect(&heimdallProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(HandleHeimdallReturned(int, QProcess::ExitStatus))); - QObject::connect(&heimdallProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(HandleHeimdallError(QProcess::ProcessError))); - - heimdallFailed = false; - - RetrieveHeimdallVersion(); -} - -void AboutForm::RetrieveHeimdallVersion(void) -{ - heimdallProcess.setReadChannel(QProcess::StandardOutput); - - heimdallProcess.start("heimdall", QStringList("version")); - heimdallProcess.waitForFinished(350); - - // OS X was playing up and not finding heimdall, so we're manually checking the PATH. - if (heimdallFailed) - { - QStringList environment = QProcess::systemEnvironment(); - - QStringList paths; - - // Ensure /usr/bin is in PATH - for (int i = 0; i < environment.length(); i++) - { - if (environment[i].left(5) == "PATH=") - { - paths = environment[i].mid(5).split(':'); - paths.prepend("/usr/bin"); - break; - } - } - - int pathIndex = -1; - - while (heimdallFailed && ++pathIndex < paths.length()) - { - QString heimdallPath = paths[pathIndex]; - - if (heimdallPath.length() > 0) - { - heimdallFailed = false; - - if (heimdallPath[heimdallPath.length() - 1] != QDir::separator()) - heimdallPath += QDir::separator(); - - heimdallPath += "heimdall"; - - heimdallProcess.start(heimdallPath, QStringList("version")); - heimdallProcess.waitForFinished(350); - } - } - - if (heimdallFailed) - versionCopyrightLabel->setText(versionCopyrightLabel->text().replace("%HEIMDALL-VERSION%", "")); - } -} - -void AboutForm::HandleHeimdallStdout(void) -{ - QString version = heimdallProcess.readAll(); - - if (version.length() > 0) - { - if (version.at(0) == QChar('v')) - version = version.mid(1); - - versionCopyrightLabel->setText(versionCopyrightLabel->text().replace("%HEIMDALL-VERSION%", "Version " + version + "
")); - } -} - -void AboutForm::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus) -{ - UNUSED(exitCode); - UNUSED(exitStatus); - - // If for some reason %HEIMDALL-VERSION% hasn't been replaced yet, we'll replace it with an empty string. - versionCopyrightLabel->setText(versionCopyrightLabel->text().replace("%HEIMDALL-VERSION%", "")); -} - -void AboutForm::HandleHeimdallError(QProcess::ProcessError error) -{ - UNUSED(error); - - heimdallFailed = true; -} - diff --git a/heimdall-frontend/Source/aboutform.h b/heimdall-frontend/Source/aboutform.h deleted file mode 100644 index 4b6a8e3..0000000 --- a/heimdall-frontend/Source/aboutform.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef ABOUTFORM_H -#define ABOUTFORM_H - -// Qt -#include -#include - -// Heimdall Frontend -#include "ui_aboutform.h" - -namespace HeimdallFrontend -{ - class AboutForm : public QWidget, public Ui::AboutForm - { - Q_OBJECT - - private: - - bool heimdallFailed; - QProcess heimdallProcess; - - void RetrieveHeimdallVersion(void); - - public: - - explicit AboutForm(QWidget *parent = 0); - - public slots: - - // Heimdall Command Line - void HandleHeimdallStdout(void); - void HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus); - void HandleHeimdallError(QProcess::ProcessError error); - }; -} - -#endif - diff --git a/heimdall-frontend/Source/main.cpp b/heimdall-frontend/Source/main.cpp deleted file mode 100644 index c327b63..0000000 --- a/heimdall-frontend/Source/main.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Qt -#include -#include - -// Heimdall Frontend -#include "mainwindow.h" - -Q_IMPORT_PLUGIN (QWindowsIntegrationPlugin); - -using namespace HeimdallFrontend; - -int main(int argc, char *argv[]) -{ - QApplication application(argc, argv); - - MainWindow window; - window.show(); - - return (application.exec()); -} diff --git a/heimdall-frontend/Source/mainwindow.cpp b/heimdall-frontend/Source/mainwindow.cpp deleted file mode 100644 index 74d9500..0000000 --- a/heimdall-frontend/Source/mainwindow.cpp +++ /dev/null @@ -1,1375 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Qt -#include -#include -#include -#include -#include -#include -#include - -// Heimdall Frontend -#include "Alerts.h" -#include "mainwindow.h" -#include "Packaging.h" - -#define UNUSED(x) (void)(x) - -using namespace HeimdallFrontend; - -void MainWindow::StartHeimdall(const QStringList& arguments) -{ - UpdateInterfaceAvailability(); - - heimdallProcess.setReadChannel(QProcess::StandardOutput); - - heimdallProcess.start("heimdall", arguments); - heimdallProcess.waitForStarted(3000); - - // OS X was playing up and not finding heimdall, so we're manually checking the PATH. - if (heimdallFailed) - { - QStringList environment = QProcess::systemEnvironment(); - - QStringList paths; - - // Ensure /usr/local/bin and /usr/bin are in PATH. - for (int i = 0; i < environment.length(); i++) - { - if (environment[i].left(5) == "PATH=") - { - paths = environment[i].mid(5).split(':'); - - if (!paths.contains("/usr/local/bin")) - paths.prepend("/usr/local/bin"); - - if (!paths.contains("/usr/bin")) - paths.prepend("/usr/bin"); - - break; - } - } - - int pathIndex = -1; - - while (heimdallFailed && ++pathIndex < paths.length()) - { - QString heimdallPath = paths[pathIndex]; - - if (heimdallPath.length() > 0) - { - utilityOutputPlainTextEdit->clear(); - heimdallFailed = false; - - if (heimdallPath[heimdallPath.length() - 1] != QDir::separator()) - heimdallPath += QDir::separator(); - - heimdallPath += "heimdall"; - - heimdallProcess.start(heimdallPath, arguments); - heimdallProcess.waitForStarted(3000); - } - } - - if (heimdallFailed) - { - flashLabel->setText("Failed to start Heimdall!"); - - heimdallState = HeimdallState::Stopped; - UpdateInterfaceAvailability(); - } - } -} - -void MainWindow::UpdateUnusedPartitionIds(void) -{ - unusedPartitionIds.clear(); - - // Initially populate unusedPartitionIds with all possible partition IDs. - for (unsigned int i = 0; i < currentPitData.GetEntryCount(); i++) - { - const PitEntry *pitEntry = currentPitData.GetEntry(i); - - if (pitEntry->IsFlashable() && strcmp(pitEntry->GetPartitionName(), "PIT") != 0 && strcmp(pitEntry->GetPartitionName(), "PT") != 0) - unusedPartitionIds.append(pitEntry->GetIdentifier()); - } - - // Remove any used partition IDs from unusedPartitionIds - QList& fileList = workingPackageData.GetFirmwareInfo().GetFileInfos(); - - for (int i = 0; i < fileList.length(); i++) - unusedPartitionIds.removeOne(fileList[i].GetPartitionId()); -} - -bool MainWindow::ReadPit(QFile *file) -{ - if(!file->open(QIODevice::ReadOnly)) - return (false); - - unsigned char *buffer = new unsigned char[file->size()]; - - file->read(reinterpret_cast(buffer), file->size()); - file->close(); - - bool success = currentPitData.Unpack(buffer); - delete buffer; - - if (!success) - currentPitData.Clear(); - - return (success); -} - -void MainWindow::UpdatePackageUserInterface(void) -{ - supportedDevicesListWidget->clear(); - includedFilesListWidget->clear(); - - if (loadedPackageData.IsCleared()) - { - // Package Interface - firmwareNameLineEdit->clear(); - versionLineEdit->clear(); - - developerNamesLineEdit->clear(); - - platformLineEdit->clear(); - - repartitionRadioButton->setChecked(false); - noRebootRadioButton->setChecked(false); - } - else - { - firmwareNameLineEdit->setText(loadedPackageData.GetFirmwareInfo().GetName()); - versionLineEdit->setText(loadedPackageData.GetFirmwareInfo().GetVersion()); - - QString developerNames; - - if (!loadedPackageData.GetFirmwareInfo().GetDevelopers().isEmpty()) - { - developerNames = loadedPackageData.GetFirmwareInfo().GetDevelopers()[0]; - for (int i = 1; i < loadedPackageData.GetFirmwareInfo().GetDevelopers().length(); i++) - developerNames += ", " + loadedPackageData.GetFirmwareInfo().GetDevelopers()[i]; - } - - developerNamesLineEdit->setText(developerNames); - - platformLineEdit->setText(loadedPackageData.GetFirmwareInfo().GetPlatformInfo().GetName() + " (" - + loadedPackageData.GetFirmwareInfo().GetPlatformInfo().GetVersion() + ")"); - - for (int i = 0; i < loadedPackageData.GetFirmwareInfo().GetDeviceInfos().length(); i++) - { - const DeviceInfo& deviceInfo = loadedPackageData.GetFirmwareInfo().GetDeviceInfos()[i]; - supportedDevicesListWidget->addItem(deviceInfo.GetManufacturer() + " " + deviceInfo.GetName() + ": " + deviceInfo.GetProduct()); - } - - for (int i = 0; i < loadedPackageData.GetFirmwareInfo().GetFileInfos().length(); i++) - { - const FileInfo& fileInfo = loadedPackageData.GetFirmwareInfo().GetFileInfos()[i]; - includedFilesListWidget->addItem(fileInfo.GetFilename()); - } - - repartitionRadioButton->setChecked(loadedPackageData.GetFirmwareInfo().GetRepartition()); - noRebootRadioButton->setChecked(loadedPackageData.GetFirmwareInfo().GetNoReboot()); - } - - UpdateLoadPackageInterfaceAvailability(); -} - -bool MainWindow::IsArchive(QString path) -{ - // Not a real check but hopefully it gets the message across, don't directly flash archives! - return (path.endsWith(".tar", Qt::CaseInsensitive) || path.endsWith(".gz", Qt::CaseInsensitive) || path.endsWith(".zip", Qt::CaseInsensitive) - || path.endsWith(".bz2", Qt::CaseInsensitive) || path.endsWith(".7z", Qt::CaseInsensitive) || path.endsWith(".rar", Qt::CaseInsensitive)); -} - -QString MainWindow::PromptFileSelection(const QString& caption, const QString& filter) -{ - QString path = QFileDialog::getOpenFileName(this, caption, lastDirectory, filter); - - if (path != "") - lastDirectory = path.left(path.lastIndexOf('/') + 1); - - return (path); -} - -QString MainWindow::PromptFileCreation(const QString& caption, const QString& filter) -{ - QString path = QFileDialog::getSaveFileName(this, caption, lastDirectory, filter); - - if (path != "") - lastDirectory = path.left(path.lastIndexOf('/') + 1); - - return (path); -} - -void MainWindow::UpdateLoadPackageInterfaceAvailability(void) -{ - if (loadedPackageData.IsCleared()) - { - developerHomepageButton->setEnabled(false); - developerDonateButton->setEnabled(false); - - loadFirmwareButton->setEnabled(false); - } - else - { - if (!loadedPackageData.GetFirmwareInfo().GetUrl().isEmpty()) - developerHomepageButton->setEnabled(true); - else - developerHomepageButton->setEnabled(false); - - if (!loadedPackageData.GetFirmwareInfo().GetDonateUrl().isEmpty()) - developerDonateButton->setEnabled(true); - else - developerDonateButton->setEnabled(false); - - loadFirmwareButton->setEnabled(heimdallState == HeimdallState::Stopped); - } -} - -void MainWindow::UpdateFlashInterfaceAvailability(void) -{ - if (heimdallState == HeimdallState::Stopped) - { - partitionNameComboBox->setEnabled(partitionsListWidget->currentRow() >= 0); - - bool allPartitionsValid = true; - QList& fileList = workingPackageData.GetFirmwareInfo().GetFileInfos(); - - for (int i = 0; i < fileList.length(); i++) - { - if (fileList[i].GetFilename().isEmpty()) - { - allPartitionsValid = false; - break; - } - } - - bool validFlashSettings = allPartitionsValid && fileList.length() > 0; - - flashProgressBar->setEnabled(false); - optionsGroup->setEnabled(true); - sessionGroup->setEnabled(true); - startFlashButton->setEnabled(validFlashSettings); - noRebootCheckBox->setEnabled(validFlashSettings); - resumeCheckbox->setEnabled(validFlashSettings); - } - else - { - partitionNameComboBox->setEnabled(false); - - flashProgressBar->setEnabled(true); - optionsGroup->setEnabled(false); - sessionGroup->setEnabled(false); - } -} - -void MainWindow::UpdateCreatePackageInterfaceAvailability(void) -{ - if (heimdallState == HeimdallState::Stopped) - { - const FirmwareInfo& firmwareInfo = workingPackageData.GetFirmwareInfo(); - - if (firmwareInfo.GetName().isEmpty() || firmwareInfo.GetVersion().isEmpty() || firmwareInfo.GetPlatformInfo().GetName().isEmpty() - || firmwareInfo.GetPlatformInfo().GetVersion().isEmpty() || firmwareInfo.GetDevelopers().isEmpty() || firmwareInfo.GetDeviceInfos().isEmpty()) - { - buildPackageButton->setEnabled(false); - } - else - { - buildPackageButton->setEnabled(true); - } - - if (addDeveloperButton->text().isEmpty()) - addDeveloperButton->setEnabled(false); - else - addDeveloperButton->setEnabled(true); - - if (createDevelopersListWidget->currentRow() >= 0) - removeDeveloperButton->setEnabled(true); - else - removeDeveloperButton->setEnabled(false); - } - else - { - buildPackageButton->setEnabled(false); - } -} - -void MainWindow::UpdateUtilitiesInterfaceAvailability(void) -{ - if (heimdallState == HeimdallState::Stopped) - { - detectDeviceButton->setEnabled(true); - closePcScreenButton->setEnabled(true); - pitSaveAsButton->setEnabled(true); - - downloadPitButton->setEnabled(!pitDestinationLineEdit->text().isEmpty()); - - if (printPitDeviceRadioBox->isChecked()) - { - // Device - printLocalPitGroup->setEnabled(false); - printPitButton->setEnabled(true); - } - else - { - // Local File - printLocalPitGroup->setEnabled(true); - printLocalPitLineEdit->setEnabled(true); - printLocalPitBrowseButton->setEnabled(true); - - printPitButton->setEnabled(!printLocalPitLineEdit->text().isEmpty()); - } - } - else - { - detectDeviceButton->setEnabled(false); - closePcScreenButton->setEnabled(false); - pitSaveAsButton->setEnabled(false); - downloadPitButton->setEnabled(false); - - printLocalPitGroup->setEnabled(false); - printPitButton->setEnabled(false); - } -} - -void MainWindow::UpdateInterfaceAvailability(void) -{ - UpdateLoadPackageInterfaceAvailability(); - UpdateFlashInterfaceAvailability(); - UpdateCreatePackageInterfaceAvailability(); - UpdateUtilitiesInterfaceAvailability(); - - if (heimdallState == HeimdallState::Stopped) - { - // Enable/disable tabs - - for (int i = 0; i < functionTabWidget->count(); i++) - functionTabWidget->setTabEnabled(i, true); - - functionTabWidget->setTabEnabled(functionTabWidget->indexOf(createPackageTab), startFlashButton->isEnabled()); - } - else - { - // Disable non-current tabs - - for (int i = 0; i < functionTabWidget->count(); i++) - { - if (i == functionTabWidget->currentIndex()) - functionTabWidget->setTabEnabled(i, true); - else - functionTabWidget->setTabEnabled(i, false); - } - } -} - -void MainWindow::UpdatePartitionNamesInterface(void) -{ - populatingPartitionNames = true; - - partitionNameComboBox->clear(); - - int partitionsListWidgetRow = partitionsListWidget->currentRow(); - - if (partitionsListWidgetRow >= 0) - { - const FileInfo& partitionInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[partitionsListWidget->currentRow()]; - - for (int i = 0; i < unusedPartitionIds.length(); i++) - partitionNameComboBox->addItem(currentPitData.FindEntry(unusedPartitionIds[i])->GetPartitionName()); - - partitionNameComboBox->addItem(currentPitData.FindEntry(partitionInfo.GetPartitionId())->GetPartitionName()); - partitionNameComboBox->setCurrentIndex(unusedPartitionIds.length()); - } - - populatingPartitionNames = false; - - UpdateFlashInterfaceAvailability(); -} - -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) -{ - setupUi(this); - - heimdallState = HeimdallState::Stopped; - - lastDirectory = QDir::toNativeSeparators(QApplication::applicationDirPath()); - - populatingPartitionNames = false; - - verboseOutput = false; - resume = false; - - tabIndex = functionTabWidget->currentIndex(); - functionTabWidget->setTabEnabled(functionTabWidget->indexOf(createPackageTab), false); - - QObject::connect(functionTabWidget, SIGNAL(currentChanged(int)), this, SLOT(FunctionTabChanged(int))); - - // Menu - QObject::connect(actionDonate, SIGNAL(triggered()), this, SLOT(OpenDonationWebpage())); - QObject::connect(actionVerboseOutput, SIGNAL(toggled(bool)), this, SLOT(SetVerboseOutput(bool))); - QObject::connect(actionResumeConnection, SIGNAL(toggled(bool)), this, SLOT(SetResume(bool))); - QObject::connect(actionAboutHeimdall, SIGNAL(triggered()), this, SLOT(ShowAbout())); - - // Load Package Tab - QObject::connect(browseFirmwarePackageButton, SIGNAL(clicked()), this, SLOT(SelectFirmwarePackage())); - QObject::connect(developerHomepageButton, SIGNAL(clicked()), this, SLOT(OpenDeveloperHomepage())); - QObject::connect(developerDonateButton, SIGNAL(clicked()), this, SLOT(OpenDeveloperDonationWebpage())); - QObject::connect(loadFirmwareButton, SIGNAL(clicked()), this, SLOT(LoadFirmwarePackage())); - - QObject::connect(partitionsListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(SelectPartition(int))); - QObject::connect(addPartitionButton, SIGNAL(clicked()), this, SLOT(AddPartition())); - QObject::connect(removePartitionButton, SIGNAL(clicked()), this, SLOT(RemovePartition())); - - // Flash Tab - QObject::connect(partitionNameComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SelectPartitionName(int))); - QObject::connect(partitionFileBrowseButton, SIGNAL(clicked()), this, SLOT(SelectPartitionFile())); - - QObject::connect(pitBrowseButton, SIGNAL(clicked()), this, SLOT(SelectPit())); - - QObject::connect(repartitionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(SetRepartition(int))); - - QObject::connect(noRebootCheckBox, SIGNAL(stateChanged(int)), this, SLOT(SetNoReboot(int))); - QObject::connect(resumeCheckbox, SIGNAL(stateChanged(int)), this, SLOT(SetResume(int))); - - QObject::connect(startFlashButton, SIGNAL(clicked()), this, SLOT(StartFlash())); - - // Create Package Tab - QObject::connect(createFirmwareNameLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(FirmwareNameChanged(const QString&))); - QObject::connect(createFirmwareVersionLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(FirmwareVersionChanged(const QString&))); - QObject::connect(createPlatformNameLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(PlatformNameChanged(const QString&))); - QObject::connect(createPlatformVersionLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(PlatformVersionChanged(const QString&))); - - QObject::connect(createHomepageLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(HomepageUrlChanged(const QString&))); - QObject::connect(createDonateLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(DonateUrlChanged(const QString&))); - - QObject::connect(createDevelopersListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(SelectDeveloper(int))); - QObject::connect(createDeveloperNameLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(DeveloperNameChanged(const QString&))); - QObject::connect(addDeveloperButton, SIGNAL(clicked()), this, SLOT(AddDeveloper())); - QObject::connect(removeDeveloperButton, SIGNAL(clicked()), this, SLOT(RemoveDeveloper())); - - QObject::connect(createDevicesListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(SelectDevice(int))); - QObject::connect(deviceManufacturerLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(DeviceInfoChanged(const QString&))); - QObject::connect(deviceNameLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(DeviceInfoChanged(const QString&))); - QObject::connect(deviceProductCodeLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(DeviceInfoChanged(const QString&))); - QObject::connect(addDeviceButton, SIGNAL(clicked()), this, SLOT(AddDevice())); - QObject::connect(removeDeviceButton, SIGNAL(clicked()), this, SLOT(RemoveDevice())); - - QObject::connect(buildPackageButton, SIGNAL(clicked()), this, SLOT(BuildPackage())); - - // Utilities Tab - QObject::connect(detectDeviceButton, SIGNAL(clicked()), this, SLOT(DetectDevice())); - - QObject::connect(closePcScreenButton, SIGNAL(clicked()), this, SLOT(ClosePcScreen())); - - QObject::connect(printPitDeviceRadioBox, SIGNAL(toggled(bool)), this, SLOT(DevicePrintPitToggled(bool))); - QObject::connect(printPitLocalFileRadioBox, SIGNAL(toggled(bool)), this, SLOT(LocalFilePrintPitToggled(bool))); - QObject::connect(printLocalPitBrowseButton, SIGNAL(clicked()), this, SLOT(SelectPrintPitFile())); - QObject::connect(printPitButton, SIGNAL(clicked()), this, SLOT(PrintPit())); - - QObject::connect(pitSaveAsButton, SIGNAL(clicked()), this, SLOT(SelectPitDestination())); - QObject::connect(downloadPitButton, SIGNAL(clicked()), this, SLOT(DownloadPit())); - - // Heimdall Command Line - QObject::connect(&heimdallProcess, SIGNAL(readyRead()), this, SLOT(HandleHeimdallStdout())); - QObject::connect(&heimdallProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(HandleHeimdallReturned(int, QProcess::ExitStatus))); - QObject::connect(&heimdallProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(HandleHeimdallError(QProcess::ProcessError))); -} - -MainWindow::~MainWindow() -{ -} - -void MainWindow::OpenDonationWebpage(void) -{ - QDesktopServices::openUrl(QUrl("http://www.glassechidna.com.au/donate/", QUrl::StrictMode)); -} - -void MainWindow::SetVerboseOutput(bool enabled) -{ - verboseOutput = enabled; -} - -void MainWindow::ShowAbout(void) -{ - aboutForm.show(); -} - -void MainWindow::FunctionTabChanged(int index) -{ - tabIndex = index; - deviceDetectedRadioButton->setChecked(false); -} - -void MainWindow::SelectFirmwarePackage(void) -{ - loadedPackageData.Clear(); - UpdatePackageUserInterface(); - - QString path = PromptFileSelection("Select Package", "*.tar.gz"); - firmwarePackageLineEdit->setText(path); - - if (firmwarePackageLineEdit->text() != "") - { - if (Packaging::ExtractPackage(firmwarePackageLineEdit->text(), &loadedPackageData)) - UpdatePackageUserInterface(); - else - loadedPackageData.Clear(); - } -} - -void MainWindow::OpenDeveloperHomepage(void) -{ - if(!QDesktopServices::openUrl(QUrl(loadedPackageData.GetFirmwareInfo().GetUrl(), QUrl::TolerantMode))) - Alerts::DisplayWarning(QString("Cannot open invalid URL:\n%1").arg(loadedPackageData.GetFirmwareInfo().GetUrl())); -} - -void MainWindow::OpenDeveloperDonationWebpage(void) -{ - if (!QDesktopServices::openUrl(QUrl(loadedPackageData.GetFirmwareInfo().GetDonateUrl(), QUrl::TolerantMode))) - Alerts::DisplayWarning(QString("Cannot open invalid URL:\n%1").arg(loadedPackageData.GetFirmwareInfo().GetDonateUrl())); -} - -void MainWindow::LoadFirmwarePackage(void) -{ - workingPackageData.Clear(); - currentPitData.Clear(); - - workingPackageData.GetFiles().append(loadedPackageData.GetFiles()); - loadedPackageData.RemoveAllFiles(); - - const QList packageFileInfos = loadedPackageData.GetFirmwareInfo().GetFileInfos(); - - for (int i = 0; i < packageFileInfos.length(); i++) - { - bool fileFound = false; - - for (int j = 0; j < workingPackageData.GetFiles().length(); j++) - { - if (workingPackageData.GetFiles()[j]->fileTemplate() == ("XXXXXX-" + packageFileInfos[i].GetFilename())) - { - FileInfo partitionInfo(packageFileInfos[i].GetPartitionId(), QDir::current().absoluteFilePath(workingPackageData.GetFiles()[j]->fileName())); - workingPackageData.GetFirmwareInfo().GetFileInfos().append(partitionInfo); - - fileFound = true; - break; - } - } - - if (!fileFound) - Alerts::DisplayWarning(QString("%1 is missing from the package.").arg(packageFileInfos[i].GetFilename())); - } - - // Find the PIT file and read it - for (int i = 0; i < workingPackageData.GetFiles().length(); i++) - { - QTemporaryFile *file = workingPackageData.GetFiles()[i]; - - if (file->fileTemplate() == ("XXXXXX-" + loadedPackageData.GetFirmwareInfo().GetPitFilename())) - { - workingPackageData.GetFirmwareInfo().SetPitFilename(QDir::current().absoluteFilePath(file->fileName())); - - if (!ReadPit(file)) - { - Alerts::DisplayError("Failed to read PIT file."); - - loadedPackageData.Clear(); - UpdatePackageUserInterface(); - - workingPackageData.Clear(); - UpdateUnusedPartitionIds(); - return; - } - - break; - } - } - - UpdateUnusedPartitionIds(); - workingPackageData.GetFirmwareInfo().SetRepartition(loadedPackageData.GetFirmwareInfo().GetRepartition()); - workingPackageData.GetFirmwareInfo().SetNoReboot(loadedPackageData.GetFirmwareInfo().GetNoReboot()); - - loadedPackageData.Clear(); - UpdatePackageUserInterface(); - firmwarePackageLineEdit->clear(); - - partitionsListWidget->clear(); - - // Populate partitionsListWidget with partition names (from the PIT file) - for (int i = 0; i < workingPackageData.GetFirmwareInfo().GetFileInfos().length(); i++) - { - const FileInfo& partitionInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[i]; - - const PitEntry *pitEntry = currentPitData.FindEntry(partitionInfo.GetPartitionId()); - - if (pitEntry) - { - partitionsListWidget->addItem(pitEntry->GetPartitionName()); - } - else - { - Alerts::DisplayError("Firmware package includes invalid partition IDs."); - - loadedPackageData.GetFirmwareInfo().Clear(); - currentPitData.Clear(); - UpdateUnusedPartitionIds(); - - partitionsListWidget->clear(); - return; - } - } - - partitionNameComboBox->clear(); - partitionIdLineEdit->clear(); - partitionFileLineEdit->clear(); - partitionFileBrowseButton->setEnabled(false); - - repartitionCheckBox->setEnabled(true); - repartitionCheckBox->setChecked(workingPackageData.GetFirmwareInfo().GetRepartition()); - noRebootCheckBox->setEnabled(true); - noRebootCheckBox->setChecked(workingPackageData.GetFirmwareInfo().GetNoReboot()); - - partitionsListWidget->setEnabled(true); - addPartitionButton->setEnabled(true); - removePartitionButton->setEnabled(true && partitionsListWidget->currentRow() >= 0); - - pitLineEdit->setText(workingPackageData.GetFirmwareInfo().GetPitFilename()); - - functionTabWidget->setCurrentWidget(flashTab); - - UpdateInterfaceAvailability(); -} - -void MainWindow::SelectPartitionName(int index) -{ - if (!populatingPartitionNames && index != -1 && index != unusedPartitionIds.length()) - { - unsigned int newPartitionIndex = unusedPartitionIds[index]; - unusedPartitionIds.removeAt(index); - - FileInfo& fileInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[partitionsListWidget->currentRow()]; - unusedPartitionIds.append(fileInfo.GetPartitionId()); - fileInfo.SetPartitionId(newPartitionIndex); - - PitEntry *pitEntry = currentPitData.FindEntry(newPartitionIndex); - - QString title("File"); - - if (pitEntry && strlen(pitEntry->GetFlashFilename()) > 0) - title += " (" + QString(pitEntry->GetFlashFilename()) + ")"; - - partitionFileGroup->setTitle(title); - - if (!fileInfo.GetFilename().isEmpty()) - { - QString partitionFilename = pitEntry->GetFlashFilename(); - int lastPeriod = partitionFilename.lastIndexOf(QChar('.')); - - if (lastPeriod >= 0) - { - QString partitionFileExtension = partitionFilename.mid(lastPeriod + 1); - - lastPeriod = fileInfo.GetFilename().lastIndexOf(QChar('.')); - - if (lastPeriod < 0 || fileInfo.GetFilename().mid(lastPeriod + 1) != partitionFileExtension) - Alerts::DisplayWarning(QString("%1 partition expects files with file extension \"%2\".").arg(pitEntry->GetPartitionName(), partitionFileExtension)); - } - } - - partitionNameComboBox->clear(); - - // Update interface - UpdatePartitionNamesInterface(); - partitionIdLineEdit->setText(QString::number(newPartitionIndex)); - partitionsListWidget->currentItem()->setText(currentPitData.FindEntry(newPartitionIndex)->GetPartitionName()); - } -} - -void MainWindow::SelectPartitionFile(void) -{ - QString path = PromptFileSelection(); - - if (path != "") - { - FileInfo& fileInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[partitionsListWidget->currentRow()]; - PitEntry *pitEntry = currentPitData.FindEntry(fileInfo.GetPartitionId()); - - QString partitionFilename = pitEntry->GetFlashFilename(); - int lastPeriod = partitionFilename.lastIndexOf(QChar('.')); - - if (lastPeriod >= 0) - { - QString partitionFileExtension = partitionFilename.mid(lastPeriod + 1); - - lastPeriod = path.lastIndexOf(QChar('.')); - - if (lastPeriod < 0 || path.mid(lastPeriod + 1) != partitionFileExtension) - Alerts::DisplayWarning(QString("%1 partition expects files with file extension \"%2\".").arg(pitEntry->GetPartitionName(), partitionFileExtension)); - } - - fileInfo.SetFilename(path); - partitionFileLineEdit->setText(path); - - pitBrowseButton->setEnabled(true); - partitionsListWidget->setEnabled(true); - UpdateInterfaceAvailability(); - - if (unusedPartitionIds.length() > 0) - addPartitionButton->setEnabled(true); - } -} - -void MainWindow::SelectPartition(int row) -{ - if (row >= 0) - { - const FileInfo& partitionInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[row]; - - UpdatePartitionNamesInterface(); - - partitionIdLineEdit->setText(QString::number(partitionInfo.GetPartitionId())); - partitionFileLineEdit->setText(partitionInfo.GetFilename()); - partitionFileBrowseButton->setEnabled(true); - - removePartitionButton->setEnabled(true); - - QString title("File"); - - PitEntry *pitEntry = currentPitData.FindEntry(partitionInfo.GetPartitionId()); - - if (pitEntry && strlen(pitEntry->GetFlashFilename()) > 0) - title += " (" + QString(pitEntry->GetFlashFilename()) + ")"; - - partitionFileGroup->setTitle(title); - } - else - { - UpdatePartitionNamesInterface(); - - partitionIdLineEdit->clear(); - partitionFileLineEdit->clear(); - partitionFileBrowseButton->setEnabled(false); - - removePartitionButton->setEnabled(false); - - partitionFileGroup->setTitle("File"); - } -} - -void MainWindow::AddPartition(void) -{ - FileInfo partitionInfo(unusedPartitionIds.first(), ""); - workingPackageData.GetFirmwareInfo().GetFileInfos().append(partitionInfo); - UpdateUnusedPartitionIds(); - - pitBrowseButton->setEnabled(false); - addPartitionButton->setEnabled(false); - - partitionsListWidget->addItem(currentPitData.FindEntry(partitionInfo.GetPartitionId())->GetPartitionName()); - partitionsListWidget->setCurrentRow(partitionsListWidget->count() - 1); - partitionsListWidget->setEnabled(false); - - UpdateInterfaceAvailability(); -} - -void MainWindow::RemovePartition(void) -{ - workingPackageData.GetFirmwareInfo().GetFileInfos().removeAt(partitionsListWidget->currentRow()); - UpdateUnusedPartitionIds(); - - QListWidgetItem *item = partitionsListWidget->currentItem(); - partitionsListWidget->setCurrentRow(-1); - delete item; - - pitBrowseButton->setEnabled(true); - addPartitionButton->setEnabled(true); - partitionsListWidget->setEnabled(true); - UpdateInterfaceAvailability(); -} - -void MainWindow::SelectPit(void) -{ - QString path = PromptFileSelection("Select PIT", "*.pit"); - bool validPit = path != ""; - - if (validPit) - { - // In order to map files in the old PIT to file in the new one, we first must use partition names instead of IDs. - QList fileInfos = workingPackageData.GetFirmwareInfo().GetFileInfos(); - - int partitionNamesCount = fileInfos.length(); - QString *partitionNames = new QString[fileInfos.length()]; - for (int i = 0; i < fileInfos.length(); i++) - partitionNames[i] = currentPitData.FindEntry(fileInfos[i].GetPartitionId())->GetPartitionName(); - - currentPitData.Clear(); - - QFile pitFile(path); - - if (ReadPit(&pitFile)) - { - workingPackageData.GetFirmwareInfo().SetPitFilename(path); - - partitionsListWidget->clear(); - int partitionInfoIndex = 0; - - for (int i = 0; i < partitionNamesCount; i++) - { - const PitEntry *pitEntry = currentPitData.FindEntry(partitionNames[i].toLatin1().constData()); - - if (pitEntry) - { - fileInfos[partitionInfoIndex++].SetPartitionId(pitEntry->GetIdentifier()); - partitionsListWidget->addItem(pitEntry->GetPartitionName()); - } - else - { - fileInfos.removeAt(partitionInfoIndex); - } - } - } - else - { - validPit = false; - } - - // If the selected PIT was invalid, attempt to reload the old one. - if (!validPit) - { - Alerts::DisplayError("The file selected was not a valid PIT file."); - - if (!workingPackageData.GetFirmwareInfo().GetPitFilename().isEmpty()) - { - QFile originalPitFile(workingPackageData.GetFirmwareInfo().GetPitFilename()); - - if (ReadPit(&originalPitFile)) - { - validPit = true; - } - else - { - Alerts::DisplayError("Failed to reload working PIT data."); - - workingPackageData.Clear(); - partitionsListWidget->clear(); - } - } - } - - UpdateUnusedPartitionIds(); - - delete [] partitionNames; - - pitLineEdit->setText(workingPackageData.GetFirmwareInfo().GetPitFilename()); - - repartitionCheckBox->setEnabled(validPit); - noRebootCheckBox->setEnabled(validPit); - partitionsListWidget->setEnabled(validPit); - - addPartitionButton->setEnabled(validPit); - removePartitionButton->setEnabled(validPit && partitionsListWidget->currentRow() >= 0); - - UpdateInterfaceAvailability(); - } -} - - -void MainWindow::SetRepartition(int enabled) -{ - workingPackageData.GetFirmwareInfo().SetRepartition(enabled); - - repartitionCheckBox->setChecked(enabled); -} - -void MainWindow::SetNoReboot(int enabled) -{ - workingPackageData.GetFirmwareInfo().SetNoReboot(enabled); - - noRebootCheckBox->setChecked(enabled); -} - -void MainWindow::SetResume(bool enabled) -{ - resume = enabled; - - actionResumeConnection->setChecked(enabled); - resumeCheckbox->setChecked(enabled); -} - -void MainWindow::SetResume(int enabled) -{ - SetResume(enabled != 0); -} - -void MainWindow::StartFlash(void) -{ - outputPlainTextEdit->clear(); - - heimdallState = HeimdallState::Flashing; - heimdallFailed = false; - - const FirmwareInfo& firmwareInfo = workingPackageData.GetFirmwareInfo(); - const QList& fileInfos = firmwareInfo.GetFileInfos(); - - QStringList arguments; - arguments.append("flash"); - - if (firmwareInfo.GetRepartition()) - arguments.append("--repartition"); - - arguments.append("--pit"); - arguments.append(firmwareInfo.GetPitFilename()); - - for (int i = 0; i < fileInfos.length(); i++) - { - QString flag; - flag.sprintf("--%u", fileInfos[i].GetPartitionId()); - - arguments.append(flag); - arguments.append(fileInfos[i].GetFilename()); - } - - if (firmwareInfo.GetNoReboot()) - arguments.append("--no-reboot"); - - if (resume) - arguments.append("--resume"); - - if (verboseOutput) - arguments.append("--verbose"); - - arguments.append("--stdout-errors"); - - StartHeimdall(arguments); -} - -void MainWindow::FirmwareNameChanged(const QString& text) -{ - workingPackageData.GetFirmwareInfo().SetName(text); - UpdateInterfaceAvailability(); -} - -void MainWindow::FirmwareVersionChanged(const QString& text) -{ - workingPackageData.GetFirmwareInfo().SetVersion(text); - UpdateInterfaceAvailability(); -} - -void MainWindow::PlatformNameChanged(const QString& text) -{ - workingPackageData.GetFirmwareInfo().GetPlatformInfo().SetName(text); - UpdateInterfaceAvailability(); -} - -void MainWindow::PlatformVersionChanged(const QString& text) -{ - workingPackageData.GetFirmwareInfo().GetPlatformInfo().SetVersion(text); - UpdateInterfaceAvailability(); -} - -void MainWindow::HomepageUrlChanged(const QString& text) -{ - workingPackageData.GetFirmwareInfo().SetUrl(text); -} - -void MainWindow::DonateUrlChanged(const QString& text) -{ - workingPackageData.GetFirmwareInfo().SetDonateUrl(text); -} - -void MainWindow::DeveloperNameChanged(const QString& text) -{ - UNUSED(text); - - UpdateCreatePackageInterfaceAvailability(); -} - -void MainWindow::SelectDeveloper(int row) -{ - UNUSED(row); - - UpdateCreatePackageInterfaceAvailability(); -} - -void MainWindow::AddDeveloper(void) -{ - workingPackageData.GetFirmwareInfo().GetDevelopers().append(createDeveloperNameLineEdit->text()); - - createDevelopersListWidget->addItem(createDeveloperNameLineEdit->text()); - createDeveloperNameLineEdit->clear(); - - UpdateCreatePackageInterfaceAvailability(); -} - -void MainWindow::RemoveDeveloper(void) -{ - workingPackageData.GetFirmwareInfo().GetDevelopers().removeAt(createDevelopersListWidget->currentRow()); - - QListWidgetItem *item = createDevelopersListWidget->currentItem(); - createDevelopersListWidget->setCurrentRow(-1); - delete item; - - removeDeveloperButton->setEnabled(false); - - UpdateInterfaceAvailability(); -} - -void MainWindow::DeviceInfoChanged(const QString& text) -{ - UNUSED(text); - - if (deviceManufacturerLineEdit->text().isEmpty() || deviceNameLineEdit->text().isEmpty() || deviceProductCodeLineEdit->text().isEmpty()) - addDeviceButton->setEnabled(false); - else - addDeviceButton->setEnabled(true); -} - -void MainWindow::SelectDevice(int row) -{ - if (row >= 0) - removeDeviceButton->setEnabled(true); - else - removeDeviceButton->setEnabled(false); -} - -void MainWindow::AddDevice(void) -{ - workingPackageData.GetFirmwareInfo().GetDeviceInfos().append(DeviceInfo(deviceManufacturerLineEdit->text(), deviceProductCodeLineEdit->text(), - deviceNameLineEdit->text())); - - createDevicesListWidget->addItem(deviceManufacturerLineEdit->text() + " " + deviceNameLineEdit->text() + ": " + deviceProductCodeLineEdit->text()); - deviceManufacturerLineEdit->clear(); - deviceNameLineEdit->clear(); - deviceProductCodeLineEdit->clear(); - - UpdateInterfaceAvailability(); -} - -void MainWindow::RemoveDevice(void) -{ - workingPackageData.GetFirmwareInfo().GetDeviceInfos().removeAt(createDevicesListWidget->currentRow()); - - QListWidgetItem *item = createDevicesListWidget->currentItem(); - createDevicesListWidget->setCurrentRow(-1); - delete item; - - removeDeviceButton->setEnabled(false); - - UpdateInterfaceAvailability(); -} - -void MainWindow::BuildPackage(void) -{ - QString packagePath = PromptFileCreation("Save Package", "*.tar.gz"); - - if (!packagePath.isEmpty()) - { - if (!packagePath.endsWith(".tar.gz", Qt::CaseInsensitive)) - { - if (packagePath.endsWith(".tar", Qt::CaseInsensitive)) - packagePath.append(".gz"); - else if (packagePath.endsWith(".gz", Qt::CaseInsensitive)) - packagePath.replace(packagePath.length() - 3, ".tar.gz"); - else if (packagePath.endsWith(".tgz", Qt::CaseInsensitive)) - packagePath.replace(packagePath.length() - 4, ".tar.gz"); - else - packagePath.append(".tar.gz"); - } - - Packaging::BuildPackage(packagePath, workingPackageData.GetFirmwareInfo()); - } -} - -void MainWindow::DetectDevice(void) -{ - deviceDetectedRadioButton->setChecked(false); - utilityOutputPlainTextEdit->clear(); - - heimdallState = HeimdallState::DetectingDevice; - heimdallFailed = false; - - QStringList arguments; - arguments.append("detect"); - - if (verboseOutput) - arguments.append("--verbose"); - - arguments.append("--stdout-errors"); - - StartHeimdall(arguments); -} - -void MainWindow::ClosePcScreen(void) -{ - utilityOutputPlainTextEdit->clear(); - - heimdallState = HeimdallState::ClosingPcScreen; - heimdallFailed = false; - - QStringList arguments; - arguments.append("close-pc-screen"); - - if (resume) - arguments.append("--resume"); - - if (verboseOutput) - arguments.append("--verbose"); - - arguments.append("--stdout-errors"); - - StartHeimdall(arguments); -} - -void MainWindow::SelectPitDestination(void) -{ - QString path = PromptFileCreation("Save PIT", "*.pit"); - - if (path != "") - { - if (!path.endsWith(".pit")) - path.append(".pit"); - - pitDestinationLineEdit->setText(path); - - UpdateInterfaceAvailability(); - } -} - -void MainWindow::DownloadPit(void) -{ - deviceDetectedRadioButton->setChecked(false); - utilityOutputPlainTextEdit->clear(); - - heimdallState = HeimdallState::DownloadingPit; - heimdallFailed = false; - - QStringList arguments; - arguments.append("download-pit"); - - arguments.append("--output"); - arguments.append(pitDestinationLineEdit->text()); - - arguments.append("--no-reboot"); - - if (resume) - arguments.append("--resume"); - - if (verboseOutput) - arguments.append("--verbose"); - - arguments.append("--stdout-errors"); - - StartHeimdall(arguments); -} - -void MainWindow::DevicePrintPitToggled(bool checked) -{ - if (checked) - { - if (printPitLocalFileRadioBox->isChecked()) - printPitLocalFileRadioBox->setChecked(false); - } - - UpdateUtilitiesInterfaceAvailability(); -} - -void MainWindow::LocalFilePrintPitToggled(bool checked) -{ - if (checked) - { - if (printPitDeviceRadioBox->isChecked()) - printPitDeviceRadioBox->setChecked(false); - } - - UpdateUtilitiesInterfaceAvailability(); -} - -void MainWindow::SelectPrintPitFile(void) -{ - QString path = PromptFileSelection("Select PIT", "*.pit"); - - if (path != "") - printLocalPitLineEdit->setText(path); - - if (printLocalPitLineEdit->text() != "") - printPitButton->setEnabled(true); - else - printPitButton->setEnabled(false); -} - -void MainWindow::PrintPit(void) -{ - utilityOutputPlainTextEdit->clear(); - - heimdallState = HeimdallState::PrintingPit; - heimdallFailed = false; - - QStringList arguments; - arguments.append("print-pit"); - - if (printPitLocalFileRadioBox->isChecked()) - { - arguments.append("--file"); - arguments.append(printLocalPitLineEdit->text()); - } - - arguments.append("--stdout-errors"); - arguments.append("--no-reboot"); - - if (resume) - arguments.append("--resume"); - - if (verboseOutput) - arguments.append("--verbose"); - - StartHeimdall(arguments); -} - -void MainWindow::HandleHeimdallStdout(void) -{ - QString output = heimdallProcess.readAll(); - - // We often receive multiple lots of output from Heimdall at one time. So we use regular expressions - // to ensure we don't miss out on any important information. - QRegExp uploadingExp("Uploading [^\n]+\n"); - if (output.lastIndexOf(uploadingExp) > -1) - flashLabel->setText(uploadingExp.cap().left(uploadingExp.cap().length() - 1)); - - QRegExp percentExp("[\b\n][0-9]+%"); - if (output.lastIndexOf(percentExp) > -1) - { - QString percentString = percentExp.cap(); - flashProgressBar->setValue(percentString.mid(1, percentString.length() - 2).toInt()); - } - - output.remove(QChar('\b')); - output.replace(QChar('%'), QString("%\n")); - - if (heimdallState == HeimdallState::Flashing) - { - outputPlainTextEdit->insertPlainText(output); - outputPlainTextEdit->ensureCursorVisible(); - } - else - { - utilityOutputPlainTextEdit->insertPlainText(output); - utilityOutputPlainTextEdit->ensureCursorVisible(); - } -} - -void MainWindow::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus) -{ - HandleHeimdallStdout(); - - if (exitStatus == QProcess::NormalExit && exitCode == 0) - { - bool executedNoReboot = (heimdallState == HeimdallState::Flashing && loadedPackageData.GetFirmwareInfo().GetNoReboot()) - || (heimdallState == HeimdallState::PrintingPit && printPitDeviceRadioBox->isChecked()) || heimdallState == HeimdallState::DownloadingPit; - - SetResume(executedNoReboot); - - if (heimdallState == HeimdallState::Flashing) - { - flashLabel->setText("Flash completed successfully!"); - } - else if (heimdallState == HeimdallState::DetectingDevice) - { - deviceDetectedRadioButton->setChecked(true); - } - } - else - { - if (heimdallState == HeimdallState::Flashing) - { - QString error = heimdallProcess.readAllStandardError(); - - int lastNewLineChar = error.lastIndexOf('\n'); - - if (lastNewLineChar == 0) - error = error.mid(1).remove("ERROR: "); - else - error = error.left(lastNewLineChar).remove("ERROR: "); - - flashLabel->setText(error); - } - else if (heimdallState == HeimdallState::DetectingDevice) - { - deviceDetectedRadioButton->setChecked(false); - } - } - - heimdallState = HeimdallState::Stopped; - flashProgressBar->setEnabled(false); - UpdateInterfaceAvailability(); -} - -void MainWindow::HandleHeimdallError(QProcess::ProcessError error) -{ - if (error == QProcess::FailedToStart || error == QProcess::Timedout) - { - if (heimdallState == HeimdallState::Flashing) - { - flashLabel->setText("Failed to start Heimdall!"); - flashProgressBar->setEnabled(false); - } - else - { - utilityOutputPlainTextEdit->setPlainText("\nFRONTEND ERROR: Failed to start Heimdall!"); - } - - heimdallFailed = true; - heimdallState = HeimdallState::Stopped; - UpdateInterfaceAvailability(); - } - else if (error == QProcess::Crashed) - { - if (heimdallState == HeimdallState::Flashing) - { - flashLabel->setText("Heimdall crashed!"); - flashProgressBar->setEnabled(false); - } - else - { - utilityOutputPlainTextEdit->appendPlainText("\nFRONTEND ERROR: Heimdall crashed!"); - } - - heimdallState = HeimdallState::Stopped; - UpdateInterfaceAvailability(); - } - else - { - if (heimdallState == HeimdallState::Flashing) - { - flashLabel->setText("Heimdall reported an unknown error!"); - flashProgressBar->setEnabled(false); - } - else - { - utilityOutputPlainTextEdit->appendPlainText("\nFRONTEND ERROR: Heimdall reported an unknown error!"); - } - - heimdallState = HeimdallState::Stopped; - UpdateInterfaceAvailability(); - } -} diff --git a/heimdall-frontend/Source/mainwindow.h b/heimdall-frontend/Source/mainwindow.h deleted file mode 100644 index f14d919..0000000 --- a/heimdall-frontend/Source/mainwindow.h +++ /dev/null @@ -1,183 +0,0 @@ -/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -// Qt -#include -#include -#include -#include - -// libpit -#include "libpit.h" - -// Heimdall Frontend -#include "aboutform.h" -#include "ui_mainwindow.h" -#include "PackageData.h" - -using namespace libpit; - -namespace HeimdallFrontend -{ - class MainWindow : public QMainWindow, public Ui::MainWindow - { - Q_OBJECT - - private: - - enum class HeimdallState - { - Stopped = 0, - Flashing, - DetectingDevice, - ClosingPcScreen, - PrintingPit, - DownloadingPit - }; - - enum - { - kPrintPitSourceDevice = 0, - kPrintPitSourceLocalFile - }; - - AboutForm aboutForm; - - QString lastDirectory; - - int tabIndex; - - bool heimdallFailed; - HeimdallState heimdallState; - QProcess heimdallProcess; - - PackageData loadedPackageData; - - PitData currentPitData; - PackageData workingPackageData; - - bool populatingPartitionNames; - QList unusedPartitionIds; - - bool verboseOutput; - bool resume; - - - void StartHeimdall(const QStringList& arguments); - - void UpdateUnusedPartitionIds(void); - bool ReadPit(QFile *file); - - void UpdatePackageUserInterface(void); - - bool IsArchive(QString path); - - QString PromptFileSelection(const QString& caption = QString("Select File"), const QString& filter = QString()); - QString PromptFileCreation(const QString& caption = QString("Save File"), const QString& filter = QString()); - - void UpdateLoadPackageInterfaceAvailability(void); - void UpdateFlashInterfaceAvailability(void); - void UpdateCreatePackageInterfaceAvailability(void); - void UpdateUtilitiesInterfaceAvailability(void); - void UpdateInterfaceAvailability(void); - - void UpdatePartitionNamesInterface(void); - - public: - - explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); - - public slots: - - void OpenDonationWebpage(void); - void SetVerboseOutput(bool enabled); - void ShowAbout(void); - - void FunctionTabChanged(int index); - - // Load Package Tab - void SelectFirmwarePackage(void); - void OpenDeveloperHomepage(void); - void OpenDeveloperDonationWebpage(void); - void LoadFirmwarePackage(void); - - // Flash Tab - void SelectPartitionName(int index); - void SelectPartitionFile(void); - - void SelectPartition(int row); - void AddPartition(void); - void RemovePartition(void); - - void SelectPit(void); - - void SetRepartition(int enabled); - - void SetNoReboot(int enabled); - void SetResume(bool enabled); - void SetResume(int enabled); - - void StartFlash(void); - - // Create Package Tab - void FirmwareNameChanged(const QString& text); - void FirmwareVersionChanged(const QString& text); - void PlatformNameChanged(const QString& text); - void PlatformVersionChanged(const QString& text); - - void HomepageUrlChanged(const QString& text); - void DonateUrlChanged(const QString& text); - - void DeveloperNameChanged(const QString& text); - void SelectDeveloper(int row); - void AddDeveloper(void); - void RemoveDeveloper(void); - - void DeviceInfoChanged(const QString& text); - void SelectDevice(int row); - void AddDevice(void); - void RemoveDevice(void); - - void BuildPackage(void); - - // Utilities Tab - void DetectDevice(void); - void ClosePcScreen(void); - - void SelectPitDestination(void); - void DownloadPit(void); - - void DevicePrintPitToggled(bool checked); - void LocalFilePrintPitToggled(bool checked); - void SelectPrintPitFile(void); - void PrintPit(void); - - // Heimdall Command Line - void HandleHeimdallStdout(void); - void HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus); - void HandleHeimdallError(QProcess::ProcessError error); - }; -} - -#endif // MAINWINDOW_H -- cgit v1.2.3