diff options
Diffstat (limited to 'src/ui/imageviewer.cpp')
-rw-r--r-- | src/ui/imageviewer.cpp | 1339 |
1 files changed, 0 insertions, 1339 deletions
diff --git a/src/ui/imageviewer.cpp b/src/ui/imageviewer.cpp deleted file mode 100644 index 3292dd6..0000000 --- a/src/ui/imageviewer.cpp +++ /dev/null @@ -1,1339 +0,0 @@ -/*************************************************************************** - * fqterm, a terminal emulator for both BBS and *nix. * - * Copyright (C) 2008 fqterm development group. * - * * - * This program 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 2 of the License, or * - * (at your option) any later version. * - * * - * This program 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -#include <QAction> -#include <QBuffer> -#include <QCursor> -#include <QComboBox> -#include <QDateTime> -#include <QDataStream> -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QIcon> -#include <QKeyEvent> -#include <QLineEdit> -#include <QMessageBox> -#include <QMouseEvent> -#include <QMenu> -#include <QMenuBar> -#include <QPainter> -#include <QPixmap> -#include <QPushButton> -#include <QSizeGrip> -#include <QString> -#include <QTextCodec> -#include <QTimer> -#include <QToolTip> -#include <QTransform> -#include <QTreeView> -#include <QTextEdit> -#include <QHeaderView> -#include <QImageReader> - -#include "fqterm_canvas.h" -#include "fqterm_config.h" -#include "fqterm_exif_extractor.h" -#include "fqterm_filedialog.h" -#include "fqterm_path.h" -#include "fqterm_trace.h" -#include "imageviewer.h" - -namespace FQTerm { - - typedef enum { - V_UNKNOWN = -1, - V_ORIGINAL = 0, - V_SHADOW, - V_BESTFIT, - V_ZOOMIN, - V_ZOOMOUT, - V_ROTLEFT, - V_ROTRIGHT, - V_FULLSCREEN - } slideViewModes; - - typedef enum { - SORT_UNSORTED = -1, - SORT_LIKE, - SORT_NEW, - SORT_TRASH, - SORT_RECOVER, - SORT_TITLE - } slideSortFlags; - - - typedef enum { - STAT_UNKNOWN = -1, - STAT_LIKE, - STAT_NEW, - STAT_TRASH, - STAT_RECOVER, - STAT_TITLE, - STAT_ALL - } slideStatus; - - typedef enum { - GEN_UNKNOWN = -1, - GEN_CANCEL, - GEN_NOCHANGE, - GEN_RESHUFFLE, - GEN_NOTAG, - GEN_INTRASH, - GEN_INTRASHES, - GEN_TOSAVE, - GEN_TOSAVES, - GEN_TRASH, - GEN_TRASHES, - GEN_NOTRASH, - GEN_RECOVER, - GEN_RECOVERS, - GEN_NORECOVER, - GEN_SAVE, - GEN_SAVES, - GEN_DELETE, - GEN_DELETES, - GEN_SEARCHWRAP, - GEN_SEARCHNOMATCH - } generalStatus; - - static const char *fqloraTagStatus[] = { - "Like", - "New", - "Trash", - "Recover", - "Title" - }; - - static const char *fqloraGeneralStatus[] = { - "Canceled.", - "No changes for ", - "Reshuffled by ", - "No tags by ", - "item in the trash.", - "items in the trash.", - "item to save.", - "items to save.", - "image trashed.", - "images trashed.", - "Nothing to trash.", - "image recovered.", - "images recovered.", - "Nothing to recover.", - "image saved in ", - "images saved in ", - "image deleted.", - "images deleted.", - "Search wrapped.", - "No matches." - }; - - static const int toolBarFixedHeight = 40; - static const int statusBarFixedHeight = 18; - static const QSize sortBoxFixedSize(110, 25); - - static const QString &iconPath(const QString &fileName) { - - static QString p = ""; - - if (!fileName.isEmpty()) { - p = getPath(RESOURCE) + ICON_SOURCE + fileName; - } - - return p; - } - - const QString &isPlural(const int num, const int status) { - - static QString m = ""; - - if (num == 1) { - return (m = fqloraGeneralStatus[status]); - } else if (num > 1 && status > GEN_UNKNOWN && status < GEN_DELETES) { - return (m = fqloraGeneralStatus[status + 1]); - } - - return (m = fqloraGeneralStatus[GEN_UNKNOWN]); - } - - // get user's desktop rectangle - static const QRect &desktopSize() { - - static QRect size; - QDesktopWidget myDesktop; - return ((size = myDesktop.screenGeometry(myDesktop.primaryScreen()))); - } - - // FQTermImageFlow - FQTermImageFlow::~FQTermImageFlow() { - - delete statusBar_; - delete imageMenu_; - delete imageFlow_; - - statusBar_ = NULL; - imageMenu_ = NULL; - imageFlow_ = NULL; - } - - FQTermImageFlow::FQTermImageFlow(FQTermConfig * config, QWidget *parent, - Qt::WindowFlags wflag) : - FQTermImage(parent, wflag), - imageFlow_(new ImageFlow(this)), - imageMenu_(new ImageMenu(this)), - statusBar_(new QStatusBar(this)), - config_(config) { - - setWindowTitle(IMAGE_BROWSER_NAME); - setAutoFillBackground(true); - setBackgroundRole(QPalette::Midlight); - setFixedSize(desktopSize().width() / 1.3, desktopSize().height() / 1.9); - - FQ_VERIFY(connect(this, SIGNAL(isTrashEmpty()), this, SLOT(checkTrashState()))); - - // emblem state - FQ_VERIFY(connect(imageFlow_, SIGNAL(emblemStatus(const int)), imageMenu_, SLOT(updateEmblems(const int)))); - FQ_VERIFY(connect(imageMenu_, SIGNAL(toggleFlowStatus(const int)), imageFlow_, SLOT(toggleStatus(const int)))); - - // clear state - FQ_VERIFY(connect(imageFlow_, SIGNAL(clearStatus(const bool)), imageMenu_, SLOT(updateClear(const bool)))); - FQ_VERIFY(connect(imageMenu_, SIGNAL(clearImages()), this, SLOT(clearImages()))); - - // save state - FQ_VERIFY(connect(imageFlow_, SIGNAL(saveStatus(const bool)), imageMenu_, SLOT(updateSave(const bool)))); - FQ_VERIFY(connect(imageMenu_, SIGNAL(saveImages()), this, SLOT(saveImages()))); - - // trash state - FQ_VERIFY(connect(this, SIGNAL(trashStatus(const bool)), imageMenu_, SLOT(updateDustbin(const bool)))); - FQ_VERIFY(connect(imageMenu_, SIGNAL(recoverImages()), this, SLOT(recoverImages()))); - - // constructs a tool bar and its tool buttons - QAction *closeBrowserAct = new QAction(QIcon(iconPath("window-close.png")), tr("Close"), this); - closeBrowserAct->setShortcut(QKeySequence(Qt::Key_Q)); - FQ_VERIFY(connect(closeBrowserAct, SIGNAL(triggered()), this, SLOT(close()))); - - QAction *trashAllAct = new QAction(QIcon(iconPath("trash-empty.png")), tr("Trash All"), this); - trashAllAct->setShortcut(QKeySequence(Qt::Key_Delete)); - FQ_VERIFY(connect(trashAllAct, SIGNAL(triggered()), this, SLOT(trashAllImages()))); - - QLabel *sortLabel = new QLabel(this); - sortLabel->setMargin(5); - sortLabel->setToolTip("Reshuffle images by tags"); - sortLabel->setPixmap(QPixmap(iconPath("edit-shuffle.png"))); - - QComboBox *sortBox = new QComboBox(this); - sortBox->setFocusPolicy(Qt::ClickFocus); - sortBox->setFont(QFont("Serif", 12)); - sortBox->setFrame(false); - sortBox->setFixedSize(sortBoxFixedSize); - sortBox->insertItem(0, QIcon(iconPath("emblem-like-16x16.png")), tr("Like ")); - sortBox->insertItem(1, QIcon(iconPath("emblem-new-16x16.png")), tr("New ")); - sortBox->insertItem(2, QIcon(iconPath("emblem-trash-16x16.png")), tr("Trash ")); - sortBox->insertItem(3, QIcon(iconPath("emblem-recover-16x16.png")), tr("Recover ")); - sortBox->insertItem(4, QIcon(iconPath("emblem-title-16x16.png")), tr("Title ")); - FQ_VERIFY(connect(sortBox, SIGNAL(currentIndexChanged(int)), this, SLOT(reshuffleImages(int)))); - - QToolBar *toolBar = new QToolBar(this); - toolBar->setFixedHeight(toolBarFixedHeight); - toolBar->setIconSize(QSize(32, 32)); - toolBar->addAction(closeBrowserAct); - toolBar->addSeparator(); - toolBar->addWidget(sortLabel); - toolBar->addWidget(sortBox); - toolBar->addSeparator(); - toolBar->addAction(trashAllAct); - - // constructs a status bar to show instant messages - statusBar_->setSizeGripEnabled(false); - statusBar_->setFixedHeight(statusBarFixedHeight); - statusBar_->setFont(QFont("Serif", 10, QFont::Bold)); - FQ_VERIFY(connect(imageFlow_, SIGNAL(statusMessage(const QString &)), this, SLOT(showStatusMessage(const QString &)))); - FQ_VERIFY(connect(this, SIGNAL(statusMessage(const QString &)), this, SLOT(showStatusMessage(const QString &)))); - // constructs a horizontal layout - QVBoxLayout *vBox = new QVBoxLayout(this); - vBox->setMargin(0); - vBox->setSpacing(0); - vBox->addWidget(toolBar); - vBox->addWidget(imageFlow_); - vBox->addWidget(imageMenu_); - vBox->addWidget(statusBar_); - vBox->setEnabled(true); - setLayout(vBox); - } - - const QString &FQTermImageFlow::poolSource(void) const { - - static QString p = ""; - - p = config_->getItemValue("preference", "pool"); - - if (p.isEmpty()) { - p = getPath(USER_CONFIG) + POOL_SOURCE; - } - - return p; - } - - const QString &FQTermImageFlow::trashSource(void) const { - - static QString p = ""; - - p = poolSource() + TRASH_SOURCE; - return p; - } - - // these three functions below are kept for - // API compatibility. - void FQTermImageFlow::adjustItemSize() { - - } - - void FQTermImageFlow::scrollTo(const QString &filePath) { - - } - - void FQTermImageFlow::updateImage(const QString &filePath) { - - } - - // slots and functions - void FQTermImageFlow::loadImages(const int status) { - - int i; - int itemStatus = (status == STAT_RECOVER) ? status : STAT_UNKNOWN; - QString comment; - QFileInfoList sourceList = sortedList(poolSource()); - QFileInfoList targetList = imageFlow_->digest(STAT_ALL); - - for (i = 0; i < sourceList.count(); i++) { - - if (!targetList.contains(sourceList[i])) { - - QImage image; - - if (!image.load(sourceList[i].absoluteFilePath())) { - QFileIconProvider iconProvider; - image = iconProvider.icon(sourceList[i]).pixmap(desktopSize().height() / 6.0).toImage(); - } else { - image = image.scaled(desktopSize().width() / 6.0, desktopSize().height() / 6.0, - Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - } - - /* TODO */ - /* there should be a more flexible */ - /* method to deal with items' status */ - if (status == STAT_ALL) { - itemStatus = STAT_NEW; - } - - ImageFlowItem newItem(image, sourceList[i], comment,itemStatus); - imageFlow_->add(newItem); - } - } - } - - void FQTermImageFlow::reshuffleImages(const int status) { - - // there are images in the pool directory - QList<qint64> itemKeys = imageFlow_->sort(status); - - if (imageFlow_->reorder(itemKeys)) { - imageFlow_->setCurrentSlide(0); - emit statusMessage(tr(fqloraGeneralStatus[GEN_RESHUFFLE]) + tr(fqloraTagStatus[status])); - } else { - emit statusMessage(tr(fqloraGeneralStatus[GEN_NOCHANGE]) + tr(fqloraTagStatus[status])); - } - } - - void FQTermImageFlow::saveImages() { - - QFileInfoList toSave = imageFlow_->digest(STAT_LIKE); - - if (!toSave.isEmpty()) { - - QMessageBox box; - box.setWindowModality(Qt::NonModal); - box.setWindowTitle("Information"); - box.setIconPixmap(QPixmap(iconPath("emblem-info.png"))); - box.setTextFormat(Qt::RichText); - box.setText(QString("<b>%1</b> ").arg(toSave.count()) + isPlural(toSave.count(), GEN_TOSAVE)); - QPushButton *cancelButton = box.addButton(QMessageBox::Cancel); - QPushButton *saveAllButton = box.addButton(QMessageBox::SaveAll); - box.setDefaultButton(cancelButton); - box.exec(); - - if (box.clickedButton() == saveAllButton) { - - FQTermFileDialog fileDialog(config_); - QString savePath = - fileDialog.getExistingDirectory(tr("Save your likes under"), "*"); - - if (savePath.isEmpty()) { - emit statusMessage(tr(fqloraGeneralStatus[GEN_CANCEL])); - return; - } - - int i; - for (i = 0; i < toSave.count(); i++) { - QFile::rename(toSave[i].absoluteFilePath(), savePath + toSave[i].fileName()); - } - - imageFlow_->strip(STAT_LIKE); - emit statusMessage(QString("%1 ").arg(i) + isPlural(i, GEN_SAVE) + savePath); - } else { - emit statusMessage(tr(fqloraGeneralStatus[GEN_CANCEL])); - } - } else { - emit statusMessage(tr(fqloraGeneralStatus[GEN_NOTAG]) + tr(fqloraTagStatus[STAT_LIKE])); - } - } - - void FQTermImageFlow::checkTrashState() { - - QDir trashPath(trashSource()); - - if (trashPath.count() <= 2) { - emit trashStatus(false); - } else { - emit trashStatus(true); - } - } - - void FQTermImageFlow::clearImages() { - - int i; - QString trashPath = trashSource(); - QDir trashDir(trashPath); - QFileInfoList toRemove = imageFlow_->digest(STAT_TRASH); - - if (!trashDir.exists()) { - trashDir.mkdir(trashPath); - } - - if (!toRemove.isEmpty()) { - - for (i = 0; i < toRemove.count(); i++) { - if (QFile::exists(toRemove[i].absoluteFilePath())) { - QFile::rename(toRemove[i].absoluteFilePath(), trashPath + toRemove[i].fileName()); - } - } - - imageFlow_->strip(STAT_TRASH); - emit statusMessage(QString("%1 ").arg(i) + isPlural(i, GEN_TRASH)); - emit isTrashEmpty(); - } else { - emit statusMessage(tr(fqloraGeneralStatus[GEN_NOTAG]) + tr(fqloraTagStatus[STAT_TRASH])); - } - } - - void FQTermImageFlow::trashAllImages() { - - int i; - QString trashPath = trashSource(); - QDir trashDir(trashPath); - QFileInfoList toRemove = imageFlow_->digest(STAT_ALL); - - if (!trashDir.exists()) { - trashDir.mkdir(trashPath); - } - - if (imageFlow_->count() > 0) { - for (i = 0; i < imageFlow_->count(); i++) { - if (QFile::exists(toRemove[i].absoluteFilePath())) { - QFile::rename(toRemove[i].absoluteFilePath(), trashPath + toRemove[i].fileName()); - } - } - - imageFlow_->clear(); - emit statusMessage(QString("%1 ").arg(i) + isPlural(i, GEN_TRASH)); - emit isTrashEmpty(); - } else { - emit statusMessage(tr(fqloraGeneralStatus[GEN_NOTAG]) + tr(fqloraTagStatus[STAT_TRASH])); - } - } - - void FQTermImageFlow::recoverImages() { - - QString trashPath = trashSource(); - QDir trashDir(trashPath); - - if (!trashDir.exists()) { - trashDir.mkdir(trashPath); - } else if (trashDir.count() > 2) { - - int action = -1;; - QFileInfoList toRecover = sortedList(trashPath); - - if (!toRecover.isEmpty()) { - - QMessageBox box; - box.setWindowModality(Qt::NonModal); - box.setWindowTitle("Take action"); - box.setIconPixmap(QPixmap(iconPath("emblem-info.png"))); - box.setTextFormat(Qt::RichText); - box.setText(QString("<b>%1</b> ").arg(toRecover.count()) + isPlural(toRecover.count(), GEN_INTRASH)); - QPushButton *cancelButton = box.addButton(QMessageBox::Cancel); - QPushButton *recoverButton = box.addButton(tr("Recover"), QMessageBox::ApplyRole); - recoverButton->setIcon(QIcon(iconPath("button-recover.png"))); - QPushButton *deleteButton = box.addButton(tr("Delete"), QMessageBox::ApplyRole); - deleteButton->setIcon(QIcon(iconPath("button-delete.png"))); - box.setDefaultButton(cancelButton); - box.exec(); - - if (box.clickedButton() == cancelButton) { - emit statusMessage(tr(fqloraGeneralStatus[GEN_CANCEL])); - return; - } else if (box.clickedButton() == recoverButton) { - action = 1; - } else if (box.clickedButton() == deleteButton) { - action = 0; - } - - int i; - QFile imageFile; - QString poolPath = poolSource(); - - for (i = 0; i < toRecover.count(); i++) { - if (action == 1) { - QFile::rename(toRecover[i].absoluteFilePath(), poolPath + toRecover[i].fileName()); - } else if (action == 0) { - imageFile.setFileName(toRecover[i].absoluteFilePath()); - imageFile.remove(); - } - } - - if (action == 1) { - loadImages(STAT_RECOVER); - emit statusMessage(QString("%1 ").arg(i) + isPlural(i, GEN_RECOVER)); - } else if (action == 0) { - emit statusMessage(QString("%1 ").arg(i) + isPlural(i, GEN_DELETE)); - } - } - } else { - - emit statusMessage(tr(fqloraGeneralStatus[GEN_NORECOVER])); - } - - emit isTrashEmpty(); - } - - - void FQTermImageFlow::showStatusMessage(const QString &message) { - - if (statusBar_) { - statusBar_->showMessage(message, 3000); - } - } - - QFileInfoList FQTermImageFlow::sortedList(const QString &path) { - - QDir sortPath(path); - - if (!sortPath.exists()) { - sortPath.mkdir(path); - } - - QStringList filters; - QList<QByteArray> formats = QImageReader::supportedImageFormats(); - for (QList<QByteArray>::iterator it = formats.begin(); - it != formats.end(); - ++it) { - QString filter("*."); - filter.append(it->data()); - filters << filter; - } - sortPath.setNameFilters(filters); - - return (sortPath.entryInfoList(QDir::Files | QDir::Readable | QDir::NoSymLinks, QDir::Time)); - } - - // FQTermImageFlow events. - void FQTermImageFlow::showEvent(QShowEvent *event) { - - emit isTrashEmpty(); - - if (imageFlow_->count() <= 0) { - loadImages(STAT_UNKNOWN); - move((desktopSize().width() - width()) / 2.0, (desktopSize().height() - height()) / 2.0); - } else { - // TODO: insert new images - loadImages(STAT_ALL); - } - } - - void FQTermImageFlow::closeEvent(QCloseEvent *event) { - - hide(); - } - - class ImageMenu::Private { - public: - int emblemStatus; - bool dustbinStatus; - bool saveStatus; - bool clearStatus; - - QString tipMessage; - - QRect rectLike; - QRect rectTrash; - QRect rectNew; - QRect rectRecover; - QRect rectEmblems; - - QRect rectClear; - QRect rectSave; - QRect rectDustbin; - - QPixmap pixmapLike, pixmapLikeGray; - QPixmap pixmapTrash, pixmapTrashGray; - QPixmap pixmapNew, pixmapNewGray; - QPixmap pixmapRecover, pixmapRecoverGray; - - QPixmap pixmapClear, pixmapClearGray; - QPixmap pixmapSave, pixmapSaveGray; - QPixmap pixmapDustbin, pixmapDustbinGray; - }; - - //ImageMenu - ImageMenu::ImageMenu(QWidget *parent) - : fh(new ImageMenu::Private) { - - setAutoFillBackground(true); - setBackgroundRole(QPalette::Shadow); - setFocusPolicy(Qt::NoFocus); - setMouseTracking(true); - setFixedHeight(60); - - fh->emblemStatus = -2; - fh->dustbinStatus = false; - fh->saveStatus = false; - fh->clearStatus = false; - - fh->tipMessage = ""; - - fh->rectLike = QRect(50, 14, 32, 32); - fh->rectTrash = QRect(100, 14, 32, 32); - fh->rectNew = QRect(150, 14, 32, 32); - fh->rectRecover = QRect(200, 14, 32, 32); - fh->rectEmblems = QRect(50, 14, 232, 32); - - fh->rectClear = QRect(300, 14, 32, 32); - fh->rectSave = QRect(350, 14, 32, 32); - fh->rectDustbin = QRect(400, 14, 32, 32); - - fh->pixmapLike = QPixmap(iconPath("emblem-like.png")); - fh->pixmapLikeGray = QPixmap(iconPath("emblem-like-gray.png")); - - fh->pixmapTrash = QPixmap(iconPath("emblem-trash.png")); - fh->pixmapTrashGray = QPixmap(iconPath("emblem-trash-gray.png")); - - fh->pixmapNew = QPixmap(iconPath("emblem-new.png")); - fh->pixmapNewGray = QPixmap(iconPath("emblem-new-gray.png")); - - fh->pixmapRecover = QPixmap(iconPath("emblem-recover.png")); - fh->pixmapRecoverGray = QPixmap(iconPath("emblem-recover-gray.png")); - - fh->pixmapClear = QPixmap(iconPath("clear-state.png")); - fh->pixmapClearGray = QPixmap(iconPath("clear-state-gray.png")); - - fh->pixmapSave = QPixmap(iconPath("save-state.png")); - fh->pixmapSaveGray = QPixmap(iconPath("save-state-gray.png")); - - fh->pixmapDustbin = QPixmap(iconPath("trash-state.png")); - fh->pixmapDustbinGray = QPixmap(iconPath("trash-state-gray.png")); - } - - ImageMenu::~ImageMenu() { - - delete fh; - fh = NULL; - } - - void ImageMenu::updateEmblems(const int status) { - - if (fh->emblemStatus != status) { - update(fh->rectEmblems); - } - - fh->emblemStatus = status; - } - - void ImageMenu::updateClear(const bool hasOrNot) { - - if (fh->clearStatus != hasOrNot) { - update(fh->rectClear); - } - - fh->clearStatus = hasOrNot; - } - - void ImageMenu::updateSave(const bool hasOrNot) { - - if (fh->saveStatus != hasOrNot) { - update(fh->rectSave); - } - - fh->saveStatus = hasOrNot; - } - - void ImageMenu::updateDustbin(const bool fullOrNot) { - - if (fh->dustbinStatus != fullOrNot) { - update(fh->rectDustbin); - } - - fh->dustbinStatus = fullOrNot; - } - - void ImageMenu::paintEvent(QPaintEvent *event) { - - QPainter p(this); - - p.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); - - if (fh->emblemStatus == STAT_LIKE) { - p.drawPixmap(fh->rectLike, fh->pixmapLike); - } else { - p.drawPixmap(fh->rectLike, fh->pixmapLikeGray); - } - - if (fh->emblemStatus == STAT_TRASH) { - p.drawPixmap(fh->rectTrash, fh->pixmapTrash); - } else { - p.drawPixmap(fh->rectTrash, fh->pixmapTrashGray); - } - - if (fh->emblemStatus == STAT_NEW) { - p.drawPixmap(fh->rectNew, fh->pixmapNew); - } else { - p.drawPixmap(fh->rectNew, fh->pixmapNewGray); - } - - if (fh->emblemStatus == STAT_RECOVER) { - p.drawPixmap(fh->rectRecover, fh->pixmapRecover); - } else { - p.drawPixmap(fh->rectRecover, fh->pixmapRecoverGray); - } - - if (fh->clearStatus == true) { - p.drawPixmap(fh->rectClear, fh->pixmapClear); - } else { - p.drawPixmap(fh->rectClear, fh->pixmapClearGray); - } - - if (fh->saveStatus == true) { - p.drawPixmap(fh->rectSave, fh->pixmapSave); - } else { - p.drawPixmap(fh->rectSave, fh->pixmapSaveGray); - } - - if (fh->dustbinStatus == true) { - p.drawPixmap(fh->rectDustbin, fh->pixmapDustbin); - } else { - p.drawPixmap(fh->rectDustbin, fh->pixmapDustbinGray); - } - - p.end(); - } - - void ImageMenu::mouseReleaseEvent(QMouseEvent *event) { - - if (event->button() == Qt::LeftButton - || event->button() == Qt::RightButton) { - - if (fh->rectLike.contains(event->pos())) { - emit toggleFlowStatus(STAT_LIKE); - } - - if (fh->rectTrash.contains(event->pos())) { - emit toggleFlowStatus(STAT_TRASH); - } - - if (fh->rectClear.contains(event->pos())) { - emit clearImages(); - } - - if (fh->rectSave.contains(event->pos())) { - emit saveImages(); - } - - if (fh->rectDustbin.contains(event->pos())) { - emit recoverImages(); - } - } - } - - // ImageFlow: this subclasses PictureFlow - class ImageFlow::Private { - public: - int emblemStatus; - int likeCount; - int clearCount; - - QList<QByteArray> itemsTitles; - QHash<QByteArray, qint64> itemsTitleKeyPairs; - QList<ImageFlowItem> items; - }; - - ImageFlow::~ImageFlow() { - - delete m; - m = NULL; - } - - // construct an emptry pictureflow. - ImageFlow::ImageFlow(QWidget *parent) - : PictureFlow(parent), m(new ImageFlow::Private) { - - // initial setup - setFocusPolicy(Qt::StrongFocus); - setZoomFactor(120); - setSlideCount(0); - m->emblemStatus = -1; - m->likeCount = 0; - m->clearCount = 0; - } - - const ImageFlowItem& ImageFlow::operator[](int index) const { - - return (m->items[index]); - } - - ImageFlowItem& ImageFlow::operator[](int index) { - - return (m->items[index]); - } - - const ImageFlowItem& ImageFlow::at(int index) const { - - return (m->items[index]); - } - - void ImageFlow::add(const ImageFlowItem &item) { - - QByteArray title = item.info().fileName().toLocal8Bit(); - - m->items.append(item); - m->itemsTitles.append(title); - m->itemsTitleKeyPairs.insert(title, item.key()); - - // set the status pixmap - int index = m->items.indexOf(item); - m->items[index].setStatus(item.status()); - - int count = m->items.count(); - setSlideCount(count); - setSlide(count - 1, item.image()); - } - - QList<QByteArray>& ImageFlow::itemsTitles() const { - - return (m->itemsTitles); - } - - void ImageFlow::clear() { - - m->items.clear(); - setSlideCount(0); - setCurrentSlide(0); - PictureFlow::clear(); - } - - int ImageFlow::count() const { - - return (m->items.count()); - } - - int ImageFlow::size() const { - - return (m->items.size()); - } - - QFileInfoList& ImageFlow::digest(const int status) { - - int i; - int count = m->items.size(); - static QFileInfoList result; - - result.clear(); - - for (i = 0; i < count; i++) { - switch (status) { - case STAT_ALL: - result.append(m->items[i].info()); - break; - default: - if (m->items[i].status() == status) { - result.append(m->items[i].info()); - } - break; - } - } - - return result; - } - - void ImageFlow::strip(const int status) { - - int i; - int count = m->items.count(); - QList<int> dirtyIndexes; - - // We cannot delete items in a loop because - // items count will change while deleting. - // A better method is to use another list - // to record 'dirty' items, and by looping this - // dirty list, we can correctly delete those - // dirty items successfully. - for (i = 0; i < count; i++) { - if (m->items[i].status() == status) { - dirtyIndexes.append(i); - } - } - - if (!dirtyIndexes.isEmpty()) { - - for (i = 0; i < dirtyIndexes.count(); i++) { - // Note: dirtyIndexes[i] - i: the actual - // position of the dirty item. - m->items.removeAt(dirtyIndexes[i] - i); - } - - dirtyIndexes.clear(); - reorder(sort(STAT_ALL)); - - for (i = 0; i < m->items.count(); i++) { - setSlide(i, m->items[i].image()); - } - - setSlideCount(i); - setCurrentSlide(0); - - switch(status) { - case STAT_LIKE: - m->likeCount = 0; - emit saveStatus(false); - emit emblemStatus(STAT_UNKNOWN); - break; - case STAT_TRASH: - m->clearCount = 0; - emit clearStatus(false); - emit emblemStatus(STAT_UNKNOWN); - break; - default: - break; - } - } - } - - QList<qint64> ImageFlow::sort(const int status) { - - int i; - int count = m->items.count(); - QList<qint64> itemKeys; - - switch (status) { - case STAT_TITLE: - qStableSort(m->itemsTitles.begin(), m->itemsTitles.end(), qLess<QByteArray>()); - for (i = 0; i < m->itemsTitles.count(); i++) { - itemKeys.append(m->itemsTitleKeyPairs.value(m->itemsTitles[i])); - } - break; - default: - for (i = 0; i < count; i++) { - if (m->items[i].status() == status) { - itemKeys.prepend(m->items[i].key()); - } else { - itemKeys.append(m->items[i].key()); - } - } - break; - } - - // this might be unnecessary here. - return itemKeys; - } - - bool ImageFlow::reorder(const QList<qint64>& itemsKey) { - - int items_count = m->items.size(); - - if (itemsKey.size() != items_count) { - - return (false); - } - - // Collect Items Key - QList<qint64> currentItemsKey; - for (int i = 0; i < items_count; i++) { - - currentItemsKey.append(m->items.at(i).key()); - } - - if (currentItemsKey == itemsKey) { - // if identical, we don't sort. - return (false); - } - - // Swap Items - for (int i=0; i < items_count; i++) { - - int index = currentItemsKey.indexOf(itemsKey.at(i)); - if (i == index) { - continue; - } - - QImage imgA = m->items[i].image(); - QImage imgB = m->items[index].image(); - - setSlide(index, imgA); - setSlide(i, imgB); - - m->items.swap(i, index); - currentItemsKey.swap(i, index); - } - - update(); - rehash(); - return(true); - } - - void ImageFlow::rehash(void) { - - int count = m->items.count(); - - if (count <= 0) { - return; - } - - int i; - - m->itemsTitles.clear(); - m->itemsTitleKeyPairs.clear(); - - qint64 k; - QByteArray b; - - for (i = 0; i < count; i++) { - k = m->items[i].key(); - b = m->items[i].info().fileName().toLocal8Bit(); - m->itemsTitles.append(b); - m->itemsTitleKeyPairs.insert(b, k); - } - } - - void ImageFlow::toggleStatus(const int status) { - - int index = currentSlide(); - int count = m->items.count(); - - if (index >= 0 && index < count) { - - setUpdatesEnabled(false); - if (m->items[index].status() != status) { - - switch (status) { - case STAT_LIKE: - m->likeCount++; - if (m->items[index].status() == STAT_TRASH) { - m->clearCount--; - } - emit saveStatus(true); - break; - case STAT_TRASH: - m->clearCount++; - if (m->items[index].status() == STAT_LIKE) { - m->likeCount--; - } - emit clearStatus(true); - break; - default: - break; - } - - m->items[index].setStatus(status); - emit statusMessage(tr("Tagged as ") + tr(fqloraTagStatus[status])); - - } else { - - switch (status) { - case STAT_LIKE: - m->likeCount--; - break; - case STAT_TRASH: - m->clearCount--; - break; - default: - break; - } - - m->items[index].setStatus(STAT_UNKNOWN); - emit statusMessage("Tag cleared"); - } - - if (m->likeCount <= 0) { - emit saveStatus(false); - } else { - emit saveStatus(true); - } - - if (m->clearCount <= 0) { - emit clearStatus(false); - } else { - emit clearStatus(true); - } - - setUpdatesEnabled(true); - } - } - - void ImageFlow::setCurrentImage(const int index) { - - int count = size(); - - if (count > 0 && index > 0 && index < count) { - - setCurrentSlide(index); - } - } - -// events - void ImageFlow::paintEvent(QPaintEvent *event) { - - PictureFlow::paintEvent(event); - - if (slideCount() < 1) { - return; - } - - QPainter p(this); - - // White Pen for File Info - p.setPen(Qt::gray); - - int cw = width() / 2; - int wh = height(); - - ImageFlowItem& item = m->items[currentSlide()]; - - // Draw File Name if it's not empty - QString title = item.info().fileName(); - if (!title.isEmpty()) { - - p.setFont(QFont(p.font().family(), p.font().pointSize() + 1, QFont::Bold)); - p.drawText(cw - (QFontMetrics(p.font()).width(title) / 2), wh - 20, title); - } - - p.end(); - - if (m->emblemStatus != item.status()) { - emit emblemStatus(item.status()); - } - - m->emblemStatus = item.status(); - } - - // ImageFlowItem - class ImageFlowItem::Private { - public: - QString filePath; - QFileInfo info; - QString comment; - QImage image; - int status; - qint64 key; - - }; - - ImageFlowItem::~ImageFlowItem() { - - delete m; - m = NULL; - } - - // constructs an empty item - ImageFlowItem::ImageFlowItem(QObject *parent) - : QObject(parent), m(new ImageFlowItem::Private) { - - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - ImageFlowItem::ImageFlowItem(const ImageFlowItem &item) - : QObject(item.parent()), m(new ImageFlowItem::Private) { - - operator=(item); - } - - // constructs an item with a given image - ImageFlowItem::ImageFlowItem(const QImage &image, QObject *parent) - : QObject(parent), m(new ImageFlowItem::Private) { - - m->image = image; - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - // constructs an image with given image and title - ImageFlowItem::ImageFlowItem(const QImage &image, const QFileInfo &info, QObject *parent) - : QObject(parent), m(new ImageFlowItem::Private) { - - m->image = image; - m->info = info; - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - // constructs an image with given image, title and comment - ImageFlowItem::ImageFlowItem(const QImage &image, const QFileInfo &info, const QString &comment, QObject *parent) - : QObject(parent), m(new ImageFlowItem::Private) { - - m->image = image; - m->info = info; - m->comment = comment; - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - // constructs an image with given image, title, type, size, time and state - ImageFlowItem::ImageFlowItem(const QImage &image, const QFileInfo &info, const QString& comment, const int status, QObject *parent) - : QObject(parent), m(new ImageFlowItem::Private) { - - m->image = image; - m->info = info; - m->comment = comment; - m->status = status; - - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - // funcs and slots - ImageFlowItem& ImageFlowItem::operator=(const ImageFlowItem &item) { - - m->info = item.m->info; - m->comment = item.m->comment; - m->key = item.m->key; - - if (item.m->filePath.isEmpty()) { - m->image = item.m->image; - } else { - setImage(item.m->filePath, m->key); - } - - return (*this); - } - - bool ImageFlowItem::operator==(const ImageFlowItem& item) const { - - return (item.m->key == m->key); - } - - bool ImageFlowItem::operator!=(const ImageFlowItem& item) const { - - return (item.m->key != m->key); - } - - const QString& ImageFlowItem::comment() const { - - return (m->comment); - } - - const QImage& ImageFlowItem::image() const { - - return (m->image); - } - - int ImageFlowItem::status(void) const { - - return (m->status); - } - - const QFileInfo& ImageFlowItem::info(void) const { - - return (m->info); - } - - qint64 ImageFlowItem::key() const { - - return (m->key); - } - - void ImageFlowItem::setInfo(const QFileInfo& info) { - - m->info = info; - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - void ImageFlowItem::setComment(const QString &comment) { - - m->comment = comment; - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - void ImageFlowItem::setImage(const QImage &image) { - - m->image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - void ImageFlowItem::setImage(const QString &filePath, int size) { - - m->filePath = filePath; - m->key = size; - - QTimer::singleShot(1000, this, SLOT(loadImage())); - } - - void ImageFlowItem::setStatus(const int status) { - - m->status = status; - } - - void ImageFlowItem::loadImage() { - - int imageHeight = m->key; - - if (!m->image.load(m->filePath)) { - QFileIconProvider iconProvider; - m->image = iconProvider.icon(QFileInfo(m->filePath)).pixmap(imageHeight).toImage(); - } else { - m->image = resizeImage(m->image, imageHeight); - } - - m->filePath.clear(); - m->key = qHash(QString::number(m->image.cacheKey()) + m->info.fileName() + m->comment); - } - - QImage ImageFlowItem::resizeImage(const QImage &image, int size) { - - if (size == image.width() && size == image.height()) { - return image; - } - - double scaleWidth = size / (double)image.width(); - double scaleHeight = size / (double)image.height(); - double smaller = qMin(scaleWidth, scaleHeight); - - int w = (int) qRound(smaller * image.width()); - int h = (int) qRound(smaller * image.height()); - - return (image.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - } - -} // namespace FQTerm - -#include "imageviewer.moc" |