mirror of
https://invent.kde.org/system/dolphin
synced 2024-09-20 08:51:24 +00:00
589eeb4e81
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
591 lines
15 KiB
C++
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"
|