diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /kcontrol/filetypes | |
download | tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kcontrol/filetypes')
-rw-r--r-- | kcontrol/filetypes/Makefile.am | 29 | ||||
-rw-r--r-- | kcontrol/filetypes/control.cpp | 11 | ||||
-rw-r--r-- | kcontrol/filetypes/filegroupdetails.cpp | 65 | ||||
-rw-r--r-- | kcontrol/filetypes/filegroupdetails.h | 50 | ||||
-rw-r--r-- | kcontrol/filetypes/filetypedetails.cpp | 299 | ||||
-rw-r--r-- | kcontrol/filetypes/filetypedetails.h | 64 | ||||
-rw-r--r-- | kcontrol/filetypes/filetypes.desktop | 235 | ||||
-rw-r--r-- | kcontrol/filetypes/filetypesview.cpp | 440 | ||||
-rw-r--r-- | kcontrol/filetypes/filetypesview.h | 73 | ||||
-rw-r--r-- | kcontrol/filetypes/keditfiletype.cpp | 182 | ||||
-rw-r--r-- | kcontrol/filetypes/keditfiletype.h | 54 | ||||
-rw-r--r-- | kcontrol/filetypes/kservicelistwidget.cpp | 444 | ||||
-rw-r--r-- | kcontrol/filetypes/kservicelistwidget.h | 77 | ||||
-rw-r--r-- | kcontrol/filetypes/kserviceselectdlg.cpp | 66 | ||||
-rw-r--r-- | kcontrol/filetypes/kserviceselectdlg.h | 47 | ||||
-rw-r--r-- | kcontrol/filetypes/newtypedlg.cpp | 57 | ||||
-rw-r--r-- | kcontrol/filetypes/newtypedlg.h | 28 | ||||
-rw-r--r-- | kcontrol/filetypes/typeslistitem.cpp | 579 | ||||
-rw-r--r-- | kcontrol/filetypes/typeslistitem.h | 118 |
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 |