diff --git a/cdatetimepicker.cpp b/cdatetimepicker.cpp new file mode 100644 index 0000000..472a7ab --- /dev/null +++ b/cdatetimepicker.cpp @@ -0,0 +1,49 @@ +#include "cdatetimepicker.h" +#include "ui_cdatetimepicker.h" + + +cDateTimePicker::cDateTimePicker(QWidget *parent) : + QDialog(parent), + ui(new Ui::cDateTimePicker) +{ + ui->setupUi(this); + ui->m_lpText->setVisible(false); + ui->m_lpPicture->setVisible(false); +} + +cDateTimePicker::~cDateTimePicker() +{ + delete ui; +} + +void cDateTimePicker::setText(const QString& szText) +{ + if(szText.isEmpty()) + ui->m_lpText->setVisible(false); + else + { + ui->m_lpText->setVisible(true); + ui->m_lpText->setText(szText); + } +} + +void cDateTimePicker::setImage(const QImage& image) +{ + if(image.isNull()) + ui->m_lpPicture->setVisible(false); + else + { + ui->m_lpPicture->setVisible(true); + ui->m_lpPicture->setPixmap(QPixmap::fromImage(image)); + } +} + +void cDateTimePicker::setDateTime(const QDateTime dateTime) +{ + ui->m_lpDateTime->setDateTime(dateTime); +} + +QDateTime cDateTimePicker::dateTime() +{ + return(ui->m_lpDateTime->dateTime()); +} diff --git a/cdatetimepicker.h b/cdatetimepicker.h new file mode 100644 index 0000000..bd90102 --- /dev/null +++ b/cdatetimepicker.h @@ -0,0 +1,29 @@ +#ifndef CDATETIMEPICKER_H +#define CDATETIMEPICKER_H + + +#include +#include + + +namespace Ui { +class cDateTimePicker; +} + +class cDateTimePicker : public QDialog +{ + Q_OBJECT + +public: + explicit cDateTimePicker(QWidget *parent = nullptr); + ~cDateTimePicker(); + + void setText(const QString& szText); + void setImage(const QImage& image); + void setDateTime(const QDateTime dateTime); + QDateTime dateTime(); +private: + Ui::cDateTimePicker* ui; +}; + +#endif // CDATETIMEPICKER_H diff --git a/cdatetimepicker.ui b/cdatetimepicker.ui new file mode 100644 index 0000000..1119f47 --- /dev/null +++ b/cdatetimepicker.ui @@ -0,0 +1,93 @@ + + + cDateTimePicker + + + + 0 + 0 + 176 + 90 + + + + Dialog + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + cDateTimePicker + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + cDateTimePicker + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/cexif.cpp b/cexif.cpp index 8f9a294..8bbb693 100644 --- a/cexif.cpp +++ b/cexif.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -33,58 +34,59 @@ bool cEXIF::fromFile(const QString& szFileName) image->readMetadata(); Exiv2::ExifData& exifData = image->exifData(); - if(exifData.empty()) - return(false); - - Exiv2::ExifData::const_iterator end = exifData.end(); - for(Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) - { - cEXIFTag* lpTag = m_exifTagList.find(i->tag(), i->ifdId()); - - if(lpTag) - { - cEXIFValue* lpValue = m_exifValueList.add(lpTag); - if(lpValue) - lpValue->setValue(QString::fromStdString(i->value().toString()), i->typeId(), i->count()); - } - } m_iWidth = image->pixelWidth(); m_iHeight = image->pixelHeight(); m_szFileName = szFileName; - Exiv2::PreviewManager previewManager(*image); - Exiv2::PreviewPropertiesList previewPropertiesList = previewManager.getPreviewProperties(); - - for(Exiv2::PreviewPropertiesList::const_iterator i = previewPropertiesList.begin();i != previewPropertiesList.end();i++) + if(!exifData.empty()) { - Exiv2::PreviewImage previewImage = previewManager.getPreviewImage(*i); - QImage image; - image.loadFromData(static_cast(previewImage.pData()), static_cast(previewImage.size())); - - QTransform rotation; - int angle = 0; - - switch(imageOrientation()) + Exiv2::ExifData::const_iterator end = exifData.end(); + for(Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { - case 8: - angle = 270; - break; - case 3: - angle = 180; - break; - case 6: - angle = 90; - break; + cEXIFTag* lpTag = m_exifTagList.find(i->tag(), i->ifdId()); + + if(lpTag) + { + cEXIFValue* lpValue = m_exifValueList.add(lpTag); + if(lpValue) + lpValue->setValue(QString::fromStdString(i->value().toString()), i->typeId(), i->count()); + } } - if(angle != 0) - { - rotation.rotate(angle); - image = image.transformed(rotation); - } + Exiv2::PreviewManager previewManager(*image); + Exiv2::PreviewPropertiesList previewPropertiesList = previewManager.getPreviewProperties(); - m_previewList.append(image); + for(Exiv2::PreviewPropertiesList::const_iterator i = previewPropertiesList.begin();i != previewPropertiesList.end();i++) + { + Exiv2::PreviewImage previewImage = previewManager.getPreviewImage(*i); + QImage image; + image.loadFromData(static_cast(previewImage.pData()), static_cast(previewImage.size())); + + QTransform rotation; + int angle = 0; + + switch(imageOrientation()) + { + case 8: + angle = 270; + break; + case 3: + angle = 180; + break; + case 6: + angle = 90; + break; + } + + if(angle != 0) + { + rotation.rotate(angle); + image = image.transformed(rotation); + } + + m_previewList.append(image); + } } if(!m_previewList.count()) @@ -195,7 +197,9 @@ QString cEXIF::cameraModel() QDateTime cEXIF::dateTime() { - return(QDateTime::fromString(getTag(0x0132, 1).value(), "yyyy:MM:dd hh:mm:ss")); + QDateTime dateTime = QDateTime::fromString(getTag(0x0132, 1).value(), "yyyy:MM:dd hh:mm:ss"); + + return(dateTime); } QString cEXIF::fNumber() diff --git a/cimportdialog.cpp b/cimportdialog.cpp index 92f5730..cc4c55d 100644 --- a/cimportdialog.cpp +++ b/cimportdialog.cpp @@ -5,6 +5,8 @@ #include "cpicture.h" +#include "cdatetimepicker.h" + #include #include #include @@ -61,8 +63,15 @@ void cImportDialog::initUI() qint32 iWidth2 = settings.value("import/splitter2", QVariant::fromValue(-1)).toInt(); ui->m_lpSplitter->setSizes(QList() << iWidth1 << iWidth2); - ui->m_lpPath->setText(settings.value("import/path", QDir::homePath()).toString()); + + ui->m_lpRecursive->setChecked(settings.value("import/recursive", QVariant::fromValue(true)).toBool()); + if(settings.value("import/copy", QVariant::fromValue(true)).toBool()) + ui->m_lpCopy->setChecked(true); + else + ui->m_lpMove->setChecked(true); + ui->m_lpDetectHDR->setChecked(settings.value("import/detectHDR", QVariant::fromValue(true)).toBool()); + ui->m_lpDetectJPG_RAW->setChecked(settings.value("import/detectJPG_RAW", QVariant::fromValue(true)).toBool()); } bool cImportDialog::hasImported() @@ -138,6 +147,11 @@ void cImportDialog::savePosition() for(int x = 0;x < sizes.count();x++) settings.setValue(QString("import/splitter%1").arg(x+1), QVariant::fromValue(sizes[x])); + + settings.setValue("import/recursive", QVariant::fromValue(ui->m_lpRecursive->isChecked())); + settings.setValue("import/copy", QVariant::fromValue(ui->m_lpCopy->isChecked())); + settings.setValue("import/detectHDR", QVariant::fromValue(ui->m_lpDetectHDR->isChecked())); + settings.setValue("import/detectJPG_RAW", QVariant::fromValue(ui->m_lpDetectJPG_RAW->isChecked())); } void cImportDialog::onRead() @@ -149,6 +163,7 @@ void cImportDialog::onRead() } m_lpImportListModel->clear(); + ui->m_lpImport->setEnabled(false); readDirectory(ui->m_lpPath->text(), ui->m_lpRecursive->isChecked()); } @@ -156,6 +171,8 @@ void cImportDialog::onRead() void cImportDialog::onImport() { QModelIndexList selected = ui->m_lpImportList->selectionModel()->selectedRows(); + QDir dir; + QFile file; ui->m_lpProgress->setVisible(true); ui->m_lpProgress->setRange(0, selected.count()); @@ -175,20 +192,40 @@ void cImportDialog::onImport() QString szSource = lpPicture->filePath() + QDir::separator() + lpPicture->fileName(); QString szDest = m_szRootPath + QDir::separator(); + QString szDestPath = ""; if(lpPicture->dateTime().isValid()) - szDest.append(QString::number(lpPicture->dateTime().date().year()) + QDir::separator() + lpPicture->dateTime().date().toString("yyyy-mm-dd") + QDir::separator()); + szDestPath.append(QString::number(lpPicture->dateTime().date().year()) + QDir::separator() + lpPicture->dateTime().date().toString("yyyy-MM-dd") + QDir::separator()); if(!lpPicture->cameraModel().isEmpty()) - szDest.append(lpPicture->cameraModel() + QDir::separator()); + szDestPath.append(lpPicture->cameraModel() + QDir::separator()); - szDest.append(lpPicture->fileName()); + szDest.append(szDestPath); - qDebug() << "Source: " << szSource; - qDebug() << "Dest: " << szDest; + if(dir.mkpath(szDest)) + { + szDest.append(lpPicture->fileName()); + + if(file.exists(szDest)) + file.remove(szDest); + + file.copy(szSource, szDest); + + ui->m_lpProgress->setValue(x); + qApp->processEvents(); + + lpPicture->setFilePath(szDestPath); + lpPicture->toDB(); + + if(ui->m_lpMove->isChecked()) + { +// file.remove(szSource); + } + } } } - }bla + } + ui->m_lpStatusText->setText(""); ui->m_lpProgress->setVisible(false); m_bHasImported = true; @@ -200,6 +237,7 @@ void cImportDialog::readDirectory(const QString& szPath, bool bRecursive) QDir dir(szPath); QStringList szDirs = dir.entryList(QDir::Dirs); QFileInfoList szFiles = dir.entryInfoList(QDir::Files); + QDateTime oldDateTime; if(bRecursive) { @@ -225,6 +263,24 @@ void cImportDialog::readDirectory(const QString& szPath, bool bRecursive) if(lpPicture->fromFile(fileInfo.filePath())) { + if(!lpPicture->dateTime().isValid()) + { + cDateTimePicker dateTimePicker; + dateTimePicker.setWindowTitle("Warning"); + dateTimePicker.setText(QString(tr("\"%1\" has no date.\nTo import, please set a date.").arg(fileInfo.filePath()))); + dateTimePicker.setImage(lpPicture->thumbnail()); + + if(!oldDateTime.isValid()) + oldDateTime = fileInfo.birthTime(); + + dateTimePicker.setDateTime(oldDateTime); + if(dateTimePicker.exec() == QDialog::Rejected) + continue; + + oldDateTime = dateTimePicker.dateTime(); + lpPicture->setDateTime(oldDateTime); + } + if(lpPicture->thumbnail().width() != THUMBNAIL_WIDTH || lpPicture->thumbnail().height() != THUMBNAIL_HEIGHT) { QImage thumbnail(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, lpPicture->thumbnail().format()); diff --git a/cimportdialog.ui b/cimportdialog.ui index 14589a2..7eee2f3 100644 --- a/cimportdialog.ui +++ b/cimportdialog.ui @@ -73,6 +73,24 @@ + + + + + + detect HDR + + + + + + + detect JPG/RAW + + + + + diff --git a/cmainwindow.cpp b/cmainwindow.cpp index 398f467..b1a347b 100644 --- a/cmainwindow.cpp +++ b/cmainwindow.cpp @@ -20,6 +20,7 @@ cMainWindow::cMainWindow(cSplashScreen* lpSplashScreen, QWidget *parent) : QMainWindow(parent), ui(new Ui::cMainWindow), + m_lpProgressBar(nullptr), m_lpSplashScreen(lpSplashScreen), m_lpFileMenu(nullptr), m_lpFileToolBar(nullptr) @@ -43,6 +44,11 @@ void cMainWindow::initUI() m_lpThumbnailViewModel = new QStandardItemModel; ui->m_lpThumbnailView->setModel(m_lpThumbnailViewModel); + + m_lpProgressBar = new QProgressBar(this); + m_lpProgressBar->setVisible(false); + ui->m_lpStatusBar->addPermanentWidget(m_lpProgressBar); + QIcon::setThemeName("TangoMFK"); QSettings settings; @@ -100,12 +106,12 @@ void cMainWindow::createActions() // connect(ui->m_lpOutlineList, &cTreeView::dropped, this, &cMainWindow::onOutlineDropped); } -void cMainWindow::loadData() +void cMainWindow::loadData(bool bProgressBar) { m_pictureList.clear(); m_lpThumbnailViewModel->clear(); - m_pictureList.load(); + m_pictureList.load(m_lpSplashScreen, bProgressBar ? m_lpProgressBar : nullptr); for(int x = 0;x < m_pictureList.count();x++) { @@ -398,5 +404,9 @@ void cMainWindow::onFileImport() importDialog.exec(); if(importDialog.hasImported()) - loadData(); + { + m_lpProgressBar->setVisible(true); + loadData(true); + m_lpProgressBar->setVisible(false); + } } diff --git a/cmainwindow.h b/cmainwindow.h index f08e11b..93d45d9 100644 --- a/cmainwindow.h +++ b/cmainwindow.h @@ -17,6 +17,8 @@ #include #include +#include + namespace Ui { class cMainWindow; @@ -46,6 +48,7 @@ public: private: Ui::cMainWindow* ui; /**< TODO: describe */ + QProgressBar* m_lpProgressBar; /**< TODO: describe */ QStandardItemModel* m_lpThumbnailViewModel; /**< TODO: describe */ cSplashScreen* m_lpSplashScreen; /*!< Splash Screen */ cPictureLibrary m_pictureLibrary; /**< TODO: describe */ @@ -108,7 +111,7 @@ private: \fn loadData */ - void loadData(); + void loadData(bool bProgressBar = false); protected: /*! diff --git a/cpicture.cpp b/cpicture.cpp index e1ba1c0..fa70e9d 100644 --- a/cpicture.cpp +++ b/cpicture.cpp @@ -7,6 +7,8 @@ #include #include +#include + cPicture::cPicture(qint32 iID, QObject *parent) : QObject(parent), @@ -70,10 +72,10 @@ bool cPicture::fromFile(const QString& szFileName) m_focalLength35 = exif.focalLength35(); m_gps = exif.gps(); - if(!m_dateTime.isValid()) - { - setDateTime(fileInfo.birthTime()); - } +// if(!m_dateTime.isValid()) +// { +// setDateTime(fileInfo.birthTime()); +// } return(true); } @@ -417,11 +419,27 @@ cPictureList::cPictureList(QObject *parent) : { } -bool cPictureList::load() +bool cPictureList::load(cSplashScreen *lpSplashScreen, QProgressBar *lpProgressBar) { cEXIFFlashList flashList; QSqlQuery query; + query.prepare("SELECT COUNT(1) cnt FROM picture;"); + + if(!query.exec()) + { + myDebug << query.lastError().text(); + return(false); + } + query.next(); + + qint32 max = static_cast(query.value("cnt").toLongLong()); + + if(lpProgressBar) + lpProgressBar->setMaximum(max); + else if(lpSplashScreen) + lpSplashScreen->setMax(max); + query.prepare("SELECT id, " " fileName, " " filePath, " @@ -448,7 +466,8 @@ bool cPictureList::load() " gps, " " thumbnail " "FROM picture " - "ORDER BY UPPER(fileName);"); + "ORDER BY dateTime, " + " UPPER(fileName);"); if(!query.exec()) { @@ -456,6 +475,9 @@ bool cPictureList::load() return(false); } + qint32 count = 0; + qint32 step = max/50; + while(query.next()) { cPicture* lpPicture = add(query.value("id").toInt()); @@ -484,6 +506,16 @@ bool cPictureList::load() lpPicture->setFocalLength35(query.value("focalLength35").toDouble()); lpPicture->setGPS(query.value("gps").toString()); lpPicture->setThumbnail(blob2Image(query.value("thumbnail").toByteArray())); + + count++; + if(count % step) + { + if(lpProgressBar) + lpProgressBar->setValue(count); + else if(lpSplashScreen) + lpSplashScreen->setProgress(count); + qApp->processEvents(); + } } return(true); diff --git a/cpicture.h b/cpicture.h index 3632f0e..fc656f6 100644 --- a/cpicture.h +++ b/cpicture.h @@ -2,11 +2,15 @@ #define CPICTURE_H +#include "csplashscreen.h" + #include #include #include #include +#include + #include @@ -424,7 +428,7 @@ public: */ explicit cPictureList(QObject *parent = nullptr); - bool load(); + bool load(cSplashScreen* lpSplashScreen, QProgressBar* lpProgressBar = 0); /** * @brief diff --git a/csplashscreen.cpp b/csplashscreen.cpp index 9ac5791..115cbd2 100644 --- a/csplashscreen.cpp +++ b/csplashscreen.cpp @@ -1,19 +1,41 @@ #include "csplashscreen.h" #include "common.h" +#include + cSplashScreen::cSplashScreen(const QPixmap& pixmap, QFont& font) : - QSplashScreen(pixmap) + QSplashScreen(pixmap), + m_iMax(100), + m_iProgress(0) { setFont(font); m_textDocument.setDefaultFont(font); } +void cSplashScreen::setMax(qint32 max) +{ + m_iMax = max; +} + void cSplashScreen::drawContents(QPainter *painter) { painter->translate(m_rect.topLeft()); m_textDocument.setHtml(m_szMessage); m_textDocument.drawContents(painter); + + QStyleOptionProgressBar pbstyle; + pbstyle.initFrom(this); + pbstyle.state = QStyle::State_Enabled; + pbstyle.textVisible = false; + pbstyle.minimum = 0; + pbstyle.maximum = m_iMax; + pbstyle.progress = m_iProgress; + pbstyle.invertedAppearance = false; + pbstyle.rect = QRect(0, 330, 390, 10); // Where is it. + + // Draw it... + style()->drawControl(QStyle::CE_ProgressBar, &pbstyle, painter, this); } void cSplashScreen::showStatusMessage(const QString& message) @@ -33,3 +55,9 @@ void cSplashScreen::setMessageRect(QRect rect) m_rect = rect; m_textDocument.setTextWidth(rect.width()); } + +void cSplashScreen::setProgress(int value) +{ + m_iProgress = value; + update(); +} diff --git a/csplashscreen.h b/csplashscreen.h index 66e2ff3..6d9d325 100644 --- a/csplashscreen.h +++ b/csplashscreen.h @@ -41,10 +41,16 @@ public: */ void setMessageRect(QRect rect); + void setMax(qint32 max); + private: QTextDocument m_textDocument; /**< TODO: describe */ QString m_szMessage; /**< TODO: describe */ QRect m_rect; /**< TODO: describe */ + qint32 m_iMax; /**< TODO: describe */ + qint32 m_iProgress; /**< TODO: describe */ +public slots: + void setProgress(int value); }; #endif // CSPLASHSCREEN_H diff --git a/pictureLibrary.pro b/pictureLibrary.pro index 0460570..a582e38 100644 --- a/pictureLibrary.pro +++ b/pictureLibrary.pro @@ -62,7 +62,8 @@ SOURCES += \ cpicture.cpp \ cimage.cpp \ ctoolboxinfo.cpp \ - cimportdialog.cpp + cimportdialog.cpp \ + cdatetimepicker.cpp HEADERS += \ cmainwindow.h \ @@ -73,12 +74,14 @@ HEADERS += \ cpicture.h \ cimage.h \ ctoolboxinfo.h \ - cimportdialog.h + cimportdialog.h \ + cdatetimepicker.h FORMS += \ cmainwindow.ui \ ctoolboxinfo.ui \ - cimportdialog.ui + cimportdialog.ui \ + cdatetimepicker.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin