From 6cd6b35c737e0e4042a8fd79af1decc9f10ed84b Mon Sep 17 00:00:00 2001 From: Benjamin Dobell Date: Mon, 1 Oct 2012 12:43:05 +1000 Subject: Heimdall 1.4 RC1: - Massive refactoring. - Support for Qualcomm based devices. - Print PIT from file. - Use partition names as arguments e.g. --HIDDEN, --KERNEL, --MOVINAND etc. - Heimdall Frontend UI improvements. - And much more... --- heimdall-frontend/Source/FirmwareInfo.cpp | 2 + heimdall-frontend/Source/Packaging.cpp | 25 +- heimdall-frontend/Source/aboutform.cpp | 95 ++++++++ heimdall-frontend/Source/aboutform.h | 17 ++ heimdall-frontend/Source/mainwindow.cpp | 384 ++++++++++++++++++++---------- heimdall-frontend/Source/mainwindow.h | 25 +- 6 files changed, 419 insertions(+), 129 deletions(-) (limited to 'heimdall-frontend/Source') diff --git a/heimdall-frontend/Source/FirmwareInfo.cpp b/heimdall-frontend/Source/FirmwareInfo.cpp index 741ea6c..e11a002 100644 --- a/heimdall-frontend/Source/FirmwareInfo.cpp +++ b/heimdall-frontend/Source/FirmwareInfo.cpp @@ -772,7 +772,9 @@ void FirmwareInfo::WriteXml(QXmlStreamWriter& xml) const xml.writeStartElement("files"); for (int i = 0; i < fileInfos.length(); i++) + { fileInfos[i].WriteXml(xml, Packaging::ClashlessFilename(fileInfos, i)); + } xml.writeEndElement(); diff --git a/heimdall-frontend/Source/Packaging.cpp b/heimdall-frontend/Source/Packaging.cpp index 79084e9..9bf7d46 100644 --- a/heimdall-frontend/Source/Packaging.cpp +++ b/heimdall-frontend/Source/Packaging.cpp @@ -301,7 +301,7 @@ bool Packaging::WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, // Note: We don't support base-256 encoding. Support could be added later. sprintf(tarHeader.fields.size, "%011llo", file.size()); - sprintf(tarHeader.fields.modifiedTime, "%011llo", qtFileInfo.lastModified().toMSecsSinceEpoch() / 1000); + sprintf(tarHeader.fields.modifiedTime, "%011llo", qtFileInfo.lastModified().toTime_t()); // Regular File tarHeader.fields.typeFlag = '0'; @@ -381,6 +381,24 @@ bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarF 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") @@ -389,7 +407,7 @@ bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarF return (false); } - if (!WriteTarEntry(fileInfos[i].GetFilename(), tarFile, ClashlessFilename(fileInfos, i))) + if (!WriteTarEntry(fileInfos[i].GetFilename(), tarFile, filename)) { tarFile->resize(0); tarFile->close(); @@ -666,7 +684,8 @@ QString Packaging::ClashlessFilename(const QList& fileInfos, int fileI QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1); - if (filename == otherFilename) + // 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++; } diff --git a/heimdall-frontend/Source/aboutform.cpp b/heimdall-frontend/Source/aboutform.cpp index bce9791..9bb975a 100644 --- a/heimdall-frontend/Source/aboutform.cpp +++ b/heimdall-frontend/Source/aboutform.cpp @@ -18,12 +18,107 @@ 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" +#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 index 12429ab..6223e3b 100644 --- a/heimdall-frontend/Source/aboutform.h +++ b/heimdall-frontend/Source/aboutform.h @@ -19,6 +19,7 @@ THE SOFTWARE.*/ // Qt +#include #include // Heimdall Frontend @@ -28,8 +29,24 @@ 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); }; } diff --git a/heimdall-frontend/Source/mainwindow.cpp b/heimdall-frontend/Source/mainwindow.cpp index c3c97e1..621ac38 100644 --- a/heimdall-frontend/Source/mainwindow.cpp +++ b/heimdall-frontend/Source/mainwindow.cpp @@ -32,18 +32,18 @@ #include "mainwindow.h" #include "Packaging.h" +#define UNUSED(x) (void)(x) + using namespace HeimdallFrontend; void MainWindow::StartHeimdall(const QStringList& arguments) { - flashProgressBar->setEnabled(true); UpdateInterfaceAvailability(); + + heimdallProcess.setReadChannel(QProcess::StandardOutput); - int pathIndex = -1; - process.setReadChannel(QProcess::StandardOutput); - - process.start("heimdall", arguments); - process.waitForStarted(3000); + 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) @@ -63,6 +63,8 @@ void MainWindow::StartHeimdall(const QStringList& arguments) } } + int pathIndex = -1; + while (heimdallFailed && ++pathIndex < paths.length()) { QString heimdallPath = paths[pathIndex]; @@ -76,8 +78,8 @@ void MainWindow::StartHeimdall(const QStringList& arguments) heimdallPath += "heimdall"; - process.start(heimdallPath, arguments); - process.waitForStarted(3000); + heimdallProcess.start(heimdallPath, arguments); + heimdallProcess.waitForStarted(3000); } } @@ -86,7 +88,6 @@ void MainWindow::StartHeimdall(const QStringList& arguments) flashLabel->setText("Failed to start Heimdall!"); heimdallState = MainWindow::kHeimdallStateStopped; - flashProgressBar->setEnabled(false); UpdateInterfaceAvailability(); } } @@ -101,8 +102,8 @@ void MainWindow::UpdateUnusedPartitionIds(void) { const PitEntry *pitEntry = currentPitData.GetEntry(i); - if (!pitEntry->GetUnused() && strcmp(pitEntry->GetPartitionName(), "PIT") != 0) - unusedPartitionIds.append(pitEntry->GetPartitionIdentifier()); + if (pitEntry->GetBlockCount() > 0 && strcmp(pitEntry->GetPartitionName(), "PIT") != 0 && strcmp(pitEntry->GetPartitionName(), "PT") != 0) + unusedPartitionIds.append(pitEntry->GetIdentifier()); } // Remove any used partition IDs from unusedPartitionIds @@ -145,14 +146,9 @@ void MainWindow::UpdatePackageUserInterface(void) developerNamesLineEdit->clear(); platformLineEdit->clear(); - - developerHomepageButton->setEnabled(false); - developerDonateButton->setEnabled(false); repartitionRadioButton->setChecked(false); noRebootRadioButton->setChecked(false); - - loadFirmwareButton->setEnabled(false); } else { @@ -173,16 +169,6 @@ void MainWindow::UpdatePackageUserInterface(void) platformLineEdit->setText(loadedPackageData.GetFirmwareInfo().GetPlatformInfo().GetName() + " (" + loadedPackageData.GetFirmwareInfo().GetPlatformInfo().GetVersion() + ")"); - if (!loadedPackageData.GetFirmwareInfo().GetUrl().isEmpty()) - developerHomepageButton->setEnabled(true); - else - developerHomepageButton->setEnabled(false); - - if (!loadedPackageData.GetFirmwareInfo().GetDonateUrl().isEmpty()) - developerDonateButton->setEnabled(true); - else - developerDonateButton->setEnabled(false); - for (int i = 0; i < loadedPackageData.GetFirmwareInfo().GetDeviceInfos().length(); i++) { const DeviceInfo& deviceInfo = loadedPackageData.GetFirmwareInfo().GetDeviceInfos()[i]; @@ -197,9 +183,9 @@ void MainWindow::UpdatePackageUserInterface(void) repartitionRadioButton->setChecked(loadedPackageData.GetFirmwareInfo().GetRepartition()); noRebootRadioButton->setChecked(loadedPackageData.GetFirmwareInfo().GetNoReboot()); - - loadFirmwareButton->setEnabled(true); } + + UpdateLoadPackageInterfaceAvailability(); } bool MainWindow::IsArchive(QString path) @@ -209,9 +195,9 @@ bool MainWindow::IsArchive(QString path) || path.endsWith(".bz2", Qt::CaseInsensitive) || path.endsWith(".7z", Qt::CaseInsensitive) || path.endsWith(".rar", Qt::CaseInsensitive)); } -QString MainWindow::PromptFileSelection(void) +QString MainWindow::PromptFileSelection(const QString& caption, const QString& filter) { - QString path = QFileDialog::getOpenFileName(this, "Select File", lastDirectory); + QString path = QFileDialog::getOpenFileName(this, caption, lastDirectory, filter); if (path != "") lastDirectory = path.left(path.lastIndexOf('/') + 1); @@ -219,9 +205,9 @@ QString MainWindow::PromptFileSelection(void) return (path); } -QString MainWindow::PromptFileCreation(void) +QString MainWindow::PromptFileCreation(const QString& caption, const QString& filter) { - QString path = QFileDialog::getSaveFileName(this, "Save File", lastDirectory); + QString path = QFileDialog::getSaveFileName(this, caption, lastDirectory, filter); if (path != "") lastDirectory = path.left(path.lastIndexOf('/') + 1); @@ -229,49 +215,100 @@ QString MainWindow::PromptFileCreation(void) return (path); } -void MainWindow::UpdatePartitionNamesInterface(void) +void MainWindow::UpdateLoadPackageInterfaceAvailability(void) { - populatingPartitionNames = true; + if (loadedPackageData.IsCleared()) + { + developerHomepageButton->setEnabled(false); + developerDonateButton->setEnabled(false); - partitionNameComboBox->clear(); + loadFirmwareButton->setEnabled(false); + } + else + { + if (!loadedPackageData.GetFirmwareInfo().GetUrl().isEmpty()) + developerHomepageButton->setEnabled(true); + else + developerHomepageButton->setEnabled(false); - int partitionsListWidgetRow = partitionsListWidget->currentRow(); + if (!loadedPackageData.GetFirmwareInfo().GetDonateUrl().isEmpty()) + developerDonateButton->setEnabled(true); + else + developerDonateButton->setEnabled(false); - if (partitionsListWidgetRow >= 0) + loadFirmwareButton->setEnabled(heimdallState == MainWindow::kHeimdallStateStopped); + } +} + +void MainWindow::UpdateFlashInterfaceAvailability(void) +{ + if (heimdallState == MainWindow::kHeimdallStateStopped) { - const FileInfo& partitionInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[partitionsListWidget->currentRow()]; + partitionNameComboBox->setEnabled(partitionsListWidget->currentRow() >= 0); - for (int i = 0; i < unusedPartitionIds.length(); i++) - partitionNameComboBox->addItem(currentPitData.FindEntry(unusedPartitionIds[i])->GetPartitionName()); + bool allPartitionsValid = true; + QList& fileList = workingPackageData.GetFirmwareInfo().GetFileInfos(); - partitionNameComboBox->addItem(currentPitData.FindEntry(partitionInfo.GetPartitionId())->GetPartitionName()); - partitionNameComboBox->setCurrentIndex(unusedPartitionIds.length()); + for (int i = 0; i < fileList.length(); i++) + { + if (fileList[i].GetFilename().isEmpty()) + { + allPartitionsValid = false; + break; + } + } - partitionNameComboBox->setEnabled(true); + bool validFlashSettings = allPartitionsValid && fileList.length() > 0; + + flashProgressBar->setEnabled(false); + optionsGroup->setEnabled(true); + startFlashButton->setEnabled(validFlashSettings); } else { partitionNameComboBox->setEnabled(false); - } - populatingPartitionNames = false; + flashProgressBar->setEnabled(true); + optionsGroup->setEnabled(false); + startFlashButton->setEnabled(false); + } } -void MainWindow::UpdateInterfaceAvailability(void) +void MainWindow::UpdateCreatePackageInterfaceAvailability(void) { - if (heimdallState != MainWindow::kHeimdallStateStopped) + if (heimdallState == MainWindow::kHeimdallStateStopped) { - startFlashButton->setEnabled(false); + const FirmwareInfo& firmwareInfo = workingPackageData.GetFirmwareInfo(); - detectDeviceButton->setEnabled(false); - closePcScreenButton->setEnabled(false); - pitSaveAsButton->setEnabled(false); - downloadPitButton->setEnabled(false); - printPitButton->setEnabled(false); + 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); - return; + if (createDevelopersListWidget->currentRow() >= 0) + removeDeveloperButton->setEnabled(true); + else + removeDeveloperButton->setEnabled(false); } else + { + buildPackageButton->setEnabled(false); + } +} + +void MainWindow::UpdateUtilitiesInterfaceAvailability(void) +{ + if (heimdallState == MainWindow::kHeimdallStateStopped) { detectDeviceButton->setEnabled(true); closePcScreenButton->setEnabled(true); @@ -281,43 +318,86 @@ void MainWindow::UpdateInterfaceAvailability(void) downloadPitButton->setEnabled(true); else downloadPitButton->setEnabled(false); + + 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); - printPitButton->setEnabled(true); + printLocalPitGroup->setEnabled(false); + printPitButton->setEnabled(false); } +} + +void MainWindow::UpdateInterfaceAvailability(void) +{ + UpdateLoadPackageInterfaceAvailability(); + UpdateFlashInterfaceAvailability(); + UpdateCreatePackageInterfaceAvailability(); + UpdateUtilitiesInterfaceAvailability(); - bool allPartitionsValid = true; + if (heimdallState == MainWindow::kHeimdallStateStopped) + { + // Enable/disable tabs - QList& fileList = workingPackageData.GetFirmwareInfo().GetFileInfos(); + for (int i = 0; i < functionTabWidget->count(); i++) + functionTabWidget->setTabEnabled(i, true); - for (int i = 0; i < fileList.length(); i++) + functionTabWidget->setTabEnabled(functionTabWidget->indexOf(createPackageTab), startFlashButton->isEnabled()); + } + else { - if (fileList[i].GetFilename().isEmpty()) + // Disable non-current tabs + + for (int i = 0; i < functionTabWidget->count(); i++) { - allPartitionsValid = false; - break; + if (i == functionTabWidget->currentIndex()) + functionTabWidget->setTabEnabled(i, true); + else + functionTabWidget->setTabEnabled(i, false); } } - - bool validSettings = allPartitionsValid && fileList.length() > 0; - - startFlashButton->setEnabled(validSettings); - - functionTabWidget->setTabEnabled(functionTabWidget->indexOf(createPackageTab), validSettings); } -void MainWindow::UpdateBuildPackageButton(void) +void MainWindow::UpdatePartitionNamesInterface(void) { - const FirmwareInfo& firmwareInfo = workingPackageData.GetFirmwareInfo(); + populatingPartitionNames = true; - 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 + partitionNameComboBox->clear(); + + int partitionsListWidgetRow = partitionsListWidget->currentRow(); + + if (partitionsListWidgetRow >= 0) { - buildPackageButton->setEnabled(true); + 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) @@ -388,15 +468,21 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // 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(&process, SIGNAL(readyRead()), this, SLOT(HandleHeimdallStdout())); - QObject::connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(HandleHeimdallReturned(int, QProcess::ExitStatus))); - QObject::connect(&process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(HandleHeimdallError(QProcess::ProcessError))); + 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() @@ -429,7 +515,7 @@ void MainWindow::SelectFirmwarePackage(void) loadedPackageData.Clear(); UpdatePackageUserInterface(); - QString path = PromptFileSelection(); + QString path = PromptFileSelection("Select Package", "*.tar.gz"); firmwarePackageLineEdit->setText(path); if (firmwarePackageLineEdit->text() != "") @@ -458,7 +544,6 @@ void MainWindow::LoadFirmwarePackage(void) workingPackageData.Clear(); currentPitData.Clear(); - // Make flashSettings responsible for the temporary files workingPackageData.GetFiles().append(loadedPackageData.GetFiles()); loadedPackageData.RemoveAllFiles(); @@ -575,10 +660,18 @@ void MainWindow::SelectPartitionName(int index) 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()) { - PitEntry *pitEntry = currentPitData.FindEntry(newPartitionIndex); - QString partitionFilename = pitEntry->GetFilename(); + QString partitionFilename = pitEntry->GetFlashFilename(); int lastPeriod = partitionFilename.lastIndexOf(QChar('.')); if (lastPeriod >= 0) @@ -610,7 +703,7 @@ void MainWindow::SelectPartitionFile(void) FileInfo& fileInfo = workingPackageData.GetFirmwareInfo().GetFileInfos()[partitionsListWidget->currentRow()]; PitEntry *pitEntry = currentPitData.FindEntry(fileInfo.GetPartitionId()); - QString partitionFilename = pitEntry->GetFilename(); + QString partitionFilename = pitEntry->GetFlashFilename(); int lastPeriod = partitionFilename.lastIndexOf(QChar('.')); if (lastPeriod >= 0) @@ -648,6 +741,15 @@ void MainWindow::SelectPartition(int row) 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 { @@ -658,6 +760,8 @@ void MainWindow::SelectPartition(int row) partitionFileBrowseButton->setEnabled(false); removePartitionButton->setEnabled(false); + + partitionFileGroup->setTitle("File"); } } @@ -673,6 +777,7 @@ void MainWindow::AddPartition(void) partitionsListWidget->addItem(currentPitData.FindEntry(partitionInfo.GetPartitionId())->GetPartitionName()); partitionsListWidget->setCurrentRow(partitionsListWidget->count() - 1); partitionsListWidget->setEnabled(false); + UpdateInterfaceAvailability(); } @@ -693,7 +798,7 @@ void MainWindow::RemovePartition(void) void MainWindow::SelectPit(void) { - QString path = PromptFileSelection(); + QString path = PromptFileSelection("Select PIT", "*.pit"); bool validPit = path != ""; if (validPit) @@ -723,7 +828,7 @@ void MainWindow::SelectPit(void) if (pitEntry) { - fileInfos[partitionInfoIndex++].SetPartitionId(pitEntry->GetPartitionIdentifier()); + fileInfos[partitionInfoIndex++].SetPartitionId(pitEntry->GetIdentifier()); partitionsListWidget->addItem(pitEntry->GetPartitionName()); } else @@ -828,25 +933,25 @@ void MainWindow::StartFlash(void) void MainWindow::FirmwareNameChanged(const QString& text) { workingPackageData.GetFirmwareInfo().SetName(text); - UpdateBuildPackageButton(); + UpdateInterfaceAvailability(); } void MainWindow::FirmwareVersionChanged(const QString& text) { workingPackageData.GetFirmwareInfo().SetVersion(text); - UpdateBuildPackageButton(); + UpdateInterfaceAvailability(); } void MainWindow::PlatformNameChanged(const QString& text) { workingPackageData.GetFirmwareInfo().GetPlatformInfo().SetName(text); - UpdateBuildPackageButton(); + UpdateInterfaceAvailability(); } void MainWindow::PlatformVersionChanged(const QString& text) { workingPackageData.GetFirmwareInfo().GetPlatformInfo().SetVersion(text); - UpdateBuildPackageButton(); + UpdateInterfaceAvailability(); } void MainWindow::HomepageUrlChanged(const QString& text) @@ -861,18 +966,16 @@ void MainWindow::DonateUrlChanged(const QString& text) void MainWindow::DeveloperNameChanged(const QString& text) { - if (text.isEmpty()) - addDeveloperButton->setEnabled(false); - else - addDeveloperButton->setEnabled(true); + UNUSED(text); + + UpdateCreatePackageInterfaceAvailability(); } void MainWindow::SelectDeveloper(int row) { - if (row >= 0) - removeDeveloperButton->setEnabled(true); - else - removeDeveloperButton->setEnabled(false); + UNUSED(row); + + UpdateCreatePackageInterfaceAvailability(); } void MainWindow::AddDeveloper(void) @@ -881,8 +984,8 @@ void MainWindow::AddDeveloper(void) createDevelopersListWidget->addItem(createDeveloperNameLineEdit->text()); createDeveloperNameLineEdit->clear(); - - UpdateBuildPackageButton(); + + UpdateCreatePackageInterfaceAvailability(); } void MainWindow::RemoveDeveloper(void) @@ -894,12 +997,14 @@ void MainWindow::RemoveDeveloper(void) delete item; removeDeveloperButton->setEnabled(false); - - UpdateBuildPackageButton(); + + UpdateInterfaceAvailability(); } void MainWindow::DeviceInfoChanged(const QString& text) { + UNUSED(text); + if (deviceManufacturerLineEdit->text().isEmpty() || deviceNameLineEdit->text().isEmpty() || deviceProductCodeLineEdit->text().isEmpty()) addDeviceButton->setEnabled(false); else @@ -923,8 +1028,8 @@ void MainWindow::AddDevice(void) deviceManufacturerLineEdit->clear(); deviceNameLineEdit->clear(); deviceProductCodeLineEdit->clear(); - - UpdateBuildPackageButton(); + + UpdateInterfaceAvailability(); } void MainWindow::RemoveDevice(void) @@ -936,13 +1041,13 @@ void MainWindow::RemoveDevice(void) delete item; removeDeviceButton->setEnabled(false); - - UpdateBuildPackageButton(); + + UpdateInterfaceAvailability(); } void MainWindow::BuildPackage(void) { - QString packagePath = PromptFileCreation(); + QString packagePath = PromptFileCreation("Save Package", "*.tar.gz"); if (!packagePath.isEmpty()) { @@ -995,7 +1100,7 @@ void MainWindow::ClosePcScreen(void) void MainWindow::SelectPitDestination(void) { - QString path = PromptFileCreation(); + QString path = PromptFileCreation("Save PIT", "*.pit"); if (path != "") { @@ -1029,6 +1134,41 @@ void MainWindow::DownloadPit(void) 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(); @@ -1039,14 +1179,21 @@ void MainWindow::PrintPit(void) QStringList arguments; arguments.append("print-pit"); + if (printPitLocalFileRadioBox->isChecked()) + { + arguments.append("--file"); + arguments.append(printLocalPitLineEdit->text()); + } + arguments.append("--stdout-errors"); + arguments.append("--no-reboot"); StartHeimdall(arguments); } void MainWindow::HandleHeimdallStdout(void) { - QString output = process.readAll(); + 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. @@ -1078,29 +1225,22 @@ void MainWindow::HandleHeimdallStdout(void) void MainWindow::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus) { - // This is a work-around for strange issues as a result of a exitCode being cast to - // a unsigned char. - char byteExitCode = exitCode; - - if (exitStatus == QProcess::NormalExit && byteExitCode >= 0) + if (exitStatus == QProcess::NormalExit && exitCode == 0) { if (heimdallState == MainWindow::kHeimdallStateFlashing) { - if (byteExitCode == 1) - flashLabel->setText("Failed to detect compatible device!"); - else - flashLabel->setText("Flash completed sucessfully!"); + flashLabel->setText("Flash completed successfully!"); } else if (heimdallState == MainWindow::kHeimdallStateDetectingDevice) { - deviceDetectedRadioButton->setChecked(byteExitCode == 0); + deviceDetectedRadioButton->setChecked(true); } } else { if (heimdallState == MainWindow::kHeimdallStateFlashing) { - QString error = process.readAllStandardError(); + QString error = heimdallProcess.readAllStandardError(); int lastNewLineChar = error.lastIndexOf('\n'); @@ -1111,6 +1251,10 @@ void MainWindow::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitS flashLabel->setText(error); } + else if (heimdallState == MainWindow::kHeimdallStateDetectingDevice) + { + deviceDetectedRadioButton->setChecked(false); + } } heimdallState = MainWindow::kHeimdallStateStopped; diff --git a/heimdall-frontend/Source/mainwindow.h b/heimdall-frontend/Source/mainwindow.h index 9d21978..bea15cd 100644 --- a/heimdall-frontend/Source/mainwindow.h +++ b/heimdall-frontend/Source/mainwindow.h @@ -56,6 +56,12 @@ namespace HeimdallFrontend kHeimdallStateCount }; + enum + { + kPrintPitSourceDevice = 0, + kPrintPitSourceLocalFile + }; + AboutForm aboutForm; QString lastDirectory; @@ -64,7 +70,7 @@ namespace HeimdallFrontend bool heimdallFailed; int heimdallState; - QProcess process; + QProcess heimdallProcess; PackageData loadedPackageData; @@ -76,6 +82,7 @@ namespace HeimdallFrontend bool verboseOutput; + void StartHeimdall(const QStringList& arguments); void UpdateUnusedPartitionIds(void); @@ -85,13 +92,16 @@ namespace HeimdallFrontend bool IsArchive(QString path); - QString PromptFileSelection(void); - QString PromptFileCreation(void); - - void UpdatePartitionNamesInterface(void); + 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 UpdateBuildPackageButton(void); + void UpdatePartitionNamesInterface(void); public: @@ -155,6 +165,9 @@ namespace HeimdallFrontend void SelectPitDestination(void); void DownloadPit(void); + void DevicePrintPitToggled(bool checked); + void LocalFilePrintPitToggled(bool checked); + void SelectPrintPitFile(void); void PrintPit(void); // Heimdall Command Line -- cgit v1.2.3