mirror of
https://invent.kde.org/system/dolphin
synced 2024-09-17 15:31:20 +00:00
Two clicks on file/folder to rename
Summary: Make renaming of files/folders faster by clicking a second time on the items text to start renaming. BUG: 205157 Test Plan: This feature works as follows: 1. select an item by single-click, or one is already selected 2. wait the "double-click-interval" 3. click on the items text 4. none of the cancellations (see below) happens within the double-click-interval 5. inline-renaming starts Cancellations: * open any file/folder * select different item(s) * start dragging items * Dolphin loses focus This feature is just enabled while "Double-click to open files and folders" in system-settings and "Rename inline" in Dolphin are enabled. Reviewers: #dolphin, #kde_applications, elvisangelaccio, emmanuelp, ngraham, markg, rkflx Reviewed By: #dolphin, #kde_applications, elvisangelaccio, ngraham, rkflx Subscribers: rkflx, markg, funkybomber, sars, elvisangelaccio, ngraham Differential Revision: https://phabricator.kde.org/D7647
This commit is contained in:
parent
f20300256b
commit
5454283008
|
@ -583,6 +583,10 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const
|
||||||
// -> remember that the user pressed an item which had been selected already and
|
// -> remember that the user pressed an item which had been selected already and
|
||||||
// clear the selection in mouseReleaseEvent(), unless the items are dragged.
|
// clear the selection in mouseReleaseEvent(), unless the items are dragged.
|
||||||
m_clearSelectionIfItemsAreNotDragged = true;
|
m_clearSelectionIfItemsAreNotDragged = true;
|
||||||
|
|
||||||
|
if (m_selectionManager->selectedItems().count() == 1 && m_view->isAboveText(m_pressedIndex, m_pressedMousePos)) {
|
||||||
|
emit selectedItemTextPressed(m_pressedIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shiftPressed) {
|
if (!shiftPressed) {
|
||||||
|
|
|
@ -237,6 +237,8 @@ signals:
|
||||||
void modelChanged(KItemModelBase* current, KItemModelBase* previous);
|
void modelChanged(KItemModelBase* current, KItemModelBase* previous);
|
||||||
void viewChanged(KItemListView* current, KItemListView* previous);
|
void viewChanged(KItemListView* current, KItemListView* previous);
|
||||||
|
|
||||||
|
void selectedItemTextPressed(int index);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotViewScrollOffsetChanged(qreal current, qreal previous);
|
void slotViewScrollOffsetChanged(qreal current, qreal previous);
|
||||||
|
|
||||||
|
|
|
@ -453,6 +453,19 @@ bool KItemListView::isAboveExpansionToggle(int index, const QPointF& pos) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KItemListView::isAboveText(int index, const QPointF &pos) const
|
||||||
|
{
|
||||||
|
const KItemListWidget* widget = m_visibleItems.value(index);
|
||||||
|
if (widget) {
|
||||||
|
const QRectF &textRect = widget->textRect();
|
||||||
|
if (!textRect.isEmpty()) {
|
||||||
|
const QPointF mappedPos = widget->mapFromItem(this, pos);
|
||||||
|
return textRect.contains(mappedPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int KItemListView::firstVisibleIndex() const
|
int KItemListView::firstVisibleIndex() const
|
||||||
{
|
{
|
||||||
return m_layouter->firstVisibleIndex();
|
return m_layouter->firstVisibleIndex();
|
||||||
|
|
|
@ -183,6 +183,7 @@ public:
|
||||||
int itemAt(const QPointF& pos) const;
|
int itemAt(const QPointF& pos) const;
|
||||||
bool isAboveSelectionToggle(int index, const QPointF& pos) const;
|
bool isAboveSelectionToggle(int index, const QPointF& pos) const;
|
||||||
bool isAboveExpansionToggle(int index, const QPointF& pos) const;
|
bool isAboveExpansionToggle(int index, const QPointF& pos) const;
|
||||||
|
bool isAboveText(int index, const QPointF& pos) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Index of the first item that is at least partly visible.
|
* @return Index of the first item that is at least partly visible.
|
||||||
|
|
|
@ -99,7 +99,8 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
|
||||||
m_selectedUrls(),
|
m_selectedUrls(),
|
||||||
m_clearSelectionBeforeSelectingNewItems(false),
|
m_clearSelectionBeforeSelectingNewItems(false),
|
||||||
m_markFirstNewlySelectedItemAsCurrent(false),
|
m_markFirstNewlySelectedItemAsCurrent(false),
|
||||||
m_versionControlObserver(0)
|
m_versionControlObserver(0),
|
||||||
|
m_twoClicksRenamingTimer(nullptr)
|
||||||
{
|
{
|
||||||
m_topLayout = new QVBoxLayout(this);
|
m_topLayout = new QVBoxLayout(this);
|
||||||
m_topLayout->setSpacing(0);
|
m_topLayout->setSpacing(0);
|
||||||
|
@ -150,6 +151,7 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
|
||||||
connect(controller, &KItemListController::itemDropEvent, this, &DolphinView::slotItemDropEvent);
|
connect(controller, &KItemListController::itemDropEvent, this, &DolphinView::slotItemDropEvent);
|
||||||
connect(controller, &KItemListController::escapePressed, this, &DolphinView::stopLoading);
|
connect(controller, &KItemListController::escapePressed, this, &DolphinView::stopLoading);
|
||||||
connect(controller, &KItemListController::modelChanged, this, &DolphinView::slotModelChanged);
|
connect(controller, &KItemListController::modelChanged, this, &DolphinView::slotModelChanged);
|
||||||
|
connect(controller, &KItemListController::selectedItemTextPressed, this, &DolphinView::slotSelectedItemTextPressed);
|
||||||
|
|
||||||
connect(m_model, &KFileItemModel::directoryLoadingStarted, this, &DolphinView::slotDirectoryLoadingStarted);
|
connect(m_model, &KFileItemModel::directoryLoadingStarted, this, &DolphinView::slotDirectoryLoadingStarted);
|
||||||
connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::slotDirectoryLoadingCompleted);
|
connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::slotDirectoryLoadingCompleted);
|
||||||
|
@ -190,6 +192,10 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
|
||||||
connect(m_versionControlObserver, &VersionControlObserver::errorMessage, this, &DolphinView::errorMessage);
|
connect(m_versionControlObserver, &VersionControlObserver::errorMessage, this, &DolphinView::errorMessage);
|
||||||
connect(m_versionControlObserver, &VersionControlObserver::operationCompletedMessage, this, &DolphinView::operationCompletedMessage);
|
connect(m_versionControlObserver, &VersionControlObserver::operationCompletedMessage, this, &DolphinView::operationCompletedMessage);
|
||||||
|
|
||||||
|
m_twoClicksRenamingTimer = new QTimer(this);
|
||||||
|
m_twoClicksRenamingTimer->setSingleShot(true);
|
||||||
|
connect(m_twoClicksRenamingTimer, &QTimer::timeout, this, &DolphinView::slotTwoClicksRenamingTimerTimeout);
|
||||||
|
|
||||||
applyViewProperties();
|
applyViewProperties();
|
||||||
m_topLayout->addWidget(m_container);
|
m_topLayout->addWidget(m_container);
|
||||||
|
|
||||||
|
@ -726,6 +732,12 @@ void DolphinView::updatePalette()
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DolphinView::abortTwoClicksRenaming()
|
||||||
|
{
|
||||||
|
m_twoClicksRenamingItemUrl.clear();
|
||||||
|
m_twoClicksRenamingTimer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
bool DolphinView::eventFilter(QObject* watched, QEvent* event)
|
bool DolphinView::eventFilter(QObject* watched, QEvent* event)
|
||||||
{
|
{
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
|
@ -793,13 +805,14 @@ void DolphinView::hideEvent(QHideEvent* event)
|
||||||
|
|
||||||
bool DolphinView::event(QEvent* event)
|
bool DolphinView::event(QEvent* event)
|
||||||
{
|
{
|
||||||
/* See Bug 297355
|
|
||||||
* Dolphin leaves file preview tooltips open even when is not visible.
|
|
||||||
*
|
|
||||||
* Hide tool-tip when Dolphin loses focus.
|
|
||||||
*/
|
|
||||||
if (event->type() == QEvent::WindowDeactivate) {
|
if (event->type() == QEvent::WindowDeactivate) {
|
||||||
|
/* See Bug 297355
|
||||||
|
* Dolphin leaves file preview tooltips open even when is not visible.
|
||||||
|
*
|
||||||
|
* Hide tool-tip when Dolphin loses focus.
|
||||||
|
*/
|
||||||
hideToolTip();
|
hideToolTip();
|
||||||
|
abortTwoClicksRenaming();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QWidget::event(event);
|
return QWidget::event(event);
|
||||||
|
@ -812,6 +825,8 @@ void DolphinView::activate()
|
||||||
|
|
||||||
void DolphinView::slotItemActivated(int index)
|
void DolphinView::slotItemActivated(int index)
|
||||||
{
|
{
|
||||||
|
abortTwoClicksRenaming();
|
||||||
|
|
||||||
const KFileItem item = m_model->fileItem(index);
|
const KFileItem item = m_model->fileItem(index);
|
||||||
if (!item.isNull()) {
|
if (!item.isNull()) {
|
||||||
emit itemActivated(item);
|
emit itemActivated(item);
|
||||||
|
@ -822,6 +837,8 @@ void DolphinView::slotItemsActivated(const KItemSet& indexes)
|
||||||
{
|
{
|
||||||
Q_ASSERT(indexes.count() >= 2);
|
Q_ASSERT(indexes.count() >= 2);
|
||||||
|
|
||||||
|
abortTwoClicksRenaming();
|
||||||
|
|
||||||
if (indexes.count() > 5) {
|
if (indexes.count() > 5) {
|
||||||
QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
|
QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
|
||||||
const int answer = KMessageBox::warningYesNo(this, question);
|
const int answer = KMessageBox::warningYesNo(this, question);
|
||||||
|
@ -1105,6 +1122,14 @@ void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DolphinView::slotSelectedItemTextPressed(int index)
|
||||||
|
{
|
||||||
|
if (GeneralSettings::renameInline()) {
|
||||||
|
m_twoClicksRenamingItemUrl = m_model->fileItem(index).url();
|
||||||
|
m_twoClicksRenamingTimer->start(QApplication::doubleClickInterval());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DolphinView::slotItemCreated(const QUrl& url)
|
void DolphinView::slotItemCreated(const QUrl& url)
|
||||||
{
|
{
|
||||||
if (m_markFirstNewlySelectedItemAsCurrent) {
|
if (m_markFirstNewlySelectedItemAsCurrent) {
|
||||||
|
@ -1401,6 +1426,22 @@ void DolphinView::calculateItemCount(int& fileCount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DolphinView::slotTwoClicksRenamingTimerTimeout()
|
||||||
|
{
|
||||||
|
const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
|
||||||
|
|
||||||
|
// verify that only one item is selected and that no item is dragged
|
||||||
|
if (selectionManager->selectedItems().count() == 1 && !m_dragging) {
|
||||||
|
const int index = selectionManager->currentItem();
|
||||||
|
const QUrl fileItemUrl = m_model->fileItem(index).url();
|
||||||
|
|
||||||
|
// check if the selected item was the same item that started the twoClicksRenaming
|
||||||
|
if (fileItemUrl.isValid() && m_twoClicksRenamingItemUrl == fileItemUrl) {
|
||||||
|
renameSelectedItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DolphinView::slotTrashFileFinished(KJob* job)
|
void DolphinView::slotTrashFileFinished(KJob* job)
|
||||||
{
|
{
|
||||||
if (job->error() == 0) {
|
if (job->error() == 0) {
|
||||||
|
|
|
@ -577,6 +577,7 @@ private slots:
|
||||||
void slotModelChanged(KItemModelBase* current, KItemModelBase* previous);
|
void slotModelChanged(KItemModelBase* current, KItemModelBase* previous);
|
||||||
void slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons);
|
void slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons);
|
||||||
void slotRenameDialogRenamingFinished(const QList<QUrl>& urls);
|
void slotRenameDialogRenamingFinished(const QList<QUrl>& urls);
|
||||||
|
void slotSelectedItemTextPressed(int index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is called when new items get pasted or dropped.
|
* Is called when new items get pasted or dropped.
|
||||||
|
@ -707,6 +708,8 @@ private slots:
|
||||||
*/
|
*/
|
||||||
void calculateItemCount(int& fileCount, int& folderCount, KIO::filesize_t& totalFileSize) const;
|
void calculateItemCount(int& fileCount, int& folderCount, KIO::filesize_t& totalFileSize) const;
|
||||||
|
|
||||||
|
void slotTwoClicksRenamingTimerTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadDirectory(const QUrl& url, bool reload = false);
|
void loadDirectory(const QUrl& url, bool reload = false);
|
||||||
|
|
||||||
|
@ -769,6 +772,8 @@ private:
|
||||||
*/
|
*/
|
||||||
void forceUrlsSelection(const QUrl& current, const QList<QUrl>& selected);
|
void forceUrlsSelection(const QUrl& current, const QList<QUrl>& selected);
|
||||||
|
|
||||||
|
void abortTwoClicksRenaming();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updatePalette();
|
void updatePalette();
|
||||||
|
|
||||||
|
@ -804,6 +809,9 @@ private:
|
||||||
|
|
||||||
VersionControlObserver* m_versionControlObserver;
|
VersionControlObserver* m_versionControlObserver;
|
||||||
|
|
||||||
|
QTimer* m_twoClicksRenamingTimer;
|
||||||
|
QUrl m_twoClicksRenamingItemUrl;
|
||||||
|
|
||||||
// For unit tests
|
// For unit tests
|
||||||
friend class TestBase;
|
friend class TestBase;
|
||||||
friend class DolphinDetailsViewTest;
|
friend class DolphinDetailsViewTest;
|
||||||
|
|
Loading…
Reference in a new issue