mirror of
https://github.com/digarok/buckshot.git
synced 2024-05-31 12:41:31 +00:00
790 lines
28 KiB
C++
790 lines
28 KiB
C++
#include "mainwindow.h"
|
|
#include "ui_mainwindow.h"
|
|
#include "qfiledialog.h"
|
|
#include "qprocess.h"
|
|
#include "qdebug.h"
|
|
#include "qtimer.h"
|
|
#include "qmessagebox.h"
|
|
#include "qinputdialog.h"
|
|
#include "qformlayout.h"
|
|
#include "qdialogbuttonbox.h"
|
|
const QString MainWindow::programName = QString("buckshot");
|
|
const QString MainWindow::version = QString("0.05");
|
|
const QString MainWindow::imageName = QString("saved");
|
|
|
|
MainWindow::MainWindow(QWidget *parent) :
|
|
QMainWindow(parent),
|
|
ui(new Ui::MainWindow)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
// Window Title
|
|
this->setWindowTitle(QString("%1 v%2").arg(programName,version));
|
|
|
|
// SET TEMP DIR FOR CACHE/BUILDING
|
|
tmpDir = new QTemporaryDir();
|
|
if (tmpDir->isValid()) {
|
|
tmpDirPath = tmpDir->path(); // dir.path() returns the unique directory path
|
|
} else {
|
|
tmpDirPath = "/tmp/"; // fallback. may not work on all OSes
|
|
}
|
|
|
|
// AND NOW THE PATHNAMES FOR OUR CACHE FILES
|
|
inputImgPath = QString("%1/%2.bmp").arg(tmpDirPath).arg(imageName);
|
|
previewImgPath = QString("%1/%2_Preview.bmp").arg(tmpDirPath).arg(imageName);
|
|
|
|
// POPULATE FORMAT COMBOBOX
|
|
QStringList outputFormats;
|
|
outputFormats << "LR" << "DLR" << "HGR" << "DHGR" << "MONO";
|
|
ui->comboBox_outputFormat->addItems(outputFormats);
|
|
|
|
// POPULATE RESOLUTION COMBOBOX
|
|
QStringList inputResolutions;
|
|
inputResolutions << "40 x 48 - Full Scale LGR"
|
|
<< "80 x 48 - Full Scale DLGR"
|
|
<< "140 x 192 - Full Scale (HGR & DHGR)"
|
|
<< "280 x 192 - Double Width Scale (HGR & DHGR)"
|
|
<< "320 x 200 - Classic Size"
|
|
<< "560 x 384 - Quadruple Width, Double Height Scale"
|
|
<< "640 x 400 - Classic Size"
|
|
<< "640 x 480 - Classic Size";
|
|
ui->comboBox_inputResolution->addItems(inputResolutions);
|
|
|
|
// POPULATE DITHERING COMBOBOX
|
|
QStringList ditheringAlgorithms;
|
|
ditheringAlgorithms << "Default"
|
|
<< "1- Floyd-Steinberg"
|
|
<< "2- Jarvis"
|
|
<< "3- Stucki"
|
|
<< "4- Atkinson"
|
|
<< "5- Burkes"
|
|
<< "6- Sierra"
|
|
<< "7- Sierra Two"
|
|
<< "8- Sierra Lite"
|
|
<< "9- Buckels";
|
|
ui->comboBox_dithering->addItems(ditheringAlgorithms);
|
|
|
|
|
|
// POPULATE PALETTE COMBOBOX
|
|
QStringList previewPalettes;
|
|
previewPalettes << "Kegs32 RGB"
|
|
<< "CiderPress RGB"
|
|
<< "Old AppleWin NTSC"
|
|
<< "New AppleWin NTSC"
|
|
<< "Wikipedia NTSC"
|
|
<< "tohgr NTSC DHGR"
|
|
<< " (N/A) -- Imported"
|
|
<< "Legacy Canvas"
|
|
<< "Legacy Win16"
|
|
<< "Legacy Win32"
|
|
<< "Legacy VGA BIOS"
|
|
<< "Legacy VGA PCX"
|
|
<< "Super Convert RGB"
|
|
<< "Jace NTSC"
|
|
<< "Cybernesto-Munafo NTSC"
|
|
<< "Pseudo Palette"
|
|
<< "tohgr NTSC HGR";
|
|
ui->comboBox_previewPalette->addItems(previewPalettes);
|
|
|
|
// HANDLE DISPLAY MODE SELECTION (COMPATIBILITY)
|
|
updateDisplayModes();
|
|
|
|
// live preview stuff
|
|
updateNeeded = false;
|
|
previewTimer = new QTimer(this);
|
|
connect(previewTimer, SIGNAL(timeout()), this, SLOT(previewTimerTimeout()));
|
|
// decided to enable by checking in the form and calling this.
|
|
on_checkBox_livePreview_stateChanged(1);
|
|
}
|
|
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
|
|
bool MainWindow::check_canPreview()
|
|
{
|
|
if (ui->label_source->pixmap() == nullptr) {
|
|
ui->plainTextEdit_lastCmd->setPlainText("Please open a source image to run a preview!");
|
|
repaint();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool MainWindow::check_canSave()
|
|
{
|
|
if (ui->label_preview->pixmap() == nullptr) {
|
|
ui->plainTextEdit_lastCmd->setPlainText("Please open a source image and run a preview first!");
|
|
repaint();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void MainWindow::updateDisplayModes() {
|
|
|
|
QList<int> disabledList = QList<int>();
|
|
|
|
//---- display modes
|
|
// 0 "40 x 48 - Full Scale LGR (LGR ONLY)"
|
|
// 1 "80 x 48 - Full Scale DLGR (DLGR ONLY)"
|
|
// 2 "140 x 192 - Full Scale (HGR & DHGR)"
|
|
// 3 "280 x 192 - Double Width Scale (HGR & DHGR)"
|
|
// 4 "320 x 200 - Classic Size"
|
|
// 5 "560 x 384 - Quadruple Width, Double Height Scale"
|
|
// 6 "640 x 400 - Classic Size"
|
|
// 7 "640 x 480 - Classic Size";
|
|
|
|
// Enable all first
|
|
QList<int> enabledList = QList<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7;
|
|
QListIterator<int> e(enabledList);
|
|
while (e.hasNext()) {
|
|
// Get the index of the value to disable
|
|
QModelIndex index = ui->comboBox_inputResolution->model()->index(e.next(), 0);
|
|
// enable flag
|
|
QVariant vEnable(1 | 32);
|
|
// the magic
|
|
ui->comboBox_inputResolution->model()->setData(index, vEnable, Qt::UserRole - 1);
|
|
}
|
|
|
|
// SET DISABLED ITEMS LIST - AND DEFAULT RESOLUTION FOR MODE
|
|
if (ui->comboBox_outputFormat->currentText() == "LR") {
|
|
disabledList << 2 << 3;
|
|
inputWidth = 40;
|
|
inputHeight = 48;
|
|
ui->comboBox_inputResolution->setCurrentIndex(0);
|
|
} else if (ui->comboBox_outputFormat->currentText() == "DLR") {
|
|
disabledList << 2 << 3;
|
|
inputWidth = 80;
|
|
inputHeight = 48;
|
|
ui->comboBox_inputResolution->setCurrentIndex(1);
|
|
} else if (ui->comboBox_outputFormat->currentText() == "MONO") {
|
|
disabledList << 0 << 1 << 2 << 4 << 6 << 7;
|
|
inputWidth = 280;
|
|
inputHeight = 192;
|
|
ui->comboBox_inputResolution->setCurrentIndex(3);
|
|
} else if (ui->comboBox_outputFormat->currentText() == "DHGR") {
|
|
inputWidth = 280;
|
|
inputHeight = 192;
|
|
ui->comboBox_inputResolution->setCurrentIndex(3);
|
|
} else {
|
|
inputWidth = 140;
|
|
inputHeight = 192;
|
|
ui->comboBox_inputResolution->setCurrentIndex(2);
|
|
}
|
|
|
|
// NOW ACTUALLY DISABLE INVALID RESOLUTIONS IN THE COMBOBOX
|
|
QListIterator<int> d(disabledList);
|
|
while (d.hasNext()) {
|
|
// Get the index of the value to disable
|
|
QModelIndex index = ui->comboBox_inputResolution->model()->index(d.next(), 0);
|
|
// This is the effective 'disable' flag
|
|
QVariant vDisable(0);
|
|
// the magic
|
|
ui->comboBox_inputResolution->model()->setData(index, vDisable, Qt::UserRole - 1);
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::on_pushButton_sourceFilename_clicked()
|
|
{
|
|
QString filename = QFileDialog::getOpenFileName();
|
|
if (filename != nullptr) {
|
|
ui->lineEdit_sourceFilename->setText(filename);
|
|
QPixmap mypix(filename);
|
|
ui->label_source->setPixmap(mypix);
|
|
ui->label_source->setScaledContents(true);
|
|
QSize sourceSize = ui->label_source->pixmap()->size();
|
|
QString resolutionString = QString("%1 x %2").arg(sourceSize.width()).arg(sourceSize.height());
|
|
ui->label_sourceResolution->setText(resolutionString);
|
|
updateNeeded=1;
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::updateInputSize()
|
|
{
|
|
switch (ui->comboBox_inputResolution->currentIndex()) {
|
|
case 0:
|
|
inputWidth = 40;
|
|
inputHeight = 48;
|
|
break;
|
|
case 1:
|
|
inputWidth = 80;
|
|
inputHeight = 48;
|
|
break;
|
|
case 2:
|
|
inputWidth = 140;
|
|
inputHeight = 192;
|
|
break;
|
|
case 3:
|
|
inputWidth = 280;
|
|
inputHeight = 192;
|
|
break;
|
|
case 4:
|
|
inputWidth = 320;
|
|
inputHeight = 200;
|
|
break;
|
|
case 5:
|
|
inputWidth = 560;
|
|
inputHeight = 384;
|
|
break;
|
|
case 6:
|
|
inputWidth = 640;
|
|
inputHeight = 400;
|
|
break;
|
|
case 7:
|
|
inputWidth = 640;
|
|
inputHeight = 480;
|
|
break;
|
|
default:
|
|
qDebug() << "default, error?";
|
|
break;
|
|
}
|
|
|
|
QSize sourceSize = ui->label_source->pixmap()->size();
|
|
double sx = static_cast<double>(inputWidth) / sourceSize.width();
|
|
double sy = static_cast<double>(inputHeight) / sourceSize.height();
|
|
QString scaleString = QString("%1 x %2").arg(sx).arg(sy);
|
|
ui->label_scaleFactor->setText(scaleString);
|
|
}
|
|
|
|
|
|
void MainWindow::livePreview()
|
|
{
|
|
if (ui->checkBox_livePreview->isChecked()) {
|
|
on_pushButton_preview_clicked();
|
|
}
|
|
}
|
|
|
|
|
|
// This is the actual preview generation/main logic function
|
|
void MainWindow::on_pushButton_preview_clicked()
|
|
{
|
|
if (!check_canPreview()) return;
|
|
|
|
// GET SCALE FACTOR
|
|
updateInputSize();
|
|
|
|
// NOW GENERATE SCALED QPIXMAP TO SAVE
|
|
QPixmap scaledPixmap = ui->label_source->pixmap()->scaled(inputWidth,inputHeight);
|
|
scaledPixmap.save(inputImgPath,"BMP", 0);
|
|
|
|
// NOW FIND OUR OUTPUT FORMAT
|
|
QString outputFormat = "H"; // HIRES
|
|
switch (ui->comboBox_outputFormat->currentIndex()) {
|
|
case 0:
|
|
outputFormat = "L";
|
|
break;
|
|
case 1:
|
|
outputFormat = "DL";
|
|
break;
|
|
case 2:
|
|
outputFormat = "H";
|
|
break;
|
|
case 3:
|
|
outputFormat = "D";
|
|
break;
|
|
case 4:
|
|
outputFormat = "mono";
|
|
break;
|
|
}
|
|
|
|
QString converterPath = "/Users/dbrock/appleiigs/grlib/b2d";
|
|
converterPath = QString("%1/b2d").arg(QCoreApplication::applicationDirPath());
|
|
|
|
QProcess process;
|
|
QStringList args;
|
|
args << inputImgPath; // "/tmp/saved.bmp"
|
|
args << outputFormat;
|
|
if (outputFormat == "DL" || outputFormat == "L") {
|
|
args << "N";
|
|
}
|
|
|
|
if (ui->horizontalSlider_crossHatch->value() > 0) {
|
|
QString crossHatchArg = QString("Z%1").arg(ui->horizontalSlider_crossHatch->value());
|
|
args << crossHatchArg;
|
|
}
|
|
if (ui->horizontalSlider_colorBleed->value() > 0) {
|
|
QString colorBleedArg = QString("R%1").arg(ui->horizontalSlider_colorBleed->value());
|
|
args << colorBleedArg;
|
|
}
|
|
|
|
if (ui->comboBox_dithering->currentIndex() > 0) {
|
|
QString ditherArg = QString("D%1").arg(ui->comboBox_dithering->currentIndex());
|
|
args << ditherArg;
|
|
}
|
|
|
|
// MUST ALWAYS HAVE A "V" FLAG TO GENERATE OUR PREVIEW IMAGE
|
|
if (ui->comboBox_previewPalette->currentIndex() > -1) {
|
|
QString ppalArg = QString("V%1").arg(ui->comboBox_previewPalette->currentIndex());
|
|
args << ppalArg;
|
|
}
|
|
|
|
args << ui->lineEdit_addArgs->text();
|
|
|
|
// RUN THE CONVERTER SCRIPT
|
|
process.start(converterPath,args);
|
|
process.waitForFinished(); // BLOCKS!!!
|
|
|
|
QString commandString = QString("%1 %2").arg(converterPath, args.join(" "));
|
|
qDebug() << commandString;
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText(commandString);
|
|
|
|
// ALL DONE SO TRY TO LOAD PREVIEW
|
|
QPixmap previewPix(previewImgPath);
|
|
float realScale = 1;
|
|
if (previewPix.width() == 80) {
|
|
int scale = 3;
|
|
realScale = scale;
|
|
previewPix = previewPix.scaled(80*scale, 48*scale);
|
|
qDebug() << "W80";
|
|
}
|
|
if (previewPix.width() == 560) {
|
|
float scale = 0.5f;
|
|
realScale = scale;
|
|
previewPix = previewPix.scaled(qRound(560*scale),qRound(384*scale), Qt::KeepAspectRatio,Qt::SmoothTransformation);
|
|
qDebug() << "W560";
|
|
}
|
|
ui->label_preview->setPixmap(previewPix);
|
|
ui->groupBox_preview->setTitle(QString("Preview - Scale %1").arg(qRound(realScale)));
|
|
repaint();
|
|
}
|
|
|
|
|
|
// When this timer is running, it checks to see if a
|
|
// preview update has been requested, and handles it if so.
|
|
void MainWindow::previewTimerTimeout()
|
|
{
|
|
if (updateNeeded) {
|
|
on_pushButton_preview_clicked();
|
|
updateNeeded = false;
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::on_horizontalSlider_crossHatch_valueChanged(int value)
|
|
{
|
|
if (value==0){
|
|
ui->label_crossHatch->setText("Off");
|
|
} else {
|
|
ui->label_crossHatch->setText(QString::number(value));
|
|
}
|
|
updateNeeded = 1;
|
|
}
|
|
|
|
|
|
void MainWindow::on_horizontalSlider_colorBleed_valueChanged(int value)
|
|
{
|
|
if (value==0){
|
|
ui->label_colorBleed->setText("Off");
|
|
} else {
|
|
ui->label_colorBleed->setText(QString::number(value));
|
|
}
|
|
updateNeeded = 1;
|
|
}
|
|
|
|
|
|
void MainWindow::on_comboBox_outputFormat_currentIndexChanged(int /*unused*/)
|
|
{
|
|
updateNeeded = 1;
|
|
updateDisplayModes();
|
|
}
|
|
|
|
|
|
void MainWindow::on_comboBox_inputResolution_currentIndexChanged(int /*unused*/)
|
|
{
|
|
updateNeeded = 1;
|
|
}
|
|
|
|
|
|
void MainWindow::on_checkBox_livePreview_stateChanged(int arg1)
|
|
{
|
|
// preview update timer
|
|
if (arg1) {
|
|
updateNeeded = 1;
|
|
|
|
previewTimer->start(500);
|
|
} else {
|
|
previewTimer->stop();
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::on_actionWhat_is_this_triggered()
|
|
{
|
|
QMessageBox msgBox;
|
|
msgBox.setText("Image conversion tool for OSX/Windows/Linux\n"
|
|
"Take modern image formats (PNG, JPEG, BMP, etc) and convert them for use in your Apple II programs or just for fun.\n\n\n"
|
|
"*USAGE*\n"
|
|
"Once you start the program, just \"Open Source Image\", select the \"Apple ][ Display Mode\" you want to convert your image to, "
|
|
"and click \"Preview\", or even better, click the \"Live Preview\" checkbox to get real-time feedback on your conversion settings.\n\n"
|
|
"Once you are satisfied with your conversion settings, click \"Save Image File\" to save in one of the Apple ][ image formats based on the display mode. "
|
|
"If you want to save that image file directly to a ProDOS volume, that is now supported via the \"Save To ProDOS\" function!\n\n"
|
|
"Then you can load it up in your favorite emulator, or transfer it to real disks/flash storage to view on glorious vintage hardware.\n\n"
|
|
"(c)2016-2020 Dagen Brock *\n\n\n * bmp2dhr is by Bill Buckels and CADIUS is by Brutal Deluxe.");
|
|
msgBox.exec();
|
|
}
|
|
|
|
|
|
void MainWindow::on_pushButton_saveImage_clicked()
|
|
{
|
|
if (!check_canSave()) return;
|
|
|
|
QString a2filename;
|
|
QString suffix;
|
|
QString filters = QString("All Images (*.A2FC *.BIN *.SLO *.DLO);;HGR (*.BIN);;DHGR (*.A2FC);;LR (*.SLO);;DLR (*.DLO);;All files (*.*)");
|
|
QString defaultFilter;
|
|
|
|
if (ui->comboBox_outputFormat->currentText() == "LR") {
|
|
a2filename = QString("%1/%2.SLO").arg(tmpDirPath,imageName.toUpper());
|
|
suffix = ".SLO";
|
|
defaultFilter = "LR (*.SLO)";
|
|
} else if (ui->comboBox_outputFormat->currentText() == "DLR") {
|
|
a2filename = QString("%1/%2.DLO").arg(tmpDirPath,imageName.toUpper());
|
|
suffix = ".DLO";
|
|
defaultFilter = "DLR (*.DLO)";
|
|
} else if (ui->comboBox_outputFormat->currentText() == "HGR") {
|
|
a2filename = QString("%1/%2CH.BIN").arg(tmpDirPath,imageName.toUpper());
|
|
suffix = ".BIN";
|
|
defaultFilter = "HGR (*.BIN)";
|
|
} else if (ui->comboBox_outputFormat->currentText() == "DHGR") {
|
|
a2filename = QString("%1/%2.A2FC").arg(tmpDirPath,imageName.toUpper());
|
|
suffix = ".A2FC";
|
|
defaultFilter = "DHGR (*.A2FC)";
|
|
} else if (ui->comboBox_outputFormat->currentText() == "MONO") {
|
|
a2filename = QString("%1/%2M.BIN").arg(tmpDirPath,imageName.toUpper());
|
|
suffix = ".BIN";
|
|
defaultFilter = "HGR (*.BIN)";
|
|
}
|
|
|
|
// PROMPT FOR SAVE FILENAME AND COPY (HOPEFULLY) TO SAVE FILENAME
|
|
QString saveFile = QFileDialog::getSaveFileName(nullptr, "Save file", QDir::currentPath(), filters, &defaultFilter);
|
|
if (QFile::exists(saveFile)) {
|
|
QFile::remove(saveFile);
|
|
}
|
|
QFile::copy(a2filename, saveFile);
|
|
}
|
|
|
|
|
|
// HOLY CRAP WHAT IS THIS??
|
|
// Well you see, Johnny, this is a layer of hacks to try
|
|
// to wrap CADIUS, but it has no API. So I can clean this up
|
|
// but it's more of a proof of concept. I think it'd be
|
|
// smarter to add JSON output to CADIUS in the long run.
|
|
// I consider this small feature a present to the community.
|
|
void MainWindow::on_pushButton_saveToProdos_clicked()
|
|
{
|
|
if (!check_canSave()) return;
|
|
|
|
QString cadiusPath = "/Users/dbrock/appleiigs/cadius/cadius"; // Dev mode
|
|
cadiusPath = QString("%1/cadius").arg(QCoreApplication::applicationDirPath());
|
|
|
|
|
|
// MYPICBIN=Type(06),AuxType(2000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
|
|
QString filetype = "06";
|
|
QString auxtype = "2000";
|
|
|
|
|
|
QString suffix = ".po";
|
|
QString defaultFilter = tr("All ProDOS Images (*.po *.hdv *.2mg)");
|
|
QString filters = QString(tr("All ProDOS Images (*.po *.hdv *.2mg);;ProDOS Order (*.po);;HDV (*.hdv);;2MG (*.2mg);;All files (*.*)"));
|
|
|
|
|
|
// PROMPT FOR SAVE FILENAME AND COPY (HOPEFULLY) TO SAVE FILENAME
|
|
QString prodosImageFile = QFileDialog::getSaveFileName(nullptr, "Choose ProDOS Image to Save to", QDir::currentPath(), filters, &defaultFilter, QFileDialog::DontConfirmOverwrite);
|
|
|
|
// ALSO GENERATE PRODOS SAFE BASENAME
|
|
QFileInfo fi(prodosImageFile);
|
|
QString prodosVolumeName = fi.baseName().left(15); // get max volume name
|
|
// EMPTY FILENAME?!
|
|
if (prodosImageFile.length() == 0) {
|
|
return;
|
|
}
|
|
|
|
QString imageSize = "140KB";
|
|
|
|
// NOW SEE IF IT'S A NEW FILE OR EXISTING IMAGE
|
|
QFileInfo check_file(prodosImageFile);
|
|
// check if file exists and if yes: Is it really a file and no directory?
|
|
if (check_file.exists() && check_file.isFile()) {
|
|
// nothing yet. We'll open it below, either way.
|
|
} else {
|
|
// NEW FILE, PROMPT FOR IMAGE SIZE
|
|
QMessageBox msgBox;
|
|
msgBox.setText(tr("Select size for new ProDOS image"));
|
|
msgBox.addButton(tr("Cancel"), QMessageBox::NoRole);
|
|
QAbstractButton* pButton140 = msgBox.addButton(tr("140KB"), QMessageBox::ApplyRole);
|
|
QAbstractButton* pButton800 = msgBox.addButton(tr("800KB"), QMessageBox::ApplyRole);
|
|
msgBox.setDefaultButton(QMessageBox::Yes);
|
|
|
|
msgBox.exec();
|
|
|
|
if (msgBox.clickedButton()==pButton140) {
|
|
// set above, nothing to do
|
|
} else if (msgBox.clickedButton()==pButton800) {
|
|
imageSize = "800KB";
|
|
} else {
|
|
return; // cancelled
|
|
}
|
|
|
|
// NOW CREATE AN IMAGE
|
|
QProcess process;
|
|
QStringList args;
|
|
args << "CREATEVOLUME";
|
|
args << prodosImageFile;
|
|
args << prodosVolumeName;
|
|
args << imageSize;
|
|
QString commandString = QString("%1 %2").arg(cadiusPath, args.join(" "));
|
|
|
|
// RUN THE IMAGE CREATE
|
|
process.start(cadiusPath,args);
|
|
process.waitForFinished(); // BLOCKS!!!
|
|
|
|
// NOW CHECK AGAIN TO SEE IF OUR IMAGE FILE GOT CREATED
|
|
if (check_file.exists() && check_file.isFile()) {
|
|
// qDebug() << "IMAGE FILE CREATED.";
|
|
} else {
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText(QString("Failed creating image with command: %1").arg(commandString));
|
|
return;
|
|
}
|
|
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText(commandString);
|
|
}
|
|
|
|
// NOW CATALOG WHATEVER IMAGE WE GOT... NEW/EXISTING
|
|
QProcess cat_process;
|
|
QStringList cat_args;
|
|
cat_args << "CATALOG";
|
|
cat_args << prodosImageFile;
|
|
|
|
// RUN THE CATALOG AND GET OUTPUT
|
|
cat_process.start(cadiusPath,cat_args);
|
|
cat_process.waitForFinished(); // BLOCKS!!!
|
|
QString cat_output = QString(cat_process.readAllStandardOutput());
|
|
//qDebug() << "CATALOG OUTPUT (cat_output)\n " << cat_output;
|
|
|
|
// regex scanner index
|
|
int pos = 0;
|
|
QStringList list;
|
|
|
|
// MUST MATCH FOR NEWLINES (VS USING ^ or &)
|
|
QRegExp vol_rx("\n(/.{1,15}/)\r?\n");
|
|
// OVERWRITE PRODOS VOLUME NAME IF WE KNOW BETTER
|
|
while ((pos = vol_rx.indexIn(cat_output, pos)) != -1) {
|
|
prodosVolumeName = vol_rx.cap(1);
|
|
break;
|
|
}
|
|
|
|
// NOW MATCH FOR SOME EXTRA DETAILS JUST BECAUSE WE CAN
|
|
QRegExp rx("(Block|Free|File|Directory) : (\\d+)");
|
|
pos = 0;
|
|
|
|
while ((pos = rx.indexIn(cat_output, pos)) != -1) {
|
|
list << rx.cap(1);
|
|
//qDebug() << rx.cap(1);
|
|
pos += rx.matchedLength();
|
|
}
|
|
|
|
int diskBlocks, diskFree, diskFiles, diskDirs = 0;
|
|
if (list.length() == 4) {
|
|
diskBlocks = list[0].toInt();
|
|
diskFree = list[1].toInt();
|
|
diskFiles = list[2].toInt();
|
|
diskDirs = list[3].toInt();
|
|
} else {
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText(QString("Failed to catalog ProDOS volume. Make sure that the file is one of: .po .hdv .2mg"));
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
QString a2Filename;
|
|
QString savedFilename;
|
|
if (ui->comboBox_outputFormat->currentText() == "LR") {
|
|
savedFilename = QString("%1/%2.SLO").arg(tmpDirPath,imageName.toUpper());
|
|
a2Filename = QString("%1.SLO").arg(imageName.toUpper());
|
|
auxtype = "0400"; // different auxtype (not that it matters)
|
|
} else if (ui->comboBox_outputFormat->currentText() == "DLR") {
|
|
savedFilename = QString("%1/%2.DLO").arg(tmpDirPath,imageName.toUpper());
|
|
a2Filename = QString("%1.DLO").arg(imageName.toUpper());
|
|
auxtype = "0400"; // different auxtype (not that it matters)
|
|
} else if (ui->comboBox_outputFormat->currentText() == "HGR") {
|
|
savedFilename = QString("%1/%2CH.BIN").arg(tmpDirPath,imageName.toUpper());
|
|
a2Filename = QString("%1CH.BIN").arg(imageName.toUpper());
|
|
} else if (ui->comboBox_outputFormat->currentText() == "DHGR") {
|
|
savedFilename = QString("%1/%2.A2FC").arg(tmpDirPath,imageName.toUpper());
|
|
a2Filename = QString("%1.A2FC").arg(imageName.toUpper());
|
|
} else if (ui->comboBox_outputFormat->currentText() == "MONO") {
|
|
savedFilename = QString("%1/%2M.BIN").arg(tmpDirPath,imageName.toUpper());
|
|
a2Filename = QString("%1M.BIN").arg(imageName.toUpper());
|
|
}
|
|
|
|
|
|
bool ok = false;
|
|
QString prodosFileName;
|
|
|
|
|
|
// manually build name/auxtype dialog
|
|
QDialog dialog(this);
|
|
// Use a layout allowing to have a label next to each field
|
|
QFormLayout form(&dialog);
|
|
|
|
// Add some text above the fields
|
|
form.addRow(new QLabel(tr("Save Image to ProDOS")));
|
|
|
|
// Add the lineEdits with their respective labels
|
|
QList<QLineEdit *> fields;
|
|
|
|
QLineEdit *lineEdit = new QLineEdit(&dialog);
|
|
lineEdit->setText(a2Filename);
|
|
QString label = QString("ProDOS Name (max 15 chars):");
|
|
form.addRow(label, lineEdit);
|
|
|
|
QLineEdit *lineEdit2 = new QLineEdit(&dialog);
|
|
lineEdit2->setText(auxtype);
|
|
lineEdit2->setInputMask("HHHh");
|
|
QString label2 = QString("Change auxtype (optional): $");
|
|
form.addRow(label2, lineEdit2);
|
|
|
|
fields << lineEdit << lineEdit2;
|
|
|
|
|
|
// Add some standard buttons (Cancel/Ok) at the bottom of the dialog
|
|
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
|
Qt::Horizontal, &dialog);
|
|
form.addRow(&buttonBox);
|
|
QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
|
|
QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
|
|
|
// Show the dialog as modal
|
|
if (dialog.exec() == QDialog::Accepted) {
|
|
// If the user didn't dismiss the dialog, do something with the fields
|
|
prodosFileName = fields[0]->text();
|
|
auxtype = fields[1]->text();
|
|
ok = true;
|
|
}
|
|
|
|
|
|
if (ok && !prodosFileName.isEmpty()) {
|
|
// COPY IT ... OVER EXISTING NAME?
|
|
QString saveFile = QString("%1/%2").arg(tmpDirPath,prodosFileName);
|
|
QFile::copy(savedFilename, saveFile);
|
|
|
|
// GENERATE OUR STUPID _FileInformation.txt in the same directory
|
|
QString fileinfo_text = QString("%1=Type(%2),AuxType(%3),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)").arg(prodosFileName, filetype, auxtype);
|
|
QString fileinfo_file = QString("%1/_FileInformation.txt").arg(tmpDirPath);
|
|
//qDebug() << "TMP FILE: " << fileinfo_file;
|
|
QFile file( fileinfo_file );
|
|
if (file.open(QIODevice::ReadWrite)) {
|
|
QTextStream stream( &file );
|
|
stream << fileinfo_text << endl;
|
|
}
|
|
|
|
// NOW ADD / SAVE OUR FILE
|
|
QProcess addfile_process;
|
|
QStringList addfile_args;
|
|
addfile_args << "ADDFILE" << prodosImageFile << prodosVolumeName << saveFile; // our tmp file
|
|
|
|
addfile_process.start(cadiusPath,addfile_args);
|
|
addfile_process.waitForFinished(); // BLOCKS!!!
|
|
QString addfile_output = QString(addfile_process.readAllStandardOutput());
|
|
|
|
// IF FILE ALREADY EXISTS, ASK IF THEY WANT TO OVERWRITE
|
|
if (addfile_output.contains("A file already exist with the same name")) {
|
|
QMessageBox::StandardButton reply;
|
|
reply = QMessageBox::question(this, "File exists in image", "File exists, Replace?",
|
|
QMessageBox::Yes|QMessageBox::No);
|
|
if (reply == QMessageBox::Yes) {
|
|
|
|
// ../tools/Cadius DELETEFILE <[2mg|hdv|po]_image_path> <prodos_file_path>
|
|
// YES - DELETE
|
|
QString deleteFile = QString("%1%2").arg(prodosVolumeName,prodosFileName);
|
|
// qDebug() << "DELETEFILE : " <<deleteFile;
|
|
QProcess delfile_process;
|
|
QStringList delfile_args;
|
|
delfile_args << "DELETEFILE";
|
|
delfile_args << prodosImageFile;
|
|
delfile_args << deleteFile;
|
|
|
|
// NOW ADD / SAVE OUR FILE
|
|
delfile_process.start(cadiusPath,delfile_args);
|
|
delfile_process.waitForFinished(); // BLOCKS!!!
|
|
QString delfile_output = QString(delfile_process.readAllStandardOutput());
|
|
// MAYBE CHECK? BUT WE CAN JUST TRY TO RESAVE AND FAIL THERE
|
|
|
|
// TRY ADDFILE AGAIN
|
|
QProcess addfile2_process;
|
|
QStringList addfile2_args;
|
|
addfile2_args << "ADDFILE" << prodosImageFile << prodosVolumeName << saveFile; // our tmp file
|
|
|
|
addfile2_process.start(cadiusPath,addfile_args);
|
|
addfile2_process.waitForFinished(); // BLOCKS!!!
|
|
QString addfile2_output = QString(addfile2_process.readAllStandardOutput());
|
|
|
|
// IF FILE ALREADY EXISTS, ASK IF THEY WANT TO OVERWRITE
|
|
if (addfile2_output.contains("Error :")) {
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText("Save failed. Couldn't delete/overwrite file? I really am not sure what went wrong. Try saving the pictures to your computer and transferring them to ProDOS with another program.");
|
|
return;
|
|
}
|
|
} else {
|
|
if (ui->label_preview->pixmap() == nullptr) {
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText("Save cancelled because file exists.");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// IF WE MADE IT THIS FAR, ALL GOOD?
|
|
QFile::remove(saveFile); // remove our tmp file
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText("File saved.");
|
|
|
|
} else {
|
|
ui->plainTextEdit_lastCmd->document()->setPlainText("Save cancelled.");
|
|
// cancelled?
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
void MainWindow::on_comboBox_dithering_currentIndexChanged(int /*unused*/)
|
|
{
|
|
updateNeeded = 1;
|
|
}
|
|
|
|
void MainWindow::on_comboBox_previewPalette_currentIndexChanged(int /*unused*/)
|
|
{
|
|
updateNeeded = 1;
|
|
}
|
|
|
|
void MainWindow::on_pushButton_savePreview_clicked()
|
|
{
|
|
if (!check_canSave()) return;
|
|
QString a2filename;
|
|
|
|
QString filters = QString("All Images (*.BMP *.PNG);;Bitmap (*.BMP);;PNG (*.PNG);;All files (*.*)");
|
|
QString defaultFilter = "PNG (*.PNG)";
|
|
QString suffix = ".PNG";
|
|
|
|
// PROMPT FOR SAVE FILENAME AND COPY (HOPEFULLY) TO SAVE FILENAME
|
|
QString saveFile = QFileDialog::getSaveFileName(nullptr, "Save file", QDir::currentPath(), filters, &defaultFilter);
|
|
if (QFile::exists(saveFile)) {
|
|
QFile::remove(saveFile);
|
|
}
|
|
|
|
// TRY TO SET CORRECT TYPE FOR SAVE, DEFAULT TO PNG
|
|
QFileInfo fi(saveFile);
|
|
QString ext = fi.completeSuffix().toUpper();
|
|
if (ext == "BMP") {
|
|
ui->label_preview->pixmap()->save(saveFile,"BMP", 0);
|
|
} else {
|
|
ui->label_preview->pixmap()->save(saveFile,"PNG", 0);
|
|
}
|
|
}
|