504 lines
15 KiB
C++
504 lines
15 KiB
C++
#include "qbrainfuck.h"
|
|
#include "ui_qbrainfuck.h"
|
|
|
|
QBrainfuck::QBrainfuck(QWidget *parent) :
|
|
QMainWindow(parent),
|
|
ui(new Ui::QBrainfuck)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
decoder = new DecoderThread();
|
|
QObject::connect(decoder, &DecoderThread::programDecoded, this, &QBrainfuck::setText);
|
|
QObject::connect(decoder, &DecoderThread::errorMessage, this, &QBrainfuck::errorMessage);
|
|
}
|
|
|
|
QBrainfuck::~QBrainfuck()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
/********** Text part **********/
|
|
|
|
void QBrainfuck::on_encodeButton_clicked()
|
|
{
|
|
QByteArray text = ui->textTextEdit->document()->toPlainText().toLatin1();
|
|
ui->programTextEdit->setPlainText("");
|
|
|
|
// First pass : find decades/steps
|
|
QList<unsigned char> decades; // Store the decades for initial loop
|
|
decades.append(0);
|
|
QList<unsigned char> memory; // Store the program's memory
|
|
memory.append(0);
|
|
QList<unsigned char> steps; // Store the steps to construct the program
|
|
|
|
QByteArray::const_iterator textIterator;
|
|
for (textIterator = text.constBegin(); textIterator != text.constEnd(); ++textIterator) {
|
|
int max_diff = ui->maxSignsSpinBox->value()+1;
|
|
QList<unsigned char>::iterator index;
|
|
|
|
// Find nearest memory's case and store it
|
|
QList<unsigned char>::iterator memoryIterator;
|
|
for (memoryIterator = memory.begin(); memoryIterator != memory.end(); ++memoryIterator) {
|
|
if (qAbs(*memoryIterator-*textIterator) < max_diff) {
|
|
max_diff = qAbs(*memoryIterator-*textIterator);
|
|
index = memoryIterator;
|
|
}
|
|
}
|
|
|
|
// Add step and insert current value in the memory, else add a decade if we don't find a case nearer than max_diff
|
|
if (max_diff <= ui->maxSignsSpinBox->value()) {
|
|
steps.append(*index);
|
|
*index = *textIterator;
|
|
} else {
|
|
steps.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value());
|
|
decades.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value());
|
|
memory.append(*textIterator);
|
|
}
|
|
}
|
|
|
|
qSort(decades);
|
|
|
|
// Second pass : write program
|
|
QString program = "";
|
|
|
|
for (int i = 0; i < ui->decadesSpinBox->value(); ++i) {
|
|
program += "+";
|
|
}
|
|
|
|
program += "\[";
|
|
|
|
QList<unsigned char>::iterator decadesIterator;
|
|
for (decadesIterator = decades.begin()+1; decadesIterator != decades.end(); ++decadesIterator) {
|
|
program += ">";
|
|
for (int i = 0; i < *decadesIterator; i+=ui->decadesSpinBox->value()) {
|
|
program += "+";
|
|
}
|
|
}
|
|
for (int i = 0; i < decades.size()-1; ++i) {
|
|
program += "<";
|
|
}
|
|
program += "-]";
|
|
|
|
int prev_ptr = 0;
|
|
|
|
QList<unsigned char>::const_iterator stepsIterator;
|
|
textIterator = text.constBegin();
|
|
for (stepsIterator = steps.constBegin(); stepsIterator != steps.constEnd(); ++stepsIterator) {
|
|
int next_ptr = decades.indexOf(*stepsIterator);
|
|
|
|
if (next_ptr > prev_ptr) {
|
|
for (int i = 0; i < next_ptr-prev_ptr; ++i) {
|
|
program += ">";
|
|
}
|
|
} else {
|
|
for (int i = 0; i < prev_ptr-next_ptr; ++i) {
|
|
program += "<";
|
|
}
|
|
}
|
|
|
|
if (*textIterator > *stepsIterator) {
|
|
for (int i = 0; i < *textIterator-*stepsIterator; ++i) {
|
|
program += "+";
|
|
}
|
|
} else {
|
|
for (int i = 0; i < *stepsIterator-*textIterator; ++i) {
|
|
program += "-";
|
|
}
|
|
}
|
|
|
|
program += ".";
|
|
prev_ptr = next_ptr;
|
|
decades[next_ptr] = *textIterator;
|
|
++textIterator;
|
|
}
|
|
|
|
ui->programTextEdit->setPlainText(program);
|
|
|
|
ui->tabWidget->setCurrentIndex(1);
|
|
}
|
|
|
|
void QBrainfuck::on_textLoadButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Txt Files (*.txt)");
|
|
dialog.setDefaultSuffix("txt");
|
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
|
|
|
if (dialog.exec()) {
|
|
QFile loadFile(dialog.selectedFiles().first());
|
|
|
|
if (!loadFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
|
|
ui->textTextEdit->document()->setPlainText(loadFile.readAll());
|
|
|
|
loadFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_textSaveButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Txt Files (*.txt)");
|
|
dialog.setDefaultSuffix("txt");
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (dialog.exec()) {
|
|
QFile saveFile(dialog.selectedFiles().first());
|
|
|
|
if (!saveFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
|
|
saveFile.write(ui->textTextEdit->document()->toPlainText().toUtf8());
|
|
saveFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_textTextEdit_textChanged()
|
|
{
|
|
ui->textLabel->setText("Text length: " + QString().setNum(ui->textTextEdit->document()->toPlainText().length()));
|
|
}
|
|
|
|
/********** Program part **********/
|
|
|
|
void QBrainfuck::on_decodeButton_clicked()
|
|
{
|
|
ui->textTextEdit->setPlainText("");
|
|
|
|
QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1();
|
|
QByteArray input = ui->inputLineEdit->text().toLatin1();
|
|
|
|
decoder->decode(program, input);
|
|
|
|
ui->tabWidget->setCurrentIndex(0);
|
|
}
|
|
|
|
void QBrainfuck::on_programLoadButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Bf Files (*.bf)");
|
|
dialog.setDefaultSuffix("bf");
|
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
|
|
|
if (dialog.exec()) {
|
|
QFile loadFile(dialog.selectedFiles().first());
|
|
|
|
if (!loadFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
|
|
ui->programTextEdit->document()->setPlainText(loadFile.readAll());
|
|
|
|
loadFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_programSaveButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Bf Files (*.bf)");
|
|
dialog.setDefaultSuffix("bf");
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (dialog.exec()) {
|
|
QFile saveFile(dialog.selectedFiles().first());
|
|
|
|
if (!saveFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
|
|
saveFile.write(ui->programTextEdit->document()->toPlainText().toUtf8());
|
|
saveFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_programTextEdit_textChanged()
|
|
{
|
|
ui->programLabel->setText("Program length: " + QString().setNum(ui->programTextEdit->document()->toPlainText().count(QRegExp(">|<|\\+|-|\\.|,|\\[|\\]"))));
|
|
}
|
|
|
|
/********** Motif part **********/
|
|
|
|
void QBrainfuck::on_motifButton_clicked()
|
|
{
|
|
QString motif = ui->motifTextEdit->document()->toPlainText();
|
|
QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1();
|
|
|
|
if (motif.contains(QRegExp(">|<|\\+|-|\\.|,|\\[|\\]"))) {
|
|
QMessageBox::critical(this, "QBrainfuck error", "Error: Motif contains Brainfuck characters");
|
|
return;
|
|
}
|
|
|
|
QByteArray::const_iterator programIterator;
|
|
for (programIterator = program.constBegin(); programIterator != program.constEnd(); ++programIterator) {
|
|
switch (*programIterator) {
|
|
case '>':
|
|
case '<':
|
|
case '+':
|
|
case '-':
|
|
case '.':
|
|
case ',':
|
|
case '[':
|
|
case ']':
|
|
int index = motif.indexOf(QRegExp(ui->regexLineEdit->text()));
|
|
if (index==-1) {
|
|
motif += *programIterator;
|
|
} else {
|
|
motif.replace(index, 1, *programIterator);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
ui->resultTextEdit->setPlainText(motif);
|
|
ui->tabWidget->setCurrentIndex(3);
|
|
}
|
|
|
|
void QBrainfuck::on_motifLoadButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Txt Files (*.txt)");
|
|
dialog.setDefaultSuffix("txt");
|
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
|
|
|
if (dialog.exec()) {
|
|
QFile loadFile(dialog.selectedFiles().first());
|
|
|
|
if (!loadFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
|
|
ui->motifTextEdit->document()->setPlainText(loadFile.readAll());
|
|
|
|
loadFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_motifSaveButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Txt Files (*.txt)");
|
|
dialog.setDefaultSuffix("txt");
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (dialog.exec()) {
|
|
QFile saveFile(dialog.selectedFiles().first());
|
|
|
|
if (!saveFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
|
|
saveFile.write(ui->motifTextEdit->document()->toPlainText().toUtf8());
|
|
saveFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_motifTextEdit_textChanged()
|
|
{
|
|
ui->motifLabel->setText("Motif length: " + QString().setNum(ui->motifTextEdit->document()->toPlainText().count(QRegExp(ui->regexLineEdit->text()))));
|
|
}
|
|
|
|
void QBrainfuck::on_regexLineEdit_textChanged(const QString &arg1)
|
|
{
|
|
on_motifTextEdit_textChanged();
|
|
}
|
|
|
|
/********** Result part **********/
|
|
|
|
void QBrainfuck::on_qrcodeButton_clicked()
|
|
{
|
|
char* text = new char[ui->resultTextEdit->document()->toPlainText().toLatin1().size() + 1];
|
|
strcpy(text, ui->resultTextEdit->document()->toPlainText().toLatin1().data());
|
|
|
|
QRcode *qrCode=QRcode_encodeString(text, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
|
|
if(qrCode) {
|
|
int width = qrCode->width;
|
|
|
|
QImage image((width + 4)*8, (width + 4)*8, QImage::Format_RGB32);;
|
|
QPainter painter(&image);
|
|
|
|
QLinearGradient linearGrad(QPointF(2*8, 2*8), QPointF((width + 2)*8, (width + 2)*8));
|
|
linearGrad.setColorAt(0, Qt::black);
|
|
linearGrad.setColorAt(1, Qt::black);
|
|
|
|
painter.fillRect(0, 0, (width + 4)*8, (width + 4)*8, Qt::white);
|
|
painter.fillRect(2*8, 2*8, width*8, width*8, linearGrad);
|
|
|
|
for (int i = 0; i < width*width; ++i) {
|
|
if (!(qrCode->data[i] &0x01)) {
|
|
int col = i % width;
|
|
int row = (i - col) / width;
|
|
|
|
painter.fillRect((col + 2)*8, (row + 2)*8, 8, 8, Qt::white);
|
|
}
|
|
}
|
|
|
|
ui->qrcodeLabel->setPixmap(QPixmap::fromImage(image));
|
|
|
|
ui->tabWidget->setCurrentIndex(4);
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_resultLoadButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Txt Files (*.txt)");
|
|
dialog.setDefaultSuffix("txt");
|
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
|
|
|
if (dialog.exec()) {
|
|
QFile loadFile(dialog.selectedFiles().first());
|
|
|
|
if (!loadFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
|
|
ui->resultTextEdit->document()->setPlainText(loadFile.readAll());
|
|
|
|
loadFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_resultSaveButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("Txt Files (*.txt)");
|
|
dialog.setDefaultSuffix("txt");
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (dialog.exec()) {
|
|
QFile saveFile(dialog.selectedFiles().first());
|
|
|
|
if (!saveFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
|
|
saveFile.write(ui->resultTextEdit->document()->toPlainText().toUtf8());
|
|
saveFile.close();
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_resultTextEdit_textChanged()
|
|
{
|
|
ui->resultLabel->setText("Result length: " + QString().setNum(ui->resultTextEdit->document()->toPlainText().length()));
|
|
}
|
|
|
|
/********** QRCode part **********/
|
|
|
|
void QBrainfuck::on_qrcodeSaveButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilter("PNG Files (*.png)");
|
|
dialog.setDefaultSuffix("png");
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (dialog.exec()) {
|
|
ui->qrcodeLabel->pixmap()->toImage().save(dialog.selectedFiles().first(), "PNG");
|
|
}
|
|
}
|
|
|
|
/*******************************/
|
|
|
|
void QBrainfuck::setText(QString text) {
|
|
ui->textTextEdit->setPlainText(text);
|
|
}
|
|
|
|
void QBrainfuck::errorMessage(QString message) {
|
|
QMessageBox::critical(this, "QBrainfuck error", "Error: " + message);
|
|
}
|
|
|
|
void QBrainfuck::on_saveAllButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::Directory);
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (dialog.exec()) {
|
|
QString saveDir(dialog.selectedFiles().first());
|
|
|
|
QFile textFile(saveDir + "/text.txt");
|
|
if (!textFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
textFile.write(ui->textTextEdit->document()->toPlainText().toUtf8());
|
|
textFile.close();
|
|
|
|
QFile programFile(saveDir + "/program.bf");
|
|
if (!programFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
programFile.write(ui->programTextEdit->document()->toPlainText().toUtf8());
|
|
programFile.close();
|
|
|
|
QFile motifFile(saveDir + "/motif.txt");
|
|
if (!motifFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
motifFile.write(ui->motifTextEdit->document()->toPlainText().toUtf8());
|
|
motifFile.close();
|
|
|
|
QFile resultFile(saveDir + "/result.txt");
|
|
if (!resultFile.open(QIODevice::WriteOnly)) {
|
|
return;
|
|
}
|
|
resultFile.write(ui->resultTextEdit->document()->toPlainText().toUtf8());
|
|
resultFile.close();
|
|
|
|
ui->qrcodeLabel->pixmap()->toImage().save(saveDir + "/qrcode.png", "PNG");
|
|
}
|
|
}
|
|
|
|
void QBrainfuck::on_loadAllButton_clicked()
|
|
{
|
|
QFileDialog dialog(this);
|
|
dialog.setFileMode(QFileDialog::Directory);
|
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
|
|
|
if (dialog.exec()) {
|
|
QString saveDir(dialog.selectedFiles().first());
|
|
|
|
QFile textFile(saveDir + "/text.txt");
|
|
if (!textFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
ui->textTextEdit->document()->setPlainText(textFile.readAll());
|
|
textFile.close();
|
|
|
|
QFile programFile(saveDir + "/program.bf");
|
|
if (!programFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
ui->programTextEdit->document()->setPlainText(programFile.readAll());
|
|
programFile.close();
|
|
|
|
QFile motifFile(saveDir + "/motif.txt");
|
|
if (!motifFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
ui->motifTextEdit->document()->setPlainText(motifFile.readAll());
|
|
motifFile.close();
|
|
|
|
QFile resultFile(saveDir + "/result.txt");
|
|
if (!resultFile.open(QIODevice::ReadOnly)) {
|
|
return;
|
|
}
|
|
ui->resultTextEdit->document()->setPlainText(resultFile.readAll());
|
|
resultFile.close();
|
|
|
|
QImage image;
|
|
image.load(saveDir + "/qrcode.png", "PNG");
|
|
ui->qrcodeLabel->setPixmap(QPixmap::fromImage(image));
|
|
}
|
|
}
|