DolphinFileItemDelegate::DolphinFileItemDelegate(QObject* parent) :
KFileItemDelegate(parent),
- m_hasMinimizedNameColumn(false)
+ m_hasMinimizedNameColumn(false),
+ m_cachedSize(),
+ m_cachedEmblems()
{
}
const QVariant data = dolphinModel->data(revisionIndex, Qt::DecorationRole);
const RevisionControlPlugin::RevisionState state = static_cast<RevisionControlPlugin::RevisionState>(data.toInt());
- 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);
- const QPixmap emblem = emblemForState(state, iconRect.size());
- painter->drawPixmap(iconRect.x(), iconRect.y(), emblem);
+ if (state != RevisionControlPlugin::UnversionedRevision) {
+ const QRect rect = iconRect(option, index);
+ const QPixmap emblem = emblemForState(state, rect.size());
+ painter->drawPixmap(rect.x(), rect.y() + rect.height() - emblem.height(), emblem);
}
}
}
}
}
-QPixmap DolphinFileItemDelegate::emblemForState(RevisionControlPlugin::RevisionState state, const QSize& size)
+QPixmap DolphinFileItemDelegate::emblemForState(RevisionControlPlugin::RevisionState state, const QSize& size) const
{
- // TODO #1: all icons that are use here will be replaced by revision control emblems provided by the
+ // TODO: 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 RevisionControlPlugin::LatestRevision:
- return KIcon("dialog-ok-apply").pixmap(size);
- 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);
- default:
- break;
+ Q_ASSERT(state <= RevisionControlPlugin::ConflictingRevision);
+ if ((m_cachedSize != size) || !m_cachedEmblems[state].isNull()) {
+ m_cachedSize = size;
+
+ const int iconHeight = size.height();
+ int emblemHeight = KIconLoader::SizeSmall;
+ if (iconHeight >= KIconLoader::SizeEnormous) {
+ emblemHeight = KIconLoader::SizeMedium;
+ } else if (iconHeight >= KIconLoader::SizeLarge) {
+ emblemHeight = KIconLoader::SizeSmallMedium;
+ } else if (iconHeight >= KIconLoader::SizeMedium) {
+ emblemHeight = KIconLoader::SizeSmall;
+ } else {
+ // TODO: it depends on the final icons whether a smaller size works
+ emblemHeight = KIconLoader::SizeSmall /* / 2 */;
+ }
+
+ const QSize emblemSize(emblemHeight, emblemHeight);
+ for (int i = 0; i <= RevisionControlPlugin::ConflictingRevision; ++i) {
+ QString iconName;
+ switch (state) {
+ case RevisionControlPlugin::NormalRevision: iconName = "dialog-ok-apply"; break;
+ case RevisionControlPlugin::UpdateRequiredRevision: iconName = "rating"; break;
+ case RevisionControlPlugin::LocallyModifiedRevision: iconName = "emblem-important"; break;
+ case RevisionControlPlugin::AddedRevision: iconName = "list-add"; break;
+ case RevisionControlPlugin::ConflictingRevision: iconName = "application-exit"; break;
+ default: Q_ASSERT(false); break;
+ }
+
+ m_cachedEmblems[i] = KIcon(iconName).pixmap(emblemSize);
+ }
}
- return QPixmap();
+ return m_cachedEmblems[state];
}
const DolphinModel* dolphinModel,
const QModelIndex& index);
- static QPixmap emblemForState(RevisionControlPlugin::RevisionState state, const QSize& size);
+ QPixmap emblemForState(RevisionControlPlugin::RevisionState state, const QSize& size) const;
private:
bool m_hasMinimizedNameColumn;
+ mutable QSize m_cachedSize;
+ mutable QPixmap m_cachedEmblems[RevisionControlPlugin::ConflictingRevision + 1];
};
inline void DolphinFileItemDelegate::setMinimizedNameColumn(bool minimized)
const QPersistentModelIndex key = index;
const RevisionControlPlugin::RevisionState state = static_cast<RevisionControlPlugin::RevisionState>(value.toInt());
- if (m_revisionHash.value(key, RevisionControlPlugin::LocalRevision) != state) {
+ if (m_revisionHash.value(key, RevisionControlPlugin::UnversionedRevision) != state) {
if (!m_hasRevisionData) {
connect(this, SIGNAL(rowsRemoved (const QModelIndex&, int, int)),
this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
case Qt::DecorationRole:
if (index.column() == DolphinModel::Revision) {
- return m_revisionHash.value(index, RevisionControlPlugin::LocalRevision);
+ return m_revisionHash.value(index, RevisionControlPlugin::UnversionedRevision);
}
break;
case Qt::DisplayRole:
if (index.column() == DolphinModel::Revision) {
- switch (m_revisionHash.value(index, RevisionControlPlugin::LocalRevision)) {
- case RevisionControlPlugin::LatestRevision:
- return i18nc("@item::intable", "Latest");
- case RevisionControlPlugin::EditingRevision:
- return i18nc("@item::intable", "Editing");
+ switch (m_revisionHash.value(index, RevisionControlPlugin::UnversionedRevision)) {
+ case RevisionControlPlugin::NormalRevision:
+ return i18nc("@item::intable", "Normal");
+ case RevisionControlPlugin::LocallyModifiedRevision:
+ return i18nc("@item::intable", "Locally modified");
case RevisionControlPlugin::UpdateRequiredRevision:
return i18nc("@item::intable", "Update required");
- case RevisionControlPlugin::LocalRevision:
+ case RevisionControlPlugin::UnversionedRevision:
default:
- return i18nc("@item::intable", "Local");
+ return i18nc("@item::intable", "Unversioned");
}
}
break;
return KDirModel::columnCount(parent) + (ExtraColumnCount - ColumnCount);
}
+void DolphinModel::clearRevisionData()
+{
+ m_revisionHash.clear();
+ m_hasRevisionData = false;
+}
+
bool DolphinModel::hasRevisionData() const
{
return m_hasRevisionData;
void DolphinModel::slotRowsRemoved(const QModelIndex& parent, int start, int end)
{
- Q_ASSERT(hasRevisionData());
-
- const int column = parent.column();
- for (int row = start; row <= end; ++row) {
- m_revisionHash.remove(parent.child(row, column));
+ if (m_hasRevisionData) {
+ const int column = parent.column();
+ for (int row = start; row <= end; ++row) {
+ m_revisionHash.remove(parent.child(row, column));
+ }
}
}
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ void clearRevisionData();
bool hasRevisionData() const;
private slots:
loadDirectory(url);
}
+ // When changing the URL there is no need to keep the revision
+ // data of the previous URL.
+ m_dolphinModel->clearRevisionData();
+
emit startedPathLoading(url);
}
#include <QAbstractProxyModel>
#include <QAbstractItemView>
+#include <QMutexLocker>
#include <QTimer>
/**
class UpdateItemStatesThread : public QThread
{
public:
- UpdateItemStatesThread(QObject* parent);
+ UpdateItemStatesThread(QObject* parent, QMutex* pluginMutex);
void setData(RevisionControlPlugin* plugin,
const QList<RevisionControlObserver::ItemState>& itemStates);
QList<RevisionControlObserver::ItemState> itemStates() const;
private:
RevisionControlPlugin* m_plugin;
+ QMutex* m_pluginMutex;
QList<RevisionControlObserver::ItemState> m_itemStates;
};
-UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent) :
- QThread(parent)
+UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent, QMutex* pluginMutex) :
+ QThread(parent),
+ m_pluginMutex(pluginMutex)
{
}
// it is assumed that all items have the same parent directory
const QString directory = m_itemStates.first().item.url().directory(KUrl::AppendTrailingSlash);
-
+
+ QMutexLocker locker(m_pluginMutex);
if (m_plugin->beginRetrieval(directory)) {
const int count = m_itemStates.count();
for (int i = 0; i < count; ++i) {
return m_itemStates;
}
-// ---
+// ------------------------------------------------------------------------------------------------
RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) :
QObject(view),
m_dirLister(0),
m_dolphinModel(0),
m_dirVerificationTimer(0),
+ m_pluginMutex(QMutex::Recursive),
m_plugin(0),
m_updateItemStatesThread(0)
{
QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>(view->model());
m_dolphinModel = (proxyModel == 0) ?
- qobject_cast<DolphinModel*>(view->model()) :
- qobject_cast<DolphinModel*>(proxyModel->sourceModel());
+ qobject_cast<DolphinModel*>(view->model()) :
+ qobject_cast<DolphinModel*>(proxyModel->sourceModel());
if (m_dolphinModel != 0) {
m_dirLister = m_dolphinModel->dirLister();
connect(m_dirLister, SIGNAL(completed()),
QList<QAction*> RevisionControlObserver::contextMenuActions(const KFileItemList& items) const
{
if (m_dolphinModel->hasRevisionData() && (m_plugin != 0)) {
+ QMutexLocker locker(&m_pluginMutex);
return m_plugin->contextMenuActions(items);
}
return QList<QAction*>();
QList<QAction*> RevisionControlObserver::contextMenuActions(const QString& directory) const
{
if (m_dolphinModel->hasRevisionData() && (m_plugin != 0)) {
+ QMutexLocker locker(&m_pluginMutex);
return m_plugin->contextMenuActions(directory);
}
revisionControlUrl.addPath(m_plugin->fileName());
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);
- m_revisionedDirectory = false;
- disconnect(m_dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
- this, SLOT(delayedDirectoryVerification()));
- disconnect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
- this, SLOT(delayedDirectoryVerification()));
- } else if (!item.isNull()) {
+
+ bool foundRevisionInfo = !item.isNull();
+ if (!foundRevisionInfo && m_revisionedDirectory) {
+ // Revision control systems like Git provide the revision information
+ // file only in the root directory. Check whether the revision information file can
+ // be found in one of the parent directories.
+
+ // TODO...
+ }
+
+ if (foundRevisionInfo) {
if (!m_revisionedDirectory) {
+ m_revisionedDirectory = true;
+
// 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<QPair<KFileItem,KFileItem>>&)),
this, SLOT(delayedDirectoryVerification()));
connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
this, SLOT(delayedDirectoryVerification()));
+ connect(m_plugin, SIGNAL(revisionStatesChanged(const QString&)),
+ this, SLOT(delayedDirectoryVerification()));
}
updateItemStates();
+ } else if (m_revisionedDirectory) {
+ m_revisionedDirectory = false;
+
+ // 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);
+ disconnect(m_dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
+ this, SLOT(delayedDirectoryVerification()));
+ disconnect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
+ this, SLOT(delayedDirectoryVerification()));
+ disconnect(m_plugin, SIGNAL(revisionStatesChanged(const QString&)),
+ this, SLOT(delayedDirectoryVerification()));
}
}
{
Q_ASSERT(m_plugin != 0);
if (m_updateItemStatesThread == 0) {
- m_updateItemStatesThread = new UpdateItemStatesThread(this);
+ m_updateItemStatesThread = new UpdateItemStatesThread(this, &m_pluginMutex);
connect(m_updateItemStatesThread, SIGNAL(finished()),
this, SLOT(applyUpdatedItemStates()));
}
ItemState itemState;
itemState.index = index;
itemState.item = m_dolphinModel->itemForIndex(index);
- itemState.revision = RevisionControlPlugin::LocalRevision;
-
+ itemState.revision = RevisionControlPlugin::UnversionedRevision;
+
itemStates.append(itemState);
}
#include <kfileitem.h>
#include <revisioncontrolplugin.h>
#include <QList>
+#include <QMutex>
#include <QObject>
#include <QPersistentModelIndex>
#include <QString>
QTimer* m_dirVerificationTimer;
+ mutable QMutex m_pluginMutex;
RevisionControlPlugin* m_plugin;
UpdateItemStatesThread* m_updateItemStatesThread;
#include "revisioncontrolplugin.h"
-#include <kaction.h>
-#include <kicon.h>
-#include <klocale.h>
-#include <kfileitem.h>
-#include <QDir>
-#include <QString>
-#include <QTextStream>
-
RevisionControlPlugin::RevisionControlPlugin()
{
}
// ----------------------------------------------------------------------------
+#include <kaction.h>
+#include <kdialog.h>
+#include <kicon.h>
+#include <klocale.h>
+#include <krun.h>
+#include <kshell.h>
+#include <kfileitem.h>
+#include <kvbox.h>
+#include <QDir>
+#include <QLabel>
+#include <QString>
+#include <QTextEdit>
+#include <QTextStream>
+
SubversionPlugin::SubversionPlugin() :
- m_directory(),
+ m_retrievalDir(),
m_revisionInfoHash(),
m_updateAction(0),
+ m_showLocalChangesAction(0),
m_commitAction(0),
m_addAction(0),
- m_removeAction(0)
+ m_removeAction(0),
+ m_contextDir(),
+ m_contextItems()
{
m_updateAction = new KAction(this);
m_updateAction->setIcon(KIcon("view-refresh"));
m_updateAction->setText(i18nc("@item:inmenu", "SVN Update"));
+ connect(m_updateAction, SIGNAL(triggered()),
+ this, SLOT(updateFiles()));
+
+ m_showLocalChangesAction = new KAction(this);
+ m_showLocalChangesAction->setIcon(KIcon("view-split-left-right"));
+ m_showLocalChangesAction->setText(i18nc("@item:inmenu", "Show Local SVN Changes"));
+ connect(m_showLocalChangesAction, SIGNAL(triggered()),
+ this, SLOT(showLocalChanges()));
m_commitAction = new KAction(this);
m_commitAction->setText(i18nc("@item:inmenu", "SVN Commit..."));
+ connect(m_commitAction, SIGNAL(triggered()),
+ this, SLOT(commitFiles()));
m_addAction = new KAction(this);
m_addAction->setIcon(KIcon("list-add"));
m_addAction->setText(i18nc("@item:inmenu", "SVN Add"));
+ connect(m_addAction, SIGNAL(triggered()),
+ this, SLOT(addFiles()));
m_removeAction = new KAction(this);
m_removeAction->setIcon(KIcon("list-remove"));
m_removeAction->setText(i18nc("@item:inmenu", "SVN Delete"));
+ connect(m_removeAction, SIGNAL(triggered()),
+ this, SLOT(removeFiles()));
}
SubversionPlugin::~SubversionPlugin()
bool SubversionPlugin::beginRetrieval(const QString& directory)
{
Q_ASSERT(directory.endsWith('/'));
- m_directory = directory;
+ m_retrievalDir = directory;
const QString path = directory + ".svn/text-base/";
QDir dir(path);
const int size = fileInfoList.size();
QString fileName;
for (int i = 0; i < size; ++i) {
- fileName = fileInfoList.at(i).fileName();
+ const QFileInfo fileInfo = fileInfoList.at(i);
+ fileName = fileInfo.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);
+ info.size = fileInfo.size();
+ info.timeStamp = fileInfo.lastModified();
+ m_revisionInfoHash.insert(directory + fileName, info);
}
}
return size > 0;
RevisionControlPlugin::RevisionState SubversionPlugin::revisionState(const KFileItem& item)
{
- const QString name = item.name();
+ const QString itemUrl = item.localPath();
if (item.isDir()) {
- QFile file(m_directory + name + "/.svn");
+ QFile file(itemUrl + "/.svn");
if (file.open(QIODevice::ReadOnly)) {
file.close();
- // TODO...
- return RevisionControlPlugin::LatestRevision;
+ return RevisionControlPlugin::NormalRevision;
}
- } else if (m_revisionInfoHash.contains(name)) {
- const RevisionInfo info = m_revisionInfoHash.value(item.name());
+ } else if (m_revisionInfoHash.contains(itemUrl)) {
+ const RevisionInfo info = m_revisionInfoHash.value(itemUrl);
const QDateTime localTimeStamp = item.time(KFileItem::ModificationTime).dateTime();
const QDateTime versionedTimeStamp = info.timeStamp;
if (localTimeStamp > versionedTimeStamp) {
if ((info.size != item.size()) || !equalRevisionContent(item.name())) {
- return RevisionControlPlugin::EditingRevision;
+ return RevisionControlPlugin::LocallyModifiedRevision;
}
} else if (localTimeStamp < versionedTimeStamp) {
if ((info.size != item.size()) || !equalRevisionContent(item.name())) {
return RevisionControlPlugin::UpdateRequiredRevision;
}
}
- return RevisionControlPlugin::LatestRevision;
+ return RevisionControlPlugin::NormalRevision;
}
- return RevisionControlPlugin::LocalRevision;
+ return RevisionControlPlugin::UnversionedRevision;
}
-QList<QAction*> SubversionPlugin::contextMenuActions(const KFileItemList& items) const
+QList<QAction*> SubversionPlugin::contextMenuActions(const KFileItemList& items)
{
- Q_UNUSED(items);
+ Q_ASSERT(!items.isEmpty());
+
+ m_contextItems = items;
+ m_contextDir.clear();
+
+ // iterate all items and check the revision state to know which
+ // actions can be enabled
+ const int itemsCount = items.count();
+ int revisionedCount = 0;
+ int editingCount = 0;
+ foreach (const KFileItem& item, items) {
+ const RevisionState state = revisionState(item);
+ if (state != UnversionedRevision) {
+ ++revisionedCount;
+ }
+
+ switch (state) {
+ case LocallyModifiedRevision:
+ case ConflictingRevision:
+ ++editingCount;
+ break;
+ default:
+ break;
+ }
+ }
+ m_commitAction->setEnabled(editingCount > 0);
+ m_addAction->setEnabled(revisionedCount == 0);
+ m_removeAction->setEnabled(revisionedCount == itemsCount);
QList<QAction*> actions;
actions.append(m_updateAction);
return actions;
}
-QList<QAction*> SubversionPlugin::contextMenuActions(const QString& directory) const
+QList<QAction*> SubversionPlugin::contextMenuActions(const QString& directory)
{
- Q_UNUSED(directory);
+ m_contextDir = directory;
+ m_contextItems.clear();
QList<QAction*> actions;
actions.append(m_updateAction);
+ actions.append(m_showLocalChangesAction);
actions.append(m_commitAction);
return actions;
}
+void SubversionPlugin::updateFiles()
+{
+ execSvnCommand("update");
+}
+
+void SubversionPlugin::showLocalChanges()
+{
+ Q_ASSERT(!m_contextDir.isEmpty());
+ Q_ASSERT(m_contextItems.isEmpty());
+
+ const QString command = "mkfifo /tmp/fifo; svn diff " +
+ KShell::quoteArg(m_contextDir) +
+ " > /tmp/fifo & kompare /tmp/fifo; rm /tmp/fifo";
+ KRun::runCommand(command, 0);
+}
+
+void SubversionPlugin::commitFiles()
+{
+ KDialog dialog(0, Qt::Dialog);
+
+ KVBox* box = new KVBox(&dialog);
+ new QLabel(i18nc("@label", "Description:"), box);
+ QTextEdit* editor = new QTextEdit(box);
+
+ dialog.setMainWidget(box);
+ dialog.setCaption(i18nc("@title:window", "SVN Commit"));
+ dialog.setButtons(KDialog::Ok | KDialog::Cancel);
+ dialog.setDefaultButton(KDialog::Ok);
+ dialog.setButtonText(KDialog::Ok, i18nc("@action:button", "Commit"));
+
+ KConfigGroup dialogConfig(KSharedConfig::openConfig("dolphinrc"),
+ "SvnCommitDialog");
+ dialog.restoreDialogSize(dialogConfig);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ const QString description = editor->toPlainText();
+ execSvnCommand("commit -m " + KShell::quoteArg(description));
+ }
+
+ dialog.saveDialogSize(dialogConfig, KConfigBase::Persistent);
+}
+
+void SubversionPlugin::addFiles()
+{
+ execSvnCommand("add");
+}
+
+void SubversionPlugin::removeFiles()
+{
+ execSvnCommand("remove");
+}
+
+void SubversionPlugin::execSvnCommand(const QString& svnCommand)
+{
+ const QString command = "svn " + svnCommand + ' ';
+ if (!m_contextDir.isEmpty()) {
+ KRun::runCommand(command + KShell::quoteArg(m_contextDir), 0);
+ } else {
+ foreach (const KFileItem& item, m_contextItems) {
+ KRun::runCommand(command + KShell::quoteArg(item.localPath()), 0);
+ }
+ }
+}
+
bool SubversionPlugin::equalRevisionContent(const QString& name) const
{
- QFile localFile(m_directory + '/' + name);
+ QFile localFile(m_retrievalDir + '/' + name);
if (!localFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
return false;
}
- QFile revisionedFile(m_directory + "/.svn/text-base/" + name + ".svn-base");
+ QFile revisionedFile(m_retrievalDir + "/.svn/text-base/" + name + ".svn-base");
if (!revisionedFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
return false;
}
return localText.atEnd() && revisionedText.atEnd();
}
-
* @brief Base class for revision control plugins.
*
* Enables the file manager to show the revision state
- * 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.
+ * of a revisioned file.
*/
class LIBDOLPHINPRIVATE_EXPORT RevisionControlPlugin : public QObject
{
public:
enum RevisionState
{
- LocalRevision,
- LatestRevision,
+ /** The file is not under revision control. */
+ UnversionedRevision,
+ /**
+ * The file is under revision control and represents
+ * the latest version.
+ */
+ NormalRevision,
+ /**
+ * The file is under revision control and a newer
+ * version exists on the main branch.
+ */
UpdateRequiredRevision,
- EditingRevision,
+ /**
+ * The file is under revision control and has been
+ * modified locally.
+ */
+ LocallyModifiedRevision,
+ /**
+ * The file has not been under revision control but
+ * has been marked to get added with the next commit.
+ */
+ AddedRevision,
+ /**
+ * The file is under revision control and has been locally
+ * modified. A modification has also been done on the main
+ * branch.
+ */
ConflictingRevision
- // TODO...
};
RevisionControlPlugin();
* If an action triggers a change of the revisions, the signal
* RevisionControlPlugin::revisionStatesChanged() must be emitted.
*/
- virtual QList<QAction*> contextMenuActions(const KFileItemList& items) const = 0;
+ virtual QList<QAction*> contextMenuActions(const KFileItemList& items) = 0;
/**
* Returns the list of actions that should be shown in the context menu
* for the directory \p directory. If an action triggers a change of the revisions,
* the signal RevisionControlPlugin::revisionStatesChanged() must be emitted.
*/
- virtual QList<QAction*> contextMenuActions(const QString& directory) const = 0;
+ virtual QList<QAction*> contextMenuActions(const QString& directory) = 0;
signals:
/**
// TODO: This is just a temporary test class. It will be made available as
// plugin outside Dolphin later.
-#include <QFileInfoList>
+#include <kfileitem.h>
#include <QHash>
class LIBDOLPHINPRIVATE_EXPORT SubversionPlugin : public RevisionControlPlugin
{
+ Q_OBJECT
+
public:
SubversionPlugin();
virtual ~SubversionPlugin();
virtual bool beginRetrieval(const QString& directory);
virtual void endRetrieval();
virtual RevisionControlPlugin::RevisionState revisionState(const KFileItem& item);
- virtual QList<QAction*> contextMenuActions(const KFileItemList& items) const;
- virtual QList<QAction*> contextMenuActions(const QString& directory) const;
+ virtual QList<QAction*> contextMenuActions(const KFileItemList& items);
+ virtual QList<QAction*> contextMenuActions(const QString& directory);
+
+private slots:
+ void updateFiles();
+ void showLocalChanges();
+ void commitFiles();
+ void addFiles();
+ void removeFiles();
private:
+ /**
+ * Executes the command "svn {svnCommand}" for the files that have been
+ * set by getting the context menu actions (see contextMenuActions()).
+ */
+ void execSvnCommand(const QString& svnCommand);
+
/**
* Returns true, if the content of the local file \p name is equal to the
* content of the revisioned file.
QDateTime timeStamp;
};
- QString m_directory;
+ QString m_retrievalDir;
QHash<QString, RevisionInfo> m_revisionInfoHash;
QAction* m_updateAction;
+ QAction* m_showLocalChangesAction;
QAction* m_commitAction;
QAction* m_addAction;
QAction* m_removeAction;
+ mutable QString m_contextDir;
+ mutable KFileItemList m_contextItems;
};
#endif // REVISIONCONTROLPLUGIN_H