diff options
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/dolphincategorydrawer.cpp | 27 | ||||
| -rw-r--r-- | src/dolphincolumnwidget.cpp | 3 | ||||
| -rw-r--r-- | src/dolphindetailsview.cpp | 22 | ||||
| -rw-r--r-- | src/dolphinfileitemdelegate.cpp | 39 | ||||
| -rw-r--r-- | src/dolphinmodel.cpp | 137 | ||||
| -rw-r--r-- | src/dolphinmodel.h | 38 | ||||
| -rw-r--r-- | src/dolphinsortfilterproxymodel.cpp | 48 | ||||
| -rw-r--r-- | src/dolphinview.cpp | 3 | ||||
| -rw-r--r-- | src/panels/folders/paneltreeview.cpp | 3 | ||||
| -rw-r--r-- | src/revisioncontrolobserver.cpp | 124 | ||||
| -rw-r--r-- | src/revisioncontrolobserver.h | 66 | ||||
| -rw-r--r-- | src/revisioncontrolplugin.cpp | 82 | ||||
| -rw-r--r-- | src/revisioncontrolplugin.h | 103 |
14 files changed, 515 insertions, 182 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83b2eb3d9..38489fceb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,8 @@ set(dolphinprivate_LIB_SRCS draganddrophelper.cpp folderexpander.cpp renamedialog.cpp + revisioncontrolobserver.cpp + revisioncontrolplugin.cpp selectiontoggle.cpp selectionmanager.cpp settings/additionalinfodialog.cpp diff --git a/src/dolphincategorydrawer.cpp b/src/dolphincategorydrawer.cpp index b06f97560..00af90d63 100644 --- a/src/dolphincategorydrawer.cpp +++ b/src/dolphincategorydrawer.cpp @@ -193,35 +193,18 @@ void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole, break; } -#ifdef HAVE_NEPOMUK - case DolphinModel::Rating: { - paintText = false; + case DolphinModel::Revision: paintIcon = false; - - painter->setLayoutDirection( option.direction ); - QRect ratingRect( option.rect ); - ratingRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); - ratingRect.setHeight( iconSize ); - KRatingPainter::paintRating( painter, ratingRect, Qt::AlignLeft, category.toInt() ); break; - } - - case DolphinModel::Tags: - paintIcon = false; - break; -#endif } if (paintIcon) { painter->drawPixmap(QRect(option.direction == Qt::LeftToRight ? opt.rect.left() : opt.rect.right() - icon.width() + (iconSize / 4), opt.rect.top(), icon.width(), icon.height()), icon); - if (option.direction == Qt::LeftToRight) - { + if (option.direction == Qt::LeftToRight) { opt.rect.setLeft(opt.rect.left() + icon.width() + (iconSize / 4)); - } - else - { + } else { opt.rect.setRight(opt.rect.right() + (iconSize / 4)); } } @@ -232,9 +215,7 @@ void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole, painter->setPen(color); QRect textRect = opt.rect; - - if (option.direction == Qt::RightToLeft) - { + if (option.direction == Qt::RightToLeft) { textRect.setWidth(textRect.width() - (paintIcon ? icon.width() + (iconSize / 4) : -(iconSize / 4))); } diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp index b4c9f11c1..afa79e78f 100644 --- a/src/dolphincolumnwidget.cpp +++ b/src/dolphincolumnwidget.cpp @@ -30,6 +30,7 @@ #include "dolphin_generalsettings.h" #include "draganddrophelper.h" #include "folderexpander.h" +#include "revisioncontrolobserver.h" #include "selectionmanager.h" #include "tooltips/tooltipmanager.h" @@ -154,6 +155,8 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, folderExpander->setEnabled(DolphinSettings::instance().generalSettings()->autoExpandFolders()); connect (folderExpander, SIGNAL(enterDir(const QModelIndex&)), m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); + + new RevisionControlObserver(this); } DolphinColumnWidget::~DolphinColumnWidget() diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index aa65ff6bc..4a9b9038d 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -173,9 +173,6 @@ bool DolphinDetailsView::event(QEvent* event) headerView->setMovable(false); updateColumnVisibility(); - - hideColumn(DolphinModel::Rating); - hideColumn(DolphinModel::Tags); } return QTreeView::event(event); @@ -566,7 +563,7 @@ void DolphinDetailsView::configureSettings(const QPoint& pos) // add checkbox items for each column QHeaderView* headerView = header(); - for (int i = DolphinModel::Size; i <= DolphinModel::Type; ++i) { + for (int i = DolphinModel::Size; i <= DolphinModel::Revision; ++i) { const int logicalIndex = headerView->logicalIndex(i); const QString text = model()->headerData(i, Qt::Horizontal).toString(); QAction* action = popup.addAction(text); @@ -601,7 +598,7 @@ void DolphinDetailsView::configureSettings(const QPoint& pos) void DolphinDetailsView::updateColumnVisibility() { const KFileItemDelegate::InformationList list = m_controller->dolphinView()->additionalInfo(); - for (int i = DolphinModel::Size; i <= DolphinModel::Type; ++i) { + for (int i = DolphinModel::Size; i <= DolphinModel::Revision; ++i) { const KFileItemDelegate::Information info = infoForColumn(i); const bool hide = !list.contains(info); if (isColumnHidden(i) != hide) { @@ -902,13 +899,14 @@ void DolphinDetailsView::resizeColumns() QHeaderView* headerView = header(); QFontMetrics fontMetrics(viewport()->font()); - int columnWidth[KDirModel::ColumnCount]; - columnWidth[KDirModel::Size] = fontMetrics.width("00000 Items"); - columnWidth[KDirModel::ModifiedTime] = fontMetrics.width("0000-00-00 00:00"); - columnWidth[KDirModel::Permissions] = fontMetrics.width("xxxxxxxxxx"); - columnWidth[KDirModel::Owner] = fontMetrics.width("xxxxxxxxxx"); - columnWidth[KDirModel::Group] = fontMetrics.width("xxxxxxxxxx"); - columnWidth[KDirModel::Type] = fontMetrics.width("XXXX Xxxxxxx"); + int columnWidth[DolphinModel::Revision + 1]; + columnWidth[DolphinModel::Size] = fontMetrics.width("00000 Items"); + columnWidth[DolphinModel::ModifiedTime] = fontMetrics.width("0000-00-00 00:00"); + columnWidth[DolphinModel::Permissions] = fontMetrics.width("xxxxxxxxxx"); + columnWidth[DolphinModel::Owner] = fontMetrics.width("xxxxxxxxxx"); + columnWidth[DolphinModel::Group] = fontMetrics.width("xxxxxxxxxx"); + columnWidth[DolphinModel::Type] = fontMetrics.width("XXXX Xxxxxxx"); + columnWidth[DolphinModel::Revision] = fontMetrics.width("xxxxxxxx"); int requiredWidth = 0; for (int i = KDirModel::Size; i <= KDirModel::Type; ++i) { diff --git a/src/dolphinfileitemdelegate.cpp b/src/dolphinfileitemdelegate.cpp index 9be70647b..6478baf3b 100644 --- a/src/dolphinfileitemdelegate.cpp +++ b/src/dolphinfileitemdelegate.cpp @@ -19,12 +19,13 @@ #include "dolphinfileitemdelegate.h" +#include <dolphinmodel.h> +#include <kfileitem.h> + #include <QAbstractItemModel> #include <QAbstractProxyModel> #include <QFontMetrics> - -#include <kdirmodel.h> -#include <kfileitem.h> +#include <QPainter> DolphinFileItemDelegate::DolphinFileItemDelegate(QObject* parent) : KFileItemDelegate(parent), @@ -40,17 +41,19 @@ void DolphinFileItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(index.model()); + const DolphinModel* dolphinModel = static_cast<const DolphinModel*>(proxyModel->sourceModel()); + if (m_hasMinimizedNameColumn && (index.column() == KDirModel::Name)) { QStyleOptionViewItemV4 opt(option); - const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(index.model()); - const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel()); const QModelIndex dirIndex = proxyModel->mapToSource(index); - const KFileItem item = dirModel->itemForIndex(dirIndex); + const KFileItem item = dolphinModel->itemForIndex(dirIndex); if (!item.isNull()) { - // Symbolic links are displayed in an italic font - if (item.isLink()) + // symbolic links are displayed in an italic font + if (item.isLink()) { opt.font.setItalic(true); + } const int width = nameColumnWidth(item.text(), opt); opt.rect.setWidth(width); @@ -59,6 +62,26 @@ void DolphinFileItemDelegate::paint(QPainter* painter, } else { KFileItemDelegate::paint(painter, option, index); } + + if (dolphinModel->hasRevisionData()) { + // The currently shown items are under revision control. Show the current revision + // state above the decoration. + 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<DolphinModel::RevisionState>(data.toInt()); + + if (state != DolphinModel::LocalRevision) { + // TODO: The following code is just a proof of concept. Icons will be used later... + QColor color(200, 0, 0, 32); + switch (state) { + case DolphinModel::LatestRevision: color = QColor(0, 180, 0, 32); break; + // ... + default: break; + } + painter->fillRect(option.rect, color); + } + } } int DolphinFileItemDelegate::nameColumnWidth(const QString& name, const QStyleOptionViewItem& option) diff --git a/src/dolphinmodel.cpp b/src/dolphinmodel.cpp index 819b37d2a..f399c3304 100644 --- a/src/dolphinmodel.cpp +++ b/src/dolphinmodel.cpp @@ -45,13 +45,16 @@ #include <QList> #include <QSortFilterProxyModel> #include <QPainter> +#include <QPersistentModelIndex> #include <QDir> #include <QFileInfo> const char* DolphinModel::m_others = I18N_NOOP2("@title:group Name", "Others"); -DolphinModel::DolphinModel(QObject* parent) - : KDirModel(parent) +DolphinModel::DolphinModel(QObject* parent) : + KDirModel(parent), + m_hasRevisionData(false), + m_revisionHash() { } @@ -59,72 +62,80 @@ DolphinModel::~DolphinModel() { } +bool DolphinModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if ((index.column() == DolphinModel::Revision) && (role == Qt::DecorationRole)) { + // TODO: remove data again when items are deleted... + + const QPersistentModelIndex key = index; + const RevisionState state = static_cast<RevisionState>(value.toInt()); + if (m_revisionHash.value(key, LocalRevision) != state) { + m_hasRevisionData = true; + m_revisionHash.insert(key, state); + emit dataChanged(index, index); + return true; + } + } + + return KDirModel::setData(index, value, role); +} + QVariant DolphinModel::data(const QModelIndex& index, int role) const { switch (role) { case KCategorizedSortFilterProxyModel::CategoryDisplayRole: return displayRoleData(index); + case KCategorizedSortFilterProxyModel::CategorySortRole: return sortRoleData(index); + + case Qt::DecorationRole: + if (index.column() == DolphinModel::Revision) { + return m_revisionHash.value(index, LocalRevision); + } + break; + + case Qt::DisplayRole: + if (index.column() == DolphinModel::Revision) { + switch (m_revisionHash.value(index, LocalRevision)) { + case LatestRevision: + return i18nc("@item::intable", "Latest"); + + case LocalRevision: + default: + return i18nc("@item::intable", "Local"); + } + } + break; + default: - return KDirModel::data(index, role); + break; } -} -int DolphinModel::columnCount(const QModelIndex &parent) const -{ - return KDirModel::columnCount(parent) + (ExtraColumnCount - ColumnCount); + return KDirModel::data(index, role); } -quint32 DolphinModel::ratingForIndex(const QModelIndex& index) +QVariant DolphinModel::headerData(int section, Qt::Orientation orientation, int role) const { -#ifdef HAVE_NEPOMUK - quint32 rating = 0; + if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) { + if (section < KDirModel::ColumnCount) { + return KDirModel::headerData(section, orientation, role); + } - const DolphinModel* dolphinModel = static_cast<const DolphinModel*>(index.model()); - KFileItem item = dolphinModel->itemForIndex(index); - if (!item.isNull()) { - const Nepomuk::Resource resource(item.url().url(), Soprano::Vocabulary::Xesam::File()); - rating = resource.rating(); + Q_ASSERT(section == DolphinModel::Revision); + return i18nc("@title::column", "Revision"); } - return rating; -#else - Q_UNUSED(index); - return 0; -#endif + return QVariant(); } -QString DolphinModel::tagsForIndex(const QModelIndex& index) +int DolphinModel::columnCount(const QModelIndex& parent) const { -#ifdef HAVE_NEPOMUK - QString tagsString; - - const DolphinModel* dolphinModel = static_cast<const DolphinModel*>(index.model()); - KFileItem item = dolphinModel->itemForIndex(index); - if (!item.isNull()) { - const Nepomuk::Resource resource(item.url().url(), Soprano::Vocabulary::Xesam::File()); - const QList<Nepomuk::Tag> tags = resource.tags(); - QStringList stringList; - foreach (const Nepomuk::Tag& tag, tags) { - stringList.append(tag.label()); - } - stringList.sort(); - - foreach (const QString& str, stringList) { - tagsString += str; - tagsString += ", "; - } - - if (!tagsString.isEmpty()) { - tagsString.resize(tagsString.size() - 2); - } - } + return KDirModel::columnCount(parent) + (ExtraColumnCount - ColumnCount); +} - return tagsString; -#else - Q_UNUSED(index); - return QString(); -#endif +bool DolphinModel::hasRevisionData() const +{ + return m_hasRevisionData; } QVariant DolphinModel::displayRoleData(const QModelIndex& index) const @@ -328,22 +339,10 @@ QVariant DolphinModel::displayRoleData(const QModelIndex& index) const retString = item.mimeComment(); break; -#ifdef HAVE_NEPOMUK - case DolphinModel::Rating: { - const quint32 rating = ratingForIndex(index); - retString = QString::number(rating); - break; - } - - case DolphinModel::Tags: { - retString = tagsForIndex(index); - if (retString.isEmpty()) { - retString = i18nc("@title:group Tags", "Not yet tagged"); - } + case DolphinModel::Revision: + retString = "test"; break; } -#endif - } return retString; } @@ -418,18 +417,6 @@ QVariant DolphinModel::sortRoleData(const QModelIndex& index) const } break; -#ifdef HAVE_NEPOMUK - case DolphinModel::Rating: { - retVariant = ratingForIndex(index); - break; - } - - case DolphinModel::Tags: { - retVariant = tagsForIndex(index).count(); - break; - } -#endif - default: break; } diff --git a/src/dolphinmodel.h b/src/dolphinmodel.h index 44067f5a5..b03507dc5 100644 --- a/src/dolphinmodel.h +++ b/src/dolphinmodel.h @@ -22,43 +22,45 @@ #define DOLPHINMODEL_H #include <kdirmodel.h> - #include <libdolphin_export.h> -class LIBDOLPHINPRIVATE_EXPORT DolphinModel - : public KDirModel +#include <QHash> +#include <QPersistentModelIndex> + +class LIBDOLPHINPRIVATE_EXPORT DolphinModel : public KDirModel { + Q_OBJECT + public: enum AdditionalColumns { - Rating = ColumnCount, // ColumnCount defined at KDirModel - Tags, + Revision = KDirModel::ColumnCount, ExtraColumnCount }; + enum RevisionState { + LocalRevision, + LatestRevision + // TODO... + }; + DolphinModel(QObject* parent = 0); virtual ~DolphinModel(); - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; - /** - * Returns the rating for the item with the index \a index. 0 is - * returned if no item could be found. - */ - static quint32 ratingForIndex(const QModelIndex& index); - - /** - * Returns the tags for the item with the index \a index. If no - * tag is applied, a predefined string will be returned. - */ - static QString tagsForIndex(const QModelIndex& index); + bool hasRevisionData() const; private: QVariant displayRoleData(const QModelIndex& index) const; QVariant sortRoleData(const QModelIndex& index) const; private: + bool m_hasRevisionData; + QHash<QPersistentModelIndex, RevisionState> m_revisionHash; + static const char* m_others; }; diff --git a/src/dolphinsortfilterproxymodel.cpp b/src/dolphinsortfilterproxymodel.cpp index 2622f9034..d119a416f 100644 --- a/src/dolphinsortfilterproxymodel.cpp +++ b/src/dolphinsortfilterproxymodel.cpp @@ -109,50 +109,10 @@ DolphinView::Sorting DolphinSortFilterProxyModel::sortingForColumn(int column) bool DolphinSortFilterProxyModel::subSortLessThan(const QModelIndex& left, const QModelIndex& right) const { -#ifdef HAVE_NEPOMUK - switch (left.column()) { - case DolphinView::SortByRating: { - const quint32 leftRating = DolphinModel::ratingForIndex(left); - const quint32 rightRating = DolphinModel::ratingForIndex(right); - - if (leftRating == rightRating) { - DolphinModel* dolphinModel = static_cast<DolphinModel*>(sourceModel()); - const KFileItem leftFileItem = dolphinModel->itemForIndex(left); - const KFileItem rightFileItem = dolphinModel->itemForIndex(right); - bool result; - if (isDirectoryOrHidden(leftFileItem, rightFileItem, result)) { - return result; - } - - return KStringHandler::naturalCompare(leftFileItem.name(), rightFileItem.name(), sortCaseSensitivity()) < 0; - } - - return leftRating > rightRating; - } - - case DolphinView::SortByTags: { - const QString leftTags = DolphinModel::tagsForIndex(left); - const QString rightTags = DolphinModel::tagsForIndex(right); - - if (leftTags == rightTags) { - DolphinModel* dolphinModel = static_cast<DolphinModel*>(sourceModel()); - const KFileItem leftFileItem = dolphinModel->itemForIndex(left); - const KFileItem rightFileItem = dolphinModel->itemForIndex(right); - bool result; - if (isDirectoryOrHidden(leftFileItem, rightFileItem, result)) { - return result; - } - - return KStringHandler::naturalCompare(leftFileItem.name(), rightFileItem.name(), sortCaseSensitivity()) < 0; - } - - return KStringHandler::naturalCompare(leftTags, rightTags) < 0; - } - - default: - break; - } -#endif + // switch (left.column()) { + // case DolphinView::Revision: + // return left > right; + // ... return KDirSortFilterProxyModel::subSortLessThan(left, right); } diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index 4a81b12ea..c454d65a5 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -62,6 +62,7 @@ #include "draganddrophelper.h" #include "folderexpander.h" #include "renamedialog.h" +#include "revisioncontrolobserver.h" #include "tooltips/tooltipmanager.h" #include "settings/dolphinsettings.h" #include "viewproperties.h" @@ -1460,6 +1461,8 @@ void DolphinView::createView() m_previewGenerator = new KFilePreviewGenerator(view); m_previewGenerator->setPreviewShown(m_showPreview); + new RevisionControlObserver(view); + if (DolphinSettings::instance().generalSettings()->showToolTips()) { m_toolTipManager = new ToolTipManager(view, m_proxyModel); connect(m_controller, SIGNAL(hideToolTip()), diff --git a/src/panels/folders/paneltreeview.cpp b/src/panels/folders/paneltreeview.cpp index b285789f0..5d3f8a9b8 100644 --- a/src/panels/folders/paneltreeview.cpp +++ b/src/panels/folders/paneltreeview.cpp @@ -75,8 +75,7 @@ bool PanelTreeView::event(QEvent* event) hideColumn(DolphinModel::Owner); hideColumn(DolphinModel::Group); hideColumn(DolphinModel::Type); - hideColumn(DolphinModel::Rating); - hideColumn(DolphinModel::Tags); + hideColumn(DolphinModel::Revision); header()->hide(); break; diff --git a/src/revisioncontrolobserver.cpp b/src/revisioncontrolobserver.cpp new file mode 100644 index 000000000..99fd61b67 --- /dev/null +++ b/src/revisioncontrolobserver.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + * Copyright (C) 2009 by Peter Penz <[email protected]> * + * * + * 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 "revisioncontrolobserver.h" + +#include "dolphinmodel.h" +#include "revisioncontrolplugin.h" + +#include <kdirlister.h> + +#include <QAbstractProxyModel> +#include <QAbstractItemView> +#include <QTimer> + +RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) : + QObject(view), + m_view(view), + m_dirLister(0), + m_dolphinModel(0), + m_dirVerificationTimer(0), + m_plugin(0) +{ + Q_ASSERT(view != 0); + + QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>(view->model()); + m_dolphinModel = (proxyModel == 0) ? + qobject_cast<DolphinModel*>(view->model()) : + qobject_cast<DolphinModel*>(proxyModel->sourceModel()); + if (m_dolphinModel != 0) { + m_dirLister = m_dolphinModel->dirLister(); + connect(m_dirLister, SIGNAL(completed()), + this, SLOT(delayedDirectoryVerification())); + // TODO: + // connect(m_dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)), + // 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 + // The timeout will be decreased as soon as a versioned directory has been + // found (see verifyDirectory()). + m_dirVerificationTimer = new QTimer(this); + m_dirVerificationTimer->setSingleShot(true); + m_dirVerificationTimer->setInterval(500); + connect(m_dirVerificationTimer, SIGNAL(timeout()), + this, SLOT(verifyDirectory())); + } +} + +RevisionControlObserver::~RevisionControlObserver() +{ + delete m_plugin; + m_plugin = 0; +} + +void RevisionControlObserver::delayedDirectoryVerification() +{ + m_dirVerificationTimer->start(); +} + +void RevisionControlObserver::verifyDirectory() +{ + KUrl revisionControlUrl = m_dirLister->url(); + if (!revisionControlUrl.isLocalFile()) { + return; + } + + if (m_plugin == 0) { + // TODO: just for testing purposes. A plugin approach will be used later. + m_plugin = new SubversionPlugin(); + } + + revisionControlUrl.addPath(m_plugin->fileName()); + KFileItem item = m_dirLister->findByUrl(revisionControlUrl); + if (item.isNull()) { + // 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); + updateItemStates(); + } +} + +void RevisionControlObserver::updateItemStates() +{ + Q_ASSERT(m_plugin != 0); + const KUrl directory = m_dirLister->url(); + if (!m_plugin->beginRetrieval(directory.toLocalFile(KUrl::AddTrailingSlash))) { + return; + } + + const int rowCount = m_dolphinModel->rowCount(); + for (int row = 0; row < rowCount; ++row) { + const QModelIndex index = m_dolphinModel->index(row, DolphinModel::Revision); + const KFileItem item = m_dolphinModel->itemForIndex(index); + const RevisionControlPlugin::RevisionState revision = m_plugin->revisionState(item.name()); + m_dolphinModel->setData(index, QVariant(static_cast<int>(revision)), Qt::DecorationRole); + } + m_view->viewport()->repaint(); // TODO: this should not be necessary, as DolphinModel::setData() calls dataChanged() + + m_plugin->endRetrieval(); +} + +#include "revisioncontrolobserver.moc" diff --git a/src/revisioncontrolobserver.h b/src/revisioncontrolobserver.h new file mode 100644 index 000000000..14ea0528e --- /dev/null +++ b/src/revisioncontrolobserver.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2009 by Peter Penz <[email protected]> * + * * + * 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 REVISIONCONTROLOBSERVER_H +#define REVISIONCONTROLOBSERVER_H + +#include <libdolphin_export.h> + +#include <QObject> +#include <QString> + +class DolphinModel; +class KDirLister; +class QAbstractItemView; +class QTimer; +class RevisionControlPlugin; + +/** + * @brief Observes all revision control plugins. + * + * The item view gets updated automatically if the currently shown + * directory is under revision control. + * + * @see RevisionControlPlugin + */ +class LIBDOLPHINPRIVATE_EXPORT RevisionControlObserver : public QObject +{ + Q_OBJECT + +public: + RevisionControlObserver(QAbstractItemView* view); + virtual ~RevisionControlObserver(); + +private slots: + void delayedDirectoryVerification(); + void verifyDirectory(); + +private: + void updateItemStates(); + +private: + QAbstractItemView* m_view; + KDirLister* m_dirLister; + DolphinModel* m_dolphinModel; + QTimer* m_dirVerificationTimer; + RevisionControlPlugin* m_plugin; +}; + +#endif // REVISIONCONTROLOBSERVER_H + diff --git a/src/revisioncontrolplugin.cpp b/src/revisioncontrolplugin.cpp new file mode 100644 index 000000000..6c0f82fb8 --- /dev/null +++ b/src/revisioncontrolplugin.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2009 by Peter Penz <[email protected]> * + * * + * 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 "revisioncontrolplugin.h" + +#include <QDir> + +RevisionControlPlugin::RevisionControlPlugin() +{ +} + +RevisionControlPlugin::~RevisionControlPlugin() +{ +} + +// ---------------------------------------------------------------------------- + +SubversionPlugin::SubversionPlugin() : + m_directory(), + m_fileInfoHash() +{ +} + +SubversionPlugin::~SubversionPlugin() +{ +} + +QString SubversionPlugin::fileName() const +{ + return ".svn"; +} + +bool SubversionPlugin::beginRetrieval(const QString& directory) +{ + Q_ASSERT(directory.endsWith('/')); + const QString path = directory + ".svn/text-base/"; + + QDir dir(path); + const QFileInfoList fileInfoList = dir.entryInfoList(); + const int size = fileInfoList.size(); + QString fileName; + 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()) { + m_fileInfoHash.insert(fileName, fileInfoList.at(i)); + } + } + return size > 0; +} + +void SubversionPlugin::endRetrieval() +{ +} + +RevisionControlPlugin::RevisionState SubversionPlugin::revisionState(const QString& fileName) +{ + if (m_fileInfoHash.contains(fileName)) { + // TODO... + return RevisionControlPlugin::LatestRevision; + } + + return RevisionControlPlugin::LocalRevision; +} diff --git a/src/revisioncontrolplugin.h b/src/revisioncontrolplugin.h new file mode 100644 index 000000000..95850711d --- /dev/null +++ b/src/revisioncontrolplugin.h @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (C) 2009 by Peter Penz <[email protected]> * + * * + * 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 REVISIONCONTROLPLUGIN_H +#define REVISIONCONTROLPLUGIN_H + +#include <libdolphin_export.h> + +#include <QString> + +/** + * @brief Base class for revision control plugins. + * + * Enables the file manager to show the revision state + * of a revisioned file. + */ +class LIBDOLPHINPRIVATE_EXPORT RevisionControlPlugin +{ +public: + enum RevisionState + { + LocalRevision, + LatestRevision + // TODO... + }; + + RevisionControlPlugin(); + virtual ~RevisionControlPlugin(); + + /** + * Returns the name of the file which stores + * the revision control informations. + * (e. g. .svn, .cvs, .git). + */ + virtual QString fileName() const = 0; + + /** + * Is invoked whenever the revision control + * information will get retrieved for the directory + * \p directory. It is assured that the directory + * contains a trailing slash. + */ + virtual bool beginRetrieval(const QString& directory) = 0; + + /** + * Is invoked after the revision control information has been + * received. It is assured that + * RevisionControlPlugin::beginInfoRetrieval() has been + * invoked before. + */ + virtual void endRetrieval() = 0; + + /** + * Returns the revision state for the file with the name \p fileName. + * It is assured that RevisionControlPlugin::beginInfoRetrieval() has been + * invoked before and that the file is part of the directory specified + * in beginInfoRetrieval(). + */ + virtual RevisionState revisionState(const QString& fileName) = 0; + +}; + + + + +// TODO: This is just a temporary test class. It will be made available as +// plugin outside Dolphin later. + +#include <QFileInfoList> +#include <QHash> + +class LIBDOLPHINPRIVATE_EXPORT SubversionPlugin : public RevisionControlPlugin +{ +public: + SubversionPlugin(); + virtual ~SubversionPlugin(); + virtual QString fileName() const; + virtual bool beginRetrieval(const QString& directory); + virtual void endRetrieval(); + virtual RevisionControlPlugin::RevisionState revisionState(const QString& fileName); + +private: + QString m_directory; + QHash<QString, QFileInfo> m_fileInfoHash; +}; +#endif // REVISIONCONTROLPLUGIN_H + |
