Sat, 21 Jan 2023 14:27:10 +0100
The images tab now looks complete. Made the left side (thumbnails) a bit smaller. The right side of the screen now shows the current image and all data that belongs to that. After a new image is added, reload the images. Implemented delete image.
/** * 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()"; // 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"); 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); // If any, show picture 1 // Stop spinner } /* * Show thumbnails on the left. */ void EditProduct::images_Thumbnails() { 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); if (product->images_count < 1) { ui->image_filenameEdit->setText(""); ui->image_timestampEdit->setText(""); ui->image_commentEdit->setText(""); ui->image_typeEdit->setCurrentIndex(0); //ui->currentImage->setPixmap(); 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; QByteArray imageByteArray; QSqlQuery query; QSettings settings(QSettings::IniFormat, QSettings::UserScope, "mbse", "bmsapp"); QFileDialog dialog1(this, tr("Open File")); dialog1.setDirectory(settings.value("paths/images").toString()); /* Only a few image formats are valid */ QStringList mimeTypeFilters ({ "image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg+xml" }); dialog1.setMimeTypeFilters(mimeTypeFilters); dialog1.setNameFilter("Images (*.bmp *.BMP *.gif *.GIF *.jpg *.JPG *.jpeg *.JPEG *.png *.PNG *.svg *.SVG)"); dialog1.setAcceptMode(QFileDialog::AcceptOpen); // dialog1.setOption(QFileDialog::DontUseNativeDialog); 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())); } 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() { qDebug() << "downloadImage_clicked()" << product->images_current << ui->filmStrip->currentRow(); } 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); } }