/* This file is part of the KDE project Copyright (C) 2003 Waldo Bastian Copyright (C) 2003 David Faure Copyright (C) 2002 Daniel Molkentin 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 #include #include #include #include #include #include #include #include #include #include "kservicelistwidget.h" #include "kserviceselectdlg.h" #include "typeslistitem.h" #include #include 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( 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( 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 %1 can not be removed."); TQString msg2 = i18n("The service is listed here because it has been associated " "with the %1 (%2) file type and files of type " "%3 (%4) are per definition also of type " "%5."); TQString msg3 = i18n("Either select the %1 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 %1 " "file type or from the %2 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(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, ""+msg1.arg(serviceItem->text())+"

"+ msg2.arg(mimetype->name()).arg(mimetype->comment()). arg(m_item->name()).arg(m_item->comment()). arg(mimetype->name())+"

"+ 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"