summaryrefslogtreecommitdiffstats
path: root/kcontrol/filetypes
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
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')
-rw-r--r--kcontrol/filetypes/Makefile.am29
-rw-r--r--kcontrol/filetypes/control.cpp11
-rw-r--r--kcontrol/filetypes/filegroupdetails.cpp65
-rw-r--r--kcontrol/filetypes/filegroupdetails.h50
-rw-r--r--kcontrol/filetypes/filetypedetails.cpp299
-rw-r--r--kcontrol/filetypes/filetypedetails.h64
-rw-r--r--kcontrol/filetypes/filetypes.desktop235
-rw-r--r--kcontrol/filetypes/filetypesview.cpp440
-rw-r--r--kcontrol/filetypes/filetypesview.h73
-rw-r--r--kcontrol/filetypes/keditfiletype.cpp182
-rw-r--r--kcontrol/filetypes/keditfiletype.h54
-rw-r--r--kcontrol/filetypes/kservicelistwidget.cpp444
-rw-r--r--kcontrol/filetypes/kservicelistwidget.h77
-rw-r--r--kcontrol/filetypes/kserviceselectdlg.cpp66
-rw-r--r--kcontrol/filetypes/kserviceselectdlg.h47
-rw-r--r--kcontrol/filetypes/newtypedlg.cpp57
-rw-r--r--kcontrol/filetypes/newtypedlg.h28
-rw-r--r--kcontrol/filetypes/typeslistitem.cpp579
-rw-r--r--kcontrol/filetypes/typeslistitem.h118
19 files changed, 2918 insertions, 0 deletions
diff --git a/kcontrol/filetypes/Makefile.am b/kcontrol/filetypes/Makefile.am
new file mode 100644
index 000000000..b47763254
--- /dev/null
+++ b/kcontrol/filetypes/Makefile.am
@@ -0,0 +1,29 @@
+AM_CPPFLAGS = $(all_includes)
+
+kcm_filetypes_la_LIBADD = libfiletypes.la $(LIB_KIO)
+kcm_filetypes_la_LDFLAGS = -module -avoid-version -no-undefined $(all_libraries)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kcm_filetypes.la
+
+kcm_filetypes_la_SOURCES = control.cpp
+
+noinst_HEADERS = filetypesview.h filetypedetails.h filegroupdetails.h \
+ kservicelistwidget.h typeslistitem.h newtypedlg.h \
+ kserviceselectdlg.h
+
+bin_PROGRAMS = keditfiletype
+
+noinst_LTLIBRARIES = libfiletypes.la
+libfiletypes_la_SOURCES = filetypesview.cpp filetypedetails.cpp filegroupdetails.cpp \
+ kservicelistwidget.cpp typeslistitem.cpp newtypedlg.cpp \
+ kserviceselectdlg.cpp
+
+keditfiletype_SOURCES = keditfiletype.cpp
+keditfiletype_LDADD = libfiletypes.la $(LIB_KIO)
+keditfiletype_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+
+messages:
+ $(XGETTEXT) *.cpp -o $(podir)/filetypes.pot
+
+xdg_apps_DATA = filetypes.desktop
diff --git a/kcontrol/filetypes/control.cpp b/kcontrol/filetypes/control.cpp
new file mode 100644
index 000000000..55e98d95e
--- /dev/null
+++ b/kcontrol/filetypes/control.cpp
@@ -0,0 +1,11 @@
+#include "filetypesview.h"
+
+extern "C"
+{
+ KDE_EXPORT KCModule *create_filetypes(QWidget *parent, const char *)
+ {
+ return new FileTypesView(parent, "filetypes");
+ }
+
+}
+
diff --git a/kcontrol/filetypes/filegroupdetails.cpp b/kcontrol/filetypes/filegroupdetails.cpp
new file mode 100644
index 000000000..a8895965a
--- /dev/null
+++ b/kcontrol/filetypes/filegroupdetails.cpp
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 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 "filegroupdetails.h"
+#include "typeslistitem.h"
+#include <qlayout.h>
+#include <qvbuttongroup.h>
+#include <qradiobutton.h>
+#include <qwhatsthis.h>
+#include <kdialog.h>
+#include <klocale.h>
+
+FileGroupDetails::FileGroupDetails(QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ QWidget * parentWidget = this;
+ QVBoxLayout *secondLayout = new QVBoxLayout(parentWidget,
+ 0, KDialog::spacingHint());
+
+ m_autoEmbed = new QVButtonGroup( i18n("Left Click Action"), parentWidget );
+ m_autoEmbed->layout()->setSpacing( KDialog::spacingHint() );
+ secondLayout->addWidget( m_autoEmbed );
+ // The order of those two items is very important. If you change it, fix typeslistitem.cpp !
+ new QRadioButton( i18n("Show file in embedded viewer"), m_autoEmbed );
+ new QRadioButton( i18n("Show file in separate viewer"), m_autoEmbed );
+ connect(m_autoEmbed, SIGNAL( clicked( int ) ), SLOT( slotAutoEmbedClicked( int ) ));
+
+ QWhatsThis::add( m_autoEmbed, i18n("Here you can configure what the Konqueror file manager"
+ " will do when you click on a file belonging to this group. Konqueror can display the file in"
+ " an embedded viewer or start up a separate application. You can change this setting for a"
+ " specific file type in the 'Embedding' tab of the file type configuration.") );
+
+ secondLayout->addStretch();
+}
+
+void FileGroupDetails::setTypeItem( TypesListItem * item )
+{
+ Q_ASSERT( item->isMeta() );
+ m_item = item;
+ m_autoEmbed->setButton( item ? item->autoEmbed() : -1 );
+}
+
+void FileGroupDetails::slotAutoEmbedClicked(int button)
+{
+ if ( !m_item )
+ return;
+ m_item->setAutoEmbed( button );
+ emit changed(true);
+}
+
+#include "filegroupdetails.moc"
diff --git a/kcontrol/filetypes/filegroupdetails.h b/kcontrol/filetypes/filegroupdetails.h
new file mode 100644
index 000000000..1716954f3
--- /dev/null
+++ b/kcontrol/filetypes/filegroupdetails.h
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 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.
+*/
+#ifndef _FILEGROUPDETAILS_H
+#define _FILEGROUPDETAILS_H
+
+#include <qwidget.h>
+class TypesListItem;
+class QButtonGroup;
+
+/**
+ * This widget contains the details for a filetype group.
+ * Currently this only involves the embedding configuration.
+ */
+class FileGroupDetails : public QWidget
+{
+ Q_OBJECT
+public:
+ FileGroupDetails(QWidget *parent = 0, const char *name = 0);
+
+ void setTypeItem( TypesListItem * item );
+
+signals:
+ void changed(bool);
+
+protected slots:
+ void slotAutoEmbedClicked(int button);
+
+private:
+ TypesListItem * m_item;
+
+ // Embedding config
+ QButtonGroup *m_autoEmbed;
+};
+
+#endif
diff --git a/kcontrol/filetypes/filetypedetails.cpp b/kcontrol/filetypes/filetypedetails.cpp
new file mode 100644
index 000000000..436fd138d
--- /dev/null
+++ b/kcontrol/filetypes/filetypedetails.cpp
@@ -0,0 +1,299 @@
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qvbuttongroup.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kicondialog.h>
+#include <klineedit.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+
+#include "kservicelistwidget.h"
+#include "filetypedetails.h"
+#include "typeslistitem.h"
+
+FileTypeDetails::FileTypeDetails( QWidget * parent, const char * name )
+ : QTabWidget( parent, name ), m_item( 0L )
+{
+ QString wtstr;
+ // First tab - General
+ QWidget * firstWidget = new QWidget(this);
+ QVBoxLayout *firstLayout = new QVBoxLayout(firstWidget,KDialog::marginHint(),
+ KDialog::spacingHint());
+
+ QHBoxLayout *hBox = new QHBoxLayout(0L, 0, KDialog::spacingHint());
+ firstLayout->addLayout(hBox, 1);
+
+ iconButton = new KIconButton(firstWidget);
+ iconButton->setIconType(KIcon::Desktop, KIcon::MimeType);
+ connect(iconButton, SIGNAL(iconChanged(QString)), SLOT(updateIcon(QString)));
+
+ iconButton->setFixedSize(70, 70);
+ hBox->addWidget(iconButton);
+
+ QWhatsThis::add( iconButton, i18n("This button displays the icon associated"
+ " with the selected file type. Click on it to choose a different icon.") );
+
+ QGroupBox *gb = new QGroupBox(i18n("Filename Patterns"), firstWidget);
+ hBox->addWidget(gb);
+
+ QGridLayout *grid = new QGridLayout(gb, 3, 2, KDialog::marginHint(),
+ KDialog::spacingHint());
+ grid->addRowSpacing(0, fontMetrics().lineSpacing());
+
+ extensionLB = new QListBox(gb);
+ connect(extensionLB, SIGNAL(highlighted(int)), SLOT(enableExtButtons(int)));
+ grid->addMultiCellWidget(extensionLB, 1, 2, 0, 0);
+ grid->setRowStretch(0, 0);
+ grid->setRowStretch(1, 1);
+ grid->setRowStretch(2, 0);
+
+ QWhatsThis::add( extensionLB, i18n("This box contains a list of patterns that can be"
+ " used to identify files of the selected type. For example, the pattern *.txt is"
+ " associated with the file type 'text/plain'; all files ending in '.txt' are recognized"
+ " as plain text files.") );
+
+ addExtButton = new QPushButton(i18n("Add..."), gb);
+ addExtButton->setEnabled(false);
+ connect(addExtButton, SIGNAL(clicked()),
+ this, SLOT(addExtension()));
+ grid->addWidget(addExtButton, 1, 1);
+
+ QWhatsThis::add( addExtButton, i18n("Add a new pattern for the selected file type.") );
+
+ removeExtButton = new QPushButton(i18n("Remove"), gb);
+ removeExtButton->setEnabled(false);
+ connect(removeExtButton, SIGNAL(clicked()),
+ this, SLOT(removeExtension()));
+ grid->addWidget(removeExtButton, 2, 1);
+
+ QWhatsThis::add( removeExtButton, i18n("Remove the selected filename pattern.") );
+
+ gb = new QGroupBox(i18n("Description"), firstWidget);
+ firstLayout->addWidget(gb);
+
+ gb->setColumnLayout(1, Qt::Horizontal);
+ description = new KLineEdit(gb);
+ connect(description, SIGNAL(textChanged(const QString &)),
+ SLOT(updateDescription(const QString &)));
+
+ wtstr = i18n("You can enter a short description for files of the selected"
+ " file type (e.g. 'HTML Page'). This description will be used by applications"
+ " like Konqueror to display directory content.");
+ QWhatsThis::add( gb, wtstr );
+ QWhatsThis::add( description, wtstr );
+
+ serviceListWidget = new KServiceListWidget( KServiceListWidget::SERVICELIST_APPLICATIONS, firstWidget );
+ connect( serviceListWidget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool)));
+ firstLayout->addWidget(serviceListWidget, 5);
+
+ // Second tab - Embedding
+ QWidget * secondWidget = new QWidget(this);
+ QVBoxLayout *secondLayout = new QVBoxLayout(secondWidget, KDialog::marginHint(),
+ KDialog::spacingHint());
+
+ m_autoEmbed = new QVButtonGroup( i18n("Left Click Action"), secondWidget );
+ m_autoEmbed->layout()->setSpacing( KDialog::spacingHint() );
+ secondLayout->addWidget( m_autoEmbed, 1 );
+
+ m_autoEmbed->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)3, (QSizePolicy::SizeType)0, m_autoEmbed->sizePolicy().hasHeightForWidth() ) );
+
+ // The order of those three items is very important. If you change it, fix typeslistitem.cpp !
+ new QRadioButton( i18n("Show file in embedded viewer"), m_autoEmbed );
+ new QRadioButton( i18n("Show file in separate viewer"), m_autoEmbed );
+ m_rbGroupSettings = new QRadioButton( i18n("Use settings for '%1' group"), m_autoEmbed );
+ connect(m_autoEmbed, SIGNAL( clicked( int ) ), SLOT( slotAutoEmbedClicked( int ) ));
+
+ m_chkAskSave = new QCheckBox( i18n("Ask whether to save to disk instead"), m_autoEmbed);
+ connect(m_chkAskSave, SIGNAL( toggled(bool) ), SLOT( slotAskSaveToggled(bool) ));
+
+ QWhatsThis::add( m_autoEmbed, i18n("Here you can configure what the Konqueror file manager"
+ " will do when you click on a file of this type. Konqueror can display the file in"
+ " an embedded viewer or start up a separate application. If set to 'Use settings for G group',"
+ " Konqueror will behave according to the settings of the group G this type belongs to,"
+ " for instance 'image' if the current file type is image/png.") );
+
+ secondLayout->addSpacing(10);
+
+ embedServiceListWidget = new KServiceListWidget( KServiceListWidget::SERVICELIST_SERVICES, secondWidget );
+ embedServiceListWidget->setMinimumHeight( serviceListWidget->sizeHint().height() );
+ connect( embedServiceListWidget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool)));
+ secondLayout->addWidget(embedServiceListWidget, 3);
+
+ addTab( firstWidget, i18n("&General") );
+ addTab( secondWidget, i18n("&Embedding") );
+}
+
+void FileTypeDetails::updateRemoveButton()
+{
+ removeExtButton->setEnabled(extensionLB->count()>0);
+}
+
+void FileTypeDetails::updateIcon(QString icon)
+{
+ if (!m_item)
+ return;
+
+ m_item->setIcon(icon);
+
+ emit changed(true);
+}
+
+void FileTypeDetails::updateDescription(const QString &desc)
+{
+ if (!m_item)
+ return;
+
+ m_item->setComment(desc);
+
+ emit changed(true);
+}
+
+void FileTypeDetails::addExtension()
+{
+ if ( !m_item )
+ return;
+
+ bool ok;
+ QString ext = KInputDialog::getText( i18n( "Add New Extension" ),
+ i18n( "Extension:" ), "*.", &ok, this );
+ if (ok) {
+ extensionLB->insertItem(ext);
+ QStringList patt = m_item->patterns();
+ patt += ext;
+ m_item->setPatterns(patt);
+ updateRemoveButton();
+ emit changed(true);
+ }
+}
+
+void FileTypeDetails::removeExtension()
+{
+ if (extensionLB->currentItem() == -1)
+ return;
+ if ( !m_item )
+ return;
+ QStringList patt = m_item->patterns();
+ patt.remove(extensionLB->text(extensionLB->currentItem()));
+ m_item->setPatterns(patt);
+ extensionLB->removeItem(extensionLB->currentItem());
+ updateRemoveButton();
+ emit changed(true);
+}
+
+void FileTypeDetails::slotAutoEmbedClicked( int button )
+{
+ if ( !m_item || (button > 2))
+ return;
+
+ m_item->setAutoEmbed( button );
+
+ updateAskSave();
+
+ emit changed(true);
+}
+
+void FileTypeDetails::updateAskSave()
+{
+ if ( !m_item )
+ return;
+
+ int button = m_item->autoEmbed();
+ if (button == 2)
+ {
+ bool embedParent = TypesListItem::defaultEmbeddingSetting(m_item->majorType());
+ emit embedMajor(m_item->majorType(), embedParent);
+ button = embedParent ? 0 : 1;
+ }
+
+ QString mimeType = m_item->name();
+
+ QString dontAskAgainName;
+
+ if (button == 0) // Embedded
+ dontAskAgainName = "askEmbedOrSave"+mimeType;
+ else
+ dontAskAgainName = "askSave"+mimeType;
+
+ KSharedConfig::Ptr config = KSharedConfig::openConfig("konquerorrc", false, false);
+ config->setGroup("Notification Messages");
+ bool ask = config->readEntry(dontAskAgainName).isEmpty();
+ m_item->getAskSave(ask);
+
+ bool neverAsk = false;
+
+ if (button == 0)
+ {
+ KMimeType::Ptr mime = KMimeType::mimeType( mimeType );
+ // Don't ask for:
+ // - html (even new tabs would ask, due to about:blank!)
+ // - dirs obviously (though not common over HTTP :),
+ // - images (reasoning: no need to save, most of the time, because fast to see)
+ // e.g. postscript is different, because takes longer to read, so
+ // it's more likely that the user might want to save it.
+ // - multipart/* ("server push", see kmultipart)
+ // - other strange 'internal' mimetypes like print/manager...
+ if ( mime->is( "text/html" ) ||
+ mime->is( "text/xml" ) ||
+ mime->is( "inode/directory" ) ||
+ mimeType.startsWith( "image" ) ||
+ mime->is( "multipart/x-mixed-replace" ) ||
+ mime->is( "multipart/replace" ) ||
+ mimeType.startsWith( "print" ) )
+ {
+ neverAsk = true;
+ }
+ }
+
+ m_chkAskSave->blockSignals(true);
+ m_chkAskSave->setChecked(ask && !neverAsk);
+ m_chkAskSave->setEnabled(!neverAsk);
+ m_chkAskSave->blockSignals(false);
+}
+
+void FileTypeDetails::slotAskSaveToggled(bool askSave)
+{
+ if (!m_item)
+ return;
+
+ m_item->setAskSave(askSave);
+ emit changed(true);
+}
+
+void FileTypeDetails::setTypeItem( TypesListItem * tlitem )
+{
+ m_item = tlitem;
+ if ( tlitem )
+ iconButton->setIcon(tlitem->icon());
+ else
+ iconButton->resetIcon();
+ description->setText(tlitem ? tlitem->comment() : QString::null);
+ if ( tlitem )
+ m_rbGroupSettings->setText( i18n("Use settings for '%1' group").arg( tlitem->majorType() ) );
+ extensionLB->clear();
+ addExtButton->setEnabled(true);
+ removeExtButton->setEnabled(false);
+
+ serviceListWidget->setTypeItem( tlitem );
+ embedServiceListWidget->setTypeItem( tlitem );
+ m_autoEmbed->setButton( tlitem ? tlitem->autoEmbed() : -1 );
+ m_rbGroupSettings->setEnabled( tlitem->canUseGroupSetting() );
+
+ if ( tlitem )
+ extensionLB->insertStringList(tlitem->patterns());
+ else
+ extensionLB->clear();
+
+ updateAskSave();
+}
+
+void FileTypeDetails::enableExtButtons(int /*index*/)
+{
+ removeExtButton->setEnabled(true);
+}
+
+#include "filetypedetails.moc"
diff --git a/kcontrol/filetypes/filetypedetails.h b/kcontrol/filetypes/filetypedetails.h
new file mode 100644
index 000000000..6f9a0a548
--- /dev/null
+++ b/kcontrol/filetypes/filetypedetails.h
@@ -0,0 +1,64 @@
+#ifndef _FILETYPEDETAILS_H
+#define _FILETYPEDETAILS_H
+
+#include <qtabwidget.h>
+class TypesListItem;
+class KIconButton;
+class QLineEdit;
+class QListBox;
+class QButtonGroup;
+class QCheckBox;
+class QRadioButton;
+class QPushButton;
+class KServiceListWidget;
+
+/**
+ * This widget contains the right part of the file type configuration
+ * dialog, that shows the details for a file type.
+ * It is implemented as a separate class so that it can be used by
+ * the keditfiletype program to show the details of a single mimetype.
+ */
+class FileTypeDetails : public QTabWidget
+{
+ Q_OBJECT
+public:
+ FileTypeDetails(QWidget *parent = 0, const char *name = 0);
+
+ void setTypeItem( TypesListItem * item );
+
+protected:
+ void updateRemoveButton();
+ void updateAskSave();
+
+signals:
+ void embedMajor(const QString &major, bool &embed); // To adjust whether major type is being embedded
+ void changed(bool);
+
+protected slots:
+ void updateIcon(QString icon);
+ void updateDescription(const QString &desc);
+ void addExtension();
+ void removeExtension();
+ void enableExtButtons(int index);
+ void slotAutoEmbedClicked(int button);
+ void slotAskSaveToggled(bool);
+
+private:
+ TypesListItem * m_item;
+
+ // First tab - General
+ KIconButton *iconButton;
+ QListBox *extensionLB;
+ QPushButton *addExtButton, *removeExtButton;
+ QLineEdit *description;
+ KServiceListWidget *serviceListWidget;
+
+ // Second tab - Embedding
+ QButtonGroup *m_autoEmbed;
+ KServiceListWidget *embedServiceListWidget;
+ QRadioButton *m_rbOpenSeparate;
+ QCheckBox *m_chkAskSave;
+ QRadioButton *m_rbGroupSettings;
+};
+
+#endif
diff --git a/kcontrol/filetypes/filetypes.desktop b/kcontrol/filetypes/filetypes.desktop
new file mode 100644
index 000000000..372af2213
--- /dev/null
+++ b/kcontrol/filetypes/filetypes.desktop
@@ -0,0 +1,235 @@
+[Desktop Entry]
+Icon=filetypes
+Type=Application
+Exec=kcmshell filetypes
+DocPath=kcontrol/filetypes/index.html
+Categories=Qt;KDE;X-KDE-settings-components;
+
+
+X-KDE-Library=filetypes
+X-KDE-ParentApp=kcontrol
+
+Name=File Associations
+Name[af]=Lêer Assosiasies
+Name[ar]=ارتباطات الملفات
+Name[az]=Fayl Əlaqələri
+Name[be]=Асацыяцыі файлаў
+Name[bg]=Файлови асоциации
+Name[bn]=ফাইল অ্যাসোসিয়েশন
+Name[br]=Kevreañ restroù
+Name[bs]=Asociranje datoteka
+Name[ca]=Associacions de fitxers
+Name[cs]=Asociace souborů
+Name[csb]=Pòwiązania lopków
+Name[cy]=Cysylltiadau Ffeiliau
+Name[da]=Filassociationer
+Name[de]=Dateizuordnungen
+Name[el]=Συσχετίσεις αρχείων
+Name[eo]=Dosiertipoj
+Name[es]=Asociaciones de archivo
+Name[et]=Failide seosed
+Name[eu]=Fitxategi elkarketak
+Name[fa]=انجمنهای پرونده
+Name[fi]=Tiedostosidokset
+Name[fr]=Associations de fichiers
+Name[fy]=Triemassosjaasjes
+Name[gl]=Asociacións de Ficheiros
+Name[he]=שיוכי קבצים
+Name[hi]=फ़ाइल असोसिएशन
+Name[hr]=Pridruživanja datoteka
+Name[hu]=Fájltársítások
+Name[id]=Asosiasi File
+Name[is]=Skráavensl
+Name[it]=Associazioni file
+Name[ja]=ファイルの関連付け
+Name[ka]=ფაილთა მიბმა
+Name[kk]=Файл сәйкестіктері
+Name[km]=ទំនាក់​ទំនង​ឯកសារ
+Name[ko]=파일 연결
+Name[lo]=ການກຳນົດໃຊ້ແຟ້ມ
+Name[lt]=Bylų asociacijos
+Name[lv]=Failu Asociācijas
+Name[mk]=Асоцијации на датотеки
+Name[mn]=Файл холбоосууд
+Name[mt]=Assoċjazzjonijiet tal-Fajls
+Name[nb]=Filtilknytninger
+Name[nds]=Datei-Toornen
+Name[ne]=फाइल संयोजन
+Name[nl]=Bestandsassociaties
+Name[nn]=Filtilknytingar
+Name[nso]=Dikopantsho tsa Difaele
+Name[oc]=Associacions de fiquièrs
+Name[pa]=ਫਾਇਲ ਸਬੰਧ
+Name[pl]=Skojarzenia plików
+Name[pt]=Associação de Ficheiros
+Name[pt_BR]=Associações de arquivos
+Name[ro]=Asociere fișiere
+Name[ru]=Привязки файлов
+Name[rw]=Ishyirahamwe ry'Idosiye
+Name[se]=Fiilačatnagasat
+Name[sk]=Asociácie súborov
+Name[sl]=Datotečne povezave
+Name[sr]=Придружења фајловима
+Name[sr@Latn]=Pridruženja fajlovima
+Name[sv]=Filbindningar
+Name[ta]=கோப்பு ஒருங்கமைப்புகள்
+Name[tg]=Вобастагонии Файл
+Name[th]=กำหนดการใช้แฟ้ม
+Name[tr]=Dosya İlişkileri
+Name[tt]=Kiremnär Kileşterü
+Name[uk]=Асоціації файлів
+Name[uz]=Fayl turi bilan\nbogʻliqlar
+Name[uz@cyrillic]=Файл тури билан\nбоғлиқлар
+Name[ven]=U fanyisa faela
+Name[vi]=Kiểu tập tin
+Name[wa]=Elaxhaedjes di fitchîs
+Name[xh]=Uyelemaniso Lwefayile
+Name[zh_CN]=文件关联
+Name[zh_TW]=檔案關聯
+Name[zu]=Ubudlelwano befayela
+
+Comment=Configure file associations
+Comment[af]=Konfigureer lêer assosiasies
+Comment[ar]=إعداد إرتباطات الملفات
+Comment[az]=Fayl əlaqələrini quraşdır
+Comment[be]=Настаўленні асацыяцыяў файлаў
+Comment[bg]=Настройване и асоцииране на файлови типове с програми
+Comment[bn]=ফাইল অ্যাসোসিয়েশন কনফিগার করুন
+Comment[br]=Kefluniañ kevreañ restroù
+Comment[bs]=Podesite asocijacije datoteka
+Comment[ca]=Configura les associacions de fitxers
+Comment[cs]=Nastavení asociací souborů
+Comment[csb]=Konfigùracëjô pòwiązaniów lopków
+Comment[cy]=Ffurfweddu cysylltiadau ffeiliau
+Comment[da]=Indstil filassociationer
+Comment[de]=Dateizuordnungen vornehmen
+Comment[el]=Ρύθμιση των συσχετίσεων αρχείων
+Comment[eo]=Agordu de ligo de programoj al dosiertipoj
+Comment[es]=Configuración de asociaciones de archivos
+Comment[et]=Failide seoste seadistamine
+Comment[eu]=Fitxategi elkarketak konfiguratzen ditu
+Comment[fa]=پیکربندی انجمنهای پرونده
+Comment[fi]=Tiedostosidokset
+Comment[fr]=Configuration des associations de fichiers
+Comment[fy]=Hjir kinne jo de triemassosjaasjes ynstelle
+Comment[gl]=Configurar as asociacións de ficheiros
+Comment[he]=שינוי הגדרות שיוכי הקבצים
+Comment[hi]=फ़ाइल असोसिएशन कॉन्फ़िगर करें
+Comment[hr]=Konfiguriranje pridruživanja datoteka
+Comment[hu]=A fájlhozzárendelések módosítása
+Comment[is]=Stilla skráavensl
+Comment[it]=Configura associazioni dei file
+Comment[ja]=ファイルの関連付けを設定
+Comment[ka]=ფაილთა მიბმის კონფიგურირება
+Comment[kk]=Файл сәйкестіктерін баптау
+Comment[km]=កំណត់​រចនាសម្ព័ន្ធ​ទំនាក់​ទំនង​ឯកសារ
+Comment[ko]=파일 연결 설정
+Comment[lo]=ບັນທຶກຄ່າປັບແຕ່ງຂອງການເລີ່ມລະບົບ
+Comment[lt]=Konfigūruoti bylų sietis
+Comment[lv]=Konfigurēt failu asociācijas
+Comment[mk]=Конфигурирајте ги асоцијациите на датотеките
+Comment[mn]=Файлын холбоосуудыг тохируулах
+Comment[mt]=Ikkonfigura assoċjazzjoni ta' fajls
+Comment[nb]=Sette opp filtilknytninger
+Comment[nds]=Instellen, welk Dateitypen welk Programmen tohöört
+Comment[ne]=फाइल संयोजन कन्फिगर गर्नुहोस्
+Comment[nl]=Hier kunt u de bestandsassociaties instellen
+Comment[nn]=Set opp filassosiasjonar
+Comment[nso]=Beakanya dikopantsho tsa difaele
+Comment[pa]=ਫਾਇਲ ਸਬੰਧ ਸੰਰਚਨਾ
+Comment[pl]=Konfiguracja skojarzeń plików
+Comment[pt]=Configuração das associações de ficheiros
+Comment[pt_BR]=Configura associações de arquivos
+Comment[ro]=Configurează asocierea fișierelor cu aplicații
+Comment[ru]=Настройка привязки файлов
+Comment[rw]=Kuboneza Ishyirahamwe ry'Idosiye
+Comment[se]=Heivet fiilačatnagasaid
+Comment[sk]=Nastavenie asociácií súborov
+Comment[sl]=Nastavi datotečne povezave
+Comment[sr]=Подешавање придружења фајловима
+Comment[sr@Latn]=Podešavanje pridruženja fajlovima
+Comment[sv]=Anpassa filbindningar
+Comment[ta]=ஒருங்கிணைப்புகளை வடிவமை
+Comment[tg]=Танзими вобастагони Файл
+Comment[th]=ปรับแต่งการเรียกใช้งานแฟ้ม
+Comment[tr]=Dosya bağıntılarını yapılandır
+Comment[tt]=Biremnärne yazılımnarğa totaştırıp kileşterü
+Comment[uk]=Налаштування асоціацій файлів
+Comment[uz]=Fayl turi bilan bogʻliqlarni moslash
+Comment[uz@cyrillic]=Файл тури билан боғлиқларни мослаш
+Comment[ven]=Nzudzanyo yau fanyisa ha faela
+Comment[vi]=Cấu hình kiểu tập tin
+Comment[wa]=Apontiaedjes des elaxhaedjes di fitchîs
+Comment[xh]=Qwalasela uloyamiso lwefayile
+Comment[zh_CN]=配置文件关联
+Comment[zh_TW]=設定檔案關聯
+Comment[zu]=Hlanganisela ubudlelwano befayela
+
+Keywords=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern
+Keywords[ar]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,ملفات,أنواع الملفات, أنواع Mime,ارتباطات الملفات,ملفات,الملفات,نسق,الأنساق,النسق.
+Keywords[az]=Fayl Növləri,Fayl Əlaqələri,Mime Növləri,Fayl Qəlibləri,Fayllar
+Keywords[be]=Тыпы файлаў,асацыяцыі файлаў,сувязі файлаў,тыпы MIME,шаблоны файлаў,файлы,шаблон,Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern
+Keywords[bg]=файл, файлове, асоциация, асоциации, връзки, изпълнение, връзка, програма, тип на файл, тип, Filetypes, File Associations, Mime Types, File Patterns, Files, Pattern
+Keywords[ca]=Tipus de fitxer,Associacions de fitxers,Tipus Mime,Patrons de fitxer,Fitxers,Patró
+Keywords[cs]=Typy souborů,Asociace souborů,MIME typy,Vzory souborů,Soubory,Vzor
+Keywords[csb]=ôrt lopków,pòwiązania lopków,ôrtë MIME,mùster lopków,lopczi,mùster
+Keywords[cy]=Mathau o Ffeiliau,Cysylltiadau Ffeil,Mathau o Mime,Patrymau Ffeil,Ffeiliau,Patrwm
+Keywords[da]=Filtyper,Filassociationer,Mimetyper,Filmønstre,Filer,mønstre
+Keywords[de]=Dateitypen,Dateizuordnungen,MIME-Typen,Dateimuster,Filter,Muster,Dateien
+Keywords[el]=Τύποι αρχείων,Συσχετίσεις αρχείων,Τύποι mime,Μοτίβα αρχείων,Αρχεία,Μοτίβο
+Keywords[eo]=dosiertipoj,asocioj,MIME,dosieroj,ŝablonoj,dosieroj,MIME-tipoj
+Keywords[es]=Tipos de archivo,Asociaciones de archivo,Tipos MIME,Patrones de archivo,Archivos,Patrón
+Keywords[et]=Failitüübid,Failide seosed,MIME tüübid,failimustrid,failid,mustrid
+Keywords[eu]=Fitxategi motak,Fitxategi elkarketak,Mime motak, Fitxategi ereduak,Fitxategiak,Eredua
+Keywords[fa]=انواع پرونده، انجمنهای پرونده، انواع مایم، الگوهای پرونده، پرونده‌ها، الگو
+Keywords[fi]=Tiedostotyypit,Tiedostosidokset,Mimetyypit,Tiedostokuviot,Tiedostot,Kuvio
+Keywords[fo]=fíla,fílir,fíluslag
+Keywords[fr]=types de fichiers,associations de fichiers,types MIME,motifs de fichier,fichiers,motif,extension,extensions de fichiers,applications
+Keywords[fy]=Triemtypen,Triemtaheaksels,Triemassosjaasjes,mime types,Triempatroanen,Taheaksels,Triemmen
+Keywords[gl]=Tipos de ficheiro, Asociacións de ficheiro,Tipos Mime,Patróns de ficheiro,Ficheiros,Patrón
+Keywords[he]=תבניות קבצים,קבצים,תבנית,סוגי קבצים,שיוכי קבצים,טיפוסי,Mime,Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern
+Keywords[hi]=फ़ाइल क़िस्म,फ़ाइल असोसिएशन,माइम क़िस्म,फ़ाइल पैटर्न,फ़ाइलें,पैटर्न
+Keywords[hr]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,Vrste datoteka,Pridruživanje datoteka,MIME vrste,Uzorci datoteka,datoteke,uzorci
+Keywords[hu]=fájltípusok,fájlhozzárendelések,MIME-típusok,fájlminták,fájlok,minta
+Keywords[id]=TipeFile,Asosiasi File,Mime Types,Pattern File,Files,Pattern
+Keywords[is]=Skráartegund,Skráavensl,Samhengi skráa,skráarbindingar,Mime-tög,síur,skrár,mynstur
+Keywords[it]=tipi di file,associazioni file,tipi MIME,MIME,pattern dei file,file,motivi dei file,schemi
+Keywords[ja]=ファイルタイプ,ファイルの関連付け,マイムタイプ,ファイルパターン,ファイル,パターン
+Keywords[km]=ប្រភេទ​ឯកសារ,ទំនាក់​ទំនង​ឯកសារ,ប្រភេទ Mime,លំនាំ​ឯកសារ,ឯកសារ,លំនាំ
+Keywords[lt]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,Bylų tipai,Bylų Asociacijos,Mime Tipai,Bylų modeliai,Bylos,Modeliai, bylų sietys
+Keywords[lv]=Failutipi,Failu Asociācijas,Maime Tipi,Failu Maskas,Faili,Maskas
+Keywords[mk]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,Типови на датотеки,Асоцијации на датотеки,типови,Датотеки
+Keywords[mn]=Файлын төрөл,Файлын холбоос,MIME-төрөл,Файл загвар,Шүүлтүүр,Загвар,Файлууд
+Keywords[mt]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,Fajls,Assoċjazzjoni,Assoċjazzjonijiet
+Keywords[nb]=Filtyper,Filtilknytninger,Mime-typer,Filmønster,filer
+Keywords[nds]=Dateitypen,Datei-Tohören,Mime Typen,Dateimuster,Datei,Muster
+Keywords[ne]=फाइल प्रकार, फाइल संयोजन, माइम प्रकार, फाइल बाँन्की, फाइलहरू, बाँन्की
+Keywords[nl]=bestandstypen,bestandsextensies,bestandsassociaties,mime types,bestandspatronen,extensies,bestanden
+Keywords[nn]=filtypar,filtilknytingar,MIME-typar,filmønster,filer,mønster
+Keywords[nso]=Mehuta ya difaele,Dikopantsho tsa Difaele,Mehuta ya Kekiso,Mekgwa ya Difaele,Difaele,Mokgwa
+Keywords[pa]=Filetypes,File Associations,Mime Types,File Patterns,ਫਾਇਲਾਂ,Pattern,ਫਾਇਲ ਕਿਸਮ,ਫਾਇਲ ਸਬੰਧ
+Keywords[pl]=Typy plików,skojarzenia plików,typy MIME,wzorce plików,pliki,wzorzec
+Keywords[pt]=tipos de ficheiros,associações a ficheiros,tipos mime,padrões de ficheiros,ficheiros,padrão
+Keywords[pt_BR]=tipos de arquivo,associações de arquivo,tipos MIME,padrões de arquivo,arquivos,MIME,padrão
+Keywords[ro]=tipuri de fișiere,asocieri fișiere,tipuri MIME,modele de fișiere,fișiere
+Keywords[rw]=Amokodosiye,Amashyirahamwe dosiye,Amoko Mime,Amashusho Dosiye,Amadosiye,Igishushanyo
+Keywords[se]=Fiilašlájat,Fiilačatnagasat,Mime-šlájat,Fiilaminsttar, fiillat,minsttar
+Keywords[sk]=Typy súborov,Prípony,Mime typy,Súbory,Vzorky,Vzorky súborov
+Keywords[sl]=vrste datotek,vezi datotek,vzorci datotek,datoteke,vzorec
+Keywords[sr]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,врсте фајлова,узорци фајлова,узорак,придружење,MIME типови
+Keywords[sr@Latn]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,vrste fajlova,uzorci fajlova,uzorak,pridruženje,MIME tipovi
+Keywords[sv]=Filtyper,Filbindningar,Mime-typer,Filmönster,Filer,Mönster
+Keywords[ta]=கோப்பு வகைகள்,கோப்பு சேர்ப்புகள், மைம் வகைகள், கோப்பு மாதிரிகள்,கோப்புகள்,மாதிரிகள்
+Keywords[th]=ประเภทแฟ้ม,กำหนดการใช้แฟ้ม,ประเภท Mime,รูปแบบแฟ้ม,แฟ้ม,รูปแบบ
+Keywords[tr]=Dosya Türleri,Dosya İlişkileri,Mime Türleri,Dosya Kalıpları,Dosyalar
+Keywords[uk]=типи файлів,асоціації файлів,типи MIME,MIME,шаблони файлів,файли,взірці,файли
+Keywords[uz]=Fayl turlari,Fayl bilan bogʻlangan dasturlar,MIME turlari,Fayl namunalari,Fayllar,Namuna
+Keywords[uz@cyrillic]=Файл турлари,Файл билан боғланган дастурлар,MIME турлари,Файл намуналари,Файллар,Намуна
+Keywords[ven]=Tshakha dza faela,U fanyisa ha Faela,Tshakha dza Maimi,Phathene ya Faela,Dzifaela,Phathene
+Keywords[vi]=Kiểu tập tin,Đuôi tập tin,Kiểu MIME,Mẫu tập tin,Tập tin, Mẫu
+Keywords[wa]=Sôre di fitchî,sôrt di fitchî,elaxhaedje di fitchî,Sôre MIME, Sôrt MIME,Modeles di fitchî,Fitchîs,Modele
+Keywords[xh]=Iindidi zefayile,Unxubelelaniso lwefayile,Iindidi zeMime,Imilinganiselo yefayile,Iifayile,Umlinganiselo
+Keywords[zh_CN]=Filetypes,File Associations,Mime Types,File Patterns,Files,文件类型,文件关联,Mime 类型,文件模式,文件
+Keywords[zh_TW]=Filetypes,File Associations,Mime Types,File Patterns,Files,Pattern,檔案類型,檔案關聯,MIME 類型,檔案樣式,檔案,樣式
+Keywords[zu]=Izinhlobo zamafayela, Ubudlelwano bamafayela,Izinhlobo zamafayela,Amaphethini amafayela,Iphethini
+
diff --git a/kcontrol/filetypes/filetypesview.cpp b/kcontrol/filetypes/filetypesview.cpp
new file mode 100644
index 000000000..4088e9eee
--- /dev/null
+++ b/kcontrol/filetypes/filetypesview.cpp
@@ -0,0 +1,440 @@
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qwhatsthis.h>
+#include <qwidgetstack.h>
+
+#include <dcopclient.h>
+
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kipc.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+#include "newtypedlg.h"
+#include "filetypedetails.h"
+#include "filegroupdetails.h"
+#include "filetypesview.h"
+#include <ksycoca.h>
+
+FileTypesView::FileTypesView(QWidget *p, const char *name)
+ : KCModule(p, name)
+{
+ m_konqConfig = KSharedConfig::openConfig("konquerorrc", false, false);
+
+ setQuickHelp( i18n("<h1>File Associations</h1>"
+ " This module allows you to choose which applications are associated"
+ " with a given type of file. File types are also referred to MIME types"
+ " (MIME is an acronym which stands for \"Multipurpose Internet Mail"
+ " Extensions\".)<p> A file association consists of the following:"
+ " <ul><li>Rules for determining the MIME-type of a file, for example"
+ " the filename pattern *.kwd, which means 'all files with names that end"
+ " in .kwd', is associated with the MIME type \"x-kword\";</li>"
+ " <li>A short description of the MIME-type, for example the description"
+ " of the MIME type \"x-kword\" is simply 'KWord document';</li>"
+ " <li>An icon to be used for displaying files of the given MIME-type,"
+ " so that you can easily identify the type of file in, say, a Konqueror"
+ " view (at least for the types you use often);</li>"
+ " <li>A list of the applications which can be used to open files of the"
+ " given MIME-type -- if more than one application can be used then the"
+ " list is ordered by priority.</li></ul>"
+ " You may be surprised to find that some MIME types have no associated"
+ " filename patterns; in these cases, Konqueror is able to determine the"
+ " MIME-type by directly examining the contents of the file."));
+
+ setButtons(Help | Apply | Cancel | Ok);
+ QString wtstr;
+
+ QHBoxLayout *l = new QHBoxLayout(this, 0, KDialog::marginHint());
+ QGridLayout *leftLayout = new QGridLayout(0, 4, 3);
+ leftLayout->setSpacing( KDialog::spacingHint() );
+ leftLayout->setColStretch(1, 1);
+
+ l->addLayout( leftLayout );
+
+ QLabel *patternFilterLBL = new QLabel(i18n("F&ind filename pattern:"), this);
+ leftLayout->addMultiCellWidget(patternFilterLBL, 0, 0, 0, 2);
+
+ patternFilterLE = new KLineEdit(this);
+ patternFilterLBL->setBuddy( patternFilterLE );
+ leftLayout->addMultiCellWidget(patternFilterLE, 1, 1, 0, 2);
+
+ connect(patternFilterLE, SIGNAL(textChanged(const QString &)),
+ this, SLOT(slotFilter(const QString &)));
+
+ wtstr = i18n("Enter a part of a filename pattern. Only file types with a "
+ "matching file pattern will appear in the list.");
+
+ QWhatsThis::add( patternFilterLE, wtstr );
+ QWhatsThis::add( patternFilterLBL, wtstr );
+
+ typesLV = new KListView(this);
+ typesLV->setRootIsDecorated(true);
+ typesLV->setFullWidth(true);
+
+ typesLV->addColumn(i18n("Known Types"));
+ leftLayout->addMultiCellWidget(typesLV, 2, 2, 0, 2);
+ connect(typesLV, SIGNAL(selectionChanged(QListViewItem *)),
+ this, SLOT(updateDisplay(QListViewItem *)));
+ connect(typesLV, SIGNAL(doubleClicked(QListViewItem *)),
+ this, SLOT(slotDoubleClicked(QListViewItem *)));
+
+ QWhatsThis::add( typesLV, i18n("Here you can see a hierarchical list of"
+ " the file types which are known on your system. Click on the '+' sign"
+ " to expand a category, or the '-' sign to collapse it. Select a file type"
+ " (e.g. text/html for HTML files) to view/edit the information for that"
+ " file type using the controls on the right.") );
+
+ QPushButton *addTypeB = new QPushButton(i18n("Add..."), this);
+ connect(addTypeB, SIGNAL(clicked()), SLOT(addType()));
+ leftLayout->addWidget(addTypeB, 3, 0);
+
+ QWhatsThis::add( addTypeB, i18n("Click here to add a new file type.") );
+
+ m_removeTypeB = new QPushButton(i18n("&Remove"), this);
+ connect(m_removeTypeB, SIGNAL(clicked()), SLOT(removeType()));
+ leftLayout->addWidget(m_removeTypeB, 3, 2);
+ m_removeTypeB->setEnabled(false);
+
+ QWhatsThis::add( m_removeTypeB, i18n("Click here to remove the selected file type.") );
+
+ // For the right panel, prepare a widget stack
+ m_widgetStack = new QWidgetStack(this);
+
+ l->addWidget( m_widgetStack );
+
+ // File Type Details
+ m_details = new FileTypeDetails( m_widgetStack );
+ connect( m_details, SIGNAL( changed(bool) ),
+ this, SLOT( setDirty(bool) ) );
+ connect( m_details, SIGNAL( embedMajor(const QString &, bool &) ),
+ this, SLOT( slotEmbedMajor(const QString &, bool &)));
+ m_widgetStack->addWidget( m_details, 1 /*id*/ );
+
+ // File Group Details
+ m_groupDetails = new FileGroupDetails( m_widgetStack );
+ connect( m_groupDetails, SIGNAL( changed(bool) ),
+ this, SLOT( setDirty(bool) ) );
+ m_widgetStack->addWidget( m_groupDetails, 2 /*id*/ );
+
+ // Widget shown on startup
+ m_emptyWidget = new QLabel( i18n("Select a file type by name or by extension"), m_widgetStack);
+ m_emptyWidget->setAlignment(AlignCenter);
+
+ m_widgetStack->addWidget( m_emptyWidget, 3 /*id*/ );
+
+ m_widgetStack->raiseWidget( m_emptyWidget );
+
+ QTimer::singleShot( 0, this, SLOT( init() ) ); // this takes some time
+
+ connect( KSycoca::self(), SIGNAL( databaseChanged() ), SLOT( slotDatabaseChanged() ) );
+}
+
+FileTypesView::~FileTypesView()
+{
+}
+
+void FileTypesView::setDirty(bool state)
+{
+ emit changed(state);
+ m_dirty = state;
+}
+
+void FileTypesView::init()
+{
+ show();
+ setEnabled( false );
+
+ setCursor( KCursor::waitCursor() );
+ readFileTypes();
+ unsetCursor();
+
+ setDirty(false);
+ setEnabled( true );
+}
+
+// only call this method once on startup, then never again! Otherwise, newly
+// added Filetypes will be lost.
+void FileTypesView::readFileTypes()
+{
+ typesLV->clear();
+ m_majorMap.clear();
+ m_itemList.clear();
+ TypesListItem::reset();
+
+ TypesListItem *groupItem;
+ KMimeType::List mimetypes = KMimeType::allMimeTypes();
+ QValueListIterator<KMimeType::Ptr> it2(mimetypes.begin());
+ for (; it2 != mimetypes.end(); ++it2) {
+ QString mimetype = (*it2)->name();
+ int index = mimetype.find("/");
+ QString maj = mimetype.left(index);
+ QString min = mimetype.right(mimetype.length() - index+1);
+
+ QMapIterator<QString,TypesListItem*> mit = m_majorMap.find( maj );
+ if ( mit == m_majorMap.end() ) {
+ groupItem = new TypesListItem( typesLV, maj );
+ m_majorMap.insert( maj, groupItem );
+ }
+ else
+ groupItem = mit.data();
+
+ TypesListItem *item = new TypesListItem(groupItem, (*it2));
+ m_itemList.append( item );
+ }
+ updateDisplay(0L);
+
+}
+
+void FileTypesView::slotEmbedMajor(const QString &major, bool &embed)
+{
+ TypesListItem *groupItem;
+ QMapIterator<QString,TypesListItem*> mit = m_majorMap.find( major );
+ if ( mit == m_majorMap.end() )
+ return;
+
+ groupItem = mit.data();
+
+ embed = (groupItem->autoEmbed() == 0);
+}
+
+void FileTypesView::slotFilter(const QString & patternFilter)
+{
+ // one of the few ways to clear a listview without destroying the
+ // listviewitems and without making QListView crash.
+ QListViewItem *item;
+ while ( (item = typesLV->firstChild()) ) {
+ while ( item->firstChild() )
+ item->takeItem( item->firstChild() );
+
+ typesLV->takeItem( item );
+ }
+
+ // insert all items and their group that match the filter
+ QPtrListIterator<TypesListItem> it( m_itemList );
+ while ( it.current() ) {
+ if ( patternFilter.isEmpty() ||
+ !((*it)->patterns().grep( patternFilter, false )).isEmpty() ) {
+
+ TypesListItem *group = m_majorMap[ (*it)->majorType() ];
+ // QListView makes sure we don't insert a group-item more than once
+ typesLV->insertItem( group );
+ group->insertItem( *it );
+ }
+ ++it;
+ }
+}
+
+void FileTypesView::addType()
+{
+ QStringList allGroups;
+ QMapIterator<QString,TypesListItem*> it = m_majorMap.begin();
+ while ( it != m_majorMap.end() ) {
+ allGroups.append( it.key() );
+ ++it;
+ }
+
+ NewTypeDialog m(allGroups, this);
+
+ if (m.exec()) {
+ QListViewItemIterator it(typesLV);
+ QString loc = m.group() + "/" + m.text() + ".desktop";
+ loc = locateLocal("mime", loc);
+ KMimeType::Ptr mimetype = new KMimeType(loc,
+ m.group() + "/" + m.text(),
+ QString(), QString(),
+ QStringList());
+
+ TypesListItem *group = m_majorMap[ m.group() ];
+ if ( !group )
+ {
+ //group = new TypesListItem(
+ //TODO ! (The combo in NewTypeDialog must be made editable again when that happens)
+ Q_ASSERT(group);
+ }
+
+ // find out if our group has been filtered out -> insert if necessary
+ QListViewItem *item = typesLV->firstChild();
+ bool insert = true;
+ while ( item ) {
+ if ( item == group ) {
+ insert = false;
+ break;
+ }
+ item = item->nextSibling();
+ }
+ if ( insert )
+ typesLV->insertItem( group );
+
+ TypesListItem *tli = new TypesListItem(group, mimetype, true);
+ m_itemList.append( tli );
+
+ group->setOpen(true);
+ typesLV->setSelected(tli, true);
+
+ setDirty(true);
+ }
+}
+
+void FileTypesView::removeType()
+{
+ TypesListItem *current = (TypesListItem *) typesLV->currentItem();
+
+ if ( !current )
+ return;
+
+ // Can't delete groups
+ if ( current->isMeta() )
+ return;
+ // nor essential mimetypes
+ if ( current->isEssential() )
+ return;
+
+ QListViewItem *li = current->itemAbove();
+ if (!li)
+ li = current->itemBelow();
+ if (!li)
+ li = current->parent();
+
+ removedList.append(current->name());
+ current->parent()->takeItem(current);
+ m_itemList.removeRef( current );
+ setDirty(true);
+
+ if ( li )
+ typesLV->setSelected(li, true);
+}
+
+void FileTypesView::slotDoubleClicked(QListViewItem *item)
+{
+ if ( !item ) return;
+ item->setOpen( !item->isOpen() );
+}
+
+void FileTypesView::updateDisplay(QListViewItem *item)
+{
+ if (!item)
+ {
+ m_widgetStack->raiseWidget( m_emptyWidget );
+ m_removeTypeB->setEnabled(false);
+ return;
+ }
+
+ bool wasDirty = m_dirty;
+
+ TypesListItem *tlitem = (TypesListItem *) item;
+ if (tlitem->isMeta()) // is a group
+ {
+ m_widgetStack->raiseWidget( m_groupDetails );
+ m_groupDetails->setTypeItem( tlitem );
+ m_removeTypeB->setEnabled(false);
+ }
+ else
+ {
+ m_widgetStack->raiseWidget( m_details );
+ m_details->setTypeItem( tlitem );
+ m_removeTypeB->setEnabled( !tlitem->isEssential() );
+ }
+
+ // Updating the display indirectly called change(true)
+ if ( !wasDirty )
+ setDirty(false);
+}
+
+bool FileTypesView::sync( QValueList<TypesListItem *>& itemsModified )
+{
+ bool didIt = false;
+ // first, remove those items which we are asked to remove.
+ QStringList::Iterator it(removedList.begin());
+ QString loc;
+
+ for (; it != removedList.end(); ++it) {
+ didIt = true;
+ KMimeType::Ptr m_ptr = KMimeType::mimeType(*it);
+
+ loc = m_ptr->desktopEntryPath();
+ loc = locateLocal("mime", loc);
+
+ KDesktopFile config(loc, false, "mime");
+ config.writeEntry("Type", "MimeType");
+ config.writeEntry("MimeType", m_ptr->name());
+ config.writeEntry("Hidden", true);
+ }
+
+ // now go through all entries and sync those which are dirty.
+ // don't use typesLV, it may be filtered
+ QMapIterator<QString,TypesListItem*> it1 = m_majorMap.begin();
+ while ( it1 != m_majorMap.end() ) {
+ TypesListItem *tli = *it1;
+ if (tli->isDirty()) {
+ kdDebug() << "Entry " << tli->name() << " is dirty. Saving." << endl;
+ tli->sync();
+ itemsModified.append( tli );
+ didIt = true;
+ }
+ ++it1;
+ }
+ QPtrListIterator<TypesListItem> it2( m_itemList );
+ while ( it2.current() ) {
+ TypesListItem *tli = *it2;
+ if (tli->isDirty()) {
+ kdDebug() << "Entry " << tli->name() << " is dirty. Saving." << endl;
+ tli->sync();
+ itemsModified.append( tli );
+ didIt = true;
+ }
+ ++it2;
+ }
+
+ m_konqConfig->sync();
+
+ setDirty(false);
+ return didIt;
+}
+
+void FileTypesView::load()
+{
+ readFileTypes();
+}
+
+void FileTypesView::save()
+{
+ m_itemsModified.clear();
+ if (sync(m_itemsModified)) {
+ // only rebuild if sync() was necessary
+ KService::rebuildKSycoca(this);
+ KIPC::sendMessageAll(KIPC::SettingsChanged);
+ }
+}
+
+void FileTypesView::slotDatabaseChanged()
+{
+ if ( KSycoca::self()->isChanged( "mime" ) )
+ {
+ // ksycoca has new KMimeTypes objects for us, make sure to update
+ // our 'copies' to be in sync with it. Not important for OK, but
+ // important for Apply (how to differentiate those 2?).
+ // See BR 35071.
+ QValueList<TypesListItem *>::Iterator it = m_itemsModified.begin();
+ for( ; it != m_itemsModified.end(); ++it ) {
+ QString name = (*it)->name();
+ if ( removedList.find( name ) == removedList.end() ) // if not deleted meanwhile
+ (*it)->refresh();
+ }
+ m_itemsModified.clear();
+ }
+}
+
+void FileTypesView::defaults()
+{
+}
+
+#include "filetypesview.moc"
+
diff --git a/kcontrol/filetypes/filetypesview.h b/kcontrol/filetypes/filetypesview.h
new file mode 100644
index 000000000..bc6323d85
--- /dev/null
+++ b/kcontrol/filetypes/filetypesview.h
@@ -0,0 +1,73 @@
+#ifndef _FILETYPESVIEW_H
+#define _FILETYPESVIEW_H
+
+#include <qptrlist.h>
+#include <qmap.h>
+
+#include <kconfig.h>
+#include <kcmodule.h>
+
+#include "typeslistitem.h"
+
+class QLabel;
+class KListView;
+class QListViewItem;
+class QListBox;
+class QPushButton;
+class KIconButton;
+class QLineEdit;
+class QComboBox;
+class FileTypeDetails;
+class FileGroupDetails;
+class QWidgetStack;
+
+class FileTypesView : public KCModule
+{
+ Q_OBJECT
+public:
+ FileTypesView(QWidget *p = 0, const char *name = 0);
+ ~FileTypesView();
+
+ void load();
+ void save();
+ void defaults();
+
+protected slots:
+ /** fill in the various graphical elements, set up other stuff. */
+ void init();
+
+ void addType();
+ void removeType();
+ void updateDisplay(QListViewItem *);
+ void slotDoubleClicked(QListViewItem *);
+ void slotFilter(const QString &patternFilter);
+ void setDirty(bool state);
+
+ void slotDatabaseChanged();
+ void slotEmbedMajor(const QString &major, bool &embed);
+
+protected:
+ void readFileTypes();
+ bool sync( QValueList<TypesListItem *>& itemsModified );
+
+private:
+ KListView *typesLV;
+ QPushButton *m_removeTypeB;
+
+ QWidgetStack * m_widgetStack;
+ FileTypeDetails * m_details;
+ FileGroupDetails * m_groupDetails;
+ QLabel * m_emptyWidget;
+
+ QLineEdit *patternFilterLE;
+ QStringList removedList;
+ bool m_dirty;
+ QMap<QString,TypesListItem*> m_majorMap;
+ QPtrList<TypesListItem> m_itemList;
+
+ QValueList<TypesListItem *> m_itemsModified;
+
+ KSharedConfig::Ptr m_konqConfig;
+};
+
+#endif
diff --git a/kcontrol/filetypes/keditfiletype.cpp b/kcontrol/filetypes/keditfiletype.cpp
new file mode 100644
index 000000000..6c5c4eb6c
--- /dev/null
+++ b/kcontrol/filetypes/keditfiletype.cpp
@@ -0,0 +1,182 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 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 "filetypedetails.h"
+#include "typeslistitem.h"
+#include "keditfiletype.h"
+
+#include <qfile.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kdebug.h>
+#include <kcmdlineargs.h>
+#include <ksycoca.h>
+#include <kstandarddirs.h>
+
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+
+FileTypeDialog::FileTypeDialog( KMimeType::Ptr mime )
+ : KDialogBase( 0L, 0, false, QString::null, /* Help | */ Cancel | Apply | Ok,
+ Ok, false )
+{
+ init( mime, false );
+}
+
+FileTypeDialog::FileTypeDialog( KMimeType::Ptr mime, bool newItem )
+ : KDialogBase( 0L, 0, false, QString::null, /* Help | */ Cancel | Apply | Ok,
+ Ok, false )
+{
+ init( mime, newItem );
+}
+
+void FileTypeDialog::init( KMimeType::Ptr mime, bool newItem )
+{
+ m_details = new FileTypeDetails( this );
+ QListView * dummyListView = new QListView( m_details );
+ dummyListView->hide();
+ m_item = new TypesListItem( dummyListView, mime, newItem );
+ m_details->setTypeItem( m_item );
+
+ // This code is very similar to kcdialog.cpp
+ setMainWidget( m_details );
+ connect(m_details, SIGNAL(changed(bool)), this, SLOT(clientChanged(bool)));
+ // TODO setHelp()
+ enableButton(Apply, false);
+
+ connect( KSycoca::self(), SIGNAL( databaseChanged() ), SLOT( slotDatabaseChanged() ) );
+}
+
+void FileTypeDialog::save()
+{
+ if (m_item->isDirty()) {
+ m_item->sync();
+ KService::rebuildKSycoca(this);
+ }
+}
+
+void FileTypeDialog::slotApply()
+{
+ save();
+}
+
+void FileTypeDialog::slotOk()
+{
+ save();
+ accept();
+}
+
+void FileTypeDialog::clientChanged(bool state)
+{
+ // enable/disable buttons
+ enableButton(User1, state);
+ enableButton(Apply, state);
+}
+
+void FileTypeDialog::slotDatabaseChanged()
+{
+ if ( KSycoca::self()->isChanged( "mime" ) )
+ {
+ m_item->refresh();
+ }
+}
+
+#include "keditfiletype.moc"
+
+static KCmdLineOptions options[] =
+{
+ { "parent <winid>", I18N_NOOP("Makes the dialog transient for the window specified by winid"), 0 },
+ { "+mimetype", I18N_NOOP("File type to edit (e.g. text/html)"), 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char ** argv)
+{
+ KLocale::setMainCatalogue("filetypes");
+ KAboutData aboutData( "keditfiletype", I18N_NOOP("KEditFileType"), "1.0",
+ I18N_NOOP("KDE file type editor - simplified version for editing a single file type"),
+ KAboutData::License_GPL,
+ I18N_NOOP("(c) 2000, KDE developers") );
+ aboutData.addAuthor("Preston Brown",0, "pbrown@kde.org");
+ aboutData.addAuthor("David Faure",0, "faure@kde.org");
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+ KApplication app;
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if (args->count() == 0)
+ KCmdLineArgs::usage();
+
+ QString arg = args->arg(0);
+
+ bool createType = arg.startsWith( "*" );
+
+ KMimeType::Ptr mime;
+
+ if ( createType ) {
+ QString mimeString = "application/x-kdeuser%1";
+ QString loc;
+ int inc = 0;
+ do {
+ ++inc;
+ loc = locateLocal( "mime", mimeString.arg( inc ) + ".desktop" );
+ }
+ while ( QFile::exists( loc ) );
+
+ QStringList patterns;
+ if ( arg.length() > 2 )
+ patterns << arg.lower() << arg.upper();
+ QString comment;
+ if ( arg.startsWith( "*." ) && arg.length() >= 3 ) {
+ QString type = arg.mid( 3 ).prepend( arg[2].upper() );
+ comment = i18n( "%1 File" ).arg( type );
+ }
+ mime = new KMimeType( loc, mimeString.arg( inc ), QString::null, comment, patterns );
+ }
+ else {
+ mime = KMimeType::mimeType( arg );
+ if (!mime)
+ kdFatal() << "Mimetype " << arg << " not found" << endl;
+ }
+
+ FileTypeDialog dlg( mime, createType );
+#if defined Q_WS_X11
+ if( args->isSet( "parent" )) {
+ bool ok;
+ long id = args->getOption("parent").toLong(&ok);
+ if (ok)
+ XSetTransientForHint( qt_xdisplay(), dlg.winId(), id );
+ }
+#endif
+ args->clear();
+ if ( !createType )
+ dlg.setCaption( i18n("Edit File Type %1").arg(mime->name()) );
+ else {
+ dlg.setCaption( i18n("Create New File Type %1").arg(mime->name()) );
+ dlg.enableButton( KDialogBase::Apply, true );
+ }
+ app.setMainWidget( &dlg );
+ dlg.show(); // non-modal
+
+ return app.exec();
+}
+
diff --git a/kcontrol/filetypes/keditfiletype.h b/kcontrol/filetypes/keditfiletype.h
new file mode 100644
index 000000000..3ae7c0e35
--- /dev/null
+++ b/kcontrol/filetypes/keditfiletype.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 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.
+*/
+#ifndef __keditfiletype_h
+#define __keditfiletype_h
+
+#include <kdialogbase.h>
+#include <kmimetype.h>
+
+class TypesListItem;
+class FileTypeDetails;
+
+// A dialog for ONE file type to be edited.
+class FileTypeDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ FileTypeDialog( KMimeType::Ptr mime );
+ FileTypeDialog( KMimeType::Ptr mime, bool newItem );
+
+protected slots:
+
+ //virtual void slotDefault();
+ //virtual void slotUser1(); // Reset
+ virtual void slotApply();
+ virtual void slotOk();
+ void clientChanged(bool state);
+ void slotDatabaseChanged();
+
+protected:
+ void save();
+
+private:
+ void init( KMimeType::Ptr mime, bool newItem );
+ FileTypeDetails * m_details;
+ TypesListItem * m_item;
+};
+
+#endif
+
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"
diff --git a/kcontrol/filetypes/kservicelistwidget.h b/kcontrol/filetypes/kservicelistwidget.h
new file mode 100644
index 000000000..fb20d1c64
--- /dev/null
+++ b/kcontrol/filetypes/kservicelistwidget.h
@@ -0,0 +1,77 @@
+/* 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.
+*/
+
+#ifndef _KSERVICELISTWIDGET_H
+#define _KSERVICELISTWIDGET_H
+
+#include <qgroupbox.h>
+#include <qlistbox.h>
+class TypesListItem;
+class QLineEdit;
+class QPushButton;
+class KService;
+
+class KServiceListItem : public QListBoxText
+{
+public:
+ KServiceListItem( KService *pService, int kind );
+ bool isImmutable();
+ QString desktopPath;
+ QString localPath;
+};
+
+/**
+ * This widget holds a list of services, with 5 buttons to manage it.
+ * It's a separate class so that it can be used by both tabs of the
+ * module, once for applications and once for services.
+ * The "kind" is determined by the argument given to the constructor.
+ */
+class KServiceListWidget : public QGroupBox
+{
+ Q_OBJECT
+public:
+ enum { SERVICELIST_APPLICATIONS, SERVICELIST_SERVICES };
+ KServiceListWidget(int kind, QWidget *parent = 0, const char *name = 0);
+
+ void setTypeItem( TypesListItem * item );
+
+signals:
+ void changed(bool);
+
+protected slots:
+ void promoteService();
+ void demoteService();
+ void addService();
+ void editService();
+ void removeService();
+ void enableMoveButtons(int index);
+
+protected:
+ void updatePreferredServices();
+
+private:
+ int m_kind;
+ QListBox *servicesLB;
+ QPushButton *servUpButton, *servDownButton;
+ QPushButton *servNewButton, *servEditButton, *servRemoveButton;
+ TypesListItem *m_item;
+};
+
+#endif
diff --git a/kcontrol/filetypes/kserviceselectdlg.cpp b/kcontrol/filetypes/kserviceselectdlg.cpp
new file mode 100644
index 000000000..c3a925218
--- /dev/null
+++ b/kcontrol/filetypes/kserviceselectdlg.cpp
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 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 "kserviceselectdlg.h"
+#include "kserviceselectdlg.moc"
+#include "kservicelistwidget.h"
+
+#include <klocale.h>
+
+#include <qvbox.h>
+#include <qlabel.h>
+
+KServiceSelectDlg::KServiceSelectDlg( const QString& /*serviceType*/, const QString& /*value*/, QWidget *parent )
+ : KDialogBase( parent, "serviceSelectDlg", true,
+ i18n( "Add Service" ), Ok|Cancel, Ok )
+{
+ QVBox *vbox = new QVBox ( this );
+
+ vbox->setSpacing( KDialog::spacingHint() );
+ new QLabel( i18n( "Select service:" ), vbox );
+ m_listbox=new KListBox( vbox );
+
+ // Can't make a KTrader query since we don't have a servicetype to give,
+ // we want all services that are not applications.......
+ // So we have to do it the slow way
+ // ### Why can't we query for KParts/ReadOnlyPart as the servicetype? Should work fine!
+ KService::List allServices = KService::allServices();
+ QValueListIterator<KService::Ptr> it(allServices.begin());
+ for ( ; it != allServices.end() ; ++it )
+ if ( (*it)->hasServiceType( "KParts/ReadOnlyPart" ) )
+ {
+ m_listbox->insertItem( new KServiceListItem( (*it), KServiceListWidget::SERVICELIST_SERVICES ) );
+ }
+
+ m_listbox->sort();
+ m_listbox->setMinimumHeight(350);
+ m_listbox->setMinimumWidth(300);
+ connect(m_listbox,SIGNAL(doubleClicked ( QListBoxItem * )),SLOT(slotOk()));
+ setMainWidget(vbox);
+}
+
+KServiceSelectDlg::~KServiceSelectDlg()
+{
+}
+
+KService::Ptr KServiceSelectDlg::service()
+{
+ unsigned int selIndex = m_listbox->currentItem();
+ KServiceListItem *selItem = static_cast<KServiceListItem *>(m_listbox->item(selIndex));
+ return KService::serviceByDesktopPath( selItem->desktopPath );
+}
diff --git a/kcontrol/filetypes/kserviceselectdlg.h b/kcontrol/filetypes/kserviceselectdlg.h
new file mode 100644
index 000000000..05a2d4e9d
--- /dev/null
+++ b/kcontrol/filetypes/kserviceselectdlg.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 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.
+*/
+
+#ifndef __kserviceselectdlg_h
+#define __kserviceselectdlg_h
+#include <kdialogbase.h>
+#include <kservice.h>
+
+class KServiceSelectDlg : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Create a dialog to select a service (not application) for a given service type.
+ *
+ * @param serviceType the service type we want to choose a service for.
+ * @param value is the initial service to select (not implemented currently)
+ * @param parent parent widget
+ */
+ KServiceSelectDlg( const QString& serviceType, const QString& value = QString::null, QWidget *parent = 0L );
+
+ ~KServiceSelectDlg();
+
+ /**
+ * @return the chosen service
+ */
+ KService::Ptr service();
+private:
+ KListBox * m_listbox;
+};
+
+#endif
diff --git a/kcontrol/filetypes/newtypedlg.cpp b/kcontrol/filetypes/newtypedlg.cpp
new file mode 100644
index 000000000..24760cf1d
--- /dev/null
+++ b/kcontrol/filetypes/newtypedlg.cpp
@@ -0,0 +1,57 @@
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+
+#include <klocale.h>
+#include <klineedit.h>
+
+#include "newtypedlg.h"
+
+NewTypeDialog::NewTypeDialog(QStringList groups,
+ QWidget *parent, const char *name)
+ : KDialogBase(parent, name, true, i18n( "Create New File Type" ),
+ Ok|Cancel, Ok, true)
+{
+ QFrame *main = makeMainWidget();
+ QVBoxLayout *topl = new QVBoxLayout(main, 0, spacingHint());
+
+ QGridLayout *grid = new QGridLayout(2, 2);
+ grid->setColStretch(1, 1);
+ topl->addLayout(grid);
+
+ QLabel *l = new QLabel(i18n("Group:"), main);
+ grid->addWidget(l, 0, 0);
+
+ groupCombo = new QComboBox(main);
+ //groupCombo->setEditable( true ); M.O.: Currently, the code in filetypesview isn't capable of handling
+ //new top level types; so better not let them be added than crash.
+ groupCombo->insertStringList(groups);
+ grid->addWidget(groupCombo, 0, 1);
+
+ QWhatsThis::add( groupCombo, i18n("Select the category under which"
+ " the new file type should be added.") );
+
+ l = new QLabel(i18n("Type name:"), main);
+ grid->addWidget(l, 1, 0);
+
+ typeEd = new KLineEdit(main);
+ grid->addWidget(typeEd, 1, 1);
+
+ typeEd->setFocus();
+
+ // Set a minimum size so that caption is not half-hidden
+ setMinimumSize( 300, 50 );
+}
+
+QString NewTypeDialog::group() const
+{
+ return groupCombo->currentText();
+}
+
+
+QString NewTypeDialog::text() const
+{
+ return typeEd->text();
+}
diff --git a/kcontrol/filetypes/newtypedlg.h b/kcontrol/filetypes/newtypedlg.h
new file mode 100644
index 000000000..386b5fcdb
--- /dev/null
+++ b/kcontrol/filetypes/newtypedlg.h
@@ -0,0 +1,28 @@
+#ifndef _NEWTYPEDLG_H
+#define _NEWTYPEDLG_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <kdialogbase.h>
+
+class KLineEdit;
+class QComboBox;
+
+/**
+ * A dialog for creating a new file type, with
+ * a combobox for choosing the group and a line-edit
+ * for entering the name of the file type
+ */
+class NewTypeDialog : public KDialogBase
+{
+public:
+ NewTypeDialog(QStringList groups, QWidget *parent = 0,
+ const char *name = 0);
+ QString group() const;
+ QString text() const;
+private:
+ KLineEdit *typeEd;
+ QComboBox *groupCombo;
+};
+
+#endif
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;
+}
+
diff --git a/kcontrol/filetypes/typeslistitem.h b/kcontrol/filetypes/typeslistitem.h
new file mode 100644
index 000000000..5f44e9864
--- /dev/null
+++ b/kcontrol/filetypes/typeslistitem.h
@@ -0,0 +1,118 @@
+/* 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.
+*/
+
+#ifndef _TYPESLISTITEM_H
+#define _TYPESLISTITEM_H
+
+#include <qlistview.h>
+
+#include <kmimetype.h>
+#include <kuserprofile.h>
+
+class TypesListItem : public QListViewItem
+{
+public:
+ /**
+ * Create a filetype group
+ */
+ TypesListItem(QListView *parent, const QString & major );
+
+ /**
+ * Create a filetype item inside a group
+ */
+ TypesListItem(TypesListItem *parent, KMimeType::Ptr mimetype, bool newItem=false);
+
+ /**
+ * Create a filetype item not inside a group (used by keditfiletype)
+ */
+ TypesListItem(QListView *parent, KMimeType::Ptr mimetype);
+
+ /**
+ * Create a filetype item not inside a group (used by keditfiletype)
+ * KDE4: merge with previous
+ */
+ TypesListItem(QListView *parent, KMimeType::Ptr mimetype, bool newItem);
+
+ ~TypesListItem();
+
+ QString name() const { return m_major + "/" + m_minor; }
+ QString majorType() const { return m_major; }
+ QString minorType() const { return m_minor; }
+ void setMinor(QString m) { m_minor = m; }
+ QString comment() const { return m_comment; }
+ void setComment(QString c) { m_comment = c; }
+ /**
+ * Returns true if "this" is a group
+ */
+ bool isMeta() const { return metaType; }
+ /**
+ * Returns true if the type is essential, i.e. can't be deleted
+ * (see KMimeType::checkEssentialMimeTypes)
+ */
+ bool isEssential() const;
+ QString icon() const { return m_icon; }
+ void setIcon(const QString& i);
+ QStringList patterns() const { return m_patterns; }
+ void setPatterns(const QStringList &p) { m_patterns = p; }
+ QStringList appServices() const;
+ void setAppServices(const QStringList &dsl) { m_appServices = dsl; }
+ QStringList embedServices() const;
+ void setEmbedServices(const QStringList &dsl) { m_embedServices = dsl; }
+ int autoEmbed() const { return m_autoEmbed; }
+ void setAutoEmbed( int a ) { m_autoEmbed = a; }
+ const KMimeType::Ptr& mimeType() const { return m_mimetype; }
+ bool canUseGroupSetting() const;
+
+ void getAskSave(bool &);
+ void setAskSave(bool);
+
+ // Whether the service s lists this mimetype explicitly
+ KMimeType::Ptr findImplicitAssociation(const QString &desktop);
+
+ bool isMimeTypeDirty() const; // whether the mimetype .desktop file needs saving
+ bool isDirty() const;
+ void sync();
+ void setup();
+ void refresh(); // update m_mimetype from ksycoca when Apply is pressed
+
+ static bool defaultEmbeddingSetting( const QString& major );
+ static void reset();
+
+private:
+ void getServiceOffers( QStringList & appServices, QStringList & embedServices ) const;
+ void saveServices( KConfig & profile, QStringList services, const QString & servicetype2 );
+ void initMeta( const QString & major );
+ void init(KMimeType::Ptr mimetype);
+ static int readAutoEmbed( KMimeType::Ptr mimetype );
+
+ KMimeType::Ptr m_mimetype;
+ unsigned int groupCount:16; // shared between saveServices and sync
+ unsigned int m_autoEmbed:2; // 0 yes, 1 no, 2 use group setting
+ unsigned int metaType:1;
+ unsigned int m_bNewItem:1;
+ unsigned int m_bFullInit:1;
+ unsigned int m_askSave:2; // 0 yes, 1 no, 2 default
+ QString m_major, m_minor, m_comment, m_icon;
+ QStringList m_patterns;
+ QStringList m_appServices;
+ QStringList m_embedServices;
+ static QMap< QString, QStringList >* s_changedServices;
+};
+
+#endif