diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /kcontrol/filetypes/kservicelistwidget.cpp | |
download | tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kcontrol/filetypes/kservicelistwidget.cpp')
-rw-r--r-- | kcontrol/filetypes/kservicelistwidget.cpp | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/kcontrol/filetypes/kservicelistwidget.cpp b/kcontrol/filetypes/kservicelistwidget.cpp new file mode 100644 index 000000000..ed6819a37 --- /dev/null +++ b/kcontrol/filetypes/kservicelistwidget.cpp @@ -0,0 +1,444 @@ +/* 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 <qpushbutton.h> +#include <qlayout.h> +#include <qwhatsthis.h> + +#include <kapplication.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 ) + : QListBoxText(), 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, QWidget *parent, const char *name) + : QGroupBox( kind == SERVICELIST_APPLICATIONS ? i18n("Application Preference Order") + : i18n("Services Preference Order"), parent, name ), + m_kind( kind ), m_item( 0L ) +{ + QWidget * gb = this; + QGridLayout * grid = new QGridLayout(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 QListBox(gb); + connect(servicesLB, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int))); + grid->addMultiCellWidget(servicesLB, 1, 6, 0, 0); + connect( servicesLB, SIGNAL( doubleClicked ( QListBoxItem * )), this, SLOT( editService())); + + QString 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.")); + + QWhatsThis::add( gb, wtstr ); + QWhatsThis::add( servicesLB, wtstr ); + + servUpButton = new QPushButton(i18n("Move &Up"), gb); + servUpButton->setEnabled(false); + connect(servUpButton, SIGNAL(clicked()), SLOT(promoteService())); + grid->addWidget(servUpButton, 2, 1); + + QWhatsThis::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 QPushButton(i18n("Move &Down"), gb); + servDownButton->setEnabled(false); + connect(servDownButton, SIGNAL(clicked()), SLOT(demoteService())); + grid->addWidget(servDownButton, 3, 1); + + QWhatsThis::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 QPushButton(i18n("Add..."), gb); + servNewButton->setEnabled(false); + connect(servNewButton, SIGNAL(clicked()), SLOT(addService())); + grid->addWidget(servNewButton, 1, 1); + + QWhatsThis::add( servNewButton, i18n( "Add a new application for this file type." ) ); + + + servEditButton = new QPushButton(i18n("Edit..."), gb); + servEditButton->setEnabled(false); + connect(servEditButton, SIGNAL(clicked()), SLOT(editService())); + grid->addWidget(servEditButton, 4, 1); + + QWhatsThis::add( servEditButton, i18n( "Edit command line of the selected application." ) ); + + + servRemoveButton = new QPushButton(i18n("Remove"), gb); + servRemoveButton->setEnabled(false); + connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeService())); + grid->addWidget(servRemoveButton, 5, 1); + + QWhatsThis::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 ) + { + QStringList services = ( m_kind == SERVICELIST_APPLICATIONS ) + ? item->appServices() + : item->embedServices(); + + if (services.count() == 0) { + servicesLB->insertItem(i18n("None")); + } else { + for ( QStringList::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; + } + + QListBoxItem *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; + } + + QListBoxItem *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(), QString::null, 0L); + dlg.setSaveNewApplications(true); + if (dlg.exec() != QDialog::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(), QString::null, 0L); + if (dlg.exec() != QDialog::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 + QListBoxItem *selItem = servicesLB->item(selected); + + KService::Ptr service = KService::serviceByDesktopPath( + ((KServiceListItem*)selItem)->desktopPath ); + if (!service) + return; + + QString 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() != QDialog::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. + QString msg1 = i18n("The service <b>%1</b> can not be removed."); + QString 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>."); + QString msg3 = i18n("Either select the <b>%1</b> file type to remove the " + "service from there or move the service down " + "to deprecate it."); + QString 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; + QStringList 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" |