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.
592 lines
18 KiB
592 lines
18 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>
|
|
|
|
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 <tdeconfig.h>
|
|
#include <kdebug.h>
|
|
#include <kiconloader.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kdesktopfile.h>
|
|
#include <kstaticdeleter.h>
|
|
|
|
#include "typeslistitem.h"
|
|
|
|
TQMap< TQString, TQStringList >* TypesListItem::s_changedServices;
|
|
static KStaticDeleter< TQMap< TQString, TQStringList > > deleter;
|
|
|
|
TypesListItem::TypesListItem(TQListView *parent, const TQString & major)
|
|
: TQListViewItem(parent), metaType(true), m_bNewItem(false), m_askSave(2)
|
|
{
|
|
initMeta(major);
|
|
setText(0, majorType());
|
|
}
|
|
|
|
TypesListItem::TypesListItem(TypesListItem *parent, KMimeType::Ptr mimetype, bool newItem)
|
|
: TQListViewItem(parent), metaType(false), m_bNewItem(newItem), m_askSave(2)
|
|
{
|
|
init(mimetype);
|
|
setText(0, minorType());
|
|
}
|
|
|
|
TypesListItem::TypesListItem(TQListView *parent, KMimeType::Ptr mimetype)
|
|
: TQListViewItem(parent), metaType(false), m_bNewItem(false), m_askSave(2)
|
|
{
|
|
init(mimetype);
|
|
setText(0, majorType());
|
|
}
|
|
|
|
TypesListItem::TypesListItem(TQListView *parent, KMimeType::Ptr mimetype, bool newItem)
|
|
: TQListViewItem(parent), metaType(false), m_bNewItem(newItem), m_askSave(2)
|
|
{
|
|
init(mimetype);
|
|
setText(0, majorType());
|
|
}
|
|
|
|
TypesListItem::~TypesListItem()
|
|
{
|
|
}
|
|
|
|
void TypesListItem::initMeta( const TQString & major )
|
|
{
|
|
m_bFullInit = true;
|
|
m_mimetype = 0L;
|
|
m_major = major;
|
|
TDESharedConfig::Ptr config = TDESharedConfig::openConfig("konquerorrc", false, false);
|
|
config->setGroup("EmbedSettings");
|
|
bool defaultValue = defaultEmbeddingSetting( major );
|
|
m_autoEmbed = config->readBoolEntry( TQString::fromLatin1("embed-")+m_major, defaultValue ) ? 0 : 1;
|
|
}
|
|
|
|
bool TypesListItem::defaultEmbeddingSetting( const TQString& major )
|
|
{
|
|
// embedding is false by default except for image/*
|
|
return ( major=="image" );
|
|
}
|
|
|
|
void TypesListItem::setup()
|
|
{
|
|
if (m_mimetype)
|
|
{
|
|
setPixmap(0, m_mimetype->pixmap(TDEIcon::Small, IconSize(TDEIcon::Small)));
|
|
}
|
|
TQListViewItem::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(TQString(), false);
|
|
m_icon = mimetype->icon(TQString(), false);
|
|
m_patterns = mimetype->patterns();
|
|
m_autoEmbed = readAutoEmbed( mimetype );
|
|
}
|
|
|
|
int TypesListItem::readAutoEmbed( KMimeType::Ptr mimetype )
|
|
{
|
|
TQVariant v = mimetype->property( "X-TDE-AutoEmbed" );
|
|
if ( v.isValid() )
|
|
return (v.toBool() ? 0 : 1);
|
|
else if ( !mimetype->property( "X-TDE-LocalProtocol" ).toString().isEmpty() )
|
|
return 0; // embed by default for zip, tar etc.
|
|
else
|
|
return 2;
|
|
}
|
|
|
|
TQStringList 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;
|
|
}
|
|
|
|
TQStringList 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( TQStringList & appServices, TQStringList & embedServices ) const
|
|
{
|
|
KServiceTypeProfile::setConfigurationMode();
|
|
|
|
KServiceTypeProfile::OfferList offerList =
|
|
KServiceTypeProfile::offers(m_mimetype->name(), "Application");
|
|
TQValueListIterator<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(TQString(), false) != m_comment)
|
|
{
|
|
kdDebug() << "Mimetype Comment Dirty: old=" << m_mimetype->comment(TQString(),false) << " m_comment=" << m_comment << endl;
|
|
return true;
|
|
}
|
|
if (m_mimetype->icon(TQString(), false) != m_icon)
|
|
{
|
|
kdDebug() << "Mimetype Icon Dirty: old=" << m_mimetype->icon(TQString(),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() )
|
|
{
|
|
TQStringList oldAppServices;
|
|
TQStringList 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
|
|
{
|
|
TDESharedConfig::Ptr config = TDESharedConfig::openConfig("konquerorrc", false, false);
|
|
config->setGroup("EmbedSettings");
|
|
bool defaultValue = defaultEmbeddingSetting(m_major);
|
|
unsigned int oldAutoEmbed = config->readBoolEntry( TQString::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() )
|
|
{
|
|
TDESharedConfig::Ptr config = TDESharedConfig::openConfig("konquerorrc", false, false);
|
|
config->setGroup("EmbedSettings");
|
|
config->writeEntry( TQString::fromLatin1("embed-")+m_major, m_autoEmbed == 0 );
|
|
return;
|
|
}
|
|
|
|
if (m_askSave != 2)
|
|
{
|
|
TDESharedConfig::Ptr config = TDESharedConfig::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 TDEConfig otherwise config.deleteEntry doesn't
|
|
// properly cancel out settings already present in system files.
|
|
TDEConfig 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( TQString::fromLatin1("X-TDE-AutoEmbed"), false );
|
|
else
|
|
config.writeEntry( TQString::fromLatin1("X-TDE-AutoEmbed"), m_autoEmbed == 0 );
|
|
|
|
m_bNewItem = false;
|
|
}
|
|
|
|
TDEConfig profile("profilerc", false, false);
|
|
|
|
// Deleting current contents in profilerc relating to
|
|
// this service type
|
|
//
|
|
TQStringList groups = profile.groupList();
|
|
|
|
for (TQStringList::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();
|
|
|
|
TQValueListIterator<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 TQMap< TQString, TQStringList > );
|
|
TQStringList 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
|
|
TDEConfig *desktop;
|
|
if ( !isApplication )
|
|
{
|
|
desktop = new TDEConfig(pService->desktopEntryPath(), false, false, "services");
|
|
}
|
|
else
|
|
{
|
|
TQString path = pService->locateLocal();
|
|
TDEConfig 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.
|
|
TQStringList::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() + " - " + TQString::number(groupCount) ) )
|
|
groupCount++;
|
|
|
|
profile.setGroup( name() + " - " + TQString::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 TQStringList &mimeTypeList)
|
|
{
|
|
for(TQStringList::ConstIterator it = mimeTypeList.begin();
|
|
it != mimeTypeList.end(); ++it)
|
|
{
|
|
if (m->is(*it))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
KMimeType::Ptr TypesListItem::findImplicitAssociation(const TQString &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 TQMap< TQString, TQStringList > );
|
|
TQStringList mimeTypeList = s_changedServices->contains( s->desktopEntryPath())
|
|
? (*s_changedServices)[ s->desktopEntryPath() ] : s->serviceTypes();
|
|
|
|
for(TQStringList::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( TDEConfig & profile, TQStringList services, const TQString & genericServiceType )
|
|
{
|
|
TQStringList::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() + " - " + TQString::number(groupCount) ) )
|
|
groupCount++;
|
|
|
|
profile.setGroup( name() + " - " + TQString::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 TQMap< TQString, TQStringList > );
|
|
TQStringList mimeTypeList = s_changedServices->contains( pService->desktopEntryPath())
|
|
? (*s_changedServices)[ pService->desktopEntryPath() ] : pService->serviceTypes();
|
|
|
|
if (!mimeTypeList.contains(name()) && !inheritsMimetype(m_mimetype, mimeTypeList))
|
|
{
|
|
TDEConfig *desktop;
|
|
if ( pService->type() == TQString("Service") )
|
|
{
|
|
desktop = new TDEConfig(pService->desktopEntryPath(), false, false, "services");
|
|
}
|
|
else
|
|
{
|
|
TQString path = pService->locateLocal();
|
|
TDEConfig 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 TQString& icon )
|
|
{
|
|
m_icon = icon;
|
|
setPixmap( 0, SmallIcon( icon ) );
|
|
}
|
|
|
|
bool TypesListItem::isEssential() const
|
|
{
|
|
TQString 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;
|
|
if ( n == "media/builtin-mydocuments" )
|
|
return true;
|
|
if ( n == "media/builtin-mycomputer" )
|
|
return true;
|
|
if ( n == "media/builtin-mynetworkplaces" )
|
|
return true;
|
|
if ( n == "media/builtin-printers" )
|
|
return true;
|
|
if ( n == "media/builtin-trash" )
|
|
return true;
|
|
if ( n == "media/builtin-webbrowser" )
|
|
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-TDE-LocalProtocol" ).toString().isEmpty();
|
|
return !hasLocalProtocolRedirect;
|
|
}
|
|
|