mirror of
https://invent.kde.org/system/dolphin
synced 2024-09-12 12:54:29 +00:00
Allow showing Nepomuk metadata inside views
Metadata like image-size, rating, comments, tags, ... can be shown now in the view (e.g. as column in the Details mode). Still open: The rating-information needs to be shown as stars. In the context of this feature also the following bugs have been fixed: - Fix visual glitches in the header of the Details mode - Improve the minimum column width calculation to respect also the headling and not only the content BUG: 296782 FIXED-IN: 4.9.0
This commit is contained in:
parent
aced85db1f
commit
a4ede4e0eb
|
@ -67,6 +67,13 @@ set(dolphinprivate_LIB_SRCS
|
|||
views/zoomlevelinfo.cpp
|
||||
)
|
||||
|
||||
if (Nepomuk_FOUND)
|
||||
set(dolphinprivate_LIB_SRCS
|
||||
${dolphinprivate_LIB_SRCS}
|
||||
kitemviews/knepomukrolesprovider.cpp
|
||||
)
|
||||
endif (Nepomuk_FOUND)
|
||||
|
||||
kde4_add_kcfg_files(dolphinprivate_LIB_SRCS
|
||||
settings/dolphin_compactmodesettings.kcfgc
|
||||
settings/dolphin_directoryviewpropertysettings.kcfgc
|
||||
|
@ -80,18 +87,16 @@ kde4_add_library(dolphinprivate SHARED ${dolphinprivate_LIB_SRCS})
|
|||
|
||||
target_link_libraries(dolphinprivate ${KDE4_KFILE_LIBS} konq ${KDE4_KNEWSTUFF3_LIBS})
|
||||
if (Nepomuk_FOUND)
|
||||
target_link_libraries(dolphinprivate ${NEPOMUK_LIBRARIES} ${NEPOMUK_QUERY_LIBRARIES} nepomukutils ${SOPRANO_LIBRARIES})
|
||||
target_link_libraries(dolphinprivate ${NEPOMUK_LIBRARIES} ${NEPOMUK_QUERY_LIBRARIES} nepomukutils ${SOPRANO_LIBRARIES})
|
||||
endif (Nepomuk_FOUND)
|
||||
|
||||
if(X11_Xrender_FOUND)
|
||||
target_link_libraries(dolphinprivate ${X11_Xrender_LIB} )
|
||||
target_link_libraries(dolphinprivate ${X11_Xrender_LIB} )
|
||||
endif(X11_Xrender_FOUND)
|
||||
|
||||
|
||||
|
||||
set_target_properties(dolphinprivate PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} )
|
||||
install(TARGETS dolphinprivate ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
|
||||
##########################################
|
||||
|
||||
set(dolphinpart_SRCS
|
||||
|
@ -165,10 +170,7 @@ kde4_add_kcfg_files(dolphin_SRCS
|
|||
)
|
||||
|
||||
if(Nepomuk_FOUND)
|
||||
set(dolphin_SRCS
|
||||
${dolphin_SRCS}
|
||||
panels/search/searchpanel.cpp
|
||||
)
|
||||
set(dolphin_SRCS ${dolphin_SRCS} panels/search/searchpanel.cpp)
|
||||
endif(Nepomuk_FOUND)
|
||||
|
||||
if(NOT WIN32)
|
||||
|
|
|
@ -55,8 +55,7 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) :
|
|||
m_scaledPixmapSize(),
|
||||
m_iconRect(),
|
||||
m_hoverPixmap(),
|
||||
m_textPos(),
|
||||
m_text(),
|
||||
m_textInfo(),
|
||||
m_textRect(),
|
||||
m_sortedVisibleRoles(),
|
||||
m_expansionArea(),
|
||||
|
@ -64,14 +63,12 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) :
|
|||
m_additionalInfoTextColor(),
|
||||
m_overlay()
|
||||
{
|
||||
for (int i = 0; i < TextIdCount; ++i) {
|
||||
m_text[i].setTextFormat(Qt::PlainText);
|
||||
m_text[i].setPerformanceHint(QStaticText::AggressiveCaching);
|
||||
}
|
||||
}
|
||||
|
||||
KFileItemListWidget::~KFileItemListWidget()
|
||||
{
|
||||
qDeleteAll(m_textInfo);
|
||||
m_textInfo.clear();
|
||||
}
|
||||
|
||||
void KFileItemListWidget::setLayout(Layout layout)
|
||||
|
@ -131,7 +128,8 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte
|
|||
|
||||
painter->setFont(itemListStyleOption.font);
|
||||
painter->setPen(textColor());
|
||||
painter->drawStaticText(m_textPos[Name], m_text[Name]);
|
||||
const TextInfo* textInfo = m_textInfo.value("name");
|
||||
painter->drawStaticText(textInfo->pos, textInfo->staticText);
|
||||
|
||||
bool clipAdditionalInfoBounds = false;
|
||||
if (m_supportsItemExpanding) {
|
||||
|
@ -139,7 +137,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte
|
|||
// with the icon. This can happen if the user has minimized the width
|
||||
// of the name-column to a very small value.
|
||||
const qreal minX = m_pixmapPos.x() + m_pixmap.width() + 4 * itemListStyleOption.padding;
|
||||
if (m_textPos[Name].x() + columnWidth("name") > minX) {
|
||||
if (textInfo->pos.x() + columnWidth("name") > minX) {
|
||||
clipAdditionalInfoBounds = true;
|
||||
painter->save();
|
||||
painter->setClipRect(minX, 0, size().width() - minX, size().height(), Qt::IntersectClip);
|
||||
|
@ -148,8 +146,10 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte
|
|||
|
||||
painter->setPen(m_additionalInfoTextColor);
|
||||
painter->setFont(itemListStyleOption.font);
|
||||
for (int i = Name + 1; i < TextIdCount; ++i) {
|
||||
painter->drawStaticText(m_textPos[i], m_text[i]);
|
||||
|
||||
for (int i = 1; i < m_sortedVisibleRoles.count(); ++i) {
|
||||
const TextInfo* textInfo = m_textInfo.value(m_sortedVisibleRoles[i]);
|
||||
painter->drawStaticText(textInfo->pos, textInfo->staticText);
|
||||
}
|
||||
|
||||
if (clipAdditionalInfoBounds) {
|
||||
|
@ -579,7 +579,8 @@ void KFileItemListWidget::updatePixmapCache()
|
|||
|
||||
int scaledIconSize = 0;
|
||||
if (iconOnTop) {
|
||||
scaledIconSize = static_cast<int>(m_textPos[Name].y() - 2 * padding);
|
||||
const TextInfo* textInfo = m_textInfo.value("name");
|
||||
scaledIconSize = static_cast<int>(textInfo->pos.y() - 2 * padding);
|
||||
} else {
|
||||
const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1;
|
||||
const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height();
|
||||
|
@ -599,7 +600,8 @@ void KFileItemListWidget::updatePixmapCache()
|
|||
m_pixmapPos.setY(padding + scaledIconSize - m_scaledPixmapSize.height());
|
||||
} else {
|
||||
// Center horizontally and vertically within the icon-area
|
||||
m_pixmapPos.setX(m_textPos[Name].x() - 2 * padding
|
||||
const TextInfo* textInfo = m_textInfo.value("name");
|
||||
m_pixmapPos.setX(textInfo->pos.x() - 2 * padding
|
||||
- (scaledIconSize + m_scaledPixmapSize.width()) / 2);
|
||||
m_pixmapPos.setY(padding
|
||||
+ (scaledIconSize - m_scaledPixmapSize.height()) / 2);
|
||||
|
@ -641,9 +643,14 @@ void KFileItemListWidget::updateTextsCache()
|
|||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < TextIdCount; ++i) {
|
||||
m_text[i].setText(QString());
|
||||
m_text[i].setTextOption(textOption);
|
||||
qDeleteAll(m_textInfo);
|
||||
m_textInfo.clear();
|
||||
for (int i = 0; i < m_sortedVisibleRoles.count(); ++i) {
|
||||
TextInfo* textInfo = new TextInfo();
|
||||
textInfo->staticText.setTextFormat(Qt::PlainText);
|
||||
textInfo->staticText.setPerformanceHint(QStaticText::AggressiveCaching);
|
||||
textInfo->staticText.setTextOption(textOption);
|
||||
m_textInfo.insert(m_sortedVisibleRoles[i], textInfo);
|
||||
}
|
||||
|
||||
switch (m_layout) {
|
||||
|
@ -676,15 +683,16 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
|
|||
|
||||
// Initialize properties for the "name" role. It will be used as anchor
|
||||
// for initializing the position of the other roles.
|
||||
m_text[Name].setText(KStringHandler::preProcessWrap(values["name"].toString()));
|
||||
TextInfo* nameTextInfo = m_textInfo.value("name");
|
||||
nameTextInfo->staticText.setText(KStringHandler::preProcessWrap(values["name"].toString()));
|
||||
|
||||
// Calculate the number of lines required for the name and the required width
|
||||
int textLinesCountForName = 0;
|
||||
qreal requiredWidthForName = 0;
|
||||
QTextLine line;
|
||||
|
||||
QTextLayout layout(m_text[Name].text(), option.font);
|
||||
layout.setTextOption(m_text[Name].textOption());
|
||||
QTextLayout layout(nameTextInfo->staticText.text(), option.font);
|
||||
layout.setTextOption(nameTextInfo->staticText.textOption());
|
||||
layout.beginLayout();
|
||||
while ((line = layout.createLine()).isValid()) {
|
||||
line.setLineWidth(maxWidth);
|
||||
|
@ -698,28 +706,28 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
|
|||
const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
|
||||
textLinesCount += additionalRolesCount;
|
||||
|
||||
m_text[Name].setTextWidth(maxWidth);
|
||||
m_textPos[Name] = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding);
|
||||
nameTextInfo->staticText.setTextWidth(maxWidth);
|
||||
nameTextInfo->pos = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding);
|
||||
m_textRect = QRectF(padding + (maxWidth - requiredWidthForName) / 2,
|
||||
m_textPos[Name].y(),
|
||||
nameTextInfo->pos.y(),
|
||||
requiredWidthForName,
|
||||
textLinesCountForName * fontHeight);
|
||||
|
||||
// Calculate the position for each additional information
|
||||
qreal y = m_textPos[Name].y() + textLinesCountForName * fontHeight;
|
||||
qreal y = nameTextInfo->pos.y() + textLinesCountForName * fontHeight;
|
||||
foreach (const QByteArray& role, m_sortedVisibleRoles) {
|
||||
const TextId textId = roleTextId(role);
|
||||
if (textId == Name) {
|
||||
if (role == "name") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString text = roleText(role, values);
|
||||
m_text[textId].setText(text);
|
||||
TextInfo* textInfo = m_textInfo.value(role);
|
||||
textInfo->staticText.setText(text);
|
||||
|
||||
qreal requiredWidth = 0;
|
||||
|
||||
QTextLayout layout(text, option.font);
|
||||
layout.setTextOption(m_text[textId].textOption());
|
||||
layout.setTextOption(textInfo->staticText.textOption());
|
||||
layout.beginLayout();
|
||||
QTextLine textLine = layout.createLine();
|
||||
if (textLine.isValid()) {
|
||||
|
@ -731,13 +739,13 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
|
|||
// not get elided although it does not fit into the given width. As workaround
|
||||
// the padding is substracted.
|
||||
const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - padding);
|
||||
m_text[textId].setText(elidedText);
|
||||
textInfo->staticText.setText(elidedText);
|
||||
}
|
||||
}
|
||||
layout.endLayout();
|
||||
|
||||
m_textPos[textId] = QPointF(padding, y);
|
||||
m_text[textId].setTextWidth(maxWidth);
|
||||
textInfo->pos = QPointF(padding, y);
|
||||
textInfo->staticText.setTextWidth(maxWidth);
|
||||
|
||||
const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight);
|
||||
m_textRect |= textRect;
|
||||
|
@ -768,20 +776,19 @@ void KFileItemListWidget::updateCompactLayoutTextCache()
|
|||
qreal y = (widgetHeight - textLinesHeight) / 2;
|
||||
const qreal maxWidth = size().width() - x - option.padding;
|
||||
foreach (const QByteArray& role, m_sortedVisibleRoles) {
|
||||
const TextId textId = roleTextId(role);
|
||||
|
||||
const QString text = roleText(role, values);
|
||||
m_text[textId].setText(text);
|
||||
TextInfo* textInfo = m_textInfo.value(role);
|
||||
textInfo->staticText.setText(text);
|
||||
|
||||
qreal requiredWidth = option.fontMetrics.width(text);
|
||||
if (requiredWidth > maxWidth) {
|
||||
requiredWidth = maxWidth;
|
||||
const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth);
|
||||
m_text[textId].setText(elidedText);
|
||||
textInfo->staticText.setText(elidedText);
|
||||
}
|
||||
|
||||
m_textPos[textId] = QPointF(x, y);
|
||||
m_text[textId].setTextWidth(maxWidth);
|
||||
textInfo->pos = QPointF(x, y);
|
||||
textInfo->staticText.setTextWidth(maxWidth);
|
||||
|
||||
maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth);
|
||||
|
||||
|
@ -820,7 +827,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
|
|||
const qreal y = qMax(qreal(option.padding), (widgetHeight - fontHeight) / 2);
|
||||
|
||||
foreach (const QByteArray& role, m_sortedVisibleRoles) {
|
||||
const TextId textId = roleTextId(role);
|
||||
const RoleType type = roleType(role);
|
||||
|
||||
QString text = roleText(role, values);
|
||||
|
||||
|
@ -828,7 +835,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
|
|||
qreal requiredWidth = option.fontMetrics.width(text);
|
||||
const qreal roleWidth = columnWidth(role);
|
||||
qreal availableTextWidth = roleWidth - 2 * columnPadding;
|
||||
if (textId == Name) {
|
||||
if (type == Name) {
|
||||
availableTextWidth -= firstColumnInc;
|
||||
}
|
||||
|
||||
|
@ -837,16 +844,17 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
|
|||
requiredWidth = option.fontMetrics.width(text);
|
||||
}
|
||||
|
||||
m_text[textId].setText(text);
|
||||
m_textPos[textId] = QPointF(x + columnPadding, y);
|
||||
TextInfo* textInfo = m_textInfo.value(role);
|
||||
textInfo->staticText.setText(text);
|
||||
textInfo->pos = QPointF(x + columnPadding, y);
|
||||
x += roleWidth;
|
||||
|
||||
switch (textId) {
|
||||
switch (type) {
|
||||
case Name: {
|
||||
const qreal textWidth = option.extendedSelectionRegion
|
||||
? size().width() - m_textPos[textId].x()
|
||||
? size().width() - textInfo->pos.x()
|
||||
: requiredWidth + 2 * option.padding;
|
||||
m_textRect = QRectF(m_textPos[textId].x() - option.padding, 0,
|
||||
m_textRect = QRectF(textInfo->pos.x() - option.padding, 0,
|
||||
textWidth, size().height());
|
||||
|
||||
// The column after the name should always be aligned on the same x-position independent
|
||||
|
@ -856,7 +864,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
|
|||
}
|
||||
case Size:
|
||||
// The values for the size should be right aligned
|
||||
m_textPos[textId].rx() += roleWidth - requiredWidth - 2 * columnPadding;
|
||||
textInfo->pos.rx() += roleWidth - requiredWidth - 2 * columnPadding;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -976,22 +984,16 @@ void KFileItemListWidget::applyHiddenEffect(QPixmap& pixmap)
|
|||
KIconEffect::semiTransparent(pixmap);
|
||||
}
|
||||
|
||||
KFileItemListWidget::TextId KFileItemListWidget::roleTextId(const QByteArray& role)
|
||||
KFileItemListWidget::RoleType KFileItemListWidget::roleType(const QByteArray& role)
|
||||
{
|
||||
static QHash<QByteArray, TextId> rolesHash;
|
||||
static QHash<QByteArray, RoleType> rolesHash;
|
||||
if (rolesHash.isEmpty()) {
|
||||
rolesHash.insert("name", Name);
|
||||
rolesHash.insert("size", Size);
|
||||
rolesHash.insert("date", Date);
|
||||
rolesHash.insert("permissions", Permissions);
|
||||
rolesHash.insert("owner", Owner);
|
||||
rolesHash.insert("group", Group);
|
||||
rolesHash.insert("type", Type);
|
||||
rolesHash.insert("destination", Destination);
|
||||
rolesHash.insert("path", Path);
|
||||
}
|
||||
|
||||
return rolesHash.value(role);
|
||||
return rolesHash.value(role, Generic);
|
||||
}
|
||||
|
||||
QString KFileItemListWidget::roleText(const QByteArray& role, const QHash<QByteArray, QVariant>& values)
|
||||
|
@ -999,17 +1001,7 @@ QString KFileItemListWidget::roleText(const QByteArray& role, const QHash<QByteA
|
|||
QString text;
|
||||
const QVariant roleValue = values.value(role);
|
||||
|
||||
switch (roleTextId(role)) {
|
||||
case Name:
|
||||
case Permissions:
|
||||
case Owner:
|
||||
case Group:
|
||||
case Type:
|
||||
case Destination:
|
||||
case Path:
|
||||
text = roleValue.toString();
|
||||
break;
|
||||
|
||||
switch (roleType(role)) {
|
||||
case Size: {
|
||||
if (values.value("isDir").toBool()) {
|
||||
// The item represents a directory. Show the number of sub directories
|
||||
|
@ -1038,6 +1030,11 @@ QString KFileItemListWidget::roleText(const QByteArray& role, const QHash<QByteA
|
|||
break;
|
||||
}
|
||||
|
||||
case Name:
|
||||
case Generic:
|
||||
text = roleValue.toString();
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
|
|
|
@ -109,17 +109,11 @@ private slots:
|
|||
void slotCutItemsChanged();
|
||||
|
||||
private:
|
||||
enum TextId {
|
||||
enum RoleType {
|
||||
Name,
|
||||
Size,
|
||||
Date,
|
||||
Permissions,
|
||||
Owner,
|
||||
Group,
|
||||
Type,
|
||||
Destination,
|
||||
Path,
|
||||
TextIdCount // Mandatory last entry
|
||||
Generic // Mandatory last entry
|
||||
};
|
||||
|
||||
void triggerCacheRefreshing();
|
||||
|
@ -139,7 +133,7 @@ private:
|
|||
static QPixmap pixmapForIcon(const QString& name, int size);
|
||||
static void applyCutEffect(QPixmap& pixmap);
|
||||
static void applyHiddenEffect(QPixmap& pixmap);
|
||||
static TextId roleTextId(const QByteArray& role);
|
||||
static RoleType roleType(const QByteArray& role);
|
||||
|
||||
/**
|
||||
* @return Shown string for the role \p role of the item with the values \p values.
|
||||
|
@ -164,8 +158,13 @@ private:
|
|||
QRectF m_iconRect; // Cache for KItemListWidget::iconRect()
|
||||
QPixmap m_hoverPixmap; // Cache for modified m_pixmap when hovering the item
|
||||
|
||||
QPointF m_textPos[TextIdCount];
|
||||
QStaticText m_text[TextIdCount];
|
||||
struct TextInfo
|
||||
{
|
||||
QPointF pos;
|
||||
QStaticText staticText;
|
||||
};
|
||||
QHash<QByteArray, TextInfo*> m_textInfo;
|
||||
|
||||
QRectF m_textRect;
|
||||
|
||||
QList<QByteArray> m_sortedVisibleRoles;
|
||||
|
|
|
@ -274,19 +274,8 @@ QList<QPair<int, QVariant> > KFileItemModel::groups() const
|
|||
case SizeRole: m_groups = sizeRoleGroups(); break;
|
||||
case DateRole: m_groups = dateRoleGroups(); break;
|
||||
case PermissionsRole: m_groups = permissionRoleGroups(); break;
|
||||
case OwnerRole: m_groups = genericStringRoleGroups("owner"); break;
|
||||
case GroupRole: m_groups = genericStringRoleGroups("group"); break;
|
||||
case TypeRole: m_groups = genericStringRoleGroups("type"); break;
|
||||
case DestinationRole: m_groups = genericStringRoleGroups("destination"); break;
|
||||
case PathRole: m_groups = genericStringRoleGroups("path"); break;
|
||||
case CommentRole: m_groups = genericStringRoleGroups("comment"); break;
|
||||
case TagsRole: m_groups = genericStringRoleGroups("tags"); break;
|
||||
case RatingRole: m_groups = ratingRoleGroups(); break;
|
||||
case NoRole: break;
|
||||
case IsDirRole: break;
|
||||
case IsExpandedRole: break;
|
||||
case ExpandedParentsCountRole: break;
|
||||
default: Q_ASSERT(false); break;
|
||||
default: m_groups = genericStringRoleGroups(sortRole()); break;
|
||||
}
|
||||
|
||||
#ifdef KFILEITEMMODEL_DEBUG
|
||||
|
@ -558,6 +547,8 @@ QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation()
|
|||
info.role = map[i].role;
|
||||
info.translation = map[i].roleTranslation;
|
||||
info.group = map[i].groupTranslation;
|
||||
info.requiresNepomuk = map[i].requiresNepomuk;
|
||||
info.requiresIndexer = map[i].requiresIndexer;
|
||||
rolesInfo.append(info);
|
||||
}
|
||||
}
|
||||
|
@ -1344,6 +1335,15 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b) const
|
|||
break;
|
||||
}
|
||||
|
||||
case ImageSizeRole: {
|
||||
// Alway use a natural comparing to interpret the numbers of a string like
|
||||
// "1600 x 1200" for having a correct sorting.
|
||||
result = KStringHandler::naturalCompare(a->values.value("imageSize").toString(),
|
||||
b->values.value("imageSize").toString(),
|
||||
Qt::CaseSensitive);
|
||||
break;
|
||||
}
|
||||
|
||||
case PermissionsRole:
|
||||
case OwnerRole:
|
||||
case GroupRole:
|
||||
|
@ -1953,29 +1953,29 @@ KFileItemList KFileItemModel::childItems(const KFileItem& item) const
|
|||
const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count)
|
||||
{
|
||||
static const RoleInfoMap rolesInfoMap[] = {
|
||||
// role roleType role translation group translation
|
||||
{ 0, NoRole, 0, 0, 0, 0 },
|
||||
{ "name", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0 },
|
||||
{ "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0 },
|
||||
{ "date", DateRole, I18N_NOOP2_NOSTRIP("@label", "Date"), 0, 0 },
|
||||
{ "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), 0, 0 },
|
||||
{ "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), 0, 0 },
|
||||
{ "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), 0, 0 },
|
||||
{ "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), 0, 0 },
|
||||
{ "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document") },
|
||||
{ "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document") },
|
||||
{ "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image") },
|
||||
{ "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image") },
|
||||
{ "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Music") },
|
||||
{ "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Music") },
|
||||
{ "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Music") },
|
||||
{ "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Music") },
|
||||
{ "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other") },
|
||||
{ "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other") },
|
||||
{ "copiedFrom", CopiedFromRole, I18N_NOOP2_NOSTRIP("@label", "Copied From"), I18N_NOOP2_NOSTRIP("@label", "Other") },
|
||||
{ "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other") },
|
||||
{ "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other") },
|
||||
{ "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "Group"), I18N_NOOP2_NOSTRIP("@label", "Other") },
|
||||
// | role | roleType | role translation | group translation | requires Nepomuk | requires indexer
|
||||
{ 0, NoRole, 0, 0, 0, 0, false, false },
|
||||
{ "name", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0, false, false },
|
||||
{ "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0, false, false },
|
||||
{ "date", DateRole, I18N_NOOP2_NOSTRIP("@label", "Date"), 0, 0, false, false },
|
||||
{ "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), 0, 0, false, false },
|
||||
{ "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), 0, 0, true, false },
|
||||
{ "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), 0, 0, true, false },
|
||||
{ "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), 0, 0, true, false },
|
||||
{ "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
|
||||
{ "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
|
||||
{ "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
|
||||
{ "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
|
||||
{ "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
|
||||
{ "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
|
||||
{ "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
|
||||
{ "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true },
|
||||
{ "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
|
||||
{ "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
|
||||
{ "copiedFrom", CopiedFromRole, I18N_NOOP2_NOSTRIP("@label", "Copied From"), I18N_NOOP2_NOSTRIP("@label", "Other"), true, false },
|
||||
{ "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
|
||||
{ "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
|
||||
{ "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "User Group"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
|
||||
};
|
||||
|
||||
count = sizeof(rolesInfoMap) / sizeof(RoleInfoMap);
|
||||
|
|
|
@ -162,8 +162,16 @@ public:
|
|||
{ QByteArray role;
|
||||
QString translation;
|
||||
QString group;
|
||||
bool requiresNepomuk;
|
||||
bool requiresIndexer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return Provides static information for all available roles that
|
||||
* are supported by KFileItemModel. Some roles can only be
|
||||
* determined if Nepomuk is enabled and/or the Nepomuk
|
||||
* indexing is enabled.
|
||||
*/
|
||||
static QList<RoleInfo> rolesInformation();
|
||||
|
||||
signals:
|
||||
|
@ -344,6 +352,8 @@ private:
|
|||
const char* const roleTranslation;
|
||||
const char* const groupTranslationContext;
|
||||
const char* const groupTranslation;
|
||||
const bool requiresNepomuk;
|
||||
const bool requiresIndexer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QTimer>
|
||||
|
||||
#ifdef HAVE_NEPOMUK
|
||||
#include "knepomukrolesprovider_p.h"
|
||||
#endif
|
||||
|
||||
// Required includes for subItemsCount():
|
||||
#ifdef Q_WS_WIN
|
||||
#include <QDir>
|
||||
|
@ -74,6 +78,10 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
|
|||
m_previewJobs(),
|
||||
m_changedItemsTimer(0),
|
||||
m_changedItems()
|
||||
#ifdef HAVE_NEPOMUK
|
||||
, m_resolveNepomukRoles(false)
|
||||
#endif
|
||||
|
||||
{
|
||||
Q_ASSERT(model);
|
||||
|
||||
|
@ -219,6 +227,23 @@ void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray>& roles)
|
|||
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, m_resolveNepomukRoles
|
||||
// will be set to true and the (quite expensive) resolving will be done
|
||||
// in KFileItemModelRolesUpdater::rolesData().
|
||||
const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance();
|
||||
m_resolveNepomukRoles = false;
|
||||
QSetIterator<QByteArray> it(roles);
|
||||
while (it.hasNext()) {
|
||||
const QByteArray& role = it.next();
|
||||
if (rolesProvider.isNepomukRole(role)) {
|
||||
m_resolveNepomukRoles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_paused) {
|
||||
m_rolesChangedDuringPausing = true;
|
||||
} else {
|
||||
|
@ -754,6 +779,17 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
|
|||
|
||||
data.insert("iconOverlays", item.overlays());
|
||||
|
||||
#ifdef HAVE_NEPOMUK
|
||||
if (m_resolveNepomukRoles) {
|
||||
const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance();
|
||||
QHashIterator<QByteArray, QVariant> it(rolesProvider.roleValues(item.url(), m_roles));
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
data.insert(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#ifndef KFILEITEMMODELROLESUPDATER_H
|
||||
#define KFILEITEMMODELROLESUPDATER_H
|
||||
|
||||
#include <config-nepomuk.h>
|
||||
#include <libdolphin_export.h>
|
||||
|
||||
#include <KFileItem>
|
||||
|
@ -204,6 +205,13 @@ private:
|
|||
// of time.
|
||||
QTimer* m_changedItemsTimer;
|
||||
QSet<KFileItem> m_changedItems;
|
||||
|
||||
#ifdef HAVE_NEPOMUK
|
||||
// True if roles must be resolved with the help of Nepomuk inside
|
||||
// KFileItemModelRolesUpdater::rolesData().
|
||||
bool m_resolveNepomukRoles;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@ KItemListHeaderWidget::KItemListHeaderWidget(QGraphicsWidget* parent) :
|
|||
QGraphicsWidget(parent),
|
||||
m_automaticColumnResizing(true),
|
||||
m_model(0),
|
||||
m_offset(0),
|
||||
m_columns(),
|
||||
m_columnWidths(),
|
||||
m_preferredColumnWidths(),
|
||||
|
@ -48,10 +49,6 @@ KItemListHeaderWidget::KItemListHeaderWidget(QGraphicsWidget* parent) :
|
|||
m_movingRole.index = -1;
|
||||
|
||||
setAcceptHoverEvents(true);
|
||||
|
||||
QStyleOptionHeader option;
|
||||
const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection, &option, QSize());
|
||||
resize(0, headerSize.height());
|
||||
}
|
||||
|
||||
KItemListHeaderWidget::~KItemListHeaderWidget()
|
||||
|
@ -142,6 +139,19 @@ qreal KItemListHeaderWidget::preferredColumnWidth(const QByteArray& role) const
|
|||
return m_preferredColumnWidths.value(role);
|
||||
}
|
||||
|
||||
void KItemListHeaderWidget::setOffset(qreal offset)
|
||||
{
|
||||
if (m_offset != offset) {
|
||||
m_offset = offset;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
qreal KItemListHeaderWidget::offset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
qreal KItemListHeaderWidget::minimumColumnWidth() const
|
||||
{
|
||||
QFontMetricsF fontMetrics(font());
|
||||
|
@ -161,7 +171,7 @@ void KItemListHeaderWidget::paint(QPainter* painter, const QStyleOptionGraphicsI
|
|||
painter->setFont(font());
|
||||
painter->setPen(palette().text().color());
|
||||
|
||||
qreal x = 0;
|
||||
qreal x = -m_offset;
|
||||
int orderIndex = 0;
|
||||
foreach (const QByteArray& role, m_columns) {
|
||||
const qreal roleWidth = m_columnWidths.value(role);
|
||||
|
@ -265,7 +275,7 @@ void KItemListHeaderWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
|
|||
} else {
|
||||
m_movingRole.pixmap = createRolePixmap(roleIndex);
|
||||
|
||||
qreal roleX = 0;
|
||||
qreal roleX = -m_offset;
|
||||
for (int i = 0; i < roleIndex; ++i) {
|
||||
const QByteArray role = m_columns[i];
|
||||
roleX += m_columnWidths.value(role);
|
||||
|
@ -429,7 +439,7 @@ int KItemListHeaderWidget::roleIndexAt(const QPointF& pos) const
|
|||
{
|
||||
int index = -1;
|
||||
|
||||
qreal x = 0;
|
||||
qreal x = -m_offset;
|
||||
foreach (const QByteArray& role, m_columns) {
|
||||
++index;
|
||||
x += m_columnWidths.value(role);
|
||||
|
@ -443,7 +453,7 @@ int KItemListHeaderWidget::roleIndexAt(const QPointF& pos) const
|
|||
|
||||
bool KItemListHeaderWidget::isAboveRoleGrip(const QPointF& pos, int roleIndex) const
|
||||
{
|
||||
qreal x = 0;
|
||||
qreal x = -m_offset;
|
||||
for (int i = 0; i <= roleIndex; ++i) {
|
||||
const QByteArray role = m_columns[i];
|
||||
x += m_columnWidths.value(role);
|
||||
|
@ -484,7 +494,7 @@ int KItemListHeaderWidget::targetOfMovingRole() const
|
|||
const int movingRight = movingLeft + movingWidth - 1;
|
||||
|
||||
int targetIndex = 0;
|
||||
qreal targetLeft = 0;
|
||||
qreal targetLeft = -m_offset;
|
||||
while (targetIndex < m_columns.count()) {
|
||||
const QByteArray role = m_columns[targetIndex];
|
||||
const qreal targetWidth = m_columnWidths.value(role);
|
||||
|
@ -510,7 +520,7 @@ int KItemListHeaderWidget::targetOfMovingRole() const
|
|||
|
||||
qreal KItemListHeaderWidget::roleXPosition(const QByteArray& role) const
|
||||
{
|
||||
qreal x = 0;
|
||||
qreal x = -m_offset;
|
||||
foreach (const QByteArray& visibleRole, m_columns) {
|
||||
if (visibleRole == role) {
|
||||
return x;
|
||||
|
|
|
@ -59,6 +59,9 @@ public:
|
|||
void setPreferredColumnWidth(const QByteArray& role, qreal width);
|
||||
qreal preferredColumnWidth(const QByteArray& role) const;
|
||||
|
||||
void setOffset(qreal offset);
|
||||
qreal offset() const;
|
||||
|
||||
qreal minimumColumnWidth() const;
|
||||
|
||||
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
|
||||
|
@ -144,6 +147,7 @@ private:
|
|||
|
||||
bool m_automaticColumnResizing;
|
||||
KItemModelBase* m_model;
|
||||
qreal m_offset;
|
||||
QList<QByteArray> m_columns;
|
||||
QHash<QByteArray, qreal> m_columnWidths;
|
||||
QHash<QByteArray, qreal> m_preferredColumnWidths;
|
||||
|
|
|
@ -237,7 +237,7 @@ void KItemListView::setItemOffset(qreal offset)
|
|||
|
||||
m_layouter->setItemOffset(offset);
|
||||
if (m_headerWidget->isVisible()) {
|
||||
m_headerWidget->setPos(-offset, 0);
|
||||
m_headerWidget->setOffset(offset);
|
||||
}
|
||||
|
||||
// Don't check whether the m_layoutTimer is active: Changing the
|
||||
|
@ -418,6 +418,7 @@ void KItemListView::setGeometry(const QRectF& rect)
|
|||
|
||||
const QSizeF newSize = rect.size();
|
||||
if (m_itemSize.isEmpty()) {
|
||||
m_headerWidget->resize(rect.width(), m_headerWidget->size().height());
|
||||
if (m_headerWidget->automaticColumnResizing()) {
|
||||
applyAutomaticColumnWidths();
|
||||
} else {
|
||||
|
@ -425,7 +426,6 @@ void KItemListView::setGeometry(const QRectF& rect)
|
|||
const QSizeF dynamicItemSize(qMax(newSize.width(), requiredWidth),
|
||||
m_itemSize.height());
|
||||
m_layouter->setItemSize(dynamicItemSize);
|
||||
m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height());
|
||||
}
|
||||
|
||||
// Triggering a synchronous layout is fine from a performance point of view,
|
||||
|
@ -604,10 +604,18 @@ bool KItemListView::isTransactionActive() const
|
|||
return m_activeTransactions > 0;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
void KItemListView::setHeaderVisible(bool visible)
|
||||
{
|
||||
if (visible && !m_headerWidget->isVisible()) {
|
||||
m_headerWidget->setPos(0, 0);
|
||||
QStyleOptionHeader option;
|
||||
const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection,
|
||||
&option, QSize());
|
||||
|
||||
m_headerWidget->setPos(0, 0);
|
||||
m_headerWidget->resize(size().width(), headerSize.height());
|
||||
m_headerWidget->setModel(m_model);
|
||||
m_headerWidget->setColumns(m_visibleRoles);
|
||||
m_headerWidget->setZValue(1);
|
||||
|
@ -621,7 +629,7 @@ void KItemListView::setHeaderVisible(bool visible)
|
|||
connect(m_headerWidget, SIGNAL(sortRoleChanged(QByteArray,QByteArray)),
|
||||
this, SIGNAL(sortRoleChanged(QByteArray,QByteArray)));
|
||||
|
||||
m_layouter->setHeaderHeight(m_headerWidget->size().height());
|
||||
m_layouter->setHeaderHeight(headerSize.height());
|
||||
m_headerWidget->setVisible(true);
|
||||
} else if (!visible && m_headerWidget->isVisible()) {
|
||||
disconnect(m_headerWidget, SIGNAL(columnWidthChanged(QByteArray,qreal,qreal)),
|
||||
|
@ -1898,6 +1906,19 @@ QHash<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeLi
|
|||
|
||||
QHash<QByteArray, qreal> widths;
|
||||
|
||||
// Calculate the minimum width for each column that is required
|
||||
// to show the headline unclipped.
|
||||
const QFontMetricsF fontMetrics(m_headerWidget->font());
|
||||
const int gripMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderGripMargin);
|
||||
const int headerMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderMargin);
|
||||
foreach (const QByteArray& visibleRole, visibleRoles()) {
|
||||
const QString headerText = m_model->roleDescription(visibleRole);
|
||||
const qreal headerWidth = fontMetrics.width(headerText) + gripMargin + headerMargin * 2;
|
||||
widths.insert(visibleRole, headerWidth);
|
||||
}
|
||||
|
||||
// Calculate the preferred column withs for each item and ignore values
|
||||
// smaller than the width for showing the headline unclipped.
|
||||
int calculatedItemCount = 0;
|
||||
bool maxTimeExceeded = false;
|
||||
foreach (const KItemRange& itemRange, itemRanges) {
|
||||
|
@ -1936,7 +1957,6 @@ void KItemListView::applyColumnWidthsFromHeader()
|
|||
const QSizeF dynamicItemSize(qMax(size().width(), requiredWidth),
|
||||
m_itemSize.height());
|
||||
m_layouter->setItemSize(dynamicItemSize);
|
||||
m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height());
|
||||
|
||||
// Update the role sizes for all visible widgets
|
||||
QHashIterator<int, KItemListWidget*> it(m_visibleItems);
|
||||
|
@ -2001,13 +2021,8 @@ void KItemListView::updatePreferredColumnWidths(const KItemRangeList& itemRanges
|
|||
|
||||
void KItemListView::updatePreferredColumnWidths()
|
||||
{
|
||||
if (!m_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int itemCount = m_model->count();
|
||||
if (itemCount > 0) {
|
||||
updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, itemCount));
|
||||
if (m_model) {
|
||||
updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, m_model->count()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2056,7 +2071,6 @@ void KItemListView::applyAutomaticColumnWidths()
|
|||
dynamicItemSize.rwidth() = qMax(requiredWidth, availableWidth);
|
||||
|
||||
m_layouter->setItemSize(dynamicItemSize);
|
||||
m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height());
|
||||
|
||||
// Update the role sizes for all visible widgets
|
||||
QHashIterator<int, KItemListWidget*> it(m_visibleItems);
|
||||
|
|
153
src/kitemviews/knepomukrolesprovider.cpp
Normal file
153
src/kitemviews/knepomukrolesprovider.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com> *
|
||||
* *
|
||||
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include "knepomukrolesprovider_p.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <KGlobal>
|
||||
|
||||
#include <Nepomuk/Resource>
|
||||
#include <Nepomuk/Tag>
|
||||
#include <Nepomuk/Types/Property>
|
||||
#include <Nepomuk/Variant>
|
||||
|
||||
struct KNepomukRolesProviderSingleton
|
||||
{
|
||||
KNepomukRolesProvider instance;
|
||||
};
|
||||
K_GLOBAL_STATIC(KNepomukRolesProviderSingleton, s_nepomukRolesProvider)
|
||||
|
||||
|
||||
KNepomukRolesProvider& KNepomukRolesProvider::instance()
|
||||
{
|
||||
return s_nepomukRolesProvider->instance;
|
||||
}
|
||||
|
||||
KNepomukRolesProvider::~KNepomukRolesProvider()
|
||||
{
|
||||
}
|
||||
|
||||
bool KNepomukRolesProvider::isNepomukRole(const QByteArray& role) const
|
||||
{
|
||||
return m_roles.contains(role);
|
||||
}
|
||||
|
||||
QHash<QByteArray, QVariant> KNepomukRolesProvider::roleValues(const QUrl& url,
|
||||
const QSet<QByteArray>& roles) const
|
||||
{
|
||||
const Nepomuk::Resource resource(url);
|
||||
if (!resource.isValid()) {
|
||||
return QHash<QByteArray, QVariant>();
|
||||
}
|
||||
|
||||
QHash<QByteArray, QVariant> values;
|
||||
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
|
||||
QHashIterator<QUrl, Nepomuk::Variant> it(resource.properties());
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
|
||||
const Nepomuk::Types::Property property = it.key();
|
||||
const QByteArray role = m_roleForUri.value(property.uri());
|
||||
if (role.isEmpty() || !roles.contains(role)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Nepomuk::Variant value = it.value();
|
||||
|
||||
if (role == "imageSize") {
|
||||
// Merge the two Nepomuk properties for width and height
|
||||
// as one string into the "imageSize" role
|
||||
const QString uri = property.uri().toString();
|
||||
if (uri.endsWith("#width")) {
|
||||
width = value.toInt();
|
||||
} else if (uri.endsWith("#height")) {
|
||||
height = value.toInt();
|
||||
}
|
||||
|
||||
if (width >= 0 && height >= 0) {
|
||||
const QString widthAndHeight = QString::number(width) +
|
||||
QLatin1String(" x ") +
|
||||
QString::number(height);
|
||||
values.insert(role, widthAndHeight);
|
||||
}
|
||||
} else if (role == "tags") {
|
||||
const QString tags = tagsFromValues(value.toStringList());
|
||||
values.insert(role, tags);
|
||||
} else {
|
||||
values.insert(role, value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
KNepomukRolesProvider::KNepomukRolesProvider() :
|
||||
m_roles(),
|
||||
m_roleForUri()
|
||||
{
|
||||
struct UriInfo
|
||||
{
|
||||
const char* const uri;
|
||||
const char* const role;
|
||||
};
|
||||
|
||||
// Mapping from the URIs to the KFileItemModel roles. Note that this must not be
|
||||
// a 1:1 mapping: One role may contain several URI-values (e.g. the URIs for height and
|
||||
// width of an image are mapped to the role "imageSize")
|
||||
static const UriInfo uriInfoList[] = {
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating", "rating" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag", "tags" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description", "comment" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#wordCount", "wordCount" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#lineCount", "lineCount" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#width", "imageSize" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#height", "imageSize" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation", "orientation", },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#performer", "artist" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#musicAlbum", "album" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#duration", "duration" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#trackNumber", "track" },
|
||||
{ "http://www.semanticdesktop.org/ontologies/2010/04/30/ndo#copiedFrom", "copiedFrom" }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(uriInfoList) / sizeof(UriInfo); ++i) {
|
||||
m_roleForUri.insert(QUrl(uriInfoList[i].uri), uriInfoList[i].role);
|
||||
m_roles.insert(uriInfoList[i].role);
|
||||
}
|
||||
}
|
||||
|
||||
QString KNepomukRolesProvider::tagsFromValues(const QStringList& values) const
|
||||
{
|
||||
QString tags;
|
||||
|
||||
for (int i = 0; i < values.count(); ++i) {
|
||||
if (i > 0) {
|
||||
tags.append(QLatin1String(", "));
|
||||
}
|
||||
|
||||
const Nepomuk::Tag tag(values[i]);
|
||||
tags += tag.genericLabel();
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
66
src/kitemviews/knepomukrolesprovider_p.h
Normal file
66
src/kitemviews/knepomukrolesprovider_p.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com> *
|
||||
* *
|
||||
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef KNEPOMUKROLESPROVIDER_H
|
||||
#define KNEPOMUKROLESPROVIDER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <QUrl>
|
||||
|
||||
class QUrl;
|
||||
|
||||
/**
|
||||
* @brief Allows accessing metadata of a file by providing KFileItemModel roles.
|
||||
*
|
||||
* Is a helper class for KFileItemModelRolesUpdater to retrieve roles that
|
||||
* are only accessible with Nepomuk.
|
||||
*/
|
||||
class KNepomukRolesProvider
|
||||
{
|
||||
public:
|
||||
static KNepomukRolesProvider& instance();
|
||||
virtual ~KNepomukRolesProvider();
|
||||
|
||||
/**
|
||||
* @return True if the values of the role can be determined by Nepomuk.
|
||||
*/
|
||||
bool isNepomukRole(const QByteArray& role) const;
|
||||
|
||||
/**
|
||||
* @return Values for the roles \a roles that can be determined from the file
|
||||
* with the URL \a url.
|
||||
*/
|
||||
QHash<QByteArray, QVariant> roleValues(const QUrl& url, const QSet<QByteArray>& roles) const;
|
||||
|
||||
protected:
|
||||
KNepomukRolesProvider();
|
||||
|
||||
private:
|
||||
QString tagsFromValues(const QStringList& values) const;
|
||||
|
||||
private:
|
||||
QSet<QByteArray> m_roles;
|
||||
QHash<QUrl, QByteArray> m_roleForUri;
|
||||
|
||||
friend class KNepomukRolesProviderSingleton;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -19,12 +19,18 @@
|
|||
|
||||
#include "additionalinfodialog.h"
|
||||
|
||||
#include <config-nepomuk.h>
|
||||
|
||||
#include <KLocale>
|
||||
#include "kitemviews/kfileitemmodel.h"
|
||||
#include <QCheckBox>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef HAVE_NEPOMUK
|
||||
#include <Nepomuk/ResourceManager>
|
||||
#endif
|
||||
|
||||
AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent,
|
||||
const QList<QByteArray>& visibleRoles) :
|
||||
KDialog(parent),
|
||||
|
@ -44,12 +50,30 @@ AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent,
|
|||
header->setWordWrap(true);
|
||||
|
||||
// Add checkboxes
|
||||
bool nepomukRunning = false;
|
||||
bool indexingEnabled = false;
|
||||
#ifdef HAVE_NEPOMUK
|
||||
nepomukRunning = (Nepomuk::ResourceManager::instance()->init() == 0);
|
||||
if (nepomukRunning) {
|
||||
KConfig config("nepomukserverrc");
|
||||
indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", false);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_listWidget = new QListWidget(mainWidget);
|
||||
m_listWidget->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
const QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
|
||||
foreach (const KFileItemModel::RoleInfo& info, rolesInfo) {
|
||||
QListWidgetItem* item = new QListWidgetItem(info.translation, m_listWidget);
|
||||
item->setCheckState(visibleRoles.contains(info.role) ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) ||
|
||||
(info.requiresNepomuk && nepomukRunning) ||
|
||||
(info.requiresIndexer && indexingEnabled);
|
||||
|
||||
if (!enable) {
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(mainWidget);
|
||||
|
|
|
@ -140,6 +140,7 @@ void DolphinItemListContainer::setItemLayout(KFileItemListView::Layout layout)
|
|||
m_fileItemListView->setScrollOrientation(Qt::Vertical);
|
||||
m_fileItemListView->setHeaderVisible(true);
|
||||
m_fileItemListView->setSupportsItemExpanding(DetailsModeSettings::expandableFolders());
|
||||
|
||||
break;
|
||||
case KFileItemListView::CompactLayout:
|
||||
m_fileItemListView->setScrollOrientation(Qt::Horizontal);
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "dolphinview.h"
|
||||
|
||||
#include <config-nepomuk.h>
|
||||
|
||||
#include <QAbstractItemView>
|
||||
#include <QApplication>
|
||||
#include <QBoxLayout>
|
||||
|
@ -70,6 +72,10 @@
|
|||
#include "views/tooltips/tooltipmanager.h"
|
||||
#include "zoomlevelinfo.h"
|
||||
|
||||
#ifdef HAVE_NEPOMUK
|
||||
#include <Nepomuk/ResourceManager>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
const int MaxModeEnum = DolphinView::CompactView;
|
||||
};
|
||||
|
@ -784,6 +790,16 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos)
|
|||
KItemListView* view = m_container->controller()->view();
|
||||
const QSet<QByteArray> visibleRolesSet = view->visibleRoles().toSet();
|
||||
|
||||
bool nepomukRunning = false;
|
||||
bool indexingEnabled = false;
|
||||
#ifdef HAVE_NEPOMUK
|
||||
nepomukRunning = (Nepomuk::ResourceManager::instance()->init() == 0);
|
||||
if (nepomukRunning) {
|
||||
KConfig config("nepomukserverrc");
|
||||
indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", false);
|
||||
}
|
||||
#endif
|
||||
|
||||
QString groupName;
|
||||
QMenu* groupMenu = 0;
|
||||
|
||||
|
@ -811,6 +827,11 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos)
|
|||
action->setCheckable(true);
|
||||
action->setChecked(visibleRolesSet.contains(info.role));
|
||||
action->setData(info.role);
|
||||
|
||||
const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) ||
|
||||
(info.requiresNepomuk && nepomukRunning) ||
|
||||
(info.requiresIndexer && indexingEnabled);
|
||||
action->setEnabled(enable);
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
|
@ -861,8 +882,10 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos)
|
|||
props.setVisibleRoles(visibleRoles);
|
||||
|
||||
QList<int> columnWidths;
|
||||
foreach (const QByteArray& role, view->visibleRoles()) {
|
||||
columnWidths.append(header->columnWidth(role));
|
||||
if (!header->automaticColumnResizing()) {
|
||||
foreach (const QByteArray& role, view->visibleRoles()) {
|
||||
columnWidths.append(header->columnWidth(role));
|
||||
}
|
||||
}
|
||||
props.setHeaderColumnWidths(columnWidths);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "dolphinviewactionhandler.h"
|
||||
|
||||
#include <config-nepomuk.h>
|
||||
|
||||
#include "settings/viewpropertiesdialog.h"
|
||||
#include "views/dolphinview.h"
|
||||
#include "views/zoomlevelinfo.h"
|
||||
|
@ -37,6 +39,10 @@
|
|||
#include <KRun>
|
||||
#include <KPropertiesDialog>
|
||||
|
||||
#ifdef HAVE_NEPOMUK
|
||||
#include <Nepomuk/ResourceManager>
|
||||
#endif
|
||||
|
||||
#include <KDebug>
|
||||
|
||||
DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection* collection, QObject* parent) :
|
||||
|
@ -228,6 +234,16 @@ QActionGroup* DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt
|
|||
KActionMenu* groupMenu = 0;
|
||||
QActionGroup* groupMenuGroup = 0;
|
||||
|
||||
bool nepomukRunning = false;
|
||||
bool indexingEnabled = false;
|
||||
#ifdef HAVE_NEPOMUK
|
||||
nepomukRunning = (Nepomuk::ResourceManager::instance()->init() == 0);
|
||||
if (nepomukRunning) {
|
||||
KConfig config("nepomukserverrc");
|
||||
indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", false);
|
||||
}
|
||||
#endif
|
||||
|
||||
const QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
|
||||
foreach (const KFileItemModel::RoleInfo& info, rolesInfo) {
|
||||
if (!isSortGroup && info.role == "name") {
|
||||
|
@ -265,6 +281,11 @@ QActionGroup* DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt
|
|||
action->setText(info.translation);
|
||||
action->setData(info.role);
|
||||
|
||||
const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) ||
|
||||
(info.requiresNepomuk && nepomukRunning) ||
|
||||
(info.requiresIndexer && indexingEnabled);
|
||||
action->setEnabled(enable);
|
||||
|
||||
if (isSortGroup) {
|
||||
m_sortByActions.insert(info.role, action);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue