• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KParts

  • sources
  • kde-4.14
  • kdelibs
  • kparts
browseropenorsavequestion.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2009, 2010 David Faure <faure@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as published by
6  the Free Software Foundation; either version 2 of the License or ( at
7  your option ) version 3 or, at the discretion of KDE e.V. ( which shall
8  act as a proxy as in section 14 of the GPLv3 ), any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "browseropenorsavequestion.h"
22 #include <kdebug.h>
23 #include <kaction.h>
24 #include <kfileitemactions.h>
25 #include <kpushbutton.h>
26 #include <kmenu.h>
27 #include <ksqueezedtextlabel.h>
28 #include <knotification.h>
29 #include <kdialog.h>
30 #include <kmimetypetrader.h>
31 #include <kstandardguiitem.h>
32 #include <kguiitem.h>
33 #include <kmessagebox.h>
34 #include <kmimetype.h>
35 #include <QStyle>
36 #include <QStyleOption>
37 #include <QVBoxLayout>
38 #include <QCheckBox>
39 #include <QLabel>
40 
41 using namespace KParts;
42 Q_DECLARE_METATYPE(KService::Ptr)
43 
44 class KParts::BrowserOpenOrSaveQuestionPrivate : public KDialog
45 {
46  Q_OBJECT
47 public:
48  // Mapping to KDialog button codes
49  static const KDialog::ButtonCode Save = KDialog::Yes;
50  static const KDialog::ButtonCode OpenDefault = KDialog::User2;
51  static const KDialog::ButtonCode OpenWith = KDialog::User1;
52  static const KDialog::ButtonCode Cancel = KDialog::Cancel;
53 
54  BrowserOpenOrSaveQuestionPrivate(QWidget* parent, const KUrl& url, const QString& mimeType)
55  : KDialog(parent), url(url), mimeType(mimeType),
56  features(0)
57  {
58  // Use askSave or askEmbedOrSave from filetypesrc
59  dontAskConfig = KSharedConfig::openConfig("filetypesrc", KConfig::NoGlobals);
60 
61  setCaption(url.host());
62  setButtons(Save | OpenDefault | OpenWith | Cancel);
63  setObjectName("questionYesNoCancel");
64  setButtonGuiItem(Save, KStandardGuiItem::saveAs());
65  setButtonGuiItem(Cancel, KStandardGuiItem::cancel());
66  setDefaultButton(Save);
67 
68  QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget());
69  mainLayout->setSpacing(KDialog::spacingHint() * 2); // provide extra spacing
70  mainLayout->setMargin(0);
71 
72  QHBoxLayout *hLayout = new QHBoxLayout();
73  hLayout->setMargin(0);
74  hLayout->setSpacing(-1); // use default spacing
75  mainLayout->addLayout(hLayout, 5);
76 
77  QLabel *iconLabel = new QLabel(mainWidget());
78  QStyleOption option;
79  option.initFrom(this);
80  KIcon icon("dialog-information");
81  iconLabel->setPixmap(icon.pixmap(style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, this)));
82 
83  hLayout->addWidget(iconLabel, 0, Qt::AlignCenter);
84  hLayout->addSpacing(KDialog::spacingHint());
85 
86  QVBoxLayout* textVLayout = new QVBoxLayout;
87  questionLabel = new KSqueezedTextLabel(mainWidget());
88  textVLayout->addWidget(questionLabel);
89 
90  fileNameLabel = new QLabel(mainWidget());
91  fileNameLabel->hide();
92  textVLayout->addWidget(fileNameLabel);
93 
94  mime = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
95  QString mimeDescription (mimeType);
96  if (mime) {
97  // Always prefer the mime-type comment over the raw type for display
98  mimeDescription = (mime->comment().isEmpty() ? mime->name() : mime->comment());
99  }
100  QLabel* mimeTypeLabel = new QLabel(mainWidget());
101  mimeTypeLabel->setText(i18nc("@label Type of file", "Type: %1", mimeDescription));
102  mimeTypeLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
103  textVLayout->addWidget(mimeTypeLabel);
104 
105  hLayout->addLayout(textVLayout,5);
106 
107  mainLayout->addStretch(15);
108  dontAskAgainCheckBox = new QCheckBox(mainWidget());
109  dontAskAgainCheckBox->setText(i18nc("@label:checkbox", "Remember action for files of this type"));
110  mainLayout->addWidget(dontAskAgainCheckBox);
111  }
112 
113  bool autoEmbedMimeType(int flags);
114 
115  int executeDialog(const QString& dontShowAgainName)
116  {
117  KConfigGroup cg(dontAskConfig, "Notification Messages"); // group name comes from KMessageBox
118  const QString dontAsk = cg.readEntry(dontShowAgainName, QString()).toLower();
119  if (dontAsk == "yes" || dontAsk == "true") {
120  return Save;
121  } else if (dontAsk == "no" || dontAsk == "false") {
122  return OpenDefault;
123  }
124 
125  KNotification::event("messageQuestion", // why does KMessageBox uses Information for questionYesNoCancel?
126  questionLabel->text(), // also include mimetype?
127  QPixmap(),
128  window());
129  const int result = exec();
130 
131  if (dontAskAgainCheckBox->isChecked()) {
132  cg.writeEntry(dontShowAgainName, result == Save);
133  cg.sync();
134  }
135  return result;
136  }
137 
138  void showService(KService::Ptr selectedService)
139  {
140  KGuiItem openItem(i18nc("@label:button", "&Open with %1", selectedService->name()), selectedService->icon());
141  setButtonGuiItem(OpenWith, openItem);
142  }
143 
144  KUrl url;
145  QString mimeType;
146  KMimeType::Ptr mime;
147  KService::Ptr selectedService;
148  KSqueezedTextLabel* questionLabel;
149  BrowserOpenOrSaveQuestion::Features features;
150  QLabel* fileNameLabel;
151 
152 protected:
153  virtual void slotButtonClicked(int buttonId)
154  {
155  if (buttonId != OpenDefault)
156  selectedService = 0;
157  KPushButton* button = KDialog::button(KDialog::ButtonCode(buttonId));
158  if (button && !button->menu()) {
159  done(buttonId);
160  }
161  }
162 private:
163  QCheckBox* dontAskAgainCheckBox;
164  KSharedConfig::Ptr dontAskConfig;
165 
166 public Q_SLOTS:
167  void slotAppSelected(QAction* action)
168  {
169  selectedService = action->data().value<KService::Ptr>();
170  //showService(selectedService);
171  done(OpenDefault);
172  }
173 };
174 
175 
176 BrowserOpenOrSaveQuestion::BrowserOpenOrSaveQuestion(QWidget* parent, const KUrl& url, const QString& mimeType)
177  : d(new BrowserOpenOrSaveQuestionPrivate(parent, url, mimeType))
178 {
179 }
180 
181 BrowserOpenOrSaveQuestion::~BrowserOpenOrSaveQuestion()
182 {
183  delete d;
184 }
185 
186 static KAction* createAppAction(const KService::Ptr& service, QObject* parent)
187 {
188  QString actionName(service->name().replace('&', "&&"));
189  actionName = i18nc("@action:inmenu", "Open &with %1", actionName);
190 
191  KAction *act = new KAction(parent);
192  act->setIcon(KIcon(service->icon()));
193  act->setText(actionName);
194  act->setData(QVariant::fromValue(service));
195  return act;
196 }
197 
198 BrowserOpenOrSaveQuestion::Result BrowserOpenOrSaveQuestion::askOpenOrSave()
199 {
200  d->questionLabel->setText(i18nc("@info", "Open '%1'?", d->url.pathOrUrl()));
201  d->questionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
202  d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, false);
203 
204  KGuiItem openWithDialogItem(i18nc("@label:button", "&Open with..."), "document-open");
205 
206  // I thought about using KFileItemActions, but we don't want a submenu, nor the slots....
207  // and we want no menu at all if there's only one offer.
208  // TODO: we probably need a setTraderConstraint(), to exclude the current application?
209  const KService::List apps = KFileItemActions::associatedApplications(QStringList() << d->mimeType,
210  QString() /* TODO trader constraint */);
211  if (apps.isEmpty()) {
212  d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, openWithDialogItem);
213  } else {
214  KService::Ptr offer = apps.first();
215  KGuiItem openItem(i18nc("@label:button", "&Open with %1", offer->name()), offer->icon());
216  d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, openItem);
217  if (d->features & ServiceSelection) {
218  // OpenDefault shall use this service
219  d->selectedService = apps.first();
220  d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, true);
221  KMenu* menu = new KMenu(d);
222  if (apps.count() > 1) {
223  // Provide an additional button with a menu of associated apps
224  KGuiItem openWithItem(i18nc("@label:button", "&Open with"), "document-open");
225  d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenWith, openWithItem);
226  d->setButtonMenu(BrowserOpenOrSaveQuestionPrivate::OpenWith, menu, KDialog::InstantPopup);
227  QObject::connect(menu, SIGNAL(triggered(QAction*)), d, SLOT(slotAppSelected(QAction*)));
228  for (KService::List::const_iterator it = apps.begin(); it != apps.end(); ++it) {
229  KAction* act = createAppAction(*it, d);
230  menu->addAction(act);
231  }
232  KAction* openWithDialogAction = new KAction(d);
233  openWithDialogAction->setIcon(KIcon("document-open"));
234  openWithDialogAction->setText(openWithDialogItem.text());
235  menu->addAction(openWithDialogAction);
236  } else {
237  // Only one associated app, already offered by the other menu -> add "Open With..." button
238  d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenWith, openWithDialogItem);
239  }
240  } else {
241  kDebug() << "Not using new feature ServiceSelection; port the caller to BrowserOpenOrSaveQuestion::setFeature(ServiceSelection)";
242  //kDebug() << kBacktrace();
243  }
244  }
245 
246  // KEEP IN SYNC with kdebase/runtime/keditfiletype/filetypedetails.cpp!!!
247  const QString dontAskAgain = QLatin1String("askSave") + d->mimeType;
248 
249  const int choice = d->executeDialog(dontAskAgain);
250  return choice == BrowserOpenOrSaveQuestionPrivate::Save ? Save
251  : (choice == BrowserOpenOrSaveQuestionPrivate::Cancel ? Cancel : Open);
252 }
253 
254 KService::Ptr BrowserOpenOrSaveQuestion::selectedService() const
255 {
256  return d->selectedService;
257 }
258 
259 bool BrowserOpenOrSaveQuestionPrivate::autoEmbedMimeType(int flags)
260 {
261  // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
262  // NOTE: Keep this function in sync with
263  // kdebase/runtime/keditfiletype/filetypedetails.cpp
264  // FileTypeDetails::updateAskSave()
265 
266  // Don't ask for:
267  // - html (even new tabs would ask, due to about:blank!)
268  // - dirs obviously (though not common over HTTP :),
269  // - images (reasoning: no need to save, most of the time, because fast to see)
270  // e.g. postscript is different, because takes longer to read, so
271  // it's more likely that the user might want to save it.
272  // - multipart/* ("server push", see kmultipart)
273  // KEEP IN SYNC!!!
274  if (flags != (int)BrowserRun::AttachmentDisposition && mime && (
275  mime->is("text/html") ||
276  mime->is("application/xml") ||
277  mime->is("inode/directory") ||
278  mimeType.startsWith(QLatin1String("image")) ||
279  mime->is("multipart/x-mixed-replace") ||
280  mime->is("multipart/replace")))
281  return true;
282  return false;
283 }
284 
285 BrowserOpenOrSaveQuestion::Result BrowserOpenOrSaveQuestion::askEmbedOrSave(int flags)
286 {
287  if (d->autoEmbedMimeType(flags))
288  return Embed;
289 
290  // don't use KStandardGuiItem::open() here which has trailing ellipsis!
291  d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, KGuiItem(i18nc("@label:button", "&Open"), "document-open"));
292  d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, false);
293 
294  d->questionLabel->setText(i18nc("@info", "Open '%1'?", d->url.pathOrUrl()));
295  d->questionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
296 
297  const QString dontAskAgain = QLatin1String("askEmbedOrSave")+ d->mimeType; // KEEP IN SYNC!!!
298  // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
299 
300  const int choice = d->executeDialog(dontAskAgain);
301  return choice == BrowserOpenOrSaveQuestionPrivate::Save ? Save
302  : (choice == BrowserOpenOrSaveQuestionPrivate::Cancel ? Cancel : Embed);
303 }
304 
305 void BrowserOpenOrSaveQuestion::setFeatures(Features features)
306 {
307  d->features = features;
308 }
309 
310 void BrowserOpenOrSaveQuestion::setSuggestedFileName(const QString& suggestedFileName)
311 {
312  if (suggestedFileName.isEmpty()) {
313  return;
314  }
315 
316  d->fileNameLabel->setText(i18nc("@label File name", "Name: %1", suggestedFileName));
317  d->fileNameLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
318  d->fileNameLabel->setWhatsThis(i18nc("@info:whatsthis", "This is the file name suggested by the server"));
319  d->fileNameLabel->show();
320 }
321 
322 #include "browseropenorsavequestion.moc"
QAction::setText
void setText(const QString &text)
KStandardGuiItem::cancel
KGuiItem cancel()
kdialog.h
KSharedPtr
KPushButton
QWidget
kdebug.h
kmimetype.h
QAction::data
QVariant data() const
KMenu
KParts::BrowserOpenOrSaveQuestion::Result
Result
Definition: browseropenorsavequestion.h:74
QLabel::setPixmap
void setPixmap(const QPixmap &)
QAction::setIcon
void setIcon(const QIcon &icon)
QUrl::host
QString host() const
QMenu::addAction
void addAction(QAction *action)
KParts::BrowserOpenOrSaveQuestion::setSuggestedFileName
void setSuggestedFileName(const QString &suggestedFileName)
Sets the suggested filename, shown in the dialog.
Definition: browseropenorsavequestion.cpp:310
kstandardguiitem.h
QHBoxLayout
QVariant::value
T value() const
createAppAction
static KAction * createAppAction(const KService::Ptr &service, QObject *parent)
Definition: browseropenorsavequestion.cpp:186
KDialog
QBoxLayout::addSpacing
void addSpacing(int size)
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KUrl
browseropenorsavequestion.h
i18nc
QString i18nc(const char *ctxt, const char *text)
QStyleOption::initFrom
void initFrom(const QWidget *widget)
knotification.h
QStyleOption
KParts::BrowserOpenOrSaveQuestion::setFeatures
void setFeatures(Features features)
Enables the given features in the dialog.
Definition: browseropenorsavequestion.cpp:305
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QList::count
int count(const T &value) const
KParts::BrowserOpenOrSaveQuestion::askOpenOrSave
Result askOpenOrSave()
Ask the user whether to save or open a url in another application.
Definition: browseropenorsavequestion.cpp:198
KConfig::NoGlobals
KStandardGuiItem::saveAs
KGuiItem saveAs()
kmenu.h
QObject
QCheckBox
KGuiItem
KParts::BrowserOpenOrSaveQuestion::~BrowserOpenOrSaveQuestion
~BrowserOpenOrSaveQuestion()
Definition: browseropenorsavequestion.cpp:181
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
KParts::BrowserOpenOrSaveQuestion::BrowserOpenOrSaveQuestion
BrowserOpenOrSaveQuestion(QWidget *parent, const KUrl &url, const QString &mimeType)
Constructor, for all kinds of dialogs shown in this class.
Definition: browseropenorsavequestion.cpp:176
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
kmimetypetrader.h
KIcon
QVBoxLayout
QList::first
T & first()
QLabel::setText
void setText(const QString &)
QString
QList< Ptr >
QLayout::setMargin
void setMargin(int margin)
Save
QStringList
KSqueezedTextLabel
QPixmap
QAction::setData
void setData(const QVariant &userData)
kaction.h
QList::end
iterator end()
QString::toLower
QString toLower() const
KService::icon
QString icon() const
KParts::BrowserOpenOrSaveQuestion::Embed
Definition: browseropenorsavequestion.h:74
kpushbutton.h
Cancel
QVariant::fromValue
QVariant fromValue(const T &value)
ksqueezedtextlabel.h
KConfigGroup
QLabel::setTextInteractionFlags
void setTextInteractionFlags(QFlags< Qt::TextInteractionFlag > flags)
KNotification::event
static KNotification * event(const QString &eventId, const QString &title, const QString &text, const QPixmap &pixmap=QPixmap(), QWidget *widget=0L, const NotificationFlags &flags=CloseOnTimeout, const KComponentData &componentData=KComponentData())
KParts::BrowserOpenOrSaveQuestion::askEmbedOrSave
Result askEmbedOrSave(int flags=0)
Ask the user whether to save or open a url in another application.
Definition: browseropenorsavequestion.cpp:285
KFileItemActions::associatedApplications
static KService::List associatedApplications(const QStringList &mimeTypeList, const QString &traderConstraint)
KParts::BrowserRun::AttachmentDisposition
Definition: browserrun.h:98
QLatin1String
QBoxLayout::addStretch
void addStretch(int stretch)
QAction
KAction
KParts::BrowserOpenOrSaveQuestion::selectedService
KService::Ptr selectedService() const
Definition: browseropenorsavequestion.cpp:254
kfileitemactions.h
QPushButton::menu
QMenu * menu() const
KGuiItem::text
QString text() const
KSharedConfig::openConfig
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, const char *resourceType="config")
kmessagebox.h
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QLabel
kguiitem.h
KParts::BrowserOpenOrSaveQuestion::ServiceSelection
Shows "Open With..." with the associated applications for the mimetype.
Definition: browseropenorsavequestion.h:65
KParts::BrowserOpenOrSaveQuestion::Open
Definition: browseropenorsavequestion.h:74
QList::begin
iterator begin()
QBoxLayout::setSpacing
void setSpacing(int spacing)
QBoxLayout::addLayout
void addLayout(QLayout *layout, int stretch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:25:36 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KParts

Skip menu "KParts"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal