[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kphotoalbum] /: Show age of people on the images
From:       Jesper K. Pedersen <blackie () kde ! org>
Date:       2014-07-31 17:21:14
Message-ID: E1XCu2U-0006k8-EM () scm ! kde ! org
[Download RAW message or body]

Git commit fd04e4776aec6f075984126fe2f41b683a30fe6c by Jesper K. Pedersen.
Committed on 31/07/2014 at 17:20.
Pushed by blackie into branch 'master'.

Show age of people on the images

M  +2    -0    CMakeLists.txt
M  +3    -0    ChangeLog
M  +3    -1    DB/Category.h
A  +150  -0    MainWindow/BirthDatesDialog.cpp     [License: UNKNOWN]  *
A  +40   -0    MainWindow/BirthDatesDialog.h     [License: UNKNOWN]  *
A  +32   -0    MainWindow/CalendarPopup.cpp     [License: UNKNOWN]  *
A  +29   -0    MainWindow/CalendarPopup.h     [License: UNKNOWN]  *
M  +10   -0    MainWindow/Window.cpp
M  +1    -0    MainWindow/Window.h
M  +91   -5    Utilities/Util.cpp
M  +1    -0    Utilities/Util.h
M  +3    -0    XMLDB/FileReader.cpp
M  +3    -0    XMLDB/FileWriter.cpp
M  +10   -0    XMLDB/XMLCategory.cpp
M  +3    -0    XMLDB/XMLCategory.h
M  +2    -1    kphotoalbumui.rc

The files marked with a * at the end have a non valid license. Please read: \
http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are \
listed at that page.


http://commits.kde.org/kphotoalbum/fd04e4776aec6f075984126fe2f41b683a30fe6c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ff861e..c4c06d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -223,6 +223,8 @@ set(libMainWindow_SRCS
     ${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DuplicateMerger/DuplicateMatch.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DuplicateMerger/MergeToolTip.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/CopyPopup.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/BirthDatesDialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/CalendarPopup.cpp
 )
 
 set(libImageManager_SRCS
diff --git a/ChangeLog b/ChangeLog
index 9232df2..7e32638 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+* New Feature: Specify the birth date for people (or any other category item for \
that matter) in Maintanence->Edit Birth Dates, +  and see their age when viewing \
images. +
 ====================== KPhotoalbum 4.5 released  ======================
 
 * New Feature: Added an Android client, which can display images from
diff --git a/DB/Category.h b/DB/Category.h
index 6d09ba5..b129495 100644
--- a/DB/Category.h
+++ b/DB/Category.h
@@ -23,6 +23,7 @@
 #include <qobject.h>
 #include <ksharedptr.h>
 #include "kiconloader.h"
+#include <QDate>
 
 class QImage;
 class QPixmap;
@@ -78,7 +79,8 @@ public:
     QPixmap categoryImage( const QString& category, QString, int width, int height ) \
                const;
     void setCategoryImage( const QString& category, QString, const QImage& image );
     QString fileForCategoryImage ( const QString& category, QString member ) const;
-
+    virtual void setBirthDate(const QString& item, const QDate& birthDate) = 0;
+    virtual QDate birthDate(const QString& item) const = 0;
 
 private:
     QString defaultIconName() const;
diff --git a/MainWindow/BirthDatesDialog.cpp b/MainWindow/BirthDatesDialog.cpp
new file mode 100644
index 0000000..e0de8c2
--- /dev/null
+++ b/MainWindow/BirthDatesDialog.cpp
@@ -0,0 +1,150 @@
+#include "BirthDatesDialog.h"
+#include <KLocale>
+#include <QComboBox>
+#include <QLabel>
+#include <QVBoxLayout>
+#include "DB/ImageDB.h"
+#include "DB/CategoryCollection.h"
+#include "DB/Category.h"
+#include <QPushButton>
+#include <QScrollArea>
+#include "CalendarPopup.h"
+#include <QLineEdit>
+#include <QShortcut>
+#include "DirtyIndicator.h"
+
+namespace MainWindow {
+
+BirthDatesDialog::BirthDatesDialog(QWidget *parent) :
+    QDialog(parent)
+{
+    setWindowTitle(i18n("Configure Birth Dates"));
+    QVBoxLayout* vlay = new QVBoxLayout(this);
+
+    QString txt = i18n("Set the date of birth for items (say people) here,\nand then \
see their age when viewing the images."); +    QLabel* label = new QLabel(txt);
+    QFont fnt;
+    fnt.setPixelSize(20);
+    label->setFont(fnt);
+    label->setAlignment(Qt::AlignHCenter);
+    vlay->addWidget(label);
+    vlay->addSpacing(20);
+
+    QHBoxLayout* hlay = new QHBoxLayout;
+    vlay->addLayout(hlay);
+
+    QLabel* categoryText = new QLabel(i18n("Current Category"));
+    m_categoryBox = new QComboBox;
+
+    m_filter = new QLineEdit;
+    m_filter->setPlaceholderText(i18n("Filter (Alt+f)"));
+    new QShortcut(Qt::AltModifier + Qt::Key_F, m_filter, SLOT(setFocus()));
+
+    connect(m_filter,SIGNAL(textChanged(QString)), this, SLOT(resetCategory()));
+
+    hlay->addWidget(categoryText);
+    hlay->addWidget(m_categoryBox);
+    hlay->addSpacing(100);
+    hlay->addWidget(m_filter,1);
+
+    m_area = new QScrollArea;
+    m_area->setWidgetResizable(true);
+    vlay->addWidget(m_area);
+
+    QPushButton* close = new QPushButton(i18n("Close"));
+    connect(close, SIGNAL(clicked()), this, SLOT(accept()));
+    hlay = new QHBoxLayout;
+    vlay->addLayout(hlay);
+
+    hlay->addStretch(1);
+    hlay->addWidget(close);
+
+    int defaultIndex = 0;
+    int index = 0;
+    for (const DB::CategoryPtr& category: \
DB::ImageDB::instance()->categoryCollection()->categories()) { +        \
if(!category->isSpecialCategory()) { +            \
m_categoryBox->addItem(category->text(), category->name()); +            if ( \
category->name() == QString::fromUtf8("Persons")) +                defaultIndex = \
index; +            ++index;
+        }
+    }
+
+    connect(m_categoryBox,SIGNAL(currentIndexChanged(int)),this,SLOT(changeCategory(int)));
 +    m_categoryBox->setCurrentIndex(defaultIndex);
+    changeCategory(defaultIndex); // needed in case we didn't find the people \
category, to ensure the list is filled. +}
+
+QSize BirthDatesDialog::sizeHint() const
+{
+    return QSize(800,800);
+}
+
+void BirthDatesDialog::changeCategory(int index)
+{
+    QWidget* widget = new QWidget;
+    QGridLayout* grid = new QGridLayout(widget);
+    grid->setColumnStretch(2,1);
+
+    int row = 0;
+    const QString categoryName = m_categoryBox->itemData(index).value<QString>();
+    const DB::CategoryPtr category = \
DB::ImageDB::instance()->categoryCollection()->categoryForName(categoryName); +    \
QStringList items = category->items(); +    items.sort();
+    for (const QString& text : items) {
+        if (!m_filter->text().isEmpty() && text.indexOf(m_filter->text(), 0, \
Qt::CaseInsensitive) == -1) +            continue;
+
+        QLabel* label = new QLabel(text);
+        const QDate date = category->birthDate(text);
+        QPushButton* button = new QPushButton(textForDate(date));
+        button->setProperty("date", date);
+        button->setProperty("name", text);
+        connect(button,SIGNAL(clicked()),this,SLOT(editDate()));
+        grid->addWidget(label,row,0);
+        grid->addWidget(button,row,1);
+        ++row;
+    }
+    grid->setRowStretch(row,1);
+
+    m_area->setWidget(widget);
+    widget->show();
+}
+
+void BirthDatesDialog::resetCategory()
+{
+    changeCategory(m_categoryBox->currentIndex());
+}
+
+void BirthDatesDialog::editDate()
+{
+    if (!m_datePick) {
+        m_datePick = new CalendarPopup;
+        connect(m_datePick,SIGNAL(dateSelected(QDate)), this, SLOT(setDate(QDate)));
+    }
+    m_editButton = static_cast<QPushButton*>(sender());
+    m_datePick->move(m_editButton->mapToGlobal(QPoint(0,0))-QPoint(m_datePick->sizeHint().width()/2, \
m_datePick->sizeHint().height()/2)); +    \
m_datePick->setSelectedDate(m_editButton->property("date").value<QDate>()); +    \
m_datePick->show(); +}
+
+void BirthDatesDialog::setDate(const QDate& date)
+{
+    m_datePick->hide();
+    m_editButton->setText(textForDate(date));
+    m_editButton->setProperty("date", date);
+
+    DB::CategoryPtr category = \
DB::ImageDB::instance()->categoryCollection()->categoryForName(m_categoryBox->itemData(m_categoryBox->currentIndex()).value<QString>());
 +    DirtyIndicator::markDirty();
+    category->setBirthDate(m_editButton->property("name").value<QString>(), date);
+}
+
+QString BirthDatesDialog::textForDate(const QDate &date) const
+{
+    if (date.isNull())
+        return QString::fromUtf8("---");
+    else
+        return KGlobal::locale()->formatDate(date, KLocale::ShortDate);
+}
+
+} // namespace Settings
diff --git a/MainWindow/BirthDatesDialog.h b/MainWindow/BirthDatesDialog.h
new file mode 100644
index 0000000..2cec58d
--- /dev/null
+++ b/MainWindow/BirthDatesDialog.h
@@ -0,0 +1,40 @@
+#ifndef SETTINGS_BIRTHDAYPAGE_H
+#define SETTINGS_BIRTHDAYPAGE_H
+
+#include <QDialog>
+class QComboBox;
+class QLabel;
+class QPushButton;
+class QVBoxLayout;
+class QScrollArea;
+class QDate;
+class QLineEdit;
+
+namespace MainWindow {
+class CalendarPopup;
+
+class BirthDatesDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit BirthDatesDialog(QWidget *parent = 0);
+    QSize sizeHint() const;
+
+private slots:
+    void changeCategory(int index);
+    void resetCategory();
+    void editDate();
+    void setDate(const QDate&);
+
+private:
+    QString textForDate(const QDate& date) const;
+    QComboBox* m_categoryBox;
+    QScrollArea* m_area;
+    CalendarPopup* m_datePick = nullptr;
+    QPushButton* m_editButton;
+    QLineEdit* m_filter;
+};
+
+} // namespace Settings
+
+#endif // SETTINGS_BIRTHDAYPAGE_H
diff --git a/MainWindow/CalendarPopup.cpp b/MainWindow/CalendarPopup.cpp
new file mode 100644
index 0000000..52ab310
--- /dev/null
+++ b/MainWindow/CalendarPopup.cpp
@@ -0,0 +1,32 @@
+#include "CalendarPopup.h"
+
+#include <QCalendarWidget>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <KLocale>
+
+namespace MainWindow {
+
+CalendarPopup::CalendarPopup(QWidget *parent) :
+    QWidget(parent)
+{
+    setWindowFlags(Qt::Popup);
+
+    QVBoxLayout* vlay = new QVBoxLayout(this);
+
+    m_calendar = new QCalendarWidget;
+    vlay->addWidget(m_calendar);
+
+    QPushButton* button = new QPushButton(i18n("unset"));
+    vlay->addWidget(button);
+
+    connect(m_calendar, SIGNAL(clicked(QDate)), this, SIGNAL(dateSelected(QDate)));
+    connect(button, SIGNAL(clicked()), this, SIGNAL(dateSelected()));
+}
+
+void CalendarPopup::setSelectedDate(const QDate& date)
+{
+    m_calendar->setSelectedDate(date);
+}
+
+} // namespace Settings
diff --git a/MainWindow/CalendarPopup.h b/MainWindow/CalendarPopup.h
new file mode 100644
index 0000000..56496e4
--- /dev/null
+++ b/MainWindow/CalendarPopup.h
@@ -0,0 +1,29 @@
+#ifndef SETTINGS_CALENDARPOPUP_H
+#define SETTINGS_CALENDARPOPUP_H
+
+#include <QWidget>
+#include <QDate>
+
+class QCalendarWidget;
+
+namespace MainWindow {
+
+class CalendarPopup : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit CalendarPopup(QWidget *parent = 0);
+    void setSelectedDate(const QDate&);
+
+signals:
+    void dateSelected(const QDate& date = QDate());
+
+private:
+    void resetDate();
+
+    QCalendarWidget* m_calendar;
+};
+
+} // namespace Settings
+
+#endif // SETTINGS_CALENDARPOPUP_H
diff --git a/MainWindow/Window.cpp b/MainWindow/Window.cpp
index c397bb1..cc8eaba 100644
--- a/MainWindow/Window.cpp
+++ b/MainWindow/Window.cpp
@@ -101,6 +101,7 @@
 #  include "Exif/Database.h"
 #endif
 
+#include "BirthDatesDialog.h"
 #include "FeatureDialog.h"
 
 #include <krun.h>
@@ -869,6 +870,9 @@ void MainWindow::Window::setupMenuBar()
     _AutoStackImages = actionCollection()->addAction( QString::fromLatin1( \
                "autoStack" ), this, SLOT (slotAutoStackImages()) );
     _AutoStackImages->setText( i18n("Automatically Stack Selected Images...") );
 
+    KAction* editBirthDates = actionCollection()->addAction( \
QString::fromUtf8("editBirthDates"), this, SLOT(editBirthDates())); +    \
editBirthDates->setText(i18n("Edit Birth Dates...")); +
     a = actionCollection()->addAction( QString::fromLatin1("buildThumbs"), this, \
SLOT(slotBuildThumbnails()) );  a->setText( i18n("Build Thumbnails") );
 
@@ -1763,6 +1767,12 @@ void MainWindow::Window::mergeDuplicates()
     merger->show();
 }
 
+void MainWindow::Window::editBirthDates()
+{
+    MainWindow::BirthDatesDialog dialog;
+    dialog.exec();
+}
+
 void MainWindow::Window::createSarchBar()
 {
     // Set up the search tool bar
diff --git a/MainWindow/Window.h b/MainWindow/Window.h
index 04b9cfc..3fb8a66 100644
--- a/MainWindow/Window.h
+++ b/MainWindow/Window.h
@@ -157,6 +157,7 @@ protected slots:
     void useNextVideoThumbnail();
     void usePreviousVideoThumbnail();
     void mergeDuplicates();
+    void editBirthDates();
 
 protected:
     void configureImages( bool oneAtATime );
diff --git a/Utilities/Util.cpp b/Utilities/Util.cpp
index b2c0179..c918324 100644
--- a/Utilities/Util.cpp
+++ b/Utilities/Util.cpp
@@ -137,24 +137,25 @@ QString Utilities::createInfoText( DB::ImageInfoPtr info, QMap< \
                int,QPair<QStrin
             const StringSet items = info->itemsOfCategory( categoryName );
             if (!items.empty()) {
                 QString title = QString::fromLatin1( "<b>%1: </b> " ).arg( \
                (*categoryIt)->text() );
-                QString info;
+                QString infoText;
                 bool first = true;
                 for( StringSet::const_iterator it2 = items.constBegin(); it2 != \
items.constEnd(); ++it2 ) {  QString item = *it2;
                     if ( first )
                         first = false;
                     else
-                        info += QString::fromLatin1( ", " );
+                        infoText += QString::fromLatin1( ", " );
 
                     if ( linkMap ) {
                         ++link;
                         (*linkMap)[link] = QPair<QString,QString>( categoryName, \
                item );
-                        info += QString::fromLatin1( "<a href=\"%1\">%2</a>").arg( \
link ).arg( item ); +                        infoText += QString::fromLatin1( "<a \
href=\"%1\">%2</a>").arg( link ).arg( item ); +                        infoText += \
formatAge(*categoryIt, item, info);  }
                     else
-                        info += item;
+                        infoText += item;
                 }
-                AddNonEmptyInfo(title, info, &result);
+                AddNonEmptyInfo(title, infoText, &result);
             }
         }
     }
@@ -210,6 +211,91 @@ QString Utilities::createInfoText( DB::ImageInfoPtr info, QMap< \
int,QPair<QStrin  return result;
 }
 
+using DateSpec = QPair<int, char>;
+DateSpec dateDiff(const QDate& birthDate, const QDate& imageDate)
+{
+    const int bday = birthDate.day();
+    const int iday = imageDate.day();
+    const int bmonth = birthDate.month();
+    const int imonth = imageDate.month();
+    const int byear = birthDate.year();
+    const int iyear = imageDate.year();
+
+    // Image before birth
+    const int diff = birthDate.daysTo(imageDate);
+    if (diff < 0)
+        return qMakePair(0, 'I');
+
+    if (diff < 31)
+        return qMakePair(diff, 'D');
+
+    int months = (iyear-byear)*12;
+    months += (imonth-bmonth);
+    months += (iday >= bday) ? 0 : -1;
+
+    if ( months < 24)
+        return qMakePair(months, 'M');
+    else
+        return qMakePair(months/12, 'Y');
+}
+
+QString formatDate(const DateSpec& date)
+{
+    if (date.second == 'I')
+        return {};
+    else if (date.second == 'D')
+        return i18np("1 day", "%1 days", date.first);
+    else if (date.second == 'M')
+        return i18np("1 month", "%1 month", date.first);
+    else
+        return i18np("1 year", "%1 years", date.first);
+}
+
+void test() {
+    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1971,7,11))) == \
QString::fromLatin1("0 days")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1971,8,10))) == QString::fromLatin1("30 days")); +    \
Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1971,8,11))) == \
QString::fromLatin1("1 month")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1971,8,12))) == QString::fromLatin1("1 month")); +    \
Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1971,9,10))) == \
QString::fromLatin1("1 month")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1971,9,11))) == QString::fromLatin1("2 month")); +    \
Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1972,6,10))) == \
QString::fromLatin1("10 month")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1972,6,11))) == QString::fromLatin1("11 month")); +    \
Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1972,6,12))) == \
QString::fromLatin1("11 month")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1972,7,10))) == QString::fromLatin1("11 month")); +    \
Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1972,7,11))) == \
QString::fromLatin1("12 month")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1972,7,12))) == QString::fromLatin1("12 month")); +    \
Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), QDate(1972,12,11))) == \
QString::fromLatin1("17 month")); +    Q_ASSERT(formatDate(dateDiff(QDate(1971,7,11), \
QDate(1973,7,11))) == QString::fromLatin1("2 years")); +}
+
+QString Utilities::formatAge(DB::CategoryPtr category, const QString &item, \
DB::ImageInfoPtr info) +{
+    // test(); // I wish I could get my act together to set up a test suite.
+    const QDate birthDate = category->birthDate(item);
+    const QDate start = info->date().start().date();
+    const QDate end = info->date().end().date();
+
+    if (birthDate.isNull() || start.isNull())
+        return {};
+
+    if ( start == end)
+        return QString::fromUtf8(" (%1)").arg(formatDate(dateDiff(birthDate, \
start))); +    else {
+        DateSpec lower = dateDiff(birthDate,start);
+        DateSpec upper = dateDiff(birthDate,end);
+        if (lower == upper)
+            return QString::fromUtf8(" (%1)").arg(formatDate(lower));
+        else if (lower.second == 'I')
+            return QString::fromUtf8(" (&lt; %1)").arg(formatDate(upper));
+        else {
+            if (lower.second == upper.second)
+                return QString::fromUtf8(" \
(%1-%2)").arg(lower.first).arg(formatDate(upper)); +            else
+                return QString::fromUtf8(" \
(%1-%2)").arg(formatDate(lower)).arg(formatDate(upper)); +        }
+    }
+}
+
 void Utilities::checkForBackupFile( const QString& fileName, const QString& message \
)  {
     QString backupName = QFileInfo( fileName ).absolutePath() + \
                QString::fromLatin1("/.#") + QFileInfo( fileName ).fileName();
diff --git a/Utilities/Util.h b/Utilities/Util.h
index b6b4b03..df81c3e 100644
--- a/Utilities/Util.h
+++ b/Utilities/Util.h
@@ -37,6 +37,7 @@ namespace DB
 namespace Utilities
 {
 QString createInfoText( DB::ImageInfoPtr info, QMap<int, QPair<QString,QString> >* \
); +QString formatAge(DB::CategoryPtr category,const QString& item, DB::ImageInfoPtr \
info);  void checkForBackupFile( const QString& fileName, const QString& message = \
QString() );  bool ctrlKeyDown();
 bool copy( const QString& from, const QString& to );
diff --git a/XMLDB/FileReader.cpp b/XMLDB/FileReader.cpp
index db9167f..faf67fb 100644
--- a/XMLDB/FileReader.cpp
+++ b/XMLDB/FileReader.cpp
@@ -167,6 +167,7 @@ void XMLDB::FileReader::loadCategories( ReaderPtr reader )
     static QString _positionable_ = QString::fromUtf8("positionable");
     static QString _value_ = QString::fromUtf8("value");
     static QString _id_ = QString::fromUtf8("id");
+    static QString _birthDate_ = QString::fromUtf8("birthDate");
     static QString _Categories_ = QString::fromUtf8("Categories");
     static QString _Category_ = QString::fromUtf8("Category");
 
@@ -199,6 +200,8 @@ void XMLDB::FileReader::loadCategories( ReaderPtr reader )
                     int id = reader->attribute(_id_).toInt();
                     static_cast<XMLCategory*>(cat.data())->setIdMapping( value, id \
);  }
+                if (reader->hasAttribute(_birthDate_))
+                    \
cat->setBirthDate(value,QDate::fromString(reader->attribute(_birthDate_), \
Qt::ISODate));  items.append( value );
                 reader->readEndElement();
             }
diff --git a/XMLDB/FileWriter.cpp b/XMLDB/FileWriter.cpp
index a57e184..ad9db75 100644
--- a/XMLDB/FileWriter.cpp
+++ b/XMLDB/FileWriter.cpp
@@ -129,6 +129,9 @@ void XMLDB::FileWriter::saveCategories( QXmlStreamWriter& writer \
                )
                     writer.writeAttribute( QString::fromLatin1("value"), \
categoryName );  writer.writeAttribute( QString::fromLatin1( "id" ),
                                            \
QString::number(static_cast<XMLCategory*>( category.data() )->idForName( categoryName \
) )); +                    QDate birthDate = category->birthDate(categoryName);
+                    if (!birthDate.isNull())
+                        writer.writeAttribute( QString::fromUtf8("birthDate"), \
birthDate.toString(Qt::ISODate) );  }
             }
         }
diff --git a/XMLDB/XMLCategory.cpp b/XMLDB/XMLCategory.cpp
index 66c171d..40f31d8 100644
--- a/XMLDB/XMLCategory.cpp
+++ b/XMLDB/XMLCategory.cpp
@@ -179,5 +179,15 @@ void XMLDB::XMLCategory::setShouldSave( bool b)
     _shouldSave = b;
 }
 
+void XMLDB::XMLCategory::setBirthDate(const QString &item, const QDate &birthDate)
+{
+    _birthDates.insert(item,birthDate);
+}
+
+QDate XMLDB::XMLCategory::birthDate(const QString &item) const
+{
+    return _birthDates[item];
+}
+
 #include "XMLCategory.moc"
 // vi:expandtab:tabstop=4 shiftwidth=4:
diff --git a/XMLDB/XMLCategory.h b/XMLDB/XMLCategory.h
index fbb0e22..5128277 100644
--- a/XMLDB/XMLCategory.h
+++ b/XMLDB/XMLCategory.h
@@ -63,6 +63,8 @@ namespace XMLDB {
 
         bool shouldSave();
         void setShouldSave( bool b);
+        void setBirthDate(const QString& item, const QDate& birthDate) override;
+        QDate birthDate(const QString& item) const override;
 
     private:
         QString _name;
@@ -76,6 +78,7 @@ namespace XMLDB {
         QStringList _items;
         QMap<QString,int> _idMap;
         QMap<int,QString> _nameMap;
+        QMap<QString,QDate> _birthDates;
 
         bool _shouldSave;
     };
diff --git a/kphotoalbumui.rc b/kphotoalbumui.rc
index c5cc996..2a19948 100644
--- a/kphotoalbumui.rc
+++ b/kphotoalbumui.rc
@@ -1,5 +1,5 @@
 <!DOCTYPE kpartgui>
-<kpartgui name="kphotoalbum" version="41">
+<kpartgui name="kphotoalbum" version="42">
   <MenuBar>
     <Menu name="file">
       <Action name="exportHTML"/>
@@ -62,6 +62,7 @@
       <Action name="reReadExifInfo" />
       <Action name="sortAllImages" />
       <Action name="autoStack" />
+      <Action name="editBirthDates" />
       <Separator/>
       <Action name="removeAllThumbs"/>
       <Action name="buildThumbs"/>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic