1/* This file is part of the KDE project
2 Copyright (C) 2000, 2007 David Faure <faure@kde.org>
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public
6 License version 2 or at your option version 3 as published by
7 the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20// Own
21#include "filetypedetails.h"
22#include "sharedmimeinfoversion.h"
23
24// Qt
25#include <QBoxLayout>
26#include <QButtonGroup>
27#include <QCheckBox>
28#include <QLayout>
29#include <QListWidget>
30#include <QRadioButton>
31#include <QLabel>
32
33// KDE
34#include <kconfig.h>
35#include <kdebug.h>
36#include <kicondialog.h>
37#include <kinputdialog.h>
38#include <klineedit.h>
39#include <klocale.h>
40#include <kicon.h>
41#include <kpushbutton.h>
42
43// Local
44#include "kservicelistwidget.h"
45#include "typeslistitem.h"
46
47FileTypeDetails::FileTypeDetails( QWidget * parent )
48 : QWidget( parent ), m_mimeTypeData(0), m_item(0)
49{
50
51 QVBoxLayout* topLayout = new QVBoxLayout(this);
52
53 m_mimeTypeLabel = new QLabel(this);
54 topLayout->addWidget(m_mimeTypeLabel, 0, Qt::AlignCenter);
55
56 m_tabWidget = new QTabWidget(this);
57 topLayout->addWidget(m_tabWidget);
58
59 QString wtstr;
60 // First tab - General
61 QWidget * firstWidget = new QWidget(m_tabWidget);
62 QVBoxLayout *firstLayout = new QVBoxLayout(firstWidget);
63
64 QHBoxLayout *hBox = new QHBoxLayout();
65 firstLayout->addLayout(hBox);
66
67 if (SharedMimeInfoVersion::supportsIcon()) {
68 iconButton = new KIconButton(firstWidget);
69 iconButton->setIconType(KIconLoader::Desktop, KIconLoader::MimeType);
70 connect(iconButton, SIGNAL(iconChanged(QString)), SLOT(updateIcon(QString)));
71 iconButton->setWhatsThis( i18n("This button displays the icon associated"
72 " with the selected file type. Click on it to choose a different icon.") );
73 iconButton->setFixedSize(70, 70);
74 iconLabel = 0;
75 hBox->addWidget(iconButton);
76 } else {
77 iconButton = 0;
78 iconLabel = new QLabel(firstWidget);
79 iconLabel->setWhatsThis( i18n("This is the icon associated with the selected file type. "
80 "Choosing a different icon requires shared-mime-info to be at least version 0.40.") );
81 iconLabel->setFixedSize(70, 70);
82 hBox->addWidget(iconLabel);
83 }
84
85 QGroupBox *gb = new QGroupBox(i18n("Filename Patterns"), firstWidget);
86 hBox->addWidget(gb);
87
88 hBox = new QHBoxLayout(gb);
89
90 extensionLB = new QListWidget(gb);
91 connect(extensionLB, SIGNAL(itemSelectionChanged()), SLOT(enableExtButtons()));
92 hBox->addWidget(extensionLB);
93
94 extensionLB->setFixedHeight(extensionLB->minimumSizeHint().height());
95
96
97 extensionLB->setWhatsThis( i18n("This box contains a list of patterns that can be"
98 " used to identify files of the selected type. For example, the pattern *.txt is"
99 " associated with the file type 'text/plain'; all files ending in '.txt' are recognized"
100 " as plain text files.") );
101
102 QVBoxLayout *vbox = new QVBoxLayout();
103 hBox->addLayout(vbox);
104
105 addExtButton = new KPushButton(i18n("Add..."), gb);
106 addExtButton->setIcon(KIcon("list-add"));
107 addExtButton->setEnabled(false);
108 connect(addExtButton, SIGNAL(clicked()),
109 this, SLOT(addExtension()));
110 vbox->addWidget(addExtButton);
111 addExtButton->setWhatsThis( i18n("Add a new pattern for the selected file type.") );
112
113 removeExtButton = new KPushButton(i18n("Remove"), gb);
114 removeExtButton->setIcon(KIcon("list-remove"));
115 removeExtButton->setEnabled(false);
116 connect(removeExtButton, SIGNAL(clicked()),
117 this, SLOT(removeExtension()));
118 vbox->addWidget(removeExtButton);
119 removeExtButton->setWhatsThis( i18n("Remove the selected filename pattern.") );
120
121 vbox->addStretch(1);
122
123 gb->setFixedHeight(gb->minimumSizeHint().height());
124
125 description = new KLineEdit(firstWidget);
126 description->setClearButtonShown(true);
127 connect(description, SIGNAL(textChanged(const QString &)),
128 SLOT(updateDescription(const QString &)));
129
130 QHBoxLayout *descriptionBox = new QHBoxLayout;
131 descriptionBox->addWidget(new QLabel(i18n("Description:"),firstWidget));
132 descriptionBox->addWidget(description);
133 firstLayout->addLayout(descriptionBox);
134
135 wtstr = i18n("You can enter a short description for files of the selected"
136 " file type (e.g. 'HTML Page'). This description will be used by applications"
137 " like Konqueror to display directory content.");
138 description->setWhatsThis( wtstr );
139
140 serviceListWidget = new KServiceListWidget( KServiceListWidget::SERVICELIST_APPLICATIONS, firstWidget );
141 connect( serviceListWidget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool)));
142 firstLayout->addWidget(serviceListWidget,5);
143
144 // Second tab - Embedding
145 QWidget * secondWidget = new QWidget(m_tabWidget);
146 QVBoxLayout *secondLayout = new QVBoxLayout(secondWidget);
147
148 m_autoEmbedBox = new QGroupBox( i18n("Left Click Action in Konqueror"), secondWidget );
149 secondLayout->addWidget( m_autoEmbedBox );
150
151 m_autoEmbedBox->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
152
153 QRadioButton *embViewerRadio = new QRadioButton( i18n("Show file in embedded viewer") );
154 QRadioButton *sepViewerRadio = new QRadioButton( i18n("Show file in separate viewer") );
155 m_rbGroupSettings = new QRadioButton( QString("Use settings for '%1' group") );
156
157 m_chkAskSave = new QCheckBox( i18n("Ask whether to save to disk instead (only for Konqueror browser)") );
158 connect(m_chkAskSave, SIGNAL( toggled(bool) ), SLOT( slotAskSaveToggled(bool) ));
159
160 m_autoEmbedGroup = new QButtonGroup(m_autoEmbedBox);
161 m_autoEmbedGroup->addButton(embViewerRadio, 0);
162 m_autoEmbedGroup->addButton(sepViewerRadio, 1);
163 m_autoEmbedGroup->addButton(m_rbGroupSettings, 2);
164 connect(m_autoEmbedGroup, SIGNAL( buttonClicked(int) ), SLOT( slotAutoEmbedClicked(int) ));
165
166 vbox = new QVBoxLayout(m_autoEmbedBox);
167 vbox->addWidget(embViewerRadio);
168 vbox->addWidget(sepViewerRadio);
169 vbox->addWidget(m_rbGroupSettings);
170 vbox->addWidget(m_chkAskSave);
171
172 m_autoEmbedBox->setWhatsThis( i18n("Here you can configure what the Konqueror file manager"
173 " will do when you click on a file of this type. Konqueror can either display the file in"
174 " an embedded viewer, or start up a separate application. If set to 'Use settings for G group',"
175 " the file manager will behave according to the settings of the group G to which this type belongs;"
176 " for instance, 'image' if the current file type is image/png. Dolphin"
177 " always shows files in a separate viewer.") );
178
179 embedServiceListWidget = new KServiceListWidget( KServiceListWidget::SERVICELIST_SERVICES, secondWidget );
180// embedServiceListWidget->setMinimumHeight( serviceListWidget->sizeHint().height() );
181 connect( embedServiceListWidget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool)));
182 secondLayout->addWidget(embedServiceListWidget);
183
184 m_tabWidget->addTab( firstWidget, i18n("&General") );
185 m_tabWidget->addTab( secondWidget, i18n("&Embedding") );
186}
187
188void FileTypeDetails::updateRemoveButton()
189{
190 removeExtButton->setEnabled(extensionLB->count()>0);
191}
192
193void FileTypeDetails::updateIcon(const QString &icon)
194{
195 if (!m_mimeTypeData)
196 return;
197
198 m_mimeTypeData->setUserSpecifiedIcon(icon);
199
200 if (m_item)
201 m_item->setIcon(icon);
202
203 emit changed(true);
204}
205
206void FileTypeDetails::updateDescription(const QString &desc)
207{
208 if (!m_mimeTypeData)
209 return;
210
211 m_mimeTypeData->setComment(desc);
212
213 emit changed(true);
214}
215
216void FileTypeDetails::addExtension()
217{
218 if ( !m_mimeTypeData )
219 return;
220
221 bool ok;
222 QString ext = KInputDialog::getText( i18n( "Add New Extension" ),
223 i18n( "Extension:" ), "*.", &ok, this );
224 if (ok) {
225 extensionLB->addItem(ext);
226 QStringList patt = m_mimeTypeData->patterns();
227 patt += ext;
228 m_mimeTypeData->setPatterns(patt);
229 updateRemoveButton();
230 emit changed(true);
231 }
232}
233
234void FileTypeDetails::removeExtension()
235{
236 if (extensionLB->currentRow() == -1)
237 return;
238 if ( !m_mimeTypeData )
239 return;
240 QStringList patt = m_mimeTypeData->patterns();
241 patt.removeAll(extensionLB->currentItem()->text());
242 m_mimeTypeData->setPatterns(patt);
243 delete extensionLB->takeItem(extensionLB->currentRow());
244 updateRemoveButton();
245 emit changed(true);
246}
247
248void FileTypeDetails::slotAutoEmbedClicked( int button )
249{
250 if ( !m_mimeTypeData || (button > 2))
251 return;
252
253 m_mimeTypeData->setAutoEmbed( (MimeTypeData::AutoEmbed) button );
254
255 updateAskSave();
256
257 emit changed(true);
258}
259
260void FileTypeDetails::updateAskSave()
261{
262 if ( !m_mimeTypeData )
263 return;
264
265 MimeTypeData::AutoEmbed autoEmbed = m_mimeTypeData->autoEmbed();
266 if (m_mimeTypeData->isMeta() && autoEmbed == MimeTypeData::UseGroupSetting) {
267 // Resolve by looking at group (we could cache groups somewhere to avoid the re-parsing?)
268 autoEmbed = MimeTypeData(m_mimeTypeData->majorType()).autoEmbed();
269 }
270
271 const QString mimeType = m_mimeTypeData->name();
272
273 QString dontAskAgainName;
274 if (autoEmbed == MimeTypeData::Yes) // Embedded
275 dontAskAgainName = "askEmbedOrSave"+mimeType;
276 else
277 dontAskAgainName = "askSave"+mimeType;
278
279 KSharedConfig::Ptr config = KSharedConfig::openConfig("filetypesrc", KConfig::NoGlobals);
280 // default value
281 bool ask = config->group("Notification Messages").readEntry(dontAskAgainName, QString()).isEmpty();
282 // per-mimetype override if there's one
283 m_mimeTypeData->getAskSave(ask);
284
285 bool neverAsk = false;
286
287 if (autoEmbed == MimeTypeData::Yes) {
288 const KMimeType::Ptr mime = KMimeType::mimeType( mimeType );
289 if (mime) {
290 // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
291 // NOTE: Keep this function in sync with
292 // kdelibs/kparts/browseropenorsavequestion.cpp BrowserOpenOrSaveQuestionPrivate::autoEmbedMimeType
293
294 // Don't ask for:
295 // - html (even new tabs would ask, due to about:blank!)
296 // - dirs obviously (though not common over HTTP :),
297 // - images (reasoning: no need to save, most of the time, because fast to see)
298 // e.g. postscript is different, because takes longer to read, so
299 // it's more likely that the user might want to save it.
300 // - multipart/* ("server push", see kmultipart)
301 if ( mime->is( "text/html" ) ||
302 mime->is( "application/xml" ) ||
303 mime->is( "inode/directory" ) ||
304 mimeType.startsWith( QLatin1String("image") ) ||
305 mime->is( "multipart/x-mixed-replace" ) ||
306 mime->is( "multipart/replace" ) )
307 {
308 neverAsk = true;
309 }
310 }
311 }
312
313 m_chkAskSave->blockSignals(true);
314 m_chkAskSave->setChecked(ask && !neverAsk);
315 m_chkAskSave->setEnabled(!neverAsk);
316 m_chkAskSave->blockSignals(false);
317}
318
319void FileTypeDetails::slotAskSaveToggled(bool askSave)
320{
321 if (!m_mimeTypeData)
322 return;
323
324 m_mimeTypeData->setAskSave(askSave);
325 emit changed(true);
326}
327
328void FileTypeDetails::setMimeTypeData( MimeTypeData * mimeTypeData, TypesListItem* item )
329{
330 m_mimeTypeData = mimeTypeData;
331 m_item = item; // can be 0
332 Q_ASSERT(mimeTypeData);
333 m_mimeTypeLabel->setText(i18n("File type %1", mimeTypeData->name()));
334 if (iconButton)
335 iconButton->setIcon(mimeTypeData->icon());
336 else
337 iconLabel->setPixmap(DesktopIcon(mimeTypeData->icon()));
338 description->setText(mimeTypeData->comment());
339 m_rbGroupSettings->setText( i18n("Use settings for '%1' group", mimeTypeData->majorType() ) );
340 extensionLB->clear();
341 addExtButton->setEnabled(true);
342 removeExtButton->setEnabled(false);
343
344 serviceListWidget->setMimeTypeData( mimeTypeData );
345 embedServiceListWidget->setMimeTypeData( mimeTypeData );
346 m_autoEmbedGroup->button(mimeTypeData->autoEmbed())->setChecked(true);
347 m_rbGroupSettings->setEnabled( mimeTypeData->canUseGroupSetting() );
348
349 extensionLB->addItems(mimeTypeData->patterns());
350
351 updateAskSave();
352}
353
354void FileTypeDetails::enableExtButtons()
355{
356 removeExtButton->setEnabled(true);
357}
358
359void FileTypeDetails::refresh()
360{
361 if (!m_mimeTypeData)
362 return;
363
364 // Called when ksycoca has been updated -> refresh data, then widgets
365 m_mimeTypeData->refresh();
366 setMimeTypeData(m_mimeTypeData, m_item);
367}
368
369#include "filetypedetails.moc"
370