From 3a3bdfc81798e9805d955216cc81c4e1cc45a887 Mon Sep 17 00:00:00 2001
From: Philippe Mavridis <philippe.mavridis@yandex.com>
Date: Thu, 28 May 2026 14:05:22 +0300
Subject: Konqueror: Add enhanced renaming mode for icon view

- Select file name without the extension by default
- Allow to use Tab/Shift-Tab to rename previous/next file as is already the case with the list view modes

Had to reimplement some classes since TQIconViewItemLineEdit is private to TQIconView.

Signed-off-by: Philippe Mavridis <philippe.mavridis@yandex.com>
---
 libkonq/konq_iconviewwidget.cpp |  27 +++++-
 libkonq/konq_iconviewwidget.h   |   5 ++
 libkonq/tdefileivi.cpp          | 180 +++++++++++++++++++++++++++++++++++++++-
 libkonq/tdefileivi.h            |  14 ++++
 4 files changed, 218 insertions(+), 8 deletions(-)

diff --git a/libkonq/konq_iconviewwidget.cpp b/libkonq/konq_iconviewwidget.cpp
index 226a34413..1755bb35a 100644
--- a/libkonq/konq_iconviewwidget.cpp
+++ b/libkonq/konq_iconviewwidget.cpp
@@ -58,6 +58,7 @@ struct KonqIconViewWidgetPrivate
 {
     KonqIconViewWidgetPrivate() {
         pActiveItem = 0;
+        pRenamingItem = 0;
         bSoundPreviews = false;
         pSoundItem = 0;
         bSoundItemClicked = false;
@@ -85,6 +86,7 @@ struct KonqIconViewWidgetPrivate
         //delete pPreviewJob; done by stopImagePreview
     }
     KFileIVI *pActiveItem;
+    KFileIVI *pRenamingItem;
     // Sound preview
     KFileIVI *pSoundItem;
     KonqSoundPlayer *pSoundPlayer;
@@ -189,6 +191,21 @@ void KonqIconViewWidget::focusOutEvent( TQFocusEvent * ev )
     TDEIconView::focusOutEvent( ev );
 }
 
+bool KonqIconViewWidget::isRenaming() const
+{
+    return d->pRenamingItem && d->pRenamingItem->m_renameBox;
+}
+
+const KFileIVI* KonqIconViewWidget::renamingItem()
+{
+    return d->pRenamingItem;
+}
+
+void KonqIconViewWidget::setRenamingItem(KFileIVI *theItem)
+{
+    d->pRenamingItem = theItem;
+}
+
 void KonqIconViewWidget::slotItemRenamed(TQIconViewItem *item, const TQString &name)
 {
     kdDebug(1203) << "KonqIconViewWidget::slotItemRenamed" << endl;
@@ -1126,14 +1143,16 @@ void KonqIconViewWidget::slotSelectionChanged()
 
 void KonqIconViewWidget::renameCurrentItem()
 {
-    if ( currentItem() )
-        currentItem()->rename();
+    if (currentItem())
+    {
+        static_cast<KFileIVI *>(currentItem())->rename();
+    }
 }
 
 void KonqIconViewWidget::renameSelectedItem()
 {
     kdDebug(1203) << " -- KonqIconViewWidget::renameSelectedItem() -- " << endl;
-    TQIconViewItem * item = 0L;
+    TQIconViewItem *item = 0L;
     TQIconViewItem *it = firstItem();
     for (; it; it = it->nextItem() )
         if ( it->isVisible() && it->isSelected() && !item )
@@ -1146,7 +1165,7 @@ void KonqIconViewWidget::renameSelectedItem()
         Q_ASSERT(item);
         return;
     }
-    item->rename();
+    static_cast<KFileIVI *>(item)->rename();
 }
 
 void KonqIconViewWidget::cutSelection()
diff --git a/libkonq/konq_iconviewwidget.h b/libkonq/konq_iconviewwidget.h
index 75e3c1f37..786cd4bae 100644
--- a/libkonq/konq_iconviewwidget.h
+++ b/libkonq/konq_iconviewwidget.h
@@ -244,6 +244,8 @@ public:
     const TQStringList& previewSettings();
     void setNewURL( const TQString& url );
 
+    bool isRenaming() const; // reimplemented from TQIconView
+
 public slots:
     /**
      * Checks the new selection and emits enableAction() signals
@@ -335,6 +337,9 @@ protected:
     bool canPreview( KFileItem* item );
     void updatePreviewMimeTypes();
 
+    const KFileIVI* renamingItem();
+    void setRenamingItem(KFileIVI *theItem);
+
 private:
     KURL m_url;
     const KFileItem * m_rootItem;
diff --git a/libkonq/tdefileivi.cpp b/libkonq/tdefileivi.cpp
index 02fa748ca..b743eb68c 100644
--- a/libkonq/tdefileivi.cpp
+++ b/libkonq/tdefileivi.cpp
@@ -25,6 +25,7 @@
 #include "konq_settings.h"
 
 #include <tqpainter.h>
+#include <tqtextedit.h>
 
 #include <kurldrag.h>
 #include <kiconeffect.h>
@@ -57,7 +58,8 @@ struct KFileIVI::Private
 KFileIVI::KFileIVI( KonqIconViewWidget *iconview, KFileItem* fileitem, int size )
     : TDEIconViewItem( iconview, fileitem->text() ),
     m_size( size ), m_state( TDEIcon::DefaultState ),
-    m_bDisabled( false ), m_bThumbnail( false ), m_fileitem( fileitem )
+    m_bDisabled( false ), m_bThumbnail( false ), m_fileitem( fileitem ),
+    m_renameBox(nullptr)
 {
     d = new KFileIVI::Private;
 
@@ -85,6 +87,7 @@ KFileIVI::KFileIVI( KonqIconViewWidget *iconview, KFileItem* fileitem, int size
 
 KFileIVI::~KFileIVI()
 {
+    removeRenameBox();
     delete d->m_directoryOverlay;
     delete d->m_freeSpaceOverlay;
     delete d;
@@ -233,7 +236,7 @@ void KFileIVI::setDisabled( bool disabled )
     {
         m_bDisabled = disabled;
         bool active = ( m_state == TDEIcon::ActiveState );
-        setEffect( m_bDisabled ? TDEIcon::DisabledState : 
+        setEffect( m_bDisabled ? TDEIcon::DisabledState :
                    ( active ? TDEIcon::ActiveState : TDEIcon::DefaultState ) );
     }
 }
@@ -478,9 +481,9 @@ void KFileIVI::paintOverlayProgressBar( TQPainter *p ) const
 //         int verticalOffset = 0;
 //         int usedBarWidth = ((d->m_progress*pixmapRect().width())/100);
 //         int endPosition = x() + rect.x() + usedBarWidth;
-// 
+//
 //         p->save();
-// 
+//
 //         p->setPen(TQPen::NoPen);
 //         p->setBrush(TQt::red);
 //         p->drawRect(TQRect(x() + rect.x(), y() + rect.y() + (pixmapRect().height() - verticalOffset), usedBarWidth, 1));
@@ -619,3 +622,172 @@ void KFileIVI::mimeTypeAndIconDetermined()
 {
     updatePixmapSize();
 }
+
+// Reimplemented from tqiconview.cpp
+class KFileIVILineEdit : public TQTextEdit
+{
+    friend class KFileIVI;
+
+    public:
+        KFileIVILineEdit(const TQString &text, TQWidget *parent, KFileIVI *theItem, const char* name = 0);
+
+    protected:
+        void keyPressEvent(TQKeyEvent *e);
+        void focusOutEvent(TQFocusEvent *e);
+
+    protected:
+        KFileIVI *item;
+        TQString startText;
+
+    private:
+        KFileIVILineEdit(const KFileIVILineEdit &);
+        KFileIVILineEdit &operator=(const KFileIVILineEdit &);
+};
+
+KFileIVILineEdit::KFileIVILineEdit(const TQString &text, TQWidget *parent,
+                                   KFileIVI *theItem, const char *name)
+    : TQTextEdit(parent, name), item(theItem), startText(text)
+{
+    setFrameStyle(TQFrame::Plain | TQFrame::Box);
+    setLineWidth(1);
+
+    setHScrollBarMode(AlwaysOff);
+    setVScrollBarMode(AlwaysOff);
+
+    resize( 200, 200 ); // ### some size, there should be a forceReformat()
+    setTextFormat(PlainText);
+    setText(text);
+    setAlignment(TQt::AlignCenter);
+    setWordWrap(WidgetWidth);
+    setWrapPolicy(AtWordOrDocumentBoundary);
+    setWrapColumnOrWidth(item->iconView()->maxItemWidth() -
+            (item->iconView()->itemTextPos() == TQIconView::Bottom ?
+            0 : item->pixmapRect().width()));
+
+    resize(wrapColumnOrWidth() + 2, heightForWidth(wrapColumnOrWidth()) + 2);
+}
+
+void KFileIVILineEdit::keyPressEvent(TQKeyEvent *e)
+{
+    if (e->key() == Key_Escape)
+    {
+        item->TQIconViewItem::setText(startText);
+        item->cancelRenameItem();
+    }
+    else if (e->key() == Key_Enter || e->key() == Key_Return)
+    {
+        item->renameItem();
+    }
+    else if ((e->key() == Key_Tab || e->key() == Key_Backtab) &&
+            !(e->state() & ControlButton || e->state() & AltButton))
+    {
+        item->renameItem();
+        KFileIVI *it;
+        if (e->key() == Key_Tab && !(e->state() & ShiftButton))
+        {
+            it = static_cast<KFileIVI*>(item->nextItem());
+            if (!it) // wrap around to start
+            {
+                it = static_cast<KFileIVI*>(item->iconView()->firstItem());
+            }
+        }
+        else
+        {
+            it = static_cast<KFileIVI*>(item->prevItem());
+            if (!it) // wrap around to end
+            {
+                it = static_cast<KFileIVI*>(item->iconView()->lastItem());
+            }
+        }
+        if (it) it->rename();
+    }
+    else
+    {
+        TQTextEdit::keyPressEvent(e);
+        sync();
+        resize(width(), heightForWidth(width()) + 2);
+    }
+}
+
+void KFileIVILineEdit::focusOutEvent(TQFocusEvent *e)
+{
+    if ( e->reason() != TQFocusEvent::Popup )
+    item->cancelRenameItem();
+}
+
+void KFileIVI::rename()
+{
+    KonqIconViewWidget *view = static_cast<KonqIconViewWidget *>(iconView());
+    if (!view) return;
+
+    if (m_renameBox)
+    {
+        removeRenameBox();
+    }
+
+    oldRect = rect();
+    const TQString fileName = text();
+    m_renameBox = new KFileIVILineEdit(fileName, view->viewport(), this, "kfileivi_renamebox");
+    view->ensureItemVisible(this);
+    TQRect txtr(textRect(false));
+    view->addChild(m_renameBox, txtr.x() + (txtr.width() / 2 - m_renameBox->width() / 2),
+                                txtr.y() - 3);
+    int sel = fileName.find(".");
+    sel = sel > -1 ? sel : fileName.length();
+    m_renameBox->setSelection(0, 0, 0, sel);
+    view->viewport()->setFocusProxy(m_renameBox);
+    m_renameBox->setFocus();
+    m_renameBox->show();
+    Q_ASSERT(view->renamingItem() == nullptr);
+    view->setRenamingItem(this);
+}
+
+void KFileIVI::renameItem()
+{
+    KonqIconViewWidget *view = static_cast<KonqIconViewWidget *>(iconView());
+    if (!m_renameBox || !view) return;
+
+    if (!view->wordWrapIconText())
+    {
+        calcRect();
+    }
+    TQRect r = rect();
+    setText(m_renameBox->text());
+    view->repaintContents(oldRect.x() - 1, oldRect.y() - 1, oldRect.width() + 2, oldRect.height() + 2, false);
+    view->repaintContents(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2, false);
+    removeRenameBox();
+    view->emitRenamed(this);
+}
+
+void KFileIVI::cancelRenameItem()
+{
+    KonqIconViewWidget *view = static_cast<KonqIconViewWidget *>(iconView());
+    if (!view) return;
+
+    TQRect r = rect();
+    calcRect();
+    view->repaintContents(oldRect.x() - 1, oldRect.y() - 1, oldRect.width() + 2, oldRect.height() + 2, false);
+    view->repaintContents(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2, false);
+
+    if (!m_renameBox) return;
+
+    removeRenameBox();
+}
+
+void KFileIVI::removeRenameBox()
+{
+    KonqIconViewWidget *view = static_cast<KonqIconViewWidget *>(iconView());
+    if (!m_renameBox || !view) return;
+
+    bool resetFocus = view->viewport()->focusProxy() == m_renameBox;
+    m_renameBox->hide();
+    m_renameBox->deleteLater();
+    m_renameBox = nullptr;
+    if (resetFocus)
+    {
+        view->viewport()->setFocusProxy(view);
+        view->setFocus();
+    }
+    Q_ASSERT(view->renamingItem() == this);
+    view->setRenamingItem(nullptr);
+}
\ No newline at end of file
diff --git a/libkonq/tdefileivi.h b/libkonq/tdefileivi.h
index 7ddb2deb7..bf726a280 100644
--- a/libkonq/tdefileivi.h
+++ b/libkonq/tdefileivi.h
@@ -28,6 +28,7 @@ class KFileItem;
 class KonqIconViewWidget;
 class KIVDirectoryOverlay;
 class KIVFreeSpaceOverlay;
+class KFileIVILineEdit;
 
 /**
  * KFileIVI (short form of "Konq - File - IconViewItem")
@@ -38,6 +39,8 @@ class KIVFreeSpaceOverlay;
  */
 class LIBKONQ_EXPORT KFileIVI : public TDEIconViewItem
 {
+friend class KFileIVILineEdit;
+friend class KonqIconViewWidget;
 public:
     /**
      * Create an icon, within a qlistview, representing a file
@@ -210,6 +213,8 @@ public:
 
     void mimeTypeAndIconDetermined();
 
+    void rename();
+
 protected:
     virtual void dropped( TQDropEvent *e, const TQValueList<TQIconDragItem> &  );
 
@@ -233,6 +238,14 @@ protected:
      */
     void paintFontUpdate( TQPainter *p ) const;
 
+    /** Reimplementation of TQt inline rename */
+    void renameItem();
+    void cancelRenameItem();
+    void removeRenameBox();
+
+    KFileIVILineEdit *m_renameBox;
+
+
 private:
     /** You are not supposed to call this on a KFileIVI, from the outside,
      * it bypasses the icons cache */
@@ -248,6 +261,7 @@ private:
     bool m_bThumbnail;
     /** Pointer to the file item in KDirLister's list */
     KFileItem* m_fileitem;
+    TQRect oldRect;
 
     /**
      * Private data for KFileIVI
-- 
cgit v1.2.3

