summaryrefslogtreecommitdiffstats
path: root/kcontrol/filetypes/typeslistitem.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /kcontrol/filetypes/typeslistitem.cpp
downloadtdebase-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/typeslistitem.cpp')
-rw-r--r--kcontrol/filetypes/typeslistitem.cpp579
1 files changed, 579 insertions, 0 deletions
diff --git a/kcontrol/filetypes/typeslistitem.cpp b/kcontrol/filetypes/typeslistitem.cpp
new file mode 100644
index 000000000..88f3c8035
--- /dev/null
+++ b/kcontrol/filetypes/typeslistitem.cpp
@@ -0,0 +1,579 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
+ Copyright (C) 2003 David Faure <faure@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 <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kdesktopfile.h>
+#include <kstaticdeleter.h>
+
+#include "typeslistitem.h"
+
+QMap< QString, QStringList >* TypesListItem::s_changedServices;
+static KStaticDeleter< QMap< QString, QStringList > > deleter;
+
+TypesListItem::TypesListItem(QListView *parent, const QString & major)
+ : QListViewItem(parent), metaType(true), m_bNewItem(false), m_askSave(2)
+{
+ initMeta(major);
+ setText(0, majorType());
+}
+
+TypesListItem::TypesListItem(TypesListItem *parent, KMimeType::Ptr mimetype, bool newItem)
+ : QListViewItem(parent), metaType(false), m_bNewItem(newItem), m_askSave(2)
+{
+ init(mimetype);
+ setText(0, minorType());
+}
+
+TypesListItem::TypesListItem(QListView *parent, KMimeType::Ptr mimetype)
+ : QListViewItem(parent), metaType(false), m_bNewItem(false), m_askSave(2)
+{
+ init(mimetype);
+ setText(0, majorType());
+}
+
+TypesListItem::TypesListItem(QListView *parent, KMimeType::Ptr mimetype, bool newItem)
+ : QListViewItem(parent), metaType(false), m_bNewItem(newItem), m_askSave(2)
+{
+ init(mimetype);
+ setText(0, majorType());
+}
+
+TypesListItem::~TypesListItem()
+{
+}
+
+void TypesListItem::initMeta( const QString & major )
+{
+ m_bFullInit = true;
+ m_mimetype = 0L;
+ m_major = major;
+ KSharedConfig::Ptr config = KSharedConfig::openConfig("konquerorrc", false, false);
+ config->setGroup("EmbedSettings");
+ bool defaultValue = defaultEmbeddingSetting( major );
+ m_autoEmbed = config->readBoolEntry( QString::fromLatin1("embed-")+m_major, defaultValue ) ? 0 : 1;
+}
+
+bool TypesListItem::defaultEmbeddingSetting( const QString& major )
+{
+ // embedding is false by default except for image/*
+ return ( major=="image" );
+}
+
+void TypesListItem::setup()
+{
+ if (m_mimetype)
+ {
+ setPixmap(0, m_mimetype->pixmap(KIcon::Small, IconSize(KIcon::Small)));
+ }
+ QListViewItem::setup();
+}
+
+void TypesListItem::init(KMimeType::Ptr mimetype)
+{
+ m_bFullInit = false;
+ m_mimetype = mimetype;
+
+ int index = mimetype->name().find("/");
+ if (index != -1) {
+ m_major = mimetype->name().left(index);
+ m_minor = mimetype->name().right(mimetype->name().length() -
+ (index+1));
+ } else {
+ m_major = mimetype->name();
+ m_minor = "";
+ }
+ m_comment = mimetype->comment(QString(), false);
+ m_icon = mimetype->icon(QString(), false);
+ m_patterns = mimetype->patterns();
+ m_autoEmbed = readAutoEmbed( mimetype );
+}
+
+int TypesListItem::readAutoEmbed( KMimeType::Ptr mimetype )
+{
+ QVariant v = mimetype->property( "X-KDE-AutoEmbed" );
+ if ( v.isValid() )
+ return (v.toBool() ? 0 : 1);
+ else if ( !mimetype->property( "X-KDE-LocalProtocol" ).toString().isEmpty() )
+ return 0; // embed by default for zip, tar etc.
+ else
+ return 2;
+}
+
+QStringList TypesListItem::appServices() const
+{
+ if (!m_bFullInit)
+ {
+ TypesListItem *that = const_cast<TypesListItem *>(this);
+ that->getServiceOffers(that->m_appServices, that->m_embedServices);
+ that->m_bFullInit = true;
+ }
+ return m_appServices;
+}
+
+QStringList TypesListItem::embedServices() const
+{
+ if (!m_bFullInit)
+ {
+ TypesListItem *that = const_cast<TypesListItem *>(this);
+ that->getServiceOffers(that->m_appServices, that->m_embedServices);
+ that->m_bFullInit = true;
+ }
+ return m_embedServices;
+}
+
+void TypesListItem::getServiceOffers( QStringList & appServices, QStringList & embedServices ) const
+{
+ KServiceTypeProfile::setConfigurationMode();
+
+ KServiceTypeProfile::OfferList offerList =
+ KServiceTypeProfile::offers(m_mimetype->name(), "Application");
+ QValueListIterator<KServiceOffer> it(offerList.begin());
+ for (; it != offerList.end(); ++it)
+ if ((*it).allowAsDefault())
+ appServices.append((*it).service()->desktopEntryPath());
+
+ offerList = KServiceTypeProfile::offers(m_mimetype->name(), "KParts/ReadOnlyPart");
+ for ( it = offerList.begin(); it != offerList.end(); ++it)
+ embedServices.append((*it).service()->desktopEntryPath());
+
+ KServiceTypeProfile::unsetConfigurationMode();
+}
+
+bool TypesListItem::isMimeTypeDirty() const
+{
+ if ( m_bNewItem )
+ return true;
+ if ((m_mimetype->name() != name()) &&
+ (name() != "application/octet-stream"))
+ {
+ kdDebug() << "Mimetype Name Dirty: old=" << m_mimetype->name() << " name()=" << name() << endl;
+ return true;
+ }
+ if (m_mimetype->comment(QString(), false) != m_comment)
+ {
+ kdDebug() << "Mimetype Comment Dirty: old=" << m_mimetype->comment(QString(),false) << " m_comment=" << m_comment << endl;
+ return true;
+ }
+ if (m_mimetype->icon(QString(), false) != m_icon)
+ {
+ kdDebug() << "Mimetype Icon Dirty: old=" << m_mimetype->icon(QString(),false) << " m_icon=" << m_icon << endl;
+ return true;
+ }
+
+ if (m_mimetype->patterns() != m_patterns)
+ {
+ kdDebug() << "Mimetype Patterns Dirty: old=" << m_mimetype->patterns().join(";")
+ << " m_patterns=" << m_patterns.join(";") << endl;
+ return true;
+ }
+
+ if ( readAutoEmbed( m_mimetype ) != (int)m_autoEmbed )
+ return true;
+ return false;
+}
+
+bool TypesListItem::isDirty() const
+{
+ if ( !m_bFullInit)
+ {
+ return false;
+ }
+
+ if ( m_bNewItem )
+ {
+ kdDebug() << "New item, need to save it" << endl;
+ return true;
+ }
+
+ if ( !isMeta() )
+ {
+ QStringList oldAppServices;
+ QStringList oldEmbedServices;
+ getServiceOffers( oldAppServices, oldEmbedServices );
+
+ if (oldAppServices != m_appServices)
+ {
+ kdDebug() << "App Services Dirty: old=" << oldAppServices.join(";")
+ << " m_appServices=" << m_appServices.join(";") << endl;
+ return true;
+ }
+ if (oldEmbedServices != m_embedServices)
+ {
+ kdDebug() << "Embed Services Dirty: old=" << oldEmbedServices.join(";")
+ << " m_embedServices=" << m_embedServices.join(";") << endl;
+ return true;
+ }
+ if (isMimeTypeDirty())
+ return true;
+ }
+ else
+ {
+ KSharedConfig::Ptr config = KSharedConfig::openConfig("konquerorrc", false, false);
+ config->setGroup("EmbedSettings");
+ bool defaultValue = defaultEmbeddingSetting(m_major);
+ unsigned int oldAutoEmbed = config->readBoolEntry( QString::fromLatin1("embed-")+m_major, defaultValue ) ? 0 : 1;
+ if ( m_autoEmbed != oldAutoEmbed )
+ return true;
+ }
+
+ if (m_askSave != 2)
+ return true;
+
+ // nothing seems to have changed, it's not dirty.
+ return false;
+}
+
+void TypesListItem::sync()
+{
+ Q_ASSERT(m_bFullInit);
+ if ( isMeta() )
+ {
+ KSharedConfig::Ptr config = KSharedConfig::openConfig("konquerorrc", false, false);
+ config->setGroup("EmbedSettings");
+ config->writeEntry( QString::fromLatin1("embed-")+m_major, m_autoEmbed == 0 );
+ return;
+ }
+
+ if (m_askSave != 2)
+ {
+ KSharedConfig::Ptr config = KSharedConfig::openConfig("konquerorrc", false, false);
+ config->setGroup("Notification Messages");
+ if (m_askSave == 0)
+ {
+ // Ask
+ config->deleteEntry("askSave"+name());
+ config->deleteEntry("askEmbedOrSave"+name());
+ }
+ else
+ {
+ // Do not ask, open
+ config->writeEntry("askSave"+name(), "no" );
+ config->writeEntry("askEmbedOrSave"+name(), "no" );
+ }
+ }
+
+ if (isMimeTypeDirty())
+ {
+ // We must use KConfig otherwise config.deleteEntry doesn't
+ // properly cancel out settings already present in system files.
+ KConfig config( m_mimetype->desktopEntryPath(), false, false, "mime" );
+ config.setDesktopGroup();
+
+ config.writeEntry("Type", "MimeType");
+ config.writeEntry("MimeType", name());
+ config.writeEntry("Icon", m_icon);
+ config.writeEntry("Patterns", m_patterns, ';');
+ config.writeEntry("Comment", m_comment);
+ config.writeEntry("Hidden", false);
+
+ if ( m_autoEmbed == 2 )
+ config.deleteEntry( QString::fromLatin1("X-KDE-AutoEmbed"), false );
+ else
+ config.writeEntry( QString::fromLatin1("X-KDE-AutoEmbed"), m_autoEmbed == 0 );
+
+ m_bNewItem = false;
+ }
+
+ KConfig profile("profilerc", false, false);
+
+ // Deleting current contents in profilerc relating to
+ // this service type
+ //
+ QStringList groups = profile.groupList();
+
+ for (QStringList::Iterator it = groups.begin();
+ it != groups.end(); it++ )
+ {
+ profile.setGroup(*it);
+
+ // Entries with Preference <= 0 or AllowAsDefault == false
+ // are not in m_services
+ if ( profile.readEntry( "ServiceType" ) == name()
+ && profile.readNumEntry( "Preference" ) > 0
+ && profile.readBoolEntry( "AllowAsDefault" ) )
+ {
+ profile.deleteGroup( *it );
+ }
+ }
+
+ // Save preferred services
+ //
+
+ groupCount = 1;
+
+ saveServices( profile, m_appServices, "Application" );
+ saveServices( profile, m_embedServices, "KParts/ReadOnlyPart" );
+
+ // Handle removed services
+
+ KServiceTypeProfile::setConfigurationMode();
+ KServiceTypeProfile::OfferList offerList =
+ KServiceTypeProfile::offers(m_mimetype->name(), "Application");
+ offerList += KServiceTypeProfile::offers(m_mimetype->name(), "KParts/ReadOnlyPart");
+ KServiceTypeProfile::unsetConfigurationMode();
+
+ QValueListIterator<KServiceOffer> it_srv(offerList.begin());
+
+ for (; it_srv != offerList.end(); ++it_srv) {
+
+
+ KService::Ptr pService = (*it_srv).service();
+
+ bool isApplication = pService->type() == "Application";
+ if (isApplication && !pService->allowAsDefault())
+ continue; // Only those which were added in init()
+
+ // Look in the correct list...
+ if ( (isApplication && ! m_appServices.contains( pService->desktopEntryPath() ))
+ || (!isApplication && !m_embedServices.contains( pService->desktopEntryPath() ))
+ ) {
+ // The service was in m_appServices but has been removed
+ // create a new .desktop file without this mimetype
+
+ if( s_changedServices == NULL )
+ deleter.setObject( s_changedServices, new QMap< QString, QStringList > );
+ QStringList mimeTypeList = s_changedServices->contains( pService->desktopEntryPath())
+ ? (*s_changedServices)[ pService->desktopEntryPath() ] : pService->serviceTypes();
+
+ if ( mimeTypeList.contains( name() ) ) {
+ // The mimetype is listed explicitly in the .desktop files, so
+ // just remove it and we're done
+ KConfig *desktop;
+ if ( !isApplication )
+ {
+ desktop = new KConfig(pService->desktopEntryPath(), false, false, "services");
+ }
+ else
+ {
+ QString path = pService->locateLocal();
+ KConfig orig(pService->desktopEntryPath(), true, false, "apps");
+ desktop = orig.copyTo(path);
+ }
+ desktop->setDesktopGroup();
+
+ mimeTypeList = s_changedServices->contains( pService->desktopEntryPath())
+ ? (*s_changedServices)[ pService->desktopEntryPath() ] : desktop->readListEntry("MimeType", ';');
+
+ // Remove entry and the number that might follow.
+ QStringList::Iterator it;
+ for(;(it = mimeTypeList.find(name())) != mimeTypeList.end();)
+ {
+ it = mimeTypeList.remove(it);
+ if (it != mimeTypeList.end())
+ {
+ // Check next item
+ bool numeric;
+ (*it).toInt(&numeric);
+ if (numeric)
+ mimeTypeList.remove(it);
+ }
+ }
+
+ desktop->writeEntry("MimeType", mimeTypeList, ';');
+
+ // if two or more types have been modified, and they use the same service,
+ // accumulate the changes
+ (*s_changedServices)[ pService->desktopEntryPath() ] = mimeTypeList;
+
+ desktop->sync();
+ delete desktop;
+ }
+ else {
+ // The mimetype is not listed explicitly so it can't
+ // be removed. Preference = 0 handles this.
+
+ // Find a group header. The headers are just dummy names as far as
+ // KUserProfile is concerned, but using the mimetype makes it a
+ // bit more structured for "manual" reading
+ while ( profile.hasGroup(
+ name() + " - " + QString::number(groupCount) ) )
+ groupCount++;
+
+ profile.setGroup( name() + " - " + QString::number(groupCount) );
+
+ profile.writeEntry("Application", pService->storageId());
+ profile.writeEntry("ServiceType", name());
+ profile.writeEntry("AllowAsDefault", true);
+ profile.writeEntry("Preference", 0);
+ }
+ }
+ }
+}
+
+static bool inheritsMimetype(KMimeType::Ptr m, const QStringList &mimeTypeList)
+{
+ for(QStringList::ConstIterator it = mimeTypeList.begin();
+ it != mimeTypeList.end(); ++it)
+ {
+ if (m->is(*it))
+ return true;
+ }
+
+ return false;
+}
+
+KMimeType::Ptr TypesListItem::findImplicitAssociation(const QString &desktop)
+{
+ KService::Ptr s = KService::serviceByDesktopPath(desktop);
+ if (!s) return 0; // Hey, where did that one go?
+
+ if( s_changedServices == NULL )
+ deleter.setObject( s_changedServices, new QMap< QString, QStringList > );
+ QStringList mimeTypeList = s_changedServices->contains( s->desktopEntryPath())
+ ? (*s_changedServices)[ s->desktopEntryPath() ] : s->serviceTypes();
+
+ for(QStringList::ConstIterator it = mimeTypeList.begin();
+ it != mimeTypeList.end(); ++it)
+ {
+ if ((m_mimetype->name() != *it) && m_mimetype->is(*it))
+ {
+ return KMimeType::mimeType(*it);
+ }
+ }
+ return 0;
+}
+
+void TypesListItem::saveServices( KConfig & profile, QStringList services, const QString & genericServiceType )
+{
+ QStringList::Iterator it(services.begin());
+ for (int i = services.count(); it != services.end(); ++it, i--) {
+
+ KService::Ptr pService = KService::serviceByDesktopPath(*it);
+ if (!pService) continue; // Where did that one go?
+
+ // Find a group header. The headers are just dummy names as far as
+ // KUserProfile is concerned, but using the mimetype makes it a
+ // bit more structured for "manual" reading
+ while ( profile.hasGroup( name() + " - " + QString::number(groupCount) ) )
+ groupCount++;
+
+ profile.setGroup( name() + " - " + QString::number(groupCount) );
+
+ profile.writeEntry("ServiceType", name());
+ profile.writeEntry("GenericServiceType", genericServiceType);
+ profile.writeEntry("Application", pService->storageId());
+ profile.writeEntry("AllowAsDefault", true);
+ profile.writeEntry("Preference", i);
+
+ // merge new mimetype
+ if( s_changedServices == NULL )
+ deleter.setObject( s_changedServices, new QMap< QString, QStringList > );
+ QStringList mimeTypeList = s_changedServices->contains( pService->desktopEntryPath())
+ ? (*s_changedServices)[ pService->desktopEntryPath() ] : pService->serviceTypes();
+
+ if (!mimeTypeList.contains(name()) && !inheritsMimetype(m_mimetype, mimeTypeList))
+ {
+ KConfig *desktop;
+ if ( pService->type() == QString("Service") )
+ {
+ desktop = new KConfig(pService->desktopEntryPath(), false, false, "services");
+ }
+ else
+ {
+ QString path = pService->locateLocal();
+ KConfig orig(pService->desktopEntryPath(), true, false, "apps");
+ desktop = orig.copyTo(path);
+ }
+
+ desktop->setDesktopGroup();
+ mimeTypeList = s_changedServices->contains( pService->desktopEntryPath())
+ ? (*s_changedServices)[ pService->desktopEntryPath() ] : desktop->readListEntry("MimeType", ';');
+ mimeTypeList.append(name());
+
+ desktop->writeEntry("MimeType", mimeTypeList, ';');
+ desktop->sync();
+ delete desktop;
+
+ // if two or more types have been modified, and they use the same service,
+ // accumulate the changes
+ (*s_changedServices)[ pService->desktopEntryPath() ] = mimeTypeList;
+ }
+ }
+}
+
+void TypesListItem::setIcon( const QString& icon )
+{
+ m_icon = icon;
+ setPixmap( 0, SmallIcon( icon ) );
+}
+
+bool TypesListItem::isEssential() const
+{
+ QString n = name();
+ if ( n == "application/octet-stream" )
+ return true;
+ if ( n == "inode/directory" )
+ return true;
+ if ( n == "inode/directory-locked" )
+ return true;
+ if ( n == "inode/blockdevice" )
+ return true;
+ if ( n == "inode/chardevice" )
+ return true;
+ if ( n == "inode/socket" )
+ return true;
+ if ( n == "inode/fifo" )
+ return true;
+ if ( n == "application/x-shellscript" )
+ return true;
+ if ( n == "application/x-executable" )
+ return true;
+ if ( n == "application/x-desktop" )
+ return true;
+ return false;
+}
+
+void TypesListItem::refresh()
+{
+ kdDebug() << "TypesListItem refresh " << name() << endl;
+ m_mimetype = KMimeType::mimeType( name() );
+}
+
+void TypesListItem::reset()
+{
+ if( s_changedServices )
+ s_changedServices->clear();
+}
+
+void TypesListItem::getAskSave(bool &_askSave)
+{
+ if (m_askSave == 0)
+ _askSave = true;
+ if (m_askSave == 1)
+ _askSave = false;
+}
+
+void TypesListItem::setAskSave(bool _askSave)
+{
+ if (_askSave)
+ m_askSave = 0;
+ else
+ m_askSave = 1;
+}
+
+bool TypesListItem::canUseGroupSetting() const
+{
+ // "Use group settings" isn't available for zip, tar etc.; those have a builtin default...
+ bool hasLocalProtocolRedirect = !m_mimetype->property( "X-KDE-LocalProtocol" ).toString().isEmpty();
+ return !hasLocalProtocolRedirect;
+}
+