229 lines
7.2 KiB
C++
229 lines
7.2 KiB
C++
#include "imagegallery.h"
|
|
#include <QMouseEvent>
|
|
#include <QFileInfo>
|
|
#include <QProcess>
|
|
#include <QDesktopServices>
|
|
#include <QUrl>
|
|
#include <QPainter>
|
|
#include <QApplication>
|
|
|
|
// ImageThumbnail implementation
|
|
ImageThumbnail::ImageThumbnail(const QString &filePath, QWidget *parent)
|
|
: QLabel(parent)
|
|
, m_filePath(filePath)
|
|
{
|
|
setFixedSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
|
|
setAlignment(Qt::AlignCenter);
|
|
setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
|
setLineWidth(2);
|
|
setScaledContents(false);
|
|
setCursor(Qt::PointingHandCursor);
|
|
setToolTip(filePath);
|
|
|
|
// Enable text wrapping and text interaction
|
|
setWordWrap(true);
|
|
setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
|
|
// Set a minimum size policy
|
|
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
}
|
|
|
|
void ImageThumbnail::mousePressEvent(QMouseEvent *event)
|
|
{
|
|
if (event->button() == Qt::LeftButton) {
|
|
emit thumbnailClicked(m_filePath);
|
|
}
|
|
QLabel::mousePressEvent(event);
|
|
}
|
|
|
|
// ImageGallery implementation
|
|
ImageGallery::ImageGallery(QWidget *parent)
|
|
: QWidget(parent)
|
|
, m_dbManager(nullptr)
|
|
{
|
|
// Create scroll area
|
|
m_scrollArea = new QScrollArea(this);
|
|
m_scrollArea->setWidgetResizable(true);
|
|
m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
|
|
// Create container widget for the grid layout
|
|
m_containerWidget = new QWidget(m_scrollArea);
|
|
m_gridLayout = new QGridLayout(m_containerWidget);
|
|
m_gridLayout->setSpacing(10);
|
|
|
|
m_scrollArea->setWidget(m_containerWidget);
|
|
|
|
// Create layout for the gallery widget
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
mainLayout->addWidget(m_scrollArea);
|
|
setLayout(mainLayout);
|
|
}
|
|
|
|
ImageGallery::~ImageGallery()
|
|
{
|
|
clearGallery();
|
|
}
|
|
|
|
void ImageGallery::setDatabaseManager(DatabaseManager *dbManager)
|
|
{
|
|
m_dbManager = dbManager;
|
|
}
|
|
|
|
void ImageGallery::displayImages(const QList<DatabaseManager::ImageItem> &images)
|
|
{
|
|
// Clear existing thumbnails
|
|
clearGallery();
|
|
|
|
const int numImages = images.size();
|
|
int row = 0, col = 0;
|
|
|
|
for (int i = 0; i < numImages; ++i) {
|
|
const auto &item = images[i];
|
|
|
|
// Check if file exists before creating thumbnail
|
|
QFileInfo fileInfo(item.filePath);
|
|
if (!fileInfo.exists() || !fileInfo.isReadable()) {
|
|
qDebug() << "Image file does not exist or is not readable:" << item.filePath;
|
|
continue; // Skip this image
|
|
}
|
|
|
|
// Create and add thumbnail
|
|
QPixmap thumbnail = createThumbnail(item.filePath, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
|
|
ImageThumbnail *thumbnailLabel = new ImageThumbnail(item.filePath, this);
|
|
thumbnailLabel->setPixmap(thumbnail);
|
|
|
|
// Set tooltip to show file path and partial OCR text
|
|
QString tooltipText = item.filePath;
|
|
if (!item.ocrText.isEmpty()) {
|
|
// Limit OCR text length in tooltip
|
|
QString shortOcrText = item.ocrText;
|
|
if (shortOcrText.length() > 100) {
|
|
shortOcrText = shortOcrText.left(97) + "...";
|
|
}
|
|
tooltipText += "\n\nOCR Text:\n" + shortOcrText;
|
|
}
|
|
thumbnailLabel->setToolTip(tooltipText);
|
|
|
|
// Connect the thumbnail click signal
|
|
connect(thumbnailLabel, &ImageThumbnail::thumbnailClicked,
|
|
this, &ImageGallery::handleThumbnailClicked);
|
|
|
|
// Add to grid
|
|
m_gridLayout->addWidget(thumbnailLabel, row, col);
|
|
m_thumbnails.append(thumbnailLabel);
|
|
|
|
// Update row and column
|
|
col++;
|
|
if (col >= COLUMNS) {
|
|
col = 0;
|
|
row++;
|
|
}
|
|
}
|
|
|
|
// Display a message when no images are found
|
|
if (m_thumbnails.isEmpty()) {
|
|
// Create a special ImageThumbnail for the "no images" message
|
|
ImageThumbnail *noImagesLabel = new ImageThumbnail("", this);
|
|
noImagesLabel->setText("No images found matching your search criteria");
|
|
noImagesLabel->setAlignment(Qt::AlignCenter);
|
|
m_gridLayout->addWidget(noImagesLabel, 0, 0, 1, COLUMNS);
|
|
m_thumbnails.append(noImagesLabel);
|
|
}
|
|
|
|
// Add stretch to the bottom of the grid
|
|
m_gridLayout->setRowStretch(row + 1, 1);
|
|
}
|
|
|
|
void ImageGallery::clearGallery()
|
|
{
|
|
// Remove all thumbnails
|
|
for (auto thumbnail : m_thumbnails) {
|
|
m_gridLayout->removeWidget(thumbnail);
|
|
disconnect(thumbnail, nullptr, this, nullptr);
|
|
delete thumbnail;
|
|
}
|
|
|
|
m_thumbnails.clear();
|
|
}
|
|
|
|
void ImageGallery::handleSearchTextChanged(const QString &searchText)
|
|
{
|
|
if (m_dbManager) {
|
|
QList<DatabaseManager::ImageItem> images = m_dbManager->searchImages(searchText);
|
|
displayImages(images);
|
|
}
|
|
}
|
|
|
|
void ImageGallery::handleThumbnailClicked(const QString &filePath)
|
|
{
|
|
// Show a wait cursor while attempting to open the file
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
|
// Check if file exists
|
|
QFileInfo fileInfo(filePath);
|
|
if (fileInfo.exists() && fileInfo.isFile()) {
|
|
try {
|
|
// Use QDesktopServices to open the file with the default application
|
|
bool success = QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
|
|
if (!success) {
|
|
qDebug() << "Failed to open file with default application:" << filePath;
|
|
}
|
|
} catch (const std::exception &e) {
|
|
qDebug() << "Exception occurred while opening file:" << e.what();
|
|
}
|
|
} else {
|
|
qDebug() << "File does not exist:" << filePath;
|
|
}
|
|
|
|
// Restore cursor
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
QPixmap ImageGallery::createThumbnail(const QString &filePath, int width, int height)
|
|
{
|
|
// Verify file exists before attempting to load
|
|
QFileInfo fileInfo(filePath);
|
|
if (!fileInfo.exists() || !fileInfo.isReadable()) {
|
|
qDebug() << "Image file does not exist or is not readable:" << filePath;
|
|
return createPlaceholderThumbnail(width, height, "File not found");
|
|
}
|
|
|
|
// Try to load the image
|
|
QPixmap pixmap(filePath);
|
|
|
|
// If loading failed, create a placeholder
|
|
if (pixmap.isNull()) {
|
|
qDebug() << "Failed to load image:" << filePath;
|
|
return createPlaceholderThumbnail(width, height, "Failed to load");
|
|
}
|
|
|
|
// Scale pixmap while maintaining aspect ratio
|
|
return pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
}
|
|
|
|
QPixmap ImageGallery::createPlaceholderThumbnail(int width, int height, const QString &message)
|
|
{
|
|
// Create a placeholder image with text
|
|
QPixmap placeholder(width, height);
|
|
placeholder.fill(Qt::lightGray);
|
|
|
|
// Draw some text on the placeholder
|
|
QPainter painter(&placeholder);
|
|
painter.setPen(Qt::darkGray);
|
|
|
|
// Use a nice font
|
|
QFont font = painter.font();
|
|
font.setPointSize(12);
|
|
font.setBold(true);
|
|
painter.setFont(font);
|
|
|
|
// Draw the text centered in the pixmap
|
|
painter.drawText(placeholder.rect(), Qt::AlignCenter, message);
|
|
|
|
// Add a border
|
|
painter.setPen(QPen(Qt::darkGray, 2));
|
|
painter.drawRect(1, 1, width-2, height-2);
|
|
|
|
return placeholder;
|
|
} |