X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/1041f340a2ddb634476c5d84585a56c29e5a70fd..05082aed16cdf7e511d9c97d0cf07e270af493e5:/src/kitemviews/kfileitemmodelrolesupdater.cpp diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 7050d21c9..34165843f 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -33,6 +33,11 @@ #include #include +#ifdef HAVE_NEPOMUK + #include "knepomukrolesprovider_p.h" + #include "knepomukresourcewatcher_p.h" +#endif + // Required includes for subItemsCount(): #ifdef Q_WS_WIN #include @@ -62,6 +67,7 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO m_iconSizeChangedDuringPausing(false), m_rolesChangedDuringPausing(false), m_previewShown(false), + m_enlargeSmallPreviews(true), m_clearPreviews(false), m_model(model), m_iconSize(), @@ -74,6 +80,11 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO m_previewJobs(), m_changedItemsTimer(0), m_changedItems() + #ifdef HAVE_NEPOMUK + , m_nepomukResourceWatcher(0), + m_nepomukUriItems() + #endif + { Q_ASSERT(model); @@ -91,9 +102,9 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO this, SLOT(slotItemsChanged(KItemRangeList,QSet))); // Use a timer to prevent that each call of slotItemsChanged() results in a synchronous - // resolving of the roles. Postpone the resolving until no update has been done for 2 seconds. + // resolving of the roles. Postpone the resolving until no update has been done for 1 second. m_changedItemsTimer = new QTimer(this); - m_changedItemsTimer->setInterval(2000); + m_changedItemsTimer->setInterval(1000); m_changedItemsTimer->setSingleShot(true); connect(m_changedItemsTimer, SIGNAL(timeout()), this, SLOT(resolveChangedItems())); } @@ -145,7 +156,7 @@ void KFileItemModelRolesUpdater::setVisibleIndexRange(int index, int count) } } -void KFileItemModelRolesUpdater::setPreviewShown(bool show) +void KFileItemModelRolesUpdater::setPreviewsShown(bool show) { if (show == m_previewShown) { return; @@ -156,30 +167,35 @@ void KFileItemModelRolesUpdater::setPreviewShown(bool show) m_clearPreviews = true; } - if (m_paused) { - m_previewChangedDuringPausing = true; - } else { - sortAndResolveAllRoles(); - } + updateAllPreviews(); } -bool KFileItemModelRolesUpdater::isPreviewShown() const +bool KFileItemModelRolesUpdater::previewsShown() const { return m_previewShown; } -void KFileItemModelRolesUpdater::setEnabledPlugins(const QStringList& list) +void KFileItemModelRolesUpdater::setEnlargeSmallPreviews(bool enlarge) { - if (m_enabledPlugins == list) { - return; + if (enlarge != m_enlargeSmallPreviews) { + m_enlargeSmallPreviews = enlarge; + if (m_previewShown) { + updateAllPreviews(); + } } +} - m_enabledPlugins = list; - if (m_previewShown) { - if (m_paused) { - m_previewChangedDuringPausing = true; - } else { - sortAndResolveAllRoles(); +bool KFileItemModelRolesUpdater::enlargeSmallPreviews() const +{ + return m_enlargeSmallPreviews; +} + +void KFileItemModelRolesUpdater::setEnabledPlugins(const QStringList& list) +{ + if (m_enabledPlugins == list) { + m_enabledPlugins = list; + if (m_previewShown) { + updateAllPreviews(); } } } @@ -216,25 +232,49 @@ void KFileItemModelRolesUpdater::setPaused(bool paused) void KFileItemModelRolesUpdater::setRoles(const QSet& roles) { - if (roles.count() == m_roles.count()) { - bool isEqual = true; - foreach (const QByteArray& role, roles) { - if (!m_roles.contains(role)) { - isEqual = false; + if (m_roles != roles) { + m_roles = roles; + +#ifdef HAVE_NEPOMUK + // Check whether there is at least one role that must be resolved + // with the help of Nepomuk. If this is the case, a (quite expensive) + // resolving will be done in KFileItemModelRolesUpdater::rolesData() and + // the role gets watched for changes. + const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance(); + bool hasNepomukRole = false; + QSetIterator it(roles); + while (it.hasNext()) { + const QByteArray& role = it.next(); + if (rolesProvider.isNepomukRole(role)) { + hasNepomukRole = true; break; } } - if (isEqual) { - return; - } - } - m_roles = roles; + if (hasNepomukRole && !m_nepomukResourceWatcher) { + Q_ASSERT(m_nepomukUriItems.isEmpty()); + + m_nepomukResourceWatcher = new Nepomuk::ResourceWatcher(this); + connect(m_nepomukResourceWatcher, SIGNAL(propertyChanged(Nepomuk::Resource,Nepomuk::Types::Property,QVariantList,QVariantList)), + this, SLOT(applyChangedNepomukRoles(Nepomuk::Resource))); + connect(m_nepomukResourceWatcher, SIGNAL(propertyRemoved(Nepomuk::Resource,Nepomuk::Types::Property,QVariant)), + this, SLOT(applyChangedNepomukRoles(Nepomuk::Resource))); + connect(m_nepomukResourceWatcher, SIGNAL(propertyAdded(Nepomuk::Resource,Nepomuk::Types::Property,QVariant)), + this, SLOT(applyChangedNepomukRoles(Nepomuk::Resource))); + connect(m_nepomukResourceWatcher, SIGNAL(resourceCreated(Nepomuk::Resource,QList)), + this, SLOT(applyChangedNepomukRoles(Nepomuk::Resource))); + } else if (!hasNepomukRole && m_nepomukResourceWatcher) { + delete m_nepomukResourceWatcher; + m_nepomukResourceWatcher = 0; + m_nepomukUriItems.clear(); + } +#endif - if (m_paused) { - m_rolesChangedDuringPausing = true; - } else { - sortAndResolveAllRoles(); + if (m_paused) { + m_rolesChangedDuringPausing = true; + } else { + sortAndResolveAllRoles(); + } } } @@ -261,8 +301,32 @@ void KFileItemModelRolesUpdater::slotItemsInserted(const KItemRangeList& itemRan void KFileItemModelRolesUpdater::slotItemsRemoved(const KItemRangeList& itemRanges) { Q_UNUSED(itemRanges); + +#ifdef HAVE_NEPOMUK + if (m_nepomukResourceWatcher) { + // Don't let the ResourceWatcher watch for removed items + if (m_model->count() == 0) { + m_nepomukResourceWatcher->setResources(QList()); + m_nepomukUriItems.clear(); + } else { + QList newResources; + const QList oldResources = m_nepomukResourceWatcher->resources(); + foreach (const Nepomuk::Resource& resource, oldResources) { + const QUrl uri = resource.resourceUri(); + const KUrl itemUrl = m_nepomukUriItems.value(uri); + if (m_model->index(itemUrl) >= 0) { + newResources.append(resource); + } else { + m_nepomukUriItems.remove(uri); + } + } + m_nepomukResourceWatcher->setResources(newResources); + } + } +#endif + m_firstVisibleIndex = 0; - m_lastVisibleIndex = -1; + m_lastVisibleIndex = -1; if (!hasPendingRoles()) { return; } @@ -330,7 +394,34 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPi const int slashIndex = mimeType.indexOf(QLatin1Char('/')); const QString mimeTypeGroup = mimeType.left(slashIndex); if (mimeTypeGroup == QLatin1String("image")) { - KPixmapModifier::applyFrame(scaledPixmap, m_iconSize); + if (m_enlargeSmallPreviews) { + KPixmapModifier::applyFrame(scaledPixmap, m_iconSize); + } else { + // Assure that small previews don't get enlarged. Instead they + // should be shown centered within the frame. + const QSize contentSize = KPixmapModifier::sizeInsideFrame(m_iconSize); + const bool enlargingRequired = scaledPixmap.width() < contentSize.width() && + scaledPixmap.height() < contentSize.height(); + if (enlargingRequired) { + QSize frameSize = scaledPixmap.size(); + frameSize.scale(m_iconSize, Qt::KeepAspectRatio); + + QPixmap largeFrame(frameSize); + largeFrame.fill(Qt::transparent); + + KPixmapModifier::applyFrame(largeFrame, frameSize); + + QPainter painter(&largeFrame); + painter.drawPixmap((largeFrame.width() - scaledPixmap.width()) / 2, + (largeFrame.height() - scaledPixmap.height()) / 2, + scaledPixmap); + scaledPixmap = largeFrame; + } else { + // The image must be shrinked as it is too large to fit into + // the available icon size + KPixmapModifier::applyFrame(scaledPixmap, m_iconSize); + } + } } else { KPixmapModifier::scale(scaledPixmap, m_iconSize); } @@ -429,10 +520,36 @@ void KFileItemModelRolesUpdater::resolveChangedItems() itemRanges.append(KItemRange(index, 1)); } } + m_changedItems.clear(); startUpdating(itemRanges); } +void KFileItemModelRolesUpdater::applyChangedNepomukRoles(const Nepomuk::Resource& resource) +{ +#ifdef HAVE_NEPOMUK + const KUrl itemUrl = m_nepomukUriItems.value(resource.resourceUri()); + const KFileItem item = m_model->fileItem(itemUrl); + QHash data = rolesData(item); + + const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance(); + QHashIterator it(rolesProvider.roleValues(resource, m_roles)); + while (it.hasNext()) { + it.next(); + data.insert(it.key(), it.value()); + } + + disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet)), + this, SLOT(slotItemsChanged(KItemRangeList,QSet))); + const int index = m_model->index(item); + m_model->setData(index, data); + connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet)), + this, SLOT(slotItemsChanged(KItemRangeList,QSet))); +#else + Q_UNUSED(resource); +#endif +} + void KFileItemModelRolesUpdater::startUpdating(const KItemRangeList& itemRanges) { // If no valid index range is given assume that all items are visible. @@ -491,7 +608,7 @@ void KFileItemModelRolesUpdater::startPreviewJob(const KFileItemList& items) // worst case) might block the application for several seconds. To prevent such // a blocking the MIME-type of the items will determined until the MaxBlockTimeout // has been reached and only those items will get passed. As soon as the MIME-type - // has been resolved once KIO::filePreview() can already access the resolved + // has been resolved once KIO::PreviewJob() can already access the resolved // MIME-type in a fast way. QElapsedTimer timer; timer.start(); @@ -508,7 +625,8 @@ void KFileItemModelRolesUpdater::startPreviewJob(const KFileItemList& items) break; } } - KJob* job = KIO::filePreview(itemSubSet, cacheSize, &m_enabledPlugins); + KIO::PreviewJob* job = new KIO::PreviewJob(itemSubSet, cacheSize, &m_enabledPlugins); + job->setIgnoreMaximumSize(items.first().isLocalFile()); connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), this, SLOT(slotGotPreview(KFileItem,QPixmap))); @@ -722,7 +840,7 @@ bool KFileItemModelRolesUpdater::applyResolvedRoles(const KFileItem& item, Resol data.insert("iconName", item.iconName()); if (m_clearPreviews) { - data.insert("iconPixmap", QString()); + data.insert("iconPixmap", QPixmap()); } disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet)), @@ -764,6 +882,35 @@ QHash KFileItemModelRolesUpdater::rolesData(const KFileIte data.insert("iconOverlays", item.overlays()); +#ifdef HAVE_NEPOMUK + if (m_nepomukResourceWatcher) { + const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance(); + Nepomuk::Resource resource(item.url()); + QHashIterator it(rolesProvider.roleValues(resource, m_roles)); + while (it.hasNext()) { + it.next(); + data.insert(it.key(), it.value()); + } + + QUrl uri = resource.resourceUri(); + if (uri.isEmpty()) { + // TODO: Is there another way to explicitly create a resource? + // We need a resource to be able to track it for changes. + resource.setRating(0); + uri = resource.resourceUri(); + } + if (!uri.isEmpty() && !m_nepomukUriItems.contains(uri)) { + // TODO: Calling stop()/start() is a workaround until + // ResourceWatcher has been fixed. + m_nepomukResourceWatcher->stop(); + m_nepomukResourceWatcher->addResource(resource); + m_nepomukResourceWatcher->start(); + + m_nepomukUriItems.insert(uri, item.url()); + } + } +#endif + return data; } @@ -853,4 +1000,13 @@ int KFileItemModelRolesUpdater::subItemsCount(const QString& path) const #endif } +void KFileItemModelRolesUpdater::updateAllPreviews() +{ + if (m_paused) { + m_previewChangedDuringPausing = true; + } else { + sortAndResolveAllRoles(); + } +} + #include "kfileitemmodelrolesupdater.moc"