[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    [PATCH] New feature: closed tabs trash bin as in Opera
From:       Eduardo Robles Elvira <edulix () gmail ! com>
Date:       2006-12-07 17:51:56
Message-ID: 200612071852.03355.edulix () gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


Hello,

---- Intro

I don't remember exactly if I have written anything before this list, but 
hello everyone in case this is the first time =).

Dani and me are participating in event called "concurso de software libre" 
(which mean something like "Free Software Contest") in which students from 
any spanish university can develop a project and in the end some of them will 
get some prices. Our project was called "Konqueror on steroids" which was 
about adding some features to the web browser side of konqueror. 

That was in contrast with the rest of the projects which choosed to start a 
new app from start, but I felt like I wanted to touch some KDE 4 code and 
this was a great oportunity to do it.

-- Short Description

We set up an easy first goal and we have already achieved it: a trahbin with 
recetly closed tabs so that when the user closed a tab he didn't intend or 
simply wants to retrieve in a fast way one of those tabs he recently closed, 
he can very well do it. This is idea, as some of the others we have, came 
from Opera =)

The code is attached to this email. Also, you can get the latest version of it 
[1] along with the icons you must add to kdelibs/pics/crystalsvg that Dani 
created for the new action. You can see a screenshot of it [2]

-- Details

How does it work? easy. It maintains a list of closed URLs (views) per each 
window, and the first ten elements of that list is showed when the drop-down 
menu is shown. IF you click in the trash button or select one element of the 
list, it get's out of there and it gets opened in a new tab. When there's no 
item in the list, the button gets disabled, etc.

-- Final thoughts

This is a work in progress, and we probably will improve a bit the thing 
adding the possibility to clean the list, to customize the number of shown 
items via a configuarition file entry, add numbers and keystrokes to the 
items in the drop-down menu, maybe we should limit the number of closed URLs 
to something like 50-100 items...

Or being able to maintain also another list konqueror-wide with closed windows 
(you know, sometimes shit happens and you close the window and you want to 
get it back), or taking care not only of the urls but also of the disposition 
of the views (a tab can have any number of views in many kinds of 
dispositions). That was just a bit of wild brain storming ;-)

What do you think about this? I think it's a valuable feature that users will 
love (me for one). What are the chances of adding this to KDE3 branch? (I 
don't think that the backport effort would be difficult).

Thanks for your time,
         Eduardo Robles Elvira.

--
[1] https://forja.rediris.es/websvn/wsvn/csl-konqueror/?sc=0
[2] http://konquerization.wordpress.com/files/2006/12/trashtab.png

["parche.konqueror" (text/x-diff)]

Index: konq_mainwindow.h
===================================================================
--- konq_mainwindow.h	(revisión: 610168)
+++ konq_mainwindow.h	(copia de trabajo)
@@ -2,6 +2,8 @@
    This file is part of the KDE project
    Copyright (C) 1998, 1999 Simon Hausmann <hausmann@kde.org>
    Copyright (C) 2000-2004 David Faure <faure@kde.org>
+   Copyright (C) 2006 Eduardo Robles Elvira <edulix@gmail.com>
+   Copyright (C) 2006 Daniel García Martín <danigm@gmail.com>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
@@ -387,6 +389,9 @@
   void slotForward(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
   void slotHome();
   void slotHome(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+  void slotOpenLastClosedTab();
+  void slotClosedTabsDisable();
+  void slotAddClosedURL(KonqView *view);
   void slotGoSystem();
   void slotGoApplications();
   void slotGoMedia();
@@ -481,11 +486,13 @@
   void slotUpAboutToShow();
   void slotBackAboutToShow();
   void slotForwardAboutToShow();
+  void slotClosedTabsListAboutToShow();
 
   void slotUpActivated( int id );
   void slotBackActivated( int id );
   void slotForwardActivated( int id );
   void slotGoHistoryDelayed();
+  void slotClosedTabsActivated( int id );
 
   void slotCompletionModeChanged( KGlobalSettings::Completion );
   void slotMakeCompletion( const QString& );
@@ -548,7 +555,6 @@
    * emulating a enter key press event.
    */
   void goURL();
-
   void bookmarksIntoCompletion();
 
   void initBookmarkBar();
@@ -608,6 +614,8 @@
 private: // members
 
   KNewMenu * m_pMenuNew;
+  QList<KUrl*> m_closedTabsList;
+  unsigned short int closedTabsListLength;
 
   KAction *m_paPrint;
 
@@ -616,6 +624,7 @@
   KToolBarPopupAction *m_paUp;
   KToolBarPopupAction *m_paBack;
   KToolBarPopupAction *m_paForward;
+  KToolBarPopupAction *m_paClosedTabs;  /// Action for the trash that contains \
closed tabs  KAction *m_paHome;
 
   KonqBidiHistoryAction *m_paHistory;
@@ -647,6 +656,8 @@
   KAction *m_paCopy;
   KAction *m_paPaste;
   KAction *m_paStop;
+  KAction *trashTab;
+
   KAction *m_paRename;
 
   KAction *m_paTrash;
Index: konq_mainwindow.cc
===================================================================
--- konq_mainwindow.cc	(revisión: 610168)
+++ konq_mainwindow.cc	(copia de trabajo)
@@ -2,6 +2,8 @@
    Copyright (C) 1998, 1999 Simon Hausmann <hausmann@kde.org>
    Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
    Copyright (C) 2000-2005 David Faure <faure@kde.org>
+   Copyright (C) 2006 Eduardo Robles Elvira <edulix@gmail.com>
+   Copyright (C) 2006 Daniel García Martín <danigm@gmail.com>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
@@ -101,6 +103,7 @@
 #include <kstdaccel.h>
 #include <kstdaction.h>
 #include <kstandarddirs.h>
+#include <kstringhandler.h>
 #include <ksycoca.h>
 #include <ktemporaryfile.h>
 #include <ktoolbarpopupaction.h>
@@ -335,6 +338,7 @@
   delete m_paBookmarkBar;
   delete m_pBookmarksOwner;
   delete m_pURLCompletion;
+  delete m_paClosedTabs;
 
   KonqUndoManager::decRef();
 
@@ -3089,6 +3093,32 @@
       KonqBidiHistoryAction::fillHistoryPopup( m_currentView->history(), \
m_currentView->historyIndex(), m_paBack->menu(), true, false );  }
 
+/**
+ * Fill the closed tabs action menu before it's shown
+ */
+void KonqMainWindow::slotClosedTabsListAboutToShow()
+{
+  QMenu* popup = m_paClosedTabs->menu();
+  KUrl *url;
+  QString text;
+  
+  // Clear the menu and fill it with a maximum of closedTabsListLength number of \
urls +  popup->clear();
+  if ( m_currentView )
+  {
+      int n = (m_closedTabsList.count() > closedTabsListLength) ? \
closedTabsListLength : m_closedTabsList.count(); +      for(unsigned short int index \
= 0; index < n; ++index) +      {
+          url = m_closedTabsList[ index ];
+          text = KStringHandler::cEmSqueeze(url->prettyUrl(), popup->fontMetrics(), \
30); //CT: squeeze +          text.replace( "&", "&&" );
+          
+          popup->addAction( QIcon( KonqPixmapProvider::self()->pixmapFor(
+                                        url->url() ) ), text );
+      }
+  }
+}
+
 void KonqMainWindow::slotBack()
 {
   slotGoHistoryActivated(-1);
@@ -3105,6 +3135,37 @@
     slotGoHistoryActivated( -(backMenu->indexOf( id ) + 1), \
backMenu->mouseButtons(), backMenu->keyboardModifiers());  }
 
+/**
+ * Opens in a new tab the URL the user selected from the closed tabs menu and takes \
it from the list. + *
+ * @param id Idetifier of the picked element in the menu
+ */
+void KonqMainWindow::slotClosedTabsActivated( int id )
+{
+  // Take the last closed url and exit if there was none (that should *never* \
happend) +  KUrl *url = m_closedTabsList.takeAt( m_paClosedTabs->menu()->indexOf( id \
) ); +  if(url == 0) return;
+
+  // Generic code to open a new tab
+  KonqView* newView = m_pViewManager->addTab(QString(),
+                                             QString(),
+                                             false,
+                                             KonqSettings::openAfterCurrentPage());
+  if (newView == 0) return;
+  openUrl( newView, *(url),QString());
+  m_pViewManager->showTab( newView );
+  focusLocationBar();
+  m_pWorkingTab = 0;
+  
+  // delete the current url, we don't need it anymore
+  delete url;
+  
+  // if there's no remaining closed urls in the list,
+  // disable the action button
+  if(m_closedTabsList.empty())
+  	m_paClosedTabs->setEnabled(false);
+}
+
 void KonqMainWindow::slotForwardAboutToShow()
 {
   m_paForward->menu()->clear();
@@ -3372,6 +3433,7 @@
 
       m_paTrash->setEnabled(false);
       m_paDelete->setEnabled(false);
+      m_paClosedTabs->setEnabled(false);
 
       slotClipboardDataChanged();
 
@@ -3707,6 +3769,18 @@
 
   QPair< KGuiItem, KGuiItem > backForward = KStdGuiItem::backAndForward();
 
+  // Trash bin of closed tabs
+  m_paClosedTabs = new KToolBarPopupAction( KIcon("trashtab"),  i18n( "trashtab" ), \
actionCollection(), "trashtab" ); +  // disable by default. We need to do it with an \
instant single shot qtimer +  QTimer::singleShot( 0, this, \
SLOT(slotClosedTabsDisable())); +  // set the maximum number of showed closed tabs \
list +  closedTabsListLength = 10;
+  connect( m_paClosedTabs, SIGNAL( triggered( Qt::MouseButtons, \
Qt::KeyboardModifiers) ), this, SLOT( slotOpenLastClosedTab() ) ); +  connect( \
m_paClosedTabs->menu(), SIGNAL( aboutToShow() ), this, SLOT( \
slotClosedTabsListAboutToShow() ) ); +  connect( m_paClosedTabs->menu(), SIGNAL( \
activated( int ) ), this, SLOT( slotClosedTabsActivated( int ) ) ); +  connect( this, \
SIGNAL( viewRemoved( KonqView * ) ), this, SLOT( slotAddClosedURL( KonqView * ) ) ); \
+ +
   m_paBack = new KToolBarPopupAction( KIcon(backForward.first.iconName()), \
backForward.first.text(), actionCollection(), "back" );  m_paBack->setShortcut( \
KStdAccel::shortcut(KStdAccel::Back) );  connect( m_paBack, SIGNAL( triggered( \
Qt::MouseButtons, Qt::KeyboardModifiers) ), this, @@ -4047,6 +4121,12 @@
     m_pViewManager->moveTabForward();
 }
 
+
+void KonqMainWindow::slotClosedTabsDisable()
+{
+  m_paClosedTabs->setEnabled(false);
+}
+
 void KonqMainWindow::updateToolBarActions( bool pendingAction /*=false*/)
 {
   // Enables/disables actions that depend on the current view & url (mostly toolbar)
@@ -4404,6 +4484,8 @@
     }
     // There are things we can do, though : bookmarks, view profile, location bar, \
new window,  // settings, etc.
+    m_paClosedTabs->setEnabled( true );
+
     m_paHome->setEnabled( true );
     m_pamBookmarks->setEnabled( true );
     static const char* const s_enActions[] = { "new_window", "duplicate_window", \
"open_location", @@ -4628,6 +4710,7 @@
   // It has to be a KActionCollection instead of a KActionPtrList because we need
   // the actionStatusText signal...
   KActionCollection popupMenuCollection( (QWidget*)0 );
+  popupMenuCollection.insert( m_paClosedTabs );
   popupMenuCollection.insert( m_paBack );
   popupMenuCollection.insert( m_paForward );
   popupMenuCollection.insert( m_paUp );
@@ -5303,6 +5386,52 @@
   QApplication::sendEvent( lineEdit, &event );
 }
 
+/**
+ * Open last closed tab.
+ *
+ * If no tab has been closed yet (i.e. there's none in m_paClosedTabsList)
+ * then this methods does nothing.
+ */
+void KonqMainWindow::slotOpenLastClosedTab()
+{
+  // Take the last closed url and exit if there was none  (that should *never* \
happend) +  KUrl *url = m_closedTabsList.takeFirst( );
+  if(url == 0) return;
+
+  // Generic code to open a new tab
+  KonqView* newView = m_pViewManager->addTab(QString(),
+                                             QString(),
+                                             false,
+                                             KonqSettings::openAfterCurrentPage());
+  if (newView == 0) return;
+  openUrl( newView, *(url),QString());
+  m_pViewManager->showTab( newView );
+  focusLocationBar();
+  m_pWorkingTab = 0;
+  
+  // delete the current url, we don't need it anymore
+  delete url;
+  
+  // if there's no remaining closed urls in the list,
+  // disable the action button
+  if(m_closedTabsList.empty())
+  	m_paClosedTabs->setEnabled(false);
+
+}
+
+/**
+ * Adds the URL of a KonqView to the closed tabs list.
+ * This slot gets called everytime a View is closed
+ *
+ * @param view The KonqView that is getting closed
+ */
+void KonqMainWindow::slotAddClosedURL(KonqView *view)
+{
+  KUrl *url = new KUrl(view->url());
+  m_closedTabsList.prepend(url);
+  m_paClosedTabs->setEnabled(true);
+}
+
 void KonqMainWindow::slotLocationLabelActivated()
 {
   focusLocationBar();
Index: konqueror.rc
===================================================================
--- konqueror.rc	(revisión: 610168)
+++ konqueror.rc	(copia de trabajo)
@@ -121,6 +121,7 @@
  <Action name="stop"/>
  <Separator/>
  <Action name="print"/>
+ <Action name="trashtab" />
  <WeakSeparator/>
  <Merge/>
  <Separator/>


[Attachment #6 (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic