You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/kcontrol/filetypes/kservicelistwidget.cpp

445 lines
14 KiB

/* This file is part of the KDE project
Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
Copyright (C) 2003 David Faure <faure@kde.org>
Copyright (C) 2002 Daniel Molkentin <molkentin@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License version 2 as published by the Free Software Foundation.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <unistd.h>
#include <tqpushbutton.h>
#include <tqlayout.h>
#include <tqwhatsthis.h>
#include <tdeapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <knotifyclient.h>
#include <kopenwith.h>
#include "kservicelistwidget.h"
#include "kserviceselectdlg.h"
#include "typeslistitem.h"
#include <kpropertiesdialog.h>
#include <kstandarddirs.h>
KServiceListItem::KServiceListItem( KService *pService, int kind )
: TQListBoxText(), desktopPath(pService->desktopEntryPath())
{
if ( kind == KServiceListWidget::SERVICELIST_APPLICATIONS )
setText( pService->name() );
else
setText( i18n( "%1 (%2)" ).arg( pService->name() ).arg( pService->desktopEntryName() ) );
bool isApplication = pService->type() == "Application";
if (!isApplication)
localPath = locateLocal("services", desktopPath);
else
localPath = pService->locateLocal();
}
bool KServiceListItem::isImmutable()
{
return !checkAccess(localPath, W_OK);
}
KServiceListWidget::KServiceListWidget(int kind, TQWidget *parent, const char *name)
: TQGroupBox( kind == SERVICELIST_APPLICATIONS ? i18n("Application Preference Order")
: i18n("Services Preference Order"), parent, name ),
m_kind( kind ), m_item( 0L )
{
TQWidget * gb = this;
TQGridLayout * grid = new TQGridLayout(gb, 7, 2, KDialog::marginHint(),
KDialog::spacingHint());
grid->addRowSpacing(0, fontMetrics().lineSpacing());
grid->setRowStretch(1, 1);
grid->setRowStretch(2, 1);
grid->setRowStretch(3, 1);
grid->setRowStretch(4, 1);
grid->setRowStretch(5, 1);
grid->setRowStretch(6, 1);
servicesLB = new TQListBox(gb);
connect(servicesLB, TQT_SIGNAL(highlighted(int)), TQT_SLOT(enableMoveButtons(int)));
grid->addMultiCellWidget(servicesLB, 1, 6, 0, 0);
connect( servicesLB, TQT_SIGNAL( doubleClicked ( TQListBoxItem * )), this, TQT_SLOT( editService()));
TQString wtstr =
(kind == SERVICELIST_APPLICATIONS ?
i18n("This is a list of applications associated with files of the selected"
" file type. This list is shown in Konqueror's context menus when you select"
" \"Open With...\". If more than one application is associated with this file type,"
" then the list is ordered by priority with the uppermost item taking precedence"
" over the others.") :
i18n("This is a list of services associated with files of the selected"
" file type. This list is shown in Konqueror's context menus when you select"
" a \"Preview with...\" option. If more than one application is associated with this file type,"
" then the list is ordered by priority with the uppermost item taking precedence"
" over the others."));
TQWhatsThis::add( gb, wtstr );
TQWhatsThis::add( servicesLB, wtstr );
servUpButton = new TQPushButton(i18n("Move &Up"), gb);
servUpButton->setEnabled(false);
connect(servUpButton, TQT_SIGNAL(clicked()), TQT_SLOT(promoteService()));
grid->addWidget(servUpButton, 2, 1);
TQWhatsThis::add( servUpButton, kind == SERVICELIST_APPLICATIONS ?
i18n("Assigns a higher priority to the selected\n"
"application, moving it up in the list. Note: This\n"
"only affects the selected application if the file type is\n"
"associated with more than one application.") :
i18n("Assigns a higher priority to the selected\n"
"service, moving it up in the list."));
servDownButton = new TQPushButton(i18n("Move &Down"), gb);
servDownButton->setEnabled(false);
connect(servDownButton, TQT_SIGNAL(clicked()), TQT_SLOT(demoteService()));
grid->addWidget(servDownButton, 3, 1);
TQWhatsThis::add( servDownButton, kind == SERVICELIST_APPLICATIONS ?
i18n("Assigns a lower priority to the selected\n"
"application, moving it down in the list. Note: This \n"
"only affects the selected application if the file type is\n"
"associated with more than one application."):
i18n("Assigns a lower priority to the selected\n"
"service, moving it down in the list."));
servNewButton = new TQPushButton(i18n("Add..."), gb);
servNewButton->setEnabled(false);
connect(servNewButton, TQT_SIGNAL(clicked()), TQT_SLOT(addService()));
grid->addWidget(servNewButton, 1, 1);
TQWhatsThis::add( servNewButton, i18n( "Add a new application for this file type." ) );
servEditButton = new TQPushButton(i18n("Edit..."), gb);
servEditButton->setEnabled(false);
connect(servEditButton, TQT_SIGNAL(clicked()), TQT_SLOT(editService()));
grid->addWidget(servEditButton, 4, 1);
TQWhatsThis::add( servEditButton, i18n( "Edit command line of the selected application." ) );
servRemoveButton = new TQPushButton(i18n("Remove"), gb);
servRemoveButton->setEnabled(false);
connect(servRemoveButton, TQT_SIGNAL(clicked()), TQT_SLOT(removeService()));
grid->addWidget(servRemoveButton, 5, 1);
TQWhatsThis::add( servRemoveButton, i18n( "Remove the selected application from the list." ) );
}
void KServiceListWidget::setTypeItem( TypesListItem * item )
{
m_item = item;
if ( servNewButton )
servNewButton->setEnabled(true);
// will need a selection
servUpButton->setEnabled(false);
servDownButton->setEnabled(false);
if ( servRemoveButton )
servRemoveButton->setEnabled(false);
if ( servEditButton )
servEditButton->setEnabled(false);
servicesLB->clear();
servicesLB->setEnabled(false);
if ( item )
{
TQStringList services = ( m_kind == SERVICELIST_APPLICATIONS )
? item->appServices()
: item->embedServices();
if (services.count() == 0) {
servicesLB->insertItem(i18n("None"));
} else {
for ( TQStringList::Iterator it = services.begin();
it != services.end(); it++ )
{
KService::Ptr pService = KService::serviceByDesktopPath( *it );
if (pService)
servicesLB->insertItem( new KServiceListItem(pService, m_kind) );
}
servicesLB->setEnabled(true);
}
}
}
void KServiceListWidget::promoteService()
{
if (!servicesLB->isEnabled()) {
KNotifyClient::beep();
return;
}
unsigned int selIndex = servicesLB->currentItem();
if (selIndex == 0) {
KNotifyClient::beep();
return;
}
TQListBoxItem *selItem = servicesLB->item(selIndex);
servicesLB->takeItem(selItem);
servicesLB->insertItem(selItem, selIndex-1);
servicesLB->setCurrentItem(selIndex - 1);
updatePreferredServices();
emit changed(true);
}
void KServiceListWidget::demoteService()
{
if (!servicesLB->isEnabled()) {
KNotifyClient::beep();
return;
}
unsigned int selIndex = servicesLB->currentItem();
if (selIndex == servicesLB->count() - 1) {
KNotifyClient::beep();
return;
}
TQListBoxItem *selItem = servicesLB->item(selIndex);
servicesLB->takeItem(selItem);
servicesLB->insertItem(selItem, selIndex+1);
servicesLB->setCurrentItem(selIndex + 1);
updatePreferredServices();
emit changed(true);
}
void KServiceListWidget::addService()
{
if (!m_item)
return;
KService::Ptr service = 0L;
if ( m_kind == SERVICELIST_APPLICATIONS )
{
KOpenWithDlg dlg(m_item->name(), TQString::null, 0L);
dlg.setSaveNewApplications(true);
if (dlg.exec() != TQDialog::Accepted)
return;
service = dlg.service();
Q_ASSERT(service);
if (!service)
return; // Don't crash if KOpenWith wasn't able to create service.
}
else
{
KServiceSelectDlg dlg(m_item->name(), TQString::null, 0L);
if (dlg.exec() != TQDialog::Accepted)
return;
service = dlg.service();
Q_ASSERT(service);
if (!service)
return;
}
// if None is the only item, then there currently is no default
if (servicesLB->text(0) == i18n("None")) {
servicesLB->removeItem(0);
servicesLB->setEnabled(true);
}
else
{
// check if it is a duplicate entry
for (unsigned int index = 0; index < servicesLB->count(); index++)
if (static_cast<KServiceListItem*>( servicesLB->item(index) )->desktopPath
== service->desktopEntryPath())
return;
}
servicesLB->insertItem( new KServiceListItem(service, m_kind), 0 );
servicesLB->setCurrentItem(0);
updatePreferredServices();
emit changed(true);
}
void KServiceListWidget::editService()
{
if (!m_item)
return;
int selected = servicesLB->currentItem();
if ( selected >= 0 ) {
// Only edit applications, not services as
// they don't have any parameters
if ( m_kind == SERVICELIST_APPLICATIONS )
{
// Just like popping up an add dialog except that we
// pass the current command line as a default
TQListBoxItem *selItem = servicesLB->item(selected);
KService::Ptr service = KService::serviceByDesktopPath(
((KServiceListItem*)selItem)->desktopPath );
if (!service)
return;
TQString path = service->desktopEntryPath();
// If the path to the desktop file is relative, try to get the full
// path from KStdDirs.
path = locate("apps", path);
KURL serviceURL;
serviceURL.setPath( path );
KFileItem item( serviceURL, "application/x-desktop", KFileItem::Unknown );
KPropertiesDialog dlg( &item, this, 0, true /*modal*/, false /*no auto-show*/ );
if ( dlg.exec() != TQDialog::Accepted )
return;
// Reload service
service = KService::serviceByDesktopPath(
((KServiceListItem*)selItem)->desktopPath );
if (!service)
return;
// Remove the old one...
servicesLB->removeItem( selected );
// ...check that it's not a duplicate entry...
bool addIt = true;
for (unsigned int index = 0; index < servicesLB->count(); index++)
if (static_cast<KServiceListItem*>( servicesLB->item(index) )->desktopPath
== service->desktopEntryPath()) {
addIt = false;
break;
}
// ...and add it in the same place as the old one:
if ( addIt ) {
servicesLB->insertItem( new KServiceListItem(service, m_kind), selected );
servicesLB->setCurrentItem(selected);
}
updatePreferredServices();
emit changed(true);
}
}
}
void KServiceListWidget::removeService()
{
if (!m_item) return;
// Here are some strings already so that we don't have to break translations
// later on.
TQString msg1 = i18n("The service <b>%1</b> can not be removed.");
TQString msg2 = i18n("The service is listed here because it has been associated "
"with the <b>%1</b> (%2) file type and files of type "
"<b>%3</b> (%4) are per definition also of type "
"<b>%5</b>.");
TQString msg3 = i18n("Either select the <b>%1</b> file type to remove the "
"service from there or move the service down "
"to deprecate it.");
TQString msg4 = i18n("Do you want to remove the service from the <b>%1</b> "
"file type or from the <b>%2</b> file type?");
int selected = servicesLB->currentItem();
if ( selected >= 0 ) {
// Check if service is associated with this mimetype or with one of its parents
KServiceListItem *serviceItem = static_cast<KServiceListItem *>(servicesLB->item(selected));
KMimeType::Ptr mimetype = m_item->findImplicitAssociation(serviceItem->desktopPath);
if (serviceItem->isImmutable())
{
KMessageBox::sorry(this, i18n("You are not authorized to remove this service."));
}
else if (mimetype)
{
KMessageBox::sorry(this, "<qt>"+msg1.arg(serviceItem->text())+"<p>"+
msg2.arg(mimetype->name()).arg(mimetype->comment()).
arg(m_item->name()).arg(m_item->comment()).
arg(mimetype->name())+"<p>"+
msg3.arg(mimetype->name()));
}
else
{
servicesLB->removeItem( selected );
updatePreferredServices();
emit changed(true);
}
}
if ( servRemoveButton && servicesLB->currentItem() == -1 )
servRemoveButton->setEnabled(false);
if ( servEditButton && servicesLB->currentItem() == -1 )
servEditButton->setEnabled(false);
}
void KServiceListWidget::updatePreferredServices()
{
if (!m_item)
return;
TQStringList sl;
unsigned int count = servicesLB->count();
for (unsigned int i = 0; i < count; i++) {
KServiceListItem *sli = (KServiceListItem *) servicesLB->item(i);
sl.append( sli->desktopPath );
}
if ( m_kind == SERVICELIST_APPLICATIONS )
m_item->setAppServices(sl);
else
m_item->setEmbedServices(sl);
}
void KServiceListWidget::enableMoveButtons(int index)
{
if (servicesLB->count() <= 1)
{
servUpButton->setEnabled(false);
servDownButton->setEnabled(false);
}
else if ((uint) index == (servicesLB->count() - 1))
{
servUpButton->setEnabled(true);
servDownButton->setEnabled(false);
}
else if (index == 0)
{
servUpButton->setEnabled(false);
servDownButton->setEnabled(true);
}
else
{
servUpButton->setEnabled(true);
servDownButton->setEnabled(true);
}
if ( servRemoveButton )
servRemoveButton->setEnabled(true);
if ( servEditButton )
servEditButton->setEnabled(true && ( m_kind == SERVICELIST_APPLICATIONS ) );
}
#include "kservicelistwidget.moc"