src/EditProductTab13.cpp

Wed, 25 Jan 2023 13:11:51 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 25 Jan 2023 13:11:51 +0100
changeset 475
895c5ae1dab1
parent 474
18b72c518d0d
child 476
29487eac1183
permissions
-rw-r--r--

Some extra debug info en some removed for the product images. Clear picmap area if no pixmaps are left. Block pictype_changed and piccomment_changed if there are no pictures, prevents segfault.

/**
 * EditProduct.cpp is part of bmsapp.
 *
 * Tab 13, images and pictures.
 *
 * bmsapp is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * bmsapp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

void EditProduct::images_Init()
{
    qDebug() << "images_Init() count" << product->images_count << "current" << product->images_current << "size" << product->images_list.size();

	// Start spinner

    /*
     * Clean old picture areas.
     */
    if (product->images_count < 0 && product->images_list.size()) {
	qDebug() << "  clean images_list";
	ui->filmStrip->clear();
	product->images_list.clear();
	product->images_count = -1;
	product->images_current = -1;
    }

    /*
     * Load images data for this product uuid.
     */
    if (product->images_count < 0) {
	QSqlQuery query;

	qDebug() << "  loading data";
	query.prepare("SELECT * FROM products_pics WHERE uuid=:uuid ORDER BY record");
	query.bindValue(":uuid", product->uuid);
	query.exec();

	if (query.lastError().isValid()) {
            qWarning() << "images_init()" << query.lastError();
            QMessageBox::warning(this, tr("Database error"), tr("MySQL error: %1\n%2\n%3")
                .arg(query.lastError().nativeErrorCode()).arg(query.lastError().driverText()).arg(query.lastError().databaseText()));
	}
	product->images_count = 0;

	while (query.next()) {
	    Images i;
	    i.record = query.value("record").toInt();
	    i.uuid = query.value("uuid").toString();
	    i.pic_type = query.value("pic_type").toInt();
	    i.pic_data = query.value("pic_data").toByteArray();
	    i.pic_comment = query.value("pic_comment").toString();
	    i.filename = query.value("filename").toString();
	    i.timestamp = query.value("timestamp").toDateTime();
	    product->images_list.append(i);
	    product->images_count++;
	}
	qDebug() << "  loaded" << product->images_count << product->images_list.size();
	if (product->images_count < 1)
	    product->images_current = -1;
	else
	    product->images_current = 0;
    }

    images_Thumbnails();
    if (product->images_current >= 0) {
    	ui->filmStrip->setCurrentRow(product->images_current);
    }
    images_Main(product->images_current);

	// Stop spinner
}


/*
 * Show thumbnails on the left.
 */
void EditProduct::images_Thumbnails()
{
    qDebug() << "images_Thumbnails()" << product->images_list.size();
    ui->filmStrip->clear();

    for (int i = 0; i < product->images_list.size(); i++) {
	QListWidgetItem* newItem = new QListWidgetItem();
	QString text = QCoreApplication::translate("PicType", g_prod_pic_types[product->images_list.at(i).pic_type]);
	newItem->setText(text);
	newItem->setBackground(QColor(0x45,0x53,0x64));

	QPixmap outPixmap = QPixmap();
	outPixmap.loadFromData(product->images_list.at(i).pic_data);
//	qDebug() << "  " << outPixmap.width() << "x" << outPixmap.height() << "size" << outPixmap.size() << product->images_list.at(i).filename;
//	qDebug() << "  " << ui->filmStrip->iconSize();
	if (outPixmap.width() > 240 || outPixmap.height() > 180)
	    newItem->setIcon(QIcon(outPixmap.scaled(240, 180, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
	else
	    newItem->setIcon(QIcon(outPixmap));

	ui->filmStrip->addItem(newItem);
    }
}


void EditProduct::images_Main(int id)
{
    qDebug() << "  Main(" << id << ")";

    ui->prevImage->setEnabled((product->images_count > 0 && product->images_current > 0) ? true:false);
    ui->nextImage->setEnabled((product->images_count > 0 && (product->images_current + 1) < product->images_count) ? true:false);
    ui->downloadImage->setEnabled((product->images_count > 0) ? true:false);
    ui->printImage->setEnabled((product->images_count > 0) ? true:false);
    ui->delImage->setEnabled((product->images_count > 0) ? true:false);

    const QSignalBlocker blocker1(ui->image_typeEdit);
    const QSignalBlocker blocker2(ui->image_commentEdit);

    if (product->images_count < 1) {
	ui->image_filenameEdit->setText("");
	ui->image_timestampEdit->setText("");
	ui->image_commentEdit->setText("");
	ui->image_typeEdit->setCurrentIndex(0);
	ui->currentImage->clear();
	return;
    }

    QPixmap outPixmap = QPixmap();
    outPixmap.loadFromData(product->images_list.at(id).pic_data);
//    qDebug() << "  " << outPixmap.width() << "x" << outPixmap.height() << "size" << outPixmap.size() << product->images_list.at(id).filename;
    if (outPixmap.width() > ui->currentImage->width() || outPixmap.height() > ui->currentImage->height())
	ui->currentImage->setPixmap(outPixmap.scaled(ui->currentImage->width(), ui->currentImage->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    else
	ui->currentImage->setPixmap(outPixmap);

    ui->image_filenameEdit->setText(product->images_list.at(id).filename);
    ui->image_timestampEdit->setText(product->images_list.at(id).timestamp.toString(Qt::RFC2822Date));
    ui->image_commentEdit->setText(product->images_list.at(id).pic_comment);
    ui->image_typeEdit->setCurrentIndex(product->images_list.at(id).pic_type);
}


void EditProduct::addImage_clicked()
{
    QString fileName, dirName;
    QByteArray imageByteArray;
    QSqlQuery query;
    QSettings settings(QSettings::IniFormat, QSettings::UserScope, "mbse", "bmsapp");

    /*
     * First check if the directory stored in the settings file exists.
     * It might be on a removable media that was last used ...
     * If so, fallback to the user's home directory.
     */
    dirName = settings.value("paths/images").toString();
    if (! QDir(dirName).exists()) {
	dirName = QDir::homePath();
    }

    QFileDialog dialog1(this, tr("Open File"));
    dialog1.setDirectory(dirName);
    dialog1.setNameFilter("Images (*.bmp *.BMP *.gif *.GIF *.jpg *.JPG *.jpeg *.JPEG *.png *.PNG *.svg *.SVG)");
    dialog1.setAcceptMode(QFileDialog::AcceptOpen);
    if (dialog1.exec() != QDialog::Accepted)
	return;
    /*
     * Save our current path
     */
    settings.setValue("paths/images", dialog1.directory().absolutePath());
    fileName = dialog1.selectedFiles().constFirst();

    QImageReader reader(fileName);
    reader.setAutoTransform(true);
    const QImage newImage = reader.read();
    if (newImage.isNull()) {
	QMessageBox::information(this, QGuiApplication::applicationDisplayName(), tr("Cannot load %1: %2")
                                 .arg(QDir::toNativeSeparators(fileName), reader.errorString()));
        return;
    }
    qDebug() << "Image" << fileName << newImage.width() << newImage.height() << "size" << newImage.sizeInBytes();

    QBuffer buffer(&imageByteArray);
    buffer.open(QIODevice::WriteOnly);
    newImage.save(&buffer, "PNG");	/* Convert to lossless .png format. */

    /*
     * Now that we have selected a valid image, create a new dialog so
     * we can add extra information for this image and a Save button.
     */
    QDialog* dialog = new QDialog(this);
    dialog->resize(500, 490);
    QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
    buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
    buttonBox->setGeometry(QRect(10, 440, 480, 32));
    buttonBox->setLayoutDirection(Qt::LeftToRight);
    buttonBox->setOrientation(Qt::Horizontal);
    buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Save);
    buttonBox->setCenterButtons(true);

    QLabel *imageLabel = new QLabel(dialog);
    imageLabel->setObjectName(QString::fromUtf8("imageLabel"));
    imageLabel->setGeometry(QRect(10, 10, 480, 320));
    imageLabel->setAlignment(Qt::AlignCenter);
    imageLabel->setText(tr("Image here"));
    QPixmap outPixmap = QPixmap();
    outPixmap.loadFromData(imageByteArray);
    if (outPixmap.width() > 480 || outPixmap.height() > 320)
	imageLabel->setPixmap(outPixmap.scaled(480, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation));
    else
	imageLabel->setPixmap(outPixmap);

    QLabel *typeLabel = new QLabel(dialog);
    typeLabel->setObjectName(QString::fromUtf8("typeLabel"));
    typeLabel->setText(tr("Image type:"));
    typeLabel->setGeometry(QRect(10, 360, 141, 20));
    typeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

    QComboBox *typeEdit = new QComboBox(dialog);
    typeEdit->setObjectName(QString::fromUtf8("typeEdit"));
    typeEdit->setGeometry(QRect(160, 360, 161, 23));
    for (int i = 0; i < 7; i++)
	typeEdit->addItem(QCoreApplication::translate("PicType", g_prod_pic_types[i]));
    typeEdit->setCurrentIndex(0);

    QLabel *commentLabel = new QLabel(dialog);
    commentLabel->setObjectName(QString::fromUtf8("commentLabel"));
    commentLabel->setText(tr("Image comment:"));
    commentLabel->setGeometry(QRect(10, 390, 141, 20));
    commentLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

    QLineEdit *commentEdit = new QLineEdit(dialog);
    commentEdit->setObjectName(QString::fromUtf8("commentEdit"));
    commentEdit->setGeometry(QRect(160, 390, 320, 23));
    commentEdit->setToolTip(tr("The comment for this image."));

    connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
    connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));

    dialog->setModal(true);
    dialog->exec();
    if (dialog->result() == QDialog::Rejected) {
	return;
    }
    disconnect(buttonBox, nullptr, nullptr, nullptr);

    QFileInfo fi(fileName);
    query.prepare("INSERT INTO products_pics SET uuid=:uuid, pic_type=:pic_type, pic_data=:pic_data, "
		  "pic_comment=:pic_comment, filename=:filename, timestamp=:timestamp");
    query.bindValue(":uuid", product->uuid);
    query.bindValue(":pic_type", typeEdit->currentIndex());
    query.bindValue(":pic_data", imageByteArray);
    query.bindValue(":pic_comment", commentEdit->text());
    query.bindValue(":filename", fi.completeBaseName() + ".png");	/* The image is converted to .png */
    query.bindValue(":timestamp", fi.lastModified());

    query.exec();
    if (query.lastError().isValid()) {
	qWarning() << "addImage_clicked()" << query.lastError();
	QMessageBox::warning(this, tr("Database error"), tr("MySQL error: %1\n%2\n%3")
		.arg(query.lastError().nativeErrorCode()).arg(query.lastError().driverText()).arg(query.lastError().databaseText()));
    } else {
	qDebug() << "new image Saved";
	product->images_count = -1;         // Force reload data
	images_Init();
    }
}


void EditProduct::delImage_clicked()
{
    qDebug() << "delImage_clicked()" << ui->filmStrip->currentRow();

    int rc = QMessageBox::warning(this, tr("Delete image"), tr("Delete %1").arg(product->images_list.at(ui->filmStrip->currentRow()).filename),
                    QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
    if (rc == QMessageBox::No)
        return;

    qDebug() << "  delete record" << product->images_list.at(ui->filmStrip->currentRow()).record;

    QSqlQuery query;
    query.prepare("DELETE FROM products_pics WHERE record=:record");
    query.bindValue(":record", product->images_list.at(ui->filmStrip->currentRow()).record);
    query.exec();

    if (query.lastError().isValid()) {
	qWarning() << "delImage_clicked()" << query.lastError();
	QMessageBox::warning(this, tr("Database error"), tr("MySQL error: %1\n%2\n%3")
                .arg(query.lastError().nativeErrorCode()).arg(query.lastError().driverText()).arg(query.lastError().databaseText()));
    }
    qDebug() << "  delete record done";

    product->images_count = -1;		// Force reload data
    images_Init();
}


void EditProduct::nextImage_clicked()
{
    qDebug() << "nextImage_clicked()" << product->images_current << ui->filmStrip->currentRow();

    if (product->images_count >= 0) {
	if ((product->images_current + 1) < product->images_count) {
	    product->images_current++;
	    ui->filmStrip->setCurrentRow(product->images_current);
	    images_Main(product->images_current);
	}
    }
}


void EditProduct::prevImage_clicked()
{
    qDebug() << "prevImage_clicked()" << product->images_current << ui->filmStrip->currentRow();

    if (product->images_count >= 0) {
	if (product->images_current > 0) {
	    product->images_current--;
	    ui->filmStrip->setCurrentRow(product->images_current);
	    images_Main(product->images_current);
	}
    }
}


void EditProduct::downloadImage_clicked()
{
    QSettings settings(QSettings::IniFormat, QSettings::UserScope, "mbse", "bmsapp");
    QString dirName;

    /*
     * First check if the directory stored in the settings file exists.
     * It might be on a removable media that was last used ...
     * If so, fallback to the user's home directory.
     */
    dirName = settings.value("paths/download").toString();
    if (! QDir(dirName).exists()) {
        dirName = QDir::homePath();
    }

    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                       dirName + "/" + product->images_list.at(ui->filmStrip->currentRow()).filename, tr("Files (*.png)"));
    if (fileName == 0) {
        QMessageBox::warning(this, tr("Save File"), tr("No PNG file selected."));
        return;
    }
    /*
     * Update to current selected path
     */
    settings.setValue("paths/download", QFileInfo(fileName).absolutePath());

    qDebug() << "downloadImage_clicked()" << ui->filmStrip->currentRow() << fileName;

    QFile file(fileName);
    file.open(QIODevice::WriteOnly);
    file.write(product->images_list.at(ui->filmStrip->currentRow()).pic_data);
    if (!file.setFileTime(product->images_list.at(ui->filmStrip->currentRow()).timestamp, QFileDevice::FileModificationTime)) {
        qWarning() << "Failed to modify modify time!";
    }
    if (!file.setFileTime(product->images_list.at(ui->filmStrip->currentRow()).timestamp, QFileDevice::FileAccessTime)) {
        qWarning() << "Failed to modify access time!";
    }
//    if (!file.setFileTime(product->images_list.at(ui->filmStrip->currentRow()).timestamp, QFileDevice::FileBirthTime)) {
//	qDebug() << "Failed to modify create time!";
//    }
    file.close();
    QMessageBox::information(this, tr("Save File"), tr("Saved %1").arg(product->images_list.at(ui->filmStrip->currentRow()).filename));
}


void EditProduct::printImage_clicked()
{
    qDebug() << "printImage_clicked()" << product->images_current << ui->filmStrip->currentRow();
}


void EditProduct::selectImage_clicked(QListWidgetItem *val)
{
    qDebug() << "selectImage_clicked()" << ui->filmStrip->currentRow();

    if (product->images_count > 0) {
	product->images_current = ui->filmStrip->currentRow();
        images_Main(product->images_current);
    }
}


void EditProduct::pictype_changed(int val)
{
    if (product->images_count < 1)
	return;

    qDebug() << "pictype_changed" << val;
    product->images_list[ui->filmStrip->currentRow()].pic_type = val;

    QSqlQuery query;
    query.prepare("UPDATE products_pics SET pic_type=:pic_type WHERE record=:record");
    query.bindValue(":pic_type", val);
    query.bindValue(":record", product->images_list.at(ui->filmStrip->currentRow()).record);
    query.exec();

    if (query.lastError().isValid()) {
        qWarning() << "pictype_changed()" << query.lastError();
        QMessageBox::warning(this, tr("Database error"), tr("MySQL error: %1\n%2\n%3")
                .arg(query.lastError().nativeErrorCode()).arg(query.lastError().driverText()).arg(query.lastError().databaseText()));
    }

    images_Thumbnails();
}


void EditProduct::piccomment_changed()
{
    if (product->images_count < 1)
	return;

    qDebug() << "piccomment_changed" << ui->image_commentEdit->text();
    product->images_list[ui->filmStrip->currentRow()].pic_comment = ui->image_commentEdit->text();

    QSqlQuery query;
    qDebug() << "piccomment_changed 0";
    query.prepare("UPDATE products_pics SET pic_comment=:pic_comment WHERE record=:record");
    query.bindValue(":pic_comment", ui->image_commentEdit->text());
    query.bindValue(":record", product->images_list.at(ui->filmStrip->currentRow()).record);
    query.exec();

    if (query.lastError().isValid()) {
        qWarning() << "pictype_changed()" << query.lastError();
        QMessageBox::warning(this, tr("Database error"), tr("MySQL error: %1\n%2\n%3")
                .arg(query.lastError().nativeErrorCode()).arg(query.lastError().driverText()).arg(query.lastError().databaseText()));
    }
    qDebug() << "piccomment_changed 3";
}

mercurial