Ejemplo n.º 1
1
void TagModificationHelper::slotTagDelete(TAlbum* t)
{
    if (!t || t->isRoot())
    {
        return;
    }

    AlbumPointer<TAlbum> tag(t);

    // find number of subtags
    int children = 0;
    AlbumIterator iter(tag);

    while (iter.current())
    {
        ++children;
        ++iter;
    }

    // ask for deletion of children
    if (children)
    {
        int result = KMessageBox::warningContinueCancel(d->dialogParent,
                                                        i18np("Tag '%2' has one subtag. "
                                                              "Deleting this will also delete "
                                                              "the subtag. "
                                                              "Do you want to continue?",
                                                              "Tag '%2' has %1 subtags. "
                                                              "Deleting this will also delete "
                                                              "the subtags. "
                                                              "Do you want to continue?",
                                                              children,
                                                              tag->title()));

        if (result != KMessageBox::Continue || !tag)
        {
            return;
        }
    }

    QString message;
    QList<qlonglong> assignedItems = DatabaseAccess().db()->getItemIDsInTag(tag->id());

    if (!assignedItems.isEmpty())
    {
        message = i18np("Tag '%2' is assigned to one item. "
                        "Do you want to continue?",
                        "Tag '%2' is assigned to %1 items. "
                        "Do you want to continue?",
                        assignedItems.count(), tag->title());
    }
    else
    {
        message = i18n("Delete '%1' tag?", tag->title());
    }

    int result = KMessageBox::warningContinueCancel(0, message,
                                                    i18n("Delete Tag"),
                                                    KGuiItem(i18n("Delete"),
                                                             "edit-delete"));

    if (result == KMessageBox::Continue && tag)
    {
        emit aboutToDeleteTag(tag);
        QString errMsg;

        if (!AlbumManager::instance()->deleteTAlbum(tag, errMsg))
        {
            KMessageBox::error(0, errMsg);
        }
    }
}
Ejemplo n.º 2
0
void ImageScanner::scanImageInformation()
{
    DatabaseFields::ImageInformation dbFields = DatabaseFields::ImageInformationAll;
    QVariantList infos;

    if (m_scanMode == NewScan || m_scanMode == Rescan)
    {
        MetadataFields fields;
        fields << MetadataInfo::Rating
               << MetadataInfo::CreationDate
               << MetadataInfo::DigitizationDate
               << MetadataInfo::Orientation;
        QVariantList metadataInfos = m_metadata.getMetadataFields(fields);

        // creation date: fall back to file system property
        if (metadataInfos[1].isNull() || !metadataInfos[1].toDateTime().isValid())
        {
            metadataInfos[1] = creationDateFromFilesystem(m_fileInfo);
        }

        // Some fields should only be overwritten if set in metadata
        if (m_scanMode == Rescan)
        {
            if (metadataInfos[0].isNull() || metadataInfos[0].toInt() == -1)
            {
                dbFields &= ~DatabaseFields::Rating;
                metadataInfos.removeAt(0);
            }
        }

        infos << metadataInfos;
    }

    QSize size = m_img.size();
    infos << size.width()
          << size.height()
          << detectFormat()
          << m_img.originalBitDepth()
          << m_img.originalColorModel();

    if (m_scanMode == NewScan)
    {
        DatabaseAccess().db()->addImageInformation(m_scanInfo.id, infos, dbFields);
    }
    else if (m_scanMode == Rescan)
    {
        DatabaseAccess().db()->changeImageInformation(m_scanInfo.id, infos, dbFields);
    }
    else // ModifiedScan
    {
        // Does _not_ update rating and orientation!
        DatabaseAccess().db()->changeImageInformation(m_scanInfo.id, infos,
                DatabaseFields::Width      |
                DatabaseFields::Height     |
                DatabaseFields::Format     |
                DatabaseFields::ColorDepth |
                DatabaseFields::ColorModel);
    }
}
Ejemplo n.º 3
0
void ImageScanner::scanTags()
{
    // Check Keywords tag paths.

    QVariant var         = m_metadata.getMetadataField(MetadataInfo::Keywords);
    QStringList keywords = var.toStringList();

    if (!keywords.isEmpty())
    {
        // get tag ids, create if necessary
        QList<int> tagIds = TagsCache::instance()->getOrCreateTags(keywords);
        DatabaseAccess().db()->addTagsToItems(QList<qlonglong>() << m_scanInfo.id, tagIds);
    }

    // Check Pick Label tag.

    int pickId = m_metadata.getImagePickLabel();
    if (pickId != -1)
    {
        kDebug() << "Pick Label found : " << pickId;

        int tagId = TagsCache::instance()->getTagForPickLabel((PickLabel)pickId);
        if (tagId)
        {
            DatabaseAccess().db()->addTagsToItems(QList<qlonglong>() << m_scanInfo.id, QList<int>() << tagId);
            kDebug() << "Assigned Pick Label Tag  : " << tagId;
        }
        else
        {
            kDebug() << "Cannot find Pick Label Tag for : " << pickId;
        }
    }

    // Check Color Label tag.

    int colorId = m_metadata.getImageColorLabel();
    if (colorId != -1)
    {
        kDebug() << "Color Label found : " << colorId;

        int tagId = TagsCache::instance()->getTagForColorLabel((ColorLabel)colorId);
        if (tagId)
        {
            DatabaseAccess().db()->addTagsToItems(QList<qlonglong>() << m_scanInfo.id, QList<int>() << tagId);
            kDebug() << "Assigned Color Label Tag  : " << tagId;
        }
        else
        {
            kDebug() << "Cannot find Color Label Tag for : " << colorId;
        }
    }
}
Ejemplo n.º 4
0
bool ImageScanner::resolveImageHistory(qlonglong imageId, const QString& historyXml,
                                       QList<qlonglong>* needTaggingIds)
{
    /** Stage 2 of history scanning */

    if (historyXml.isNull())
    {
        return true;    // "true" means nothing is left to resolve
    }

    DImageHistory history = DImageHistory::fromXml(historyXml);

    if (history.isNull())
    {
        return true;
    }

    ImageHistoryGraph graph;
    graph.addScannedHistory(history, imageId);

    if (!graph.hasEdges())
    {
        return true;
    }

    QPair<QList<qlonglong>, QList<qlonglong> > cloud = graph.relationCloudParallel();
    DatabaseAccess().db()->addImageRelations(cloud.first, cloud.second, DatabaseRelation::DerivedFrom);

    int needResolvingTag = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::needResolvingHistory());
    int needTaggingTag   = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::needTaggingHistoryGraph());

    // remove the needResolvingHistory tag from all images in graph
    DatabaseAccess().db()->removeTagsFromItems(graph.allImageIds(), QList<int>() << needResolvingTag);

    // mark a single image from the graph (sufficient for find the full relation cloud)
    QList<ImageInfo> roots = graph.rootImages();

    if (!roots.isEmpty())
    {
        DatabaseAccess().db()->addItemTag(roots.first().id(), needTaggingTag);

        if (needTaggingIds)
        {
            *needTaggingIds << roots.first().id();
        }
    }

    return !graph.hasUnresolvedEntries();
}
Ejemplo n.º 5
0
void ImageScanner::updateImage()
{
    prepareImage();

    DatabaseAccess().db()->updateItem(m_scanInfo.id, m_scanInfo.category,
                                      m_scanInfo.modificationDate, m_scanInfo.fileSize, m_scanInfo.uniqueHash);
}
Ejemplo n.º 6
0
void ImageLister::listAlbum(ImageListerReceiver* const receiver, int albumRootId, const QString& album)
{
    if (d->listOnlyAvailableImages)
    {
        if (!CollectionManager::instance()->locationForAlbumRootId(albumRootId).isAvailable())
        {
            return;
        }
    }

    QList<QVariant> albumIds;

    if (d->recursive)
    {
        QList<int> intAlbumIds = DatabaseAccess().db()->getAlbumAndSubalbumsForPath(albumRootId, album);

        if (intAlbumIds.isEmpty())
        {
            return;
        }

        foreach(int id, intAlbumIds)
        {
            albumIds << id;
        }
    }
Ejemplo n.º 7
0
void TagProperties::removeProperty(const QString& key, const QString& value)
{
    if (d->properties.contains(key, value))
    {
        DatabaseAccess().db()->removeTagProperties(d->tagId, key, value);
        d->properties.remove(key, value);
    }
}
Ejemplo n.º 8
0
void TagProperties::removeProperties(const QString& key)
{
    if (!d->isNull() && d->properties.contains(key))
    {
        DatabaseAccess().db()->removeTagProperties(d->tagId, key);
        d->properties.remove(key);
    }
}
Ejemplo n.º 9
0
void ImageScanner::scanImageMetadata()
{
    QVariantList metadataInfos = m_metadata.getMetadataFields(allImageMetadataFields());

    if (hasValidField(metadataInfos))
    {
        DatabaseAccess().db()->addImageMetadata(m_scanInfo.id, metadataInfos);
    }
}
Ejemplo n.º 10
0
void TagProperties::addProperty(const QString& key, const QString& value)
{
    if (d->isNull() || d->properties.contains(key, value))
    {
        return;
    }

    d->properties.insert(key, value);
    DatabaseAccess().db()->addTagProperty(d->tagId, key, value);
}
Ejemplo n.º 11
0
void ImageScanner::scanImageHistoryIfModified()
{
    // If a file has a modified history, it must have a new UUID
    QString previousUuid = DatabaseAccess().db()->getImageUuid(m_scanInfo.id);
    QString currentUuid  = m_metadata.getImageUniqueId();

    if (previousUuid != currentUuid)
    {
        scanImageHistory();
    }
}
Ejemplo n.º 12
0
bool ImageScanner::scanFromIdenticalFile()
{
    // Get a list of other images that are identical. Source image shall not be included.
    QList<ItemScanInfo> candidates = DatabaseAccess().db()->getIdenticalFiles(m_scanInfo.uniqueHash,
                                     m_scanInfo.fileSize, m_scanInfo.id);

    if (!candidates.isEmpty())
    {
        // Sort by priority, as implemented by custom lessThan()
        qStableSort(candidates.begin(), candidates.end(), lessThanForIdentity);

        kDebug() << "Recognized" << m_fileInfo.filePath() << "as identical to item" << candidates.first().id;

        // Copy attributes.
        // Todo for the future is to worry about syncing identical files.
        DatabaseAccess().db()->copyImageAttributes(candidates.first().id, m_scanInfo.id);
        return true;
    }

    return false;
}
Ejemplo n.º 13
0
void TagProperties::setProperty(const QString& key, const QString& value)
{
    if (d->properties.contains(key, value) && d->properties.count(key) == 1)
    {
        return;
    }

    // for single entries in db, this can of course be optimized using a single UPDATE WHERE
    removeProperties(key);
    d->properties.insert(key, value);
    DatabaseAccess().db()->addTagProperty(d->tagId, key, value);
}
Ejemplo n.º 14
0
void ImageScanner::addImage(int albumId)
{
    prepareImage();

    m_scanInfo.albumID          = albumId;
    m_scanInfo.status           = DatabaseItem::Visible;

    kDebug() << "Adding new item" << m_fileInfo.filePath();
    m_scanInfo.id               = DatabaseAccess().db()->addItem(m_scanInfo.albumID, m_scanInfo.itemName,
                                  m_scanInfo.status, m_scanInfo.category,
                                  m_scanInfo.modificationDate, m_scanInfo.fileSize,
                                  m_scanInfo.uniqueHash);
}
Ejemplo n.º 15
0
void AlbumPropsEdit::slotDateHighButtonClicked()
{
    setCursor(Qt::WaitCursor);

    QDate highDate = DatabaseAccess().db()->getAlbumHighestDate(d->album->id());

    setCursor(Qt::ArrowCursor);

    if (highDate.isValid())
    {
        d->datePicker->setDate(highDate);
    }
}
Ejemplo n.º 16
0
void ImageScanner::scanImageHistory()
{
    /** Stage 1 of history scanning */

    QString historyXml = m_metadata.getImageHistory();

    if (!historyXml.isEmpty())
    {
        DatabaseAccess().db()->setImageHistory(m_scanInfo.id, historyXml);
        // Delay history resolution by setting this tag:
        // Resolution depends on the presence of other images, possibly only when the scanning process has finished
        DatabaseAccess().db()->addItemTag(m_scanInfo.id, TagsCache::instance()->
                                          getOrCreateInternalTag(InternalTagName::needResolvingHistory()));
        m_hasHistoryToResolve = true;
    }

    QString uuid = m_metadata.getImageUniqueId();

    if (!uuid.isNull())
    {
        DatabaseAccess().db()->setImageUuid(m_scanInfo.id, uuid);
    }
}
Ejemplo n.º 17
0
void AlbumPropsEdit::slotDateAverageButtonClicked()
{
    setCursor(Qt::WaitCursor);

    QDate avDate = DatabaseAccess().db()->getAlbumAverageDate(d->album->id());

    setCursor(Qt::ArrowCursor);

    if (avDate.isValid())
    {
        d->datePicker->setDate(avDate);
    }
    else
    {
        KMessageBox::error(this,
                           i18n("Could not calculate an average."),
                           i18n("Could Not Calculate Average"));
    }
}
Ejemplo n.º 18
0
void PatientManager::readDatabase()
{
    QList<Patient> patients = DatabaseAccess().db()->findPatients();
    emit progressStarted(patients.size());
    QHash<int, int> oldIds = d->patientIdHash;
    QList<Patient::Ptr> newPatientList;
    foreach (Patient data, patients)
    {
        int index = d->patientIdHash.value(data.id, -1);
        oldIds.remove(data.id);
        if (index == -1)
        {
            Patient::Ptr p = createPatient(data);
            loadData(p);
            emit patientAdded(d->patients.size()-1, p);
        }
        else
        {
            loadData(d->patients[index]);
        }
        emit progressValue(d->patients.size());
    }
Ejemplo n.º 19
0
void ImageScanner::scanImagePosition()
{
    // This list must reflect the order required by AlbumDB::addImagePosition
    MetadataFields fields;
    fields << MetadataInfo::Latitude
           << MetadataInfo::LatitudeNumber
           << MetadataInfo::Longitude
           << MetadataInfo::LongitudeNumber
           << MetadataInfo::Altitude
           << MetadataInfo::PositionOrientation
           << MetadataInfo::PositionTilt
           << MetadataInfo::PositionRoll
           << MetadataInfo::PositionAccuracy
           << MetadataInfo::PositionDescription;

    QVariantList metadataInfos = m_metadata.getMetadataFields(fields);

    if (hasValidField(metadataInfos))
    {
        DatabaseAccess().db()->addImagePosition(m_scanInfo.id, metadataInfos);
    }
}
Ejemplo n.º 20
0
void ImageWindow::slotContextMenu()
{
    if (m_contextMenu)
    {
        TagsPopupMenu*   assignTagsMenu = 0;
        TagsPopupMenu*   removeTagsMenu = 0;

        // Bulk assignment/removal of tags --------------------------

        QList<qlonglong> idList;
        idList << d->currentImageInfo.id();

        assignTagsMenu = new TagsPopupMenu(idList, TagsPopupMenu::RECENTLYASSIGNED, this);
        removeTagsMenu = new TagsPopupMenu(idList, TagsPopupMenu::REMOVE, this);
        assignTagsMenu->menuAction()->setText(i18n("Assign Tag"));
        removeTagsMenu->menuAction()->setText(i18n("Remove Tag"));

        m_contextMenu->addSeparator();

        m_contextMenu->addMenu(assignTagsMenu);
        m_contextMenu->addMenu(removeTagsMenu);

        connect(assignTagsMenu, SIGNAL(signalTagActivated(int)),
                this, SLOT(slotAssignTag(int)));

        connect(removeTagsMenu, SIGNAL(signalTagActivated(int)),
                this, SLOT(slotRemoveTag(int)));

        connect(assignTagsMenu, SIGNAL(signalPopupTagsView()),
                d->rightSideBar, SLOT(slotPopupTagsView()));

        if (!DatabaseAccess().db()->hasTags( idList ))
        {
            m_contextMenu->menuAction()->setEnabled(false);
        }

        m_contextMenu->addSeparator();

        // Assign Labels -------------------------------------------

        KMenu* menuLabels           = new KMenu(i18n("Assign Labels"), m_contextMenu);
        PickLabelMenuAction* pmenu  = new PickLabelMenuAction(m_contextMenu);
        ColorLabelMenuAction* cmenu = new ColorLabelMenuAction(m_contextMenu);
        RatingMenuAction* rmenu     = new RatingMenuAction(m_contextMenu);
        menuLabels->addAction(pmenu);
        menuLabels->addAction(cmenu);
        menuLabels->addAction(rmenu);
        m_contextMenu->addMenu(menuLabels);

        connect(pmenu, SIGNAL(signalPickLabelChanged(int)),
                this, SLOT(slotAssignPickLabel(int)));

        connect(cmenu, SIGNAL(signalColorLabelChanged(int)),
                this, SLOT(slotAssignColorLabel(int)));

        connect(rmenu, SIGNAL(signalRatingChanged(int)),
                this, SLOT(slotAssignRating(int)));

        // --------------------------------------------------------------

        m_contextMenu->exec(QCursor::pos());

        delete assignTagsMenu;
        delete removeTagsMenu;
        delete cmenu;
        delete pmenu;
        delete rmenu;
        delete menuLabels;
    }
}
Ejemplo n.º 21
0
void TagModificationHelper::slotMultipleTagDel(QList<TAlbum* >& tags)
{
    QString tagWithChildrens;
    QString tagWithImages;
    QMultiMap<int, TAlbum*> sortedTags;

    foreach(TAlbum* const t, tags)
    {

        if (!t || t->isRoot())
        {
            continue;
        }

        AlbumPointer<TAlbum> tag(t);

        // find number of subtags
        int children = 0;
        AlbumIterator iter(tag);

        while (iter.current())
        {
            ++children;
            ++iter;
        }

        if(children)
            tagWithChildrens.append(tag->title() + QString(" "));

        QList<qlonglong> assignedItems = DatabaseAccess().db()->getItemIDsInTag(tag->id());

        if(!assignedItems.isEmpty())
            tagWithImages.append(tag->title() + QString(" "));

        /**
         * Tags must be deleted from children to parents, if we don't want
         * to step on invalid index. Use QMultiMap to order them by distance
         * to root tag
         */

        Album* parent = t;
        int depth = 0;

        while(!parent->isRoot())
        {
            parent = parent->parent();
            depth++;
        }

        sortedTags.insert(depth,tag);

    }

    // ask for deletion of children

    if (!tagWithChildrens.isEmpty())
    {
        int result = KMessageBox::warningContinueCancel(0,
                                                        i18n("Tags '%1' have one or more subtags. "
                                                             "Deleting them will also delete "
                                                             "the subtags. "
                                                             "Do you want to continue?",
                                                             tagWithChildrens));

        if (result != KMessageBox::Continue)
        {
            return;
        }
    }

    QString message;

    if (!tagWithImages.isEmpty())
    {
        message = i18n("Tags '%1' are assigned to one or more items. "
                        "Do you want to continue?",
                        tagWithImages);
    }
    else
    {
        message = i18n("Delete '%1' tag(s)?", tagWithImages);
    }

    int result = KMessageBox::warningContinueCancel(0, message,
                                                    i18n("Delete Tag"),
                                                    KGuiItem(i18n("Delete"),
                                                            "edit-delete"));

    if (result == KMessageBox::Continue)
    {
        QMultiMap<int, TAlbum*>::iterator it;
        /**
         * QMultimap doesn't provide reverse iterator, -1 is required
         * because end() points after the last element
         */
        for(it = sortedTags.end()-1; it != sortedTags.begin()-1; --it)
        {
            emit aboutToDeleteTag(it.value());
            QString errMsg;

            if (!AlbumManager::instance()->deleteTAlbum(it.value(), errMsg))
            {
                KMessageBox::error(0, errMsg);
            }
        }
    }
}
Ejemplo n.º 22
0
bool ImageScanner::resolveImageHistory(qlonglong id, QList<qlonglong>* needTaggingIds)
{
    ImageHistoryEntry history = DatabaseAccess().db()->getImageHistory(id);
    return resolveImageHistory(id, history.history, needTaggingIds);
}
Ejemplo n.º 23
0
void ImageScanner::tagImageHistoryGraph(qlonglong id)
{
    /** Stage 3 of history scanning */

    ImageInfo info(id);

    if (info.isNull())
    {
        return;
    }
    //kDebug() << "tagImageHistoryGraph" << id;

    // Load relation cloud, history of info and of all leaves of the tree into the graph, fully resolved
    ImageHistoryGraph graph = ImageHistoryGraph::fromInfo(info, ImageHistoryGraph::LoadAll, ImageHistoryGraph::NoProcessing);
    kDebug() << graph;

    int originalVersionTag     = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::originalVersion());
    int currentVersionTag      = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::currentVersion());
    int intermediateVersionTag = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::intermediateVersion());

    int needTaggingTag         = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::needTaggingHistoryGraph());

    // Remove all relevant tags
    DatabaseAccess().db()->removeTagsFromItems(graph.allImageIds(), QList<int>() << originalVersionTag
            << currentVersionTag << intermediateVersionTag << needTaggingTag);

    if (!graph.hasEdges())
    {
        return;
    }

    // get category info
    QList<qlonglong> originals, intermediates, currents;
    QHash<ImageInfo, HistoryImageId::Types> types = graph.categorize();
    QHash<ImageInfo, HistoryImageId::Types>::iterator it;

    for (it = types.begin(); it != types.end(); ++it)
    {
        kDebug() << "Image" << it.key().id() << "type" << it.value();
        HistoryImageId::Types types = it.value();

        if (types & HistoryImageId::Original)
        {
            originals << it.key().id();
        }
        if (types & HistoryImageId::Intermediate)
        {
            intermediates << it.key().id();
        }
        if (types & HistoryImageId::Current)
        {
            currents << it.key().id();
        }
    }

    if (!originals.isEmpty())
    {
        DatabaseAccess().db()->addTagsToItems(originals, QList<int>() << originalVersionTag);
    }

    if (!intermediates.isEmpty())
    {
        DatabaseAccess().db()->addTagsToItems(intermediates, QList<int>() << intermediateVersionTag);
    }

    if (!currents.isEmpty())
    {
        DatabaseAccess().db()->addTagsToItems(currents, QList<int>() << currentVersionTag);
    }
}