Commit 8f9f877e authored by Peter Penz's avatar Peter Penz
Browse files

Implement inline-renaming for the new view-engine

BUG: 286893
FIXED-IN: 4.9.0
parent 234818d7
......@@ -38,6 +38,7 @@ set(dolphinprivate_LIB_SRCS
kitemviews/private/kfileitemmodelfilter.cpp
kitemviews/private/kitemlistheaderwidget.cpp
kitemviews/private/kitemlistkeyboardsearchmanager.cpp
kitemviews/private/kitemlistroleeditor.cpp
kitemviews/private/kitemlistrubberband.cpp
kitemviews/private/kitemlistselectiontoggle.cpp
kitemviews/private/kitemlistsizehintresolver.cpp
......
......@@ -1288,7 +1288,7 @@ void DolphinMainWindow::handleUrl(const KUrl& url)
this, SLOT(slotHandleUrlStatFinished(KJob*)));
} else {
new KRun(url, this);
new KRun(url, this); // Automatically deletes itself after being finished
}
}
......@@ -1300,7 +1300,7 @@ void DolphinMainWindow::slotHandleUrlStatFinished(KJob* job)
if (entry.isDir()) {
activeViewContainer()->setUrl(url);
} else {
new KRun(url, this);
new KRun(url, this); // Automatically deletes itself after being finished
}
}
......
......@@ -29,6 +29,7 @@
#include <KDebug>
#include <KIcon>
#include <KTextEdit>
#include <QPainter>
#include <QTextLine>
......
......@@ -31,10 +31,13 @@
#include <KDebug>
#include "private/kfileitemclipboard.h"
#include "private/kitemlistroleeditor.h"
#include "private/kpixmapmodifier.h"
#include <QFontMetricsF>
#include <QGraphicsScene>
#include <QGraphicsSceneResizeEvent>
#include <QGraphicsView>
#include <QPainter>
#include <QStyleOption>
#include <QTextLayout>
......@@ -64,7 +67,8 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) :
m_customTextColor(),
m_additionalInfoTextColor(),
m_overlay(),
m_rating()
m_rating(),
m_roleEditor(0)
{
}
......@@ -72,6 +76,8 @@ KFileItemListWidget::~KFileItemListWidget()
{
qDeleteAll(m_textInfo);
m_textInfo.clear();
delete m_roleEditor;
}
void KFileItemListWidget::setLayout(Layout layout)
......@@ -482,10 +488,76 @@ void KFileItemListWidget::siblingsInformationChanged(const QBitArray& current, c
m_dirtyLayout = true;
}
void KFileItemListWidget::editedRoleChanged(const QByteArray& current, const QByteArray& previous)
{
Q_UNUSED(previous);
QGraphicsView* parent = scene()->views()[0];
if (current.isEmpty() || !parent || current != "name") {
if (m_roleEditor) {
emit roleEditingCanceled(index(), current, data().value(current));
m_roleEditor->deleteLater();
m_roleEditor = 0;
}
return;
}
Q_ASSERT(!m_roleEditor);
const TextInfo* textInfo = m_textInfo.value("name");
m_roleEditor = new KItemListRoleEditor(parent);
m_roleEditor->setIndex(index());
m_roleEditor->setRole(current);
const QString text = data().value(current).toString();
m_roleEditor->setPlainText(text);
QTextOption textOption = textInfo->staticText.textOption();
m_roleEditor->document()->setDefaultTextOption(textOption);
// Select the text without MIME-type extension
int selectionLength = text.length();
const QString extension = KMimeType::extractKnownExtension(text);
if (!extension.isEmpty()) {
selectionLength -= extension.length() + 1;
}
if (selectionLength > 0) {
QTextCursor cursor = m_roleEditor->textCursor();
cursor.movePosition(QTextCursor::StartOfBlock);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, selectionLength);
m_roleEditor->setTextCursor(cursor);
}
connect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)),
this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant)));
connect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)),
this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant)));
// Adjust the geometry of the editor
QRectF rect = roleEditingRect(current);
const int frameWidth = m_roleEditor->frameWidth();
rect.adjust(-frameWidth, -frameWidth, frameWidth, frameWidth);
rect.translate(pos());
if (rect.right() > parent->width()) {
rect.setWidth(parent->width() - rect.left());
}
m_roleEditor->setGeometry(rect.toRect());
m_roleEditor->show();
m_roleEditor->setFocus();
}
void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
{
if (m_roleEditor) {
setEditedRole(QByteArray());
Q_ASSERT(!m_roleEditor);
}
KItemListWidget::resizeEvent(event);
m_dirtyLayout = true;
}
......@@ -523,6 +595,26 @@ void KFileItemListWidget::slotCutItemsChanged()
}
}
void KFileItemListWidget::slotRoleEditingCanceled(int index,
const QByteArray& role,
const QVariant& value)
{
m_roleEditor->deleteLater();
m_roleEditor = 0;
emit roleEditingCanceled(index, role, value);
setEditedRole(QByteArray());
}
void KFileItemListWidget::slotRoleEditingFinished(int index,
const QByteArray& role,
const QVariant& value)
{
m_roleEditor->deleteLater();
m_roleEditor = 0;
emit roleEditingFinished(index, role, value);
setEditedRole(QByteArray());
}
void KFileItemListWidget::triggerCacheRefreshing()
{
if ((!m_dirtyContent && !m_dirtyLayout) || index() < 0) {
......@@ -1043,6 +1135,21 @@ void KFileItemListWidget::drawSiblingsInformation(QPainter* painter)
}
}
QRectF KFileItemListWidget::roleEditingRect(const QByteArray& role) const
{
const TextInfo* textInfo = m_textInfo.value(role);
if (!textInfo) {
return QRectF();
}
QRectF rect(textInfo->pos, textInfo->staticText.size());
if (m_layout == DetailsLayout) {
rect.setWidth(columnWidth(role) - rect.x());
}
return rect;
}
QPixmap KFileItemListWidget::pixmapForIcon(const QString& name, int size)
{
const KIcon icon(name);
......
......@@ -28,8 +28,9 @@
#include <QPointF>
#include <QStaticText>
class KItemListView;
class KItemListRoleEditor;
class KItemListStyleOption;
class KItemListView;
class LIBDOLPHINPRIVATE_EXPORT KFileItemListWidget : public KItemListWidget
{
......@@ -102,12 +103,15 @@ protected:
virtual void hoveredChanged(bool hovered);
virtual void selectedChanged(bool selected);
virtual void siblingsInformationChanged(const QBitArray& current, const QBitArray& previous);
virtual void editedRoleChanged(const QByteArray& current, const QByteArray& previous);
virtual void resizeEvent(QGraphicsSceneResizeEvent* event);
virtual void showEvent(QShowEvent* event);
virtual void hideEvent(QHideEvent* event);
private slots:
void slotCutItemsChanged();
void slotRoleEditingCanceled(int index, const QByteArray& role, const QVariant& value);
void slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value);
private:
/**
......@@ -137,6 +141,8 @@ private:
void drawPixmap(QPainter* painter, const QPixmap& pixmap);
void drawSiblingsInformation(QPainter* painter);
QRectF roleEditingRect(const QByteArray &role) const;
static QPixmap pixmapForIcon(const QString& name, int size);
static void applyCutEffect(QPixmap& pixmap);
static void applyHiddenEffect(QPixmap& pixmap);
......@@ -196,6 +202,8 @@ private:
QPixmap m_overlay;
QPixmap m_rating;
KItemListRoleEditor* m_roleEditor;
};
#endif
......
......@@ -57,6 +57,7 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
m_enabledSelectionToggles(false),
m_grouped(false),
m_supportsItemExpanding(false),
m_editingRole(false),
m_activeTransactions(0),
m_endTransactionAnimationHint(Animation),
m_itemSize(),
......@@ -667,6 +668,23 @@ QPixmap KItemListView::createDragPixmap(const QSet<int>& indexes) const
return QPixmap();
}
void KItemListView::editRole(int index, const QByteArray& role)
{
KItemListWidget* widget = m_visibleItems.value(index);
if (!widget) {
return;
}
Q_ASSERT(!m_editingRole);
m_editingRole = true;
widget->setEditedRole(role);
connect(widget, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)),
this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant)));
connect(widget, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)),
this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant)));
}
void KItemListView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QGraphicsWidget::paint(painter, option, widget);
......@@ -760,7 +778,7 @@ void KItemListView::onTransactionEnd()
bool KItemListView::event(QEvent* event)
{
// Forward all events to the controller and handle them there
if (m_controller && m_controller->processEvent(event, transform())) {
if (!m_editingRole && m_controller && m_controller->processEvent(event, transform())) {
event->accept();
return true;
}
......@@ -1331,6 +1349,18 @@ void KItemListView::slotGeometryOfGroupHeaderParentChanged()
updateGroupHeaderLayout(widget);
}
void KItemListView::slotRoleEditingCanceled(int index, const QByteArray& role, const QVariant& value)
{
emit roleEditingCanceled(index, role, value);
m_editingRole = false;
}
void KItemListView::slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value)
{
emit roleEditingFinished(index, role, value);
m_editingRole = false;
}
void KItemListView::setController(KItemListController* controller)
{
if (m_controller != controller) {
......
......@@ -265,6 +265,11 @@ public:
*/
virtual QPixmap createDragPixmap(const QSet<int>& indexes) const;
/**
* Lets the user edit the role \a role for item with the index \a index.
*/
void editRole(int index, const QByteArray& role);
/**
* @reimp
*/
......@@ -304,7 +309,14 @@ signals:
*/
void visibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous);
void roleEditingCanceled(int index, const QByteArray& role, const QVariant& value);
void roleEditingFinished(int index, const QByteArray& role, const QVariant& value);
protected:
/**
* Is called when creating a new KItemListWidget instance and allows derived
* classes to do a custom initialization.
*/
virtual void initializeItemListWidget(KItemListWidget* item);
/**
......@@ -394,6 +406,9 @@ private slots:
*/
void slotGeometryOfGroupHeaderParentChanged();
void slotRoleEditingCanceled(int index, const QByteArray& role, const QVariant& value);
void slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value);
private:
enum LayoutAnimationHint
{
......@@ -633,6 +648,7 @@ private:
bool m_enabledSelectionToggles;
bool m_grouped;
bool m_supportsItemExpanding;
bool m_editingRole;
int m_activeTransactions; // Counter for beginTransaction()/endTransaction()
LayoutAnimationHint m_endTransactionAnimationHint;
......
......@@ -51,7 +51,8 @@ KItemListWidget::KItemListWidget(QGraphicsItem* parent) :
m_hoverOpacity(0),
m_hoverCache(0),
m_hoverAnimation(0),
m_selectionToggle(0)
m_selectionToggle(0),
m_editedRole()
{
}
......@@ -112,7 +113,7 @@ void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* o
painter->fillRect(backgroundRect, backgroundColor);
}
if (m_selected) {
if (m_selected && m_editedRole.isEmpty()) {
const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0);
drawItemStyleOption(painter, widget, activeState |
QStyle::State_Enabled |
......@@ -120,7 +121,7 @@ void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* o
QStyle::State_Item);
}
if (isCurrent()) {
if (m_current && m_editedRole.isEmpty()) {
QStyleOptionFocusRect focusRectOption;
focusRectOption.initFrom(widget);
focusRectOption.rect = textFocusRect().toRect();
......@@ -309,6 +310,20 @@ QBitArray KItemListWidget::siblingsInformation() const
return m_siblingsInfo;
}
void KItemListWidget::setEditedRole(const QByteArray& role)
{
if (m_editedRole != role) {
const QByteArray previous = m_editedRole;
m_editedRole = role;
editedRoleChanged(role, previous);
}
}
QByteArray KItemListWidget::editedRole() const
{
return m_editedRole;
}
bool KItemListWidget::contains(const QPointF& point) const
{
if (!QGraphicsWidget::contains(point)) {
......@@ -392,6 +407,12 @@ void KItemListWidget::siblingsInformationChanged(const QBitArray& current, const
Q_UNUSED(previous);
}
void KItemListWidget::editedRoleChanged(const QByteArray& current, const QByteArray& previous)
{
Q_UNUSED(current);
Q_UNUSED(previous);
}
void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
{
QGraphicsWidget::resizeEvent(event);
......
......@@ -102,6 +102,16 @@ public:
void setSiblingsInformation(const QBitArray& siblings);
QBitArray siblingsInformation() const;
/**
* Allows the user to edit the role \a role. The signals
* roleEditingCanceled() or roleEditingFinished() will be
* emitted after editing. An ongoing editing gets canceled if
* the role is empty. Derived classes must implement
* editedRoleChanged().
*/
void setEditedRole(const QByteArray& role);
QByteArray editedRole() const;
/**
* @return True if \a point is inside KItemListWidget::hoverRect(),
* KItemListWidget::textRect(), KItemListWidget::selectionToggleRect()
......@@ -143,6 +153,10 @@ public:
*/
virtual QRectF expansionToggleRect() const;
signals:
void roleEditingCanceled(int index, const QByteArray& role, const QVariant& value);
void roleEditingFinished(int index, const QByteArray& role, const QVariant& value);
protected:
virtual void dataChanged(const QHash<QByteArray, QVariant>& current, const QSet<QByteArray>& roles = QSet<QByteArray>());
virtual void visibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous);
......@@ -153,6 +167,7 @@ protected:
virtual void hoveredChanged(bool hovered);
virtual void alternateBackgroundChanged(bool enabled);
virtual void siblingsInformationChanged(const QBitArray& current, const QBitArray& previous);
virtual void editedRoleChanged(const QByteArray& current, const QByteArray& previous);
virtual void resizeEvent(QGraphicsSceneResizeEvent* event);
/**
......@@ -190,6 +205,8 @@ private:
QPropertyAnimation* m_hoverAnimation;
KItemListSelectionToggle* m_selectionToggle;
QByteArray m_editedRole;
};
#endif
......
/***************************************************************************
* 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 "kitemlistroleeditor.h"
#include <KDebug>
#include <QKeyEvent>
KItemListRoleEditor::KItemListRoleEditor(QWidget *parent) :
KTextEdit(parent),
m_index(0),
m_role()
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
document()->setDocumentMargin(0);
if (parent) {
parent->installEventFilter(this);
}
}
KItemListRoleEditor::~KItemListRoleEditor()
{
}
void KItemListRoleEditor::setIndex(int index)
{
m_index = index;
}
int KItemListRoleEditor::index() const
{
return m_index;
}
void KItemListRoleEditor::setRole(const QByteArray& role)
{
m_role = role;
}
QByteArray KItemListRoleEditor::role() const
{
return m_role;
}
bool KItemListRoleEditor::eventFilter(QObject* watched, QEvent* event)
{
if (watched == parentWidget() && event->type() == QEvent::Resize) {
autoAdjustSize();
}
return KTextEdit::eventFilter(watched, event);
}
bool KItemListRoleEditor::event(QEvent* event)
{
if (event->type() == QEvent::FocusOut) {
emit roleEditingFinished(m_index, m_role, toPlainText());
}
return KTextEdit::event(event);
}
void KItemListRoleEditor::keyPressEvent(QKeyEvent* event)
{
switch (event->key()) {
case Qt::Key_Escape:
emit roleEditingCanceled(m_index, m_role, toPlainText());
event->accept();
return;
case Qt::Key_Enter:
case Qt::Key_Return:
emit roleEditingFinished(m_index, m_role, toPlainText());
event->accept();
return;
default:
break;
}
KTextEdit::keyPressEvent(event);
autoAdjustSize();
}
void KItemListRoleEditor::autoAdjustSize()
{
const qreal requiredWidth = document()->size().width();
const qreal availableWidth = size().width() - 2 * frameWidth();
if (requiredWidth > availableWidth) {
qreal newWidth = requiredWidth + 2 * frameWidth();
if (parentWidget() && pos().x() + newWidth > parentWidget()->width()) {
newWidth = parentWidget()->width() - pos().x();
}
resize(newWidth, size().height());
}
}
#include "kitemlistroleeditor.moc"
/***************************************************************************
* 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 KITEMLISTROLEEDITOR_H
#define KITEMLISTROLEEDITOR_H
#include "libdolphin_export.h"
#include <KTextEdit>
/**
* @brief
*/
class LIBDOLPHINPRIVATE_EXPORT KItemListRoleEditor : public KTextEdit
{
Q_OBJECT
public:
explicit KItemListRoleEditor(QWidget* parent);
virtual ~KItemListRoleEditor();
void setIndex(int index);
int index() const;
void setRole(const QByteArray& role);
QByteArray role() const;
virtual bool eventFilter(QObject* watched, QEvent* event);