diff --git a/src/dolphinfileitemdelegate.cpp b/src/dolphinfileitemdelegate.cpp index 7232c38f58..367435cedb 100644 --- a/src/dolphinfileitemdelegate.cpp +++ b/src/dolphinfileitemdelegate.cpp @@ -63,9 +63,9 @@ void DolphinFileItemDelegate::paint(QPainter* painter, const QModelIndex dirIndex = proxyModel->mapToSource(index); const QModelIndex revisionIndex = dolphinModel->index(dirIndex.row(), DolphinModel::Revision); const QVariant data = dolphinModel->data(revisionIndex, Qt::DecorationRole); - const DolphinModel::RevisionState state = static_cast(data.toInt()); + const RevisionControlPlugin::RevisionState state = static_cast(data.toInt()); - if (state != DolphinModel::LocalRevision) { + if (state != RevisionControlPlugin::LocalRevision) { // TODO: extend KFileItemDelegate to be able to get the icon boundaries const QRect iconRect(option.rect.x(), option.rect.y(), KIconLoader::SizeSmall, KIconLoader::SizeSmall); @@ -105,22 +105,20 @@ void DolphinFileItemDelegate::adjustOptionWidth(QStyleOptionViewItemV4& option, } } -QPixmap DolphinFileItemDelegate::emblemForState(DolphinModel::RevisionState state, const QSize& size) +QPixmap DolphinFileItemDelegate::emblemForState(RevisionControlPlugin::RevisionState state, const QSize& size) { // TODO #1: all icons that are use here will be replaced by revision control emblems provided by the // Oxygen team before KDE 4.4 // TODO #2: cache the icons switch (state) { - case DolphinModel::LatestRevision: + case RevisionControlPlugin::LatestRevision: return KIcon("dialog-ok-apply").pixmap(size); - break; - - case DolphinModel::ConflictingRevision: + case RevisionControlPlugin::ConflictingRevision: + return KIcon("application-exit").pixmap(size); + case RevisionControlPlugin::UpdateRequiredRevision: + return KIcon("rating").pixmap(size); + case RevisionControlPlugin::EditingRevision: return KIcon("emblem-important").pixmap(size); - break; - - // ... - default: break; } diff --git a/src/dolphinfileitemdelegate.h b/src/dolphinfileitemdelegate.h index b6a4d45b2f..2f8d3c35f9 100644 --- a/src/dolphinfileitemdelegate.h +++ b/src/dolphinfileitemdelegate.h @@ -66,7 +66,7 @@ private: const DolphinModel* dolphinModel, const QModelIndex& index); - static QPixmap emblemForState(DolphinModel::RevisionState state, const QSize& size); + static QPixmap emblemForState(RevisionControlPlugin::RevisionState state, const QSize& size); private: bool m_hasMinimizedNameColumn; diff --git a/src/dolphinmodel.cpp b/src/dolphinmodel.cpp index c5ea06a363..542d550ae3 100644 --- a/src/dolphinmodel.cpp +++ b/src/dolphinmodel.cpp @@ -68,8 +68,8 @@ bool DolphinModel::setData(const QModelIndex& index, const QVariant& value, int // TODO: remove data again when items are deleted... const QPersistentModelIndex key = index; - const RevisionState state = static_cast(value.toInt()); - if (m_revisionHash.value(key, LocalRevision) != state) { + const RevisionControlPlugin::RevisionState state = static_cast(value.toInt()); + if (m_revisionHash.value(key, RevisionControlPlugin::LocalRevision) != state) { if (!m_hasRevisionData) { connect(this, SIGNAL(rowsRemoved (const QModelIndex&, int, int)), this, SLOT(slotRowsRemoved(const QModelIndex&, int, int))); @@ -96,17 +96,20 @@ QVariant DolphinModel::data(const QModelIndex& index, int role) const case Qt::DecorationRole: if (index.column() == DolphinModel::Revision) { - return m_revisionHash.value(index, LocalRevision); + return m_revisionHash.value(index, RevisionControlPlugin::LocalRevision); } break; case Qt::DisplayRole: if (index.column() == DolphinModel::Revision) { - switch (m_revisionHash.value(index, LocalRevision)) { - case LatestRevision: + switch (m_revisionHash.value(index, RevisionControlPlugin::LocalRevision)) { + case RevisionControlPlugin::LatestRevision: return i18nc("@item::intable", "Latest"); - - case LocalRevision: + case RevisionControlPlugin::EditingRevision: + return i18nc("@item::intable", "Editing"); + case RevisionControlPlugin::UpdateRequiredRevision: + return i18nc("@item::intable", "Update required"); + case RevisionControlPlugin::LocalRevision: default: return i18nc("@item::intable", "Local"); } diff --git a/src/dolphinmodel.h b/src/dolphinmodel.h index 45fd1efa2c..9ae3d5f7c9 100644 --- a/src/dolphinmodel.h +++ b/src/dolphinmodel.h @@ -22,6 +22,7 @@ #define DOLPHINMODEL_H #include +#include #include #include @@ -37,13 +38,6 @@ public: ExtraColumnCount }; - enum RevisionState { - LocalRevision, - LatestRevision, - ConflictingRevision - // TODO... - }; - DolphinModel(QObject* parent = 0); virtual ~DolphinModel(); @@ -63,7 +57,7 @@ private: private: bool m_hasRevisionData; - QHash m_revisionHash; + QHash m_revisionHash; static const char* m_others; }; diff --git a/src/revisioncontrolobserver.cpp b/src/revisioncontrolobserver.cpp index 95253c59ac..246450fe71 100644 --- a/src/revisioncontrolobserver.cpp +++ b/src/revisioncontrolobserver.cpp @@ -26,7 +26,6 @@ #include #include -#include #include /** @@ -163,14 +162,12 @@ void RevisionControlObserver::verifyDirectory() void RevisionControlObserver::applyUpdatedItemStates() { - // Updating items with non-uniform item sizes is a serious bottleneck - // in QListView. Temporary disable the non-uniform item sizes. - QListView* listView = qobject_cast(m_view); - bool uniformSizes = true; - if (listView != 0) { - uniformSizes = listView->uniformItemSizes(); - //listView->setUniformItemSizes(true); TODO: does not work as well as in KFilePreviewGenerator - } + // QAbstractItemModel::setData() triggers a bottleneck in combination with QListView + // (a detailed description of the root cause is given in the class KFilePreviewGenerator + // from kdelibs). To bypass this bottleneck, the signals of the model are temporary blocked. + // This works as the update of the data does not require a relayout of the views used in Dolphin. + const bool signalsBlocked = m_dolphinModel->signalsBlocked(); + m_dolphinModel->blockSignals(true); const QList itemStates = m_updateItemStatesThread->itemStates(); foreach (const ItemState& itemState, itemStates) { @@ -179,11 +176,8 @@ void RevisionControlObserver::applyUpdatedItemStates() Qt::DecorationRole); } - if (listView != 0) { - listView->setUniformItemSizes(uniformSizes); - } - - m_view->viewport()->repaint(); // TODO: this should not be necessary, as DolphinModel::setData() calls dataChanged() + m_dolphinModel->blockSignals(signalsBlocked); + m_view->viewport()->repaint(); if (m_pendingItemStatesUpdate) { m_pendingItemStatesUpdate = false; diff --git a/src/revisioncontrolplugin.cpp b/src/revisioncontrolplugin.cpp index dde8d86654..5e6783335c 100644 --- a/src/revisioncontrolplugin.cpp +++ b/src/revisioncontrolplugin.cpp @@ -53,27 +53,25 @@ bool SubversionPlugin::beginRetrieval(const QString& directory) { Q_ASSERT(directory.endsWith('/')); m_directory = directory; + const QString path = directory + ".svn/text-base/"; - QFile file(directory + ".svn/entries"); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - return false; - } - - QTextStream in(&file); + QDir dir(path); + const QFileInfoList fileInfoList = dir.entryInfoList(); + const int size = fileInfoList.size(); QString fileName; - QString line; - while (!in.atEnd()) { - fileName = line; - line = in.readLine(); - const bool isRevisioned = !line.isEmpty() && - ((line == QLatin1String("dir")) || - (line == QLatin1String("file"))); - if (isRevisioned) { - RevisionInfo info; // TODO + for (int i = 0; i < size; ++i) { + fileName = fileInfoList.at(i).fileName(); + // Remove the ".svn-base" postfix to be able to compare the filenames + // in a fast way in SubversionPlugin::revisionState(). + fileName.chop(sizeof(".svn-base") / sizeof(char) - 1); + if (!fileName.isEmpty()) { + RevisionInfo info; + info.size = fileInfoList.at(i).size(); + info.timeStamp = fileInfoList.at(i).lastModified(); m_revisionInfoHash.insert(fileName, info); } } - return true; + return size > 0; } void SubversionPlugin::endRetrieval() @@ -83,9 +81,30 @@ void SubversionPlugin::endRetrieval() RevisionControlPlugin::RevisionState SubversionPlugin::revisionState(const KFileItem& item) { const QString name = item.name(); - if (m_revisionInfoHash.contains(name)) { - // TODO... - return RevisionControlPlugin::LatestRevision; + if (item.isDir()) { + QFile file(m_directory + name + "/.svn"); + if (file.open(QIODevice::ReadOnly)) { + file.close(); + // TODO... + return RevisionControlPlugin::LatestRevision; + } + } else if (m_revisionInfoHash.contains(name)) { + const RevisionInfo info = m_revisionInfoHash.value(item.name()); + const QDateTime localTimeStamp = item.time(KFileItem::ModificationTime).dateTime(); + const QDateTime versionedTimeStamp = info.timeStamp; + + if (localTimeStamp > versionedTimeStamp) { + if (info.size != item.size()) { + return RevisionControlPlugin::EditingRevision; + } + // TODO: a comparison of the content is required + } else if (localTimeStamp < versionedTimeStamp) { + if (info.size != item.size()) { + return RevisionControlPlugin::UpdateRequiredRevision; + } + // TODO: a comparison of the content is required + } + return RevisionControlPlugin::LatestRevision; } return RevisionControlPlugin::LocalRevision; diff --git a/src/revisioncontrolplugin.h b/src/revisioncontrolplugin.h index 687160c52b..a4ad69571d 100644 --- a/src/revisioncontrolplugin.h +++ b/src/revisioncontrolplugin.h @@ -40,6 +40,8 @@ public: { LocalRevision, LatestRevision, + UpdateRequiredRevision, + EditingRevision, ConflictingRevision // TODO... }; @@ -102,7 +104,7 @@ public: private: struct RevisionInfo { - // TODO... + quint64 size; QDateTime timeStamp; };