dolphin/lib/konq/konqpopupmenu.cc
Simon Hausmann 589eeb4e81 - moved the empty-trash-bin functionality from KonqPopupMenu to KonqOperations.
The reason: In KonqpopupMenu we used to connect to the result() signal
  of the del iojob. However the slot could never be reached, because the popupmenu
  was destroyed right after the call anyway.
  Unfortuantely this still does not fix the empty-trash functionality itself
  I still get stuff like:

  kio (KIOJob):  -- with progress info --
QObject::connect: No such signal QObject::result(KIO::Job*)
QObject::connect:  (sender name:
'H÷¸@H÷¸@`XX÷¸@X÷¸@øøh÷¸@h÷¸@p÷¸@p÷¸@x÷¸@x÷¸@?÷¸@?÷¸@?÷¸@?÷¸@?÷¸@?÷¸@?÷¸@?÷¸@ ÷¸@ ÷¸@¨÷¸@¨÷¸@°÷¸@°÷¸@¸÷¸@¸÷¸@À÷¸@À÷¸@È÷¸@È÷¸@Ð÷¸@Ð÷¸@Ø÷¸@Ø÷¸@à÷¸@à÷¸@è÷¸@è÷¸@ð÷¸@ð÷¸@ø÷¸@ø÷¸@')
QObject::connect:  (receiver name: 'KonqOperations')

  with not result though (no files are being deleted) . and sometimes it crashes..

(oh, and I just noticed: The empty-trash menu item in the popupmenu appears
only when the URL is actually opened in a view. It does not appear in the popupmenu
in kdesktop)

svn path=/trunk/kdebase/libkonq/; revision=47649
2000-04-27 17:59:11 +00:00

591 lines
15 KiB
C++

/* This file is part of the KDE project
Copyright (C) 1998, 1999 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <qdir.h>
#include <qclipboard.h>
#include <qapplication.h>
#include <qdragobject.h>
#include <krun.h>
#include <kbookmark.h>
#include <kdebug.h>
#include <kio/job.h>
#include <kio/paste.h>
#include <kopenwith.h>
#include <kmessagebox.h>
#include <kprotocolmanager.h>
#include <kservice.h>
#include <ktrader.h>
#include <kurl.h>
#include <kuserprofile.h>
#include <kglobalsettings.h>
#include <kglobal.h>
#include <kstddirs.h>
#include <kxmlgui.h>
#include <kxmlguibuilder.h>
#include <assert.h>
#include "kpropsdlg.h"
#include "knewmenu.h"
#include "konqpopupmenu.h"
#include "konqoperations.h"
class KonqPopupMenuGUIBuilder : public KXMLGUIBuilder
{
public:
KonqPopupMenuGUIBuilder( QPopupMenu *menu )
: KXMLGUIBuilder( 0 )
{
m_menu = menu;
}
virtual ~KonqPopupMenuGUIBuilder()
{
}
virtual QWidget *createContainer( QWidget *parent, int index,
const QDomElement &element, const QByteArray &containerStateBuffer,
int &id )
{
if ( !parent && element.attribute( "name" ) == "popupmenu" )
return m_menu;
return KXMLGUIBuilder::createContainer( parent, index, element, containerStateBuffer, id );
}
QPopupMenu *m_menu;
};
KonqPopupMenu::KonqPopupMenu( const KFileItemList &items,
KURL viewURL,
KActionCollection & actions,
KNewMenu * newMenu )
: QPopupMenu( 0L, "konq_popupmenu" ), m_actions( actions ), m_pMenuNew( newMenu ),
m_sViewURL(viewURL), m_lstItems(items)
{
assert( m_lstItems.count() >= 1 );
bool currentDir = false;
bool sReading = true;
bool sWriting = true;
bool sDeleting = true;
bool sMoving = true;
m_sMimeType = m_lstItems.first()->mimetype();
mode_t mode = m_lstItems.first()->mode();
m_lstPopupURLs.clear();
int id;
setFont(KGlobal::menuFont());
attrName = QString::fromLatin1( "name" );
prepareXMLGUIStuff();
KProtocolManager pManager = KProtocolManager::self();
KURL url;
KFileItemListIterator it ( m_lstItems );
// Check whether all URLs are correct
for ( ; it.current(); ++it )
{
url = (*it)->url();
// Build the list of URLs
m_lstPopupURLs.append( url );
// Determine if common mode among all URLs
if ( mode != (*it)->mode() )
mode = 0; // modes are different => reset to 0
// Determine if common mimetype among all URLs
if ( m_sMimeType != (*it)->mimetype() )
m_sMimeType = QString::null; // mimetypes are different => null
QString protocol = url.protocol();
if ( sReading )
sReading = pManager.supportsReading( protocol );
if ( sWriting )
sWriting = pManager.supportsWriting( protocol );
if ( sDeleting )
sDeleting = pManager.supportsDeleting( protocol );
if ( sMoving )
sMoving = pManager.supportsMoving( protocol );
}
//check if current url is trash
url = m_sViewURL;
url.cleanPath();
bool isCurrentTrash = ( url.isLocalFile() &&
url.path(1) == KGlobalSettings::trashPath() );
//check if url is current directory
if ( m_lstItems.count() == 1 )
{
KURL firstPopupURL ( m_lstItems.first()->url() );
firstPopupURL.cleanPath();
//kdDebug(1203) << "View path is " << url.url() << endl;
//kdDebug(1203) << "First popup path is " << firstPopupURL.url() << endl;
currentDir = firstPopupURL.cmp( url, true /* ignore_trailing */ );
}
QObject::disconnect( this, SIGNAL( activated( int ) ), this, SLOT( slotPopup( int ) ) );
clear();
//////////////////////////////////////////////////////////////////////////
KAction * act;
addMerge( "konqueror" );
m_paNewView = new KAction( i18n( "New View" ), 0, this, SLOT( slotPopupNewView() ), &m_ownActions, "newview" );
if ( isCurrentTrash && currentDir )
{
addAction( m_paNewView );
addSeparator();
act = new KAction( i18n( "Empty Trash Bin" ), 0, this, SLOT( slotPopupEmptyTrashBin() ), &m_ownActions, "empytrash" );
addAction( act );
}
else
{
if ( S_ISDIR( mode ) ) // all URLs are directories
{
if ( sWriting && m_pMenuNew ) // Add the "new" menu
{
// As requested by KNewMenu :
m_pMenuNew->slotCheckUpToDate();
m_pMenuNew->setPopupFiles( m_lstPopupURLs );
addAction( m_pMenuNew );
addSeparator();
}
if ( currentDir ) {
addAction( "up" );
addAction( "back" );
addAction( "forward" );
addAction( "reload" );
addGroup( "reload" );
addSeparator();
}
addAction( m_paNewView );
addSeparator();
}
else // not all URLs are dirs
{
// HACK - should be also possible for anything we can embed
if ( m_sViewURL.protocol() == "http" )
{
addAction( m_paNewView );
addSeparator();
}
}
if ( sReading ) {
if ( sDeleting ) {
addAction( "cut" );
}
addAction( "copy" );
}
if ( sWriting ) {
addAction( "paste" );
}
if ( sMoving && !currentDir ) {
addAction( "trash" );
}
if ( sDeleting && !currentDir ) {
addAction( "del" );
if ( m_sViewURL.isLocalFile() )
addAction( "shred" );
}
}
act = new KAction( i18n( "Add To Bookmarks" ), 0, this, SLOT( slotPopupAddToBookmark() ), &m_ownActions, "addbookmark" );
addAction( act );
//////////////////////////////////////////////////////
bool bLastSepInserted = false;
if ( !m_sMimeType.isNull() ) // common mimetype among all URLs ?
{
// Query the trader for offers associated to this mimetype
// 2 - Look for builtin and user-defined services
QValueList<KDEDesktopMimeType::Service> builtin;
QValueList<KDEDesktopMimeType::Service> user;
if ( m_sMimeType == "application/x-desktop" ) // .desktop file
{
// get builtin services, like mount/unmount
builtin = KDEDesktopMimeType::builtinServices( m_lstItems.first()->url() );
user = KDEDesktopMimeType::userDefinedServices( m_lstItems.first()->url() );
}
// 3 - Look for "servicesmenus" bindings (konqueror-specific user-defined services)
QStringList dirs = KGlobal::dirs()->findDirs( "data", "konqueror/servicemenus/" );
QStringList::ConstIterator dIt = dirs.begin();
QStringList::ConstIterator dEnd = dirs.end();
for (; dIt != dEnd; ++dIt )
{
QDir dir( *dIt );
QStringList entries = dir.entryList( QDir::Files );
QStringList::ConstIterator eIt = entries.begin();
QStringList::ConstIterator eEnd = entries.end();
for (; eIt != eEnd; ++eIt )
{
KSimpleConfig cfg( *dIt + *eIt, true );
cfg.setDesktopGroup();
if ( cfg.hasKey( "Actions" ) && cfg.hasKey( "ServiceTypes" ) &&
cfg.readListEntry( "ServiceTypes" ).contains( m_sMimeType ) )
{
KURL u( *dIt + *eIt );
user += KDEDesktopMimeType::userDefinedServices( u );
}
}
}
// 4 - Query for applications
KTrader::OfferList offers = KTrader::self()->query( m_sMimeType, "Type == 'Application'" );
//// Ok, we have everything, now insert
m_mapPopup.clear();
m_mapPopupServices.clear();
QString openWithText = i18n( "Open With" );
if ( !offers.isEmpty() || !user.isEmpty() || !builtin.isEmpty() )
{
// First block, app offers + user
addSeparator();
id = 1;
bool insertedOffer = false;
QDomElement menu = m_menuElement;
if ( offers.count() > 1 )
{
menu = m_doc.createElement( "menu" );
m_menuElement.appendChild( menu );
QDomElement text = m_doc.createElement( "text" );
menu.appendChild( text );
text.appendChild( m_doc.createTextNode( openWithText ) );
openWithText = i18n( "Other..." );
}
KAction *openWithAct = new KAction( openWithText, 0, this, SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
if ( menu == m_menuElement )
{
addAction( openWithAct, menu );
addSeparator();
}
addGroup( "preview" );
// KServiceTypeProfile::OfferList::Iterator it = offers.begin();
KTrader::OfferList::ConstIterator it = offers.begin();
for( ; it != offers.end(); it++ )
{
QCString nam;
nam.setNum( id );
act = new KAction( (*it)->name(), (*it)->pixmap( KIcon::Small ), 0,
this, SLOT( slotRunService() ),
&m_ownActions, nam.prepend( "appservice_" ) );
addAction( act, menu );
m_mapPopup[ id++ ] = *it;
insertedOffer = true;
}
QValueList<KDEDesktopMimeType::Service>::Iterator it2 = user.begin();
for( ; it2 != user.end(); ++it2 )
{
if ((*it2).m_display == true)
{
QCString nam;
nam.setNum( id );
act = new KAction( (*it2).m_strName, 0, this, SLOT( slotRunService() ), &m_ownActions, nam.prepend( "userservice_" ) );
if ( !(*it2).m_strIcon.isEmpty() )
{
QPixmap pix = SmallIcon( (*it2).m_strIcon );
act->setIconSet( pix );
}
addAction( act, menu );
m_mapPopupServices[ id++ ] = *it2;
insertedOffer = true;
}
}
if ( menu != m_menuElement )
{
addSeparator( menu );
addAction( openWithAct, menu );
}
// Second block, builtin
if ( insertedOffer )
addSeparator();
insertedOffer = false;
it2 = builtin.begin();
for( ; it2 != builtin.end(); ++it2 )
{
QCString nam;
nam.setNum( id );
act = new KAction( (*it2).m_strName, 0, this, SLOT( slotRunService() ), &m_ownActions, nam.prepend( "builtinservice_" ) );
if ( !(*it2).m_strIcon.isEmpty() )
{
QPixmap pix = SmallIcon( (*it2).m_strIcon );
act->setIconSet( pix );
}
addAction( act, menu );
m_mapPopupServices[ id++ ] = *it2;
insertedOffer = true;
}
if ( insertedOffer )
addSeparator();
}
else
{
addSeparator();
openWithText += "..."; //Show "..." only when no application binding is found!!
act = new KAction( openWithText, 0, this, SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
addAction( act );
addSeparator();
}
bLastSepInserted = true;
// or "File Type Properties" ?
act = new KAction( i18n( "Edit File Type..." ), 0, this, SLOT( slotPopupMimeType() ),
&m_ownActions, "editfiletype" );
addAction( act );
}
if ( PropertiesDialog::canDisplay( m_lstItems ) )
{
if ( !bLastSepInserted ) addSeparator();
act = new KAction( i18n( "Properties..." ), 0, this, SLOT( slotPopupProperties() ),
&m_ownActions, "properties" );
addAction( act );
}
addMerge( 0 );
m_factory->addClient( this );
}
KonqPopupMenu::~KonqPopupMenu()
{
delete m_factory;
delete m_builder;
}
void KonqPopupMenu::slotPopupNewView()
{
KURL::List::ConstIterator it = m_lstPopupURLs.begin();
for ( ; it != m_lstPopupURLs.end(); it++ )
(void) new KRun(*it);
}
void KonqPopupMenu::slotPopupEmptyTrashBin()
{
KonqOperations::emptyTrash();
}
void KonqPopupMenu::slotPopupOpenWith()
{
KOpenWithDlg l( m_lstPopupURLs );
if ( l.exec() )
{
KService::Ptr service = l.service();
if ( !!service )
{
KRun::run( *service, m_lstPopupURLs );
return;
}
else
{
QString exec = l.text();
exec += " %f";
KRun::run( exec, m_lstPopupURLs );
}
}
}
void KonqPopupMenu::slotPopupAddToBookmark()
{
KBookmark *root = KBookmarkManager::self()->root();
KURL::List::ConstIterator it = m_lstPopupURLs.begin();
for ( ; it != m_lstPopupURLs.end(); it++ )
(void)new KBookmark( KBookmarkManager::self(), root, (*it).decodedURL(), *it );
}
void KonqPopupMenu::slotRunService()
{
QCString senderName = sender()->name();
int id = senderName.mid( senderName.find( '_' ) + 1 ).toInt();
// Is it a usual service (application)
QMap<int,KService::Ptr>::Iterator it = m_mapPopup.find( id );
if ( it != m_mapPopup.end() )
{
KRun::run( **it, m_lstPopupURLs );
return;
}
// Is it a service specific to desktop entry files ?
QMap<int,KDEDesktopMimeType::Service>::Iterator it2 = m_mapPopupServices.find( id );
if ( it2 != m_mapPopupServices.end() )
{
KURL::List::Iterator it3 = m_lstPopupURLs.begin();
for( ; it3 != m_lstPopupURLs.end(); ++it3 )
KDEDesktopMimeType::executeService( (*it3).path(), it2.data() );
}
return;
}
void KonqPopupMenu::slotPopupMimeType()
{
KonqOperations::editMimeType( m_sMimeType );
}
void KonqPopupMenu::slotPopupProperties()
{
(void) new PropertiesDialog( m_lstItems );
}
KAction *KonqPopupMenu::action( const QDomElement &element ) const
{
QString name = element.attribute( attrName );
KAction *res = m_ownActions.action( name );
if ( !res )
res = m_actions.action( name );
if ( !res && strcmp( name, m_pMenuNew->name() ) == 0 )
return m_pMenuNew;
return res;
}
QDomDocument KonqPopupMenu::document() const
{
return m_doc;
}
void KonqPopupMenu::addAction( KAction *act, const QDomElement &menu )
{
addAction( act->name(), menu );
}
void KonqPopupMenu::addAction( const char *name, const QDomElement &menu )
{
static QString tagAction = QString::fromLatin1( "action" );
QDomElement parent = menu;
if ( parent.isNull() )
parent = m_menuElement;
QDomElement e = m_doc.createElement( tagAction );
parent.appendChild( e );
e.setAttribute( attrName, name );
}
void KonqPopupMenu::addSeparator( const QDomElement &menu )
{
static QString tagSeparator = QString::fromLatin1( "separator" );
QDomElement parent = menu;
if ( parent.isNull() )
parent = m_menuElement;
parent.appendChild( m_doc.createElement( tagSeparator ) );
}
void KonqPopupMenu::addMerge( const char *name )
{
static QString tagMerge = QString::fromLatin1( "merge" );
QDomElement merge = m_doc.createElement( tagMerge );
m_menuElement.appendChild( merge );
if ( name )
merge.setAttribute( attrName, name );
}
void KonqPopupMenu::addGroup( const QString &grp )
{
QDomElement group = m_doc.createElement( "definegroup" );
m_menuElement.appendChild( group );
group.setAttribute( "name", grp );
}
void KonqPopupMenu::prepareXMLGUIStuff()
{
m_doc = QDomDocument( "kpartgui" );
QDomElement root = m_doc.createElement( "kpartgui" );
m_doc.appendChild( root );
root.setAttribute( attrName, "popupmenu" );
m_menuElement = m_doc.createElement( "Menu" );
root.appendChild( m_menuElement );
m_menuElement.setAttribute( attrName, "popupmenu" );
m_builder = new KonqPopupMenuGUIBuilder( this );
m_factory = new KXMLGUIFactory( m_builder );
}
#include "konqpopupmenu.moc"