aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/desktop-utils/lumina-archiver/imgDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/desktop-utils/lumina-archiver/imgDialog.cpp')
-rw-r--r--src-qt5/desktop-utils/lumina-archiver/imgDialog.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/src-qt5/desktop-utils/lumina-archiver/imgDialog.cpp b/src-qt5/desktop-utils/lumina-archiver/imgDialog.cpp
new file mode 100644
index 00000000..13268a73
--- /dev/null
+++ b/src-qt5/desktop-utils/lumina-archiver/imgDialog.cpp
@@ -0,0 +1,178 @@
+//===========================================
+// Lumina-Desktop source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "imgDialog.h"
+#include "ui_imgDialog.h"
+
+#include <QMessageBox>
+
+#include <LuminaOS.h>
+#include <LuminaXDG.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+
+imgDialog::imgDialog(QWidget *parent) : QDialog(parent), ui(new Ui::imgDialog()){
+ ui->setupUi(this); //load the designer form
+ QString title = tr("Burn IMG to Device");
+ if( getuid()==0){ title.append(" ("+tr("Admin Mode")+")"); }
+ this->setWindowTitle(title);
+ ui->frame_running->setVisible(false);
+ ui->frame_setup->setVisible(true);
+ ddProc = 0;
+ unitdiv = 1;
+ //Setup the signals/slots
+ ui->tool_refresh->setIcon( LXDG::findIcon("view-refresh","drive-removable-media-usb-pendrive") );
+ connect(ui->push_cancel, SIGNAL(clicked()), this, SLOT(cancel()) );
+ connect(ui->push_start, SIGNAL(clicked()), this, SLOT(start_process()) );
+ connect(ui->tool_refresh, SIGNAL(clicked()), this, SLOT(loadDeviceList()) );
+ loadDeviceList(); //do the initial load of the available devices
+ //Setup the possible transfer rate units
+ ui->combo_rate_units->clear();
+ ui->combo_rate_units->addItem(tr("Kilobyte(s)"), "k");
+ ui->combo_rate_units->addItem(tr("Megabyte(s)"), "m");
+ ui->combo_rate_units->addItem(tr("Gigabyte(s)"), "g");
+ ui->combo_rate_units->setCurrentIndex(1); //MB
+ //Setup the Process Timer
+ procTimer = new QTimer(this);
+ procTimer->setInterval(1000); //1 second updates
+ connect(procTimer, SIGNAL(timeout()), this, SLOT(getProcStatus()) );
+ //Determine which type of system this is for the process status signal
+ BSD_signal = LOS::OSName().contains("BSD"); //assume everything else is Linux-like
+}
+
+imgDialog::~imgDialog(){
+
+}
+
+void imgDialog::loadIMG(QString filepath){
+ ui->label_iso->setText(filepath.section("/",-1)); //only show the filename
+ ui->label_iso->setWhatsThis(filepath); //save the full path for later
+}
+
+//============================
+// PRIVATE SLOTS
+//============================
+void imgDialog::start_process(){
+ //Sanity Checks
+ if( !QFile::exists(ui->combo_devices->currentData().toString()) ){ loadDeviceList(); return; } //USB device no longer available
+ if(!QFile::exists(ui->label_iso->whatsThis()) ){ return; } //IMG file no longer available
+ qDebug() << "Start Process...";
+ //Read the size of the img file
+ QString units = ui->combo_rate_units->currentData().toString();
+ if(units=="k"){ unitdiv = 1024; }
+ else if(units=="m"){ unitdiv = 1024*1024; }
+ else if(units=="g"){ unitdiv = 1024*1024*1024; }
+ qint64 bytes = QFileInfo(ui->label_iso->whatsThis()).size();
+ //qDebug() << "IMG File size:" << bytes;
+ //Set the progressBar maximum
+ ui->progressBar->setRange(0, qRound(bytes/unitdiv) );
+ ui->progressBar->setValue(0);
+ ui->label_dev->setText( ui->combo_devices->currentText() );
+ ui->label_time->setText("0:00");
+ ui->frame_running->setVisible(true);
+ ui->frame_setup->setVisible(false);
+ //qDebug() << "Blocks:" << ui->progressBar->maximum();
+ //Initialize the process
+ if(ddProc==0){
+ ddProc = new QProcess(this);
+ connect(ddProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(procFinished()) );
+ connect(ddProc, SIGNAL(readyRead()), this, SLOT(procInfoAvailable()) );
+ ddProc->setProcessChannelMode(QProcess::MergedChannels);
+ }
+ //Generate the command
+ QString prog; QStringList args;
+ //if( ::getuid()!=0){ prog = "qsudo"; args<<"dd"; }
+ //else{
+ prog = "dd";
+ //}
+ args << "if="+ui->label_iso->whatsThis();
+ args << "of="+ui->combo_devices->currentData().toString();
+ args << "bs="+QString::number(ui->spin_rate_num->value())+units;
+ if(ui->check_sync->isChecked()){ args << "conv=sync"; }
+ //Start the process
+ startTime = QDateTime::currentDateTime();
+ ddProc->start(prog, args);
+ //Start the timer to watch for updates
+ procTimer->start();
+ ui->push_start->setEnabled(false);
+}
+
+void imgDialog::cancel(){
+ if(ddProc==0 || ddProc->state()==QProcess::NotRunning){
+ this->close();
+ }else{
+ //Prompt if the transfer should be cancelled
+ if(QMessageBox::Yes == QMessageBox::question(this, tr("Cancel Image Burn?"), tr("Do you wish to stop the current IMG burn process?")+"\n\n"+tr("Warning: This will leave the USB device in an inconsistent state")) ){
+ ddProc->kill();
+ }
+ }
+}
+
+void imgDialog::loadDeviceList(){
+ ui->combo_devices->clear();
+ //Probe the system for USB devices
+ QDir devDir("/dev");
+ QString filter = (BSD_signal) ? "da*" : "sd*";
+ QStringList usb = devDir.entryList(QStringList() << filter, QDir::System, QDir::Name);
+ //Filter out any devices which are currently mounted/used
+
+ //Create the list
+ for(int i=0; i<usb.length(); i++){
+ ui->combo_devices->addItem(usb[i], devDir.absoluteFilePath(usb[i]));
+ }
+}
+
+void imgDialog::getProcStatus(){
+ if(ddProc==0 || ddProc->state()!=QProcess::Running ){ return; }
+ QStringList pidlist = LUtils::getCmdOutput("pgrep -S -f \"dd if="+ui->label_iso->whatsThis()+"\"");
+ if(pidlist.isEmpty()){ return; }
+ int pid = pidlist.first().simplified().toInt(); //just use the first pid - the pgrep should be detailed enough to only match one
+ //qDebug() << "Sending signal to show status on PID:" << pid;
+ if(BSD_signal){ ::kill(pid, SIGINFO); } //On BSD systems, the INFO signal is used to poke dd for status updates
+ else{ ::kill(pid, SIGUSR1); } //On linux systems, the USR1 signal is used to poke dd for status updates
+ //Now update the elapsed time on the UI
+ int elapsed = startTime.secsTo( QDateTime::currentDateTime() );
+ int min = elapsed/60;
+ int secs = elapsed%60;
+ ui->label_time->setText( QString::number(min)+":"+ (secs < 10 ? "0" : "")+QString::number(secs) );
+}
+
+void imgDialog::procInfoAvailable(){
+ lastmsg = ddProc->readAll();
+ if(lastmsg.endsWith("\n")){ lastmsg.chop(1); }
+ //qDebug() << "Got Process Info:" << lastmsg;
+ //Now look for the " bytes transferred" line
+ QStringList records = lastmsg.split("\n").filter(" bytes transferred ");
+ if(!records.isEmpty()){
+ //Update the progress bar
+ //qDebug() << "Got status update:" << records.last();
+ ui->progressBar->setValue( qRound(records.last().section(" bytes",0,0).toDouble()/unitdiv) );
+ }
+}
+
+void imgDialog::procFinished(){
+ qDebug() << "Process Finished:" << ddProc->exitCode();
+ procTimer->stop();
+ ui->frame_running->setVisible(false);
+ ui->frame_setup->setVisible(true);
+ if(ddProc->exitStatus()==QProcess::NormalExit){
+ if(ddProc->exitCode() !=0 ){
+ if(lastmsg.contains("permission denied", Qt::CaseInsensitive) && LUtils::isValidBinary("qsudo") ){
+ if(QMessageBox::Yes == QMessageBox::question(this, tr("Administrator Permissions Needed"), tr("This operation requires administrator priviledges.")+"\n\n"+tr("Would you like to enable these priviledges?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ){
+ QProcess::startDetached("qsudo", QStringList() << "lumina-archiver" << "--burn-img" << ui->label_iso->whatsThis());
+ exit(0);
+ }
+ }else{
+ QMessageBox::warning(this, tr("ERROR"), tr("The process could not be completed:")+"\n\n"+lastmsg);
+ }
+ }else{
+ QMessageBox::information(this, tr("SUCCESS"), tr("The image was successfully burned to the USB device") );
+ this->close();
+ }
+ }
+}
bgstack15