#include "imagegallery.h" #include #include #include #include #include #include #include // 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 &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 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; }