diff --git a/src/revisioncontrolobserver.cpp b/src/revisioncontrolobserver.cpp index 246450fe71..7f832cef40 100644 --- a/src/revisioncontrolobserver.cpp +++ b/src/revisioncontrolobserver.cpp @@ -88,6 +88,7 @@ QList UpdateItemStatesThread::itemStates() c RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) : QObject(view), m_pendingItemStatesUpdate(false), + m_revisionedDirectory(false), m_view(view), m_dirLister(0), m_dolphinModel(0), @@ -105,10 +106,7 @@ RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) : m_dirLister = m_dolphinModel->dirLister(); connect(m_dirLister, SIGNAL(completed()), this, SLOT(delayedDirectoryVerification())); - // TODO: - // connect(m_dirLister, SIGNAL(refreshItems(const QList>&)), - // this, SLOT(refreshItems())); - + // The verification timer specifies the timeout until the shown directory // is checked whether it is versioned. Per default it is assumed that users // don't iterate through versioned directories and a high timeout is used @@ -146,16 +144,28 @@ void RevisionControlObserver::verifyDirectory() } revisionControlUrl.addPath(m_plugin->fileName()); - KFileItem item = m_dirLister->findByUrl(revisionControlUrl); - if (item.isNull()) { + const KFileItem item = m_dirLister->findByUrl(revisionControlUrl); + if (item.isNull() && m_revisionedDirectory) { // The directory is not versioned. Reset the verification timer to a higher // value, so that browsing through non-versioned directories is not slown down // by an immediate verification. m_dirVerificationTimer->setInterval(500); - } else { - // The directory is versioned. Assume that the user will further browse through - // versioned directories and decrease the verification timer. - m_dirVerificationTimer->setInterval(100); + m_revisionedDirectory = false; + disconnect(m_dirLister, SIGNAL(refreshItems(const QList>&)), + this, SLOT(delayedDirectoryVerification())); + disconnect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), + this, SLOT(delayedDirectoryVerification())); + } else if (!item.isNull()) { + if (!m_revisionedDirectory) { + // The directory is versioned. Assume that the user will further browse through + // versioned directories and decrease the verification timer. + m_dirVerificationTimer->setInterval(100); + m_revisionedDirectory = true; + connect(m_dirLister, SIGNAL(refreshItems(const QList>&)), + this, SLOT(delayedDirectoryVerification())); + connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), + this, SLOT(delayedDirectoryVerification())); + } updateItemStates(); } } diff --git a/src/revisioncontrolobserver.h b/src/revisioncontrolobserver.h index c5cf9bb0dc..7e849c2736 100644 --- a/src/revisioncontrolobserver.h +++ b/src/revisioncontrolobserver.h @@ -68,6 +68,7 @@ private: }; bool m_pendingItemStatesUpdate; + bool m_revisionedDirectory; QAbstractItemView* m_view; KDirLister* m_dirLister; diff --git a/src/revisioncontrolplugin.cpp b/src/revisioncontrolplugin.cpp index 5e6783335c..d5f2e4e5da 100644 --- a/src/revisioncontrolplugin.cpp +++ b/src/revisioncontrolplugin.cpp @@ -32,6 +32,8 @@ RevisionControlPlugin::~RevisionControlPlugin() { } +#include "revisioncontrolplugin.moc" + // ---------------------------------------------------------------------------- SubversionPlugin::SubversionPlugin() : @@ -94,18 +96,47 @@ RevisionControlPlugin::RevisionState SubversionPlugin::revisionState(const KFile const QDateTime versionedTimeStamp = info.timeStamp; if (localTimeStamp > versionedTimeStamp) { - if (info.size != item.size()) { + if ((info.size != item.size()) || !equalRevisionContent(item.name())) { return RevisionControlPlugin::EditingRevision; } - // TODO: a comparison of the content is required } else if (localTimeStamp < versionedTimeStamp) { - if (info.size != item.size()) { + if ((info.size != item.size()) || !equalRevisionContent(item.name())) { return RevisionControlPlugin::UpdateRequiredRevision; } - // TODO: a comparison of the content is required } return RevisionControlPlugin::LatestRevision; } return RevisionControlPlugin::LocalRevision; } + +QList SubversionPlugin::contextMenuActions(const KFileItemList& items) const +{ + Q_UNUSED(items); + // TODO... + return QList(); +} + +bool SubversionPlugin::equalRevisionContent(const QString& name) const +{ + QFile localFile(m_directory + '/' + name); + if (!localFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + return false; + } + + QFile revisionedFile(m_directory + "/.svn/text-base/" + name + ".svn-base"); + if (!revisionedFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + return false; + } + + QTextStream localText(&localFile); + QTextStream revisionedText(&revisionedFile); + while (!localText.atEnd() && !revisionedText.atEnd()) { + if (localText.readLine() != revisionedText.readLine()) { + return false; + } + } + + return localText.atEnd() && revisionedText.atEnd(); +} + diff --git a/src/revisioncontrolplugin.h b/src/revisioncontrolplugin.h index a4ad69571d..95751253ae 100644 --- a/src/revisioncontrolplugin.h +++ b/src/revisioncontrolplugin.h @@ -24,17 +24,28 @@ #include #include +#include class KFileItem; +class KFileItemList; +class QAction; /** * @brief Base class for revision control plugins. * * Enables the file manager to show the revision state - * of a revisioned file. + * of a revisioned file. The methods + * RevisionControlPlugin::beginRetrieval(), + * RevisionControlPlugin::endRetrieval() and + * RevisionControlPlugin::revisionState() are invoked + * from a separate thread to assure that the GUI thread + * won't be blocked. All other methods are invoked in the + * scope of the GUI thread. */ -class LIBDOLPHINPRIVATE_EXPORT RevisionControlPlugin +class LIBDOLPHINPRIVATE_EXPORT RevisionControlPlugin : public QObject { + Q_OBJECT + public: enum RevisionState { @@ -79,7 +90,26 @@ public: * in beginInfoRetrieval(). */ virtual RevisionState revisionState(const KFileItem& item) = 0; + + /** + * Returns the list of actions that should be shown in the context menu + * for the files \p items. If an action cannot be applied to the list + * of files, it is recommended to disable the action instead of removing it + * from the returned list. If an action triggers a change of the revisions, + * the signal RevisionControlPlugin::revisionStatesChanged() must be emitted. + */ + virtual QList contextMenuActions(const KFileItemList& items) const = 0; +signals: + /** + * Should be emitted when the revision state of files has been changed + * after the last retrieval. The file manager will be triggered to + * update the revision states of the directory \p directory by invoking + * RevisionControlPlugin::beginRetrieval(), + * RevisionControlPlugin::revisionState() and + * RevisionControlPlugin::endRetrieval(). + */ + void revisionStatesChanged(const QString& directory); }; @@ -100,6 +130,14 @@ public: virtual bool beginRetrieval(const QString& directory); virtual void endRetrieval(); virtual RevisionControlPlugin::RevisionState revisionState(const KFileItem& item); + virtual QList contextMenuActions(const KFileItemList& items) const; + +private: + /** + * Returns true, if the content of the local file \p name is equal to the + * content of the revisioned file. + */ + bool equalRevisionContent(const QString& name) const; private: struct RevisionInfo