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

KParts

browseropenorsavequestion.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009, 2010 David Faure <faure@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as published by
00006     the Free Software Foundation; either version 2 of the License or ( at
00007     your option ) version 3 or, at the discretion of KDE e.V. ( which shall
00008     act as a proxy as in section 14 of the GPLv3 ), any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "browseropenorsavequestion.h"
00022 #include <kdebug.h>
00023 #include <kaction.h>
00024 #include <kfileitemactions.h>
00025 #include <kpushbutton.h>
00026 #include <kmenu.h>
00027 #include <ksqueezedtextlabel.h>
00028 #include <knotification.h>
00029 #include <kdialog.h>
00030 #include <kmimetypetrader.h>
00031 #include <kstandardguiitem.h>
00032 #include <kguiitem.h>
00033 #include <kmessagebox.h>
00034 #include <kmimetype.h>
00035 #include <QStyle>
00036 #include <QStyleOption>
00037 #include <QVBoxLayout>
00038 #include <QCheckBox>
00039 #include <QLabel>
00040 
00041 using namespace KParts;
00042 Q_DECLARE_METATYPE(KService::Ptr)
00043 
00044 class KParts::BrowserOpenOrSaveQuestionPrivate : public KDialog
00045 {
00046     Q_OBJECT
00047 public:
00048     // Mapping to KDialog button codes
00049     static const KDialog::ButtonCode Save = KDialog::Yes;
00050     static const KDialog::ButtonCode OpenDefault = KDialog::User2;
00051     static const KDialog::ButtonCode OpenWith = KDialog::User1;
00052     static const KDialog::ButtonCode Cancel = KDialog::Cancel;
00053         
00054     BrowserOpenOrSaveQuestionPrivate(QWidget* parent, const KUrl& url, const QString& mimeType)
00055         : KDialog(parent), url(url), mimeType(mimeType),
00056           features(0)
00057     {
00058         // Use askSave or askEmbedOrSave from filetypesrc
00059         dontAskConfig = KSharedConfig::openConfig("filetypesrc", KConfig::NoGlobals);
00060 
00061         setCaption(url.host());
00062         setButtons(Save | OpenDefault | OpenWith | Cancel);
00063         setObjectName("questionYesNoCancel");
00064         setButtonGuiItem(Save, KStandardGuiItem::saveAs());
00065         setButtonGuiItem(Cancel, KStandardGuiItem::cancel());
00066         setDefaultButton(Save);
00067 
00068         QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget());
00069         mainLayout->setSpacing(KDialog::spacingHint() * 2); // provide extra spacing
00070         mainLayout->setMargin(0);
00071 
00072         QHBoxLayout *hLayout = new QHBoxLayout();
00073         hLayout->setMargin(0);
00074         hLayout->setSpacing(-1); // use default spacing
00075         mainLayout->addLayout(hLayout, 5);
00076 
00077         QLabel *iconLabel = new QLabel(mainWidget());
00078         QStyleOption option;
00079         option.initFrom(this);
00080         KIcon icon("dialog-information");
00081         iconLabel->setPixmap(icon.pixmap(style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, this)));
00082 
00083         hLayout->addWidget(iconLabel, 0, Qt::AlignCenter);
00084         hLayout->addSpacing(KDialog::spacingHint());
00085 
00086         QVBoxLayout* textVLayout = new QVBoxLayout;
00087         questionLabel = new KSqueezedTextLabel(mainWidget());
00088         textVLayout->addWidget(questionLabel);
00089 
00090         fileNameLabel = new QLabel(mainWidget());
00091         fileNameLabel->hide();
00092         textVLayout->addWidget(fileNameLabel);
00093 
00094         mime = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
00095         QString mimeDescription = mimeType;
00096         if (mime) { // The mime-type is known so display the comment instead of mime-type
00097             mimeDescription = mime->comment();
00098         }
00099         QLabel* mimeTypeLabel = new QLabel(mainWidget());
00100         mimeTypeLabel->setText(i18nc("@label Type of file", "Type: %1", mimeDescription));
00101         mimeTypeLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
00102         textVLayout->addWidget(mimeTypeLabel);
00103 
00104         hLayout->addLayout(textVLayout,5);
00105 
00106         mainLayout->addStretch(15);
00107         dontAskAgainCheckBox = new QCheckBox(mainWidget());
00108         dontAskAgainCheckBox->setText(i18nc("@label:checkbox", "Remember action for files of this type"));
00109         mainLayout->addWidget(dontAskAgainCheckBox);
00110     }
00111 
00112     bool autoEmbedMimeType(int flags);
00113 
00114     int executeDialog(const QString& dontShowAgainName)
00115     {
00116         KConfigGroup cg(dontAskConfig, "Notification Messages"); // group name comes from KMessageBox
00117         const QString dontAsk = cg.readEntry(dontShowAgainName, QString()).toLower();
00118         if (dontAsk == "yes" || dontAsk == "true") {
00119             return Save;
00120         } else if (dontAsk == "no" || dontAsk == "false") {
00121             return OpenDefault;
00122         }
00123 
00124         KNotification::event("messageQuestion", // why does KMessageBox uses Information for questionYesNoCancel?
00125                              questionLabel->text(), // also include mimetype?
00126                              QPixmap(),
00127                              window());
00128         const int result = exec();
00129 
00130         if (dontAskAgainCheckBox->isChecked()) {
00131             cg.writeEntry(dontShowAgainName, result == Save);
00132             cg.sync();
00133         }
00134         return result;
00135     }
00136 
00137     void showService(KService::Ptr selectedService)
00138     {
00139         KGuiItem openItem(i18nc("@label:button", "&Open with %1", selectedService->name()), selectedService->icon());
00140         setButtonGuiItem(OpenWith, openItem);
00141     }
00142 
00143     KUrl url;
00144     QString mimeType;
00145     KMimeType::Ptr mime;
00146     KService::Ptr selectedService;
00147     KSqueezedTextLabel* questionLabel;
00148     BrowserOpenOrSaveQuestion::Features features;
00149     QLabel* fileNameLabel;
00150 
00151 protected:
00152     virtual void slotButtonClicked(int buttonId)
00153     {
00154         if (buttonId != OpenDefault)
00155             selectedService = 0;
00156         KPushButton* button = KDialog::button(KDialog::ButtonCode(buttonId));
00157         if (button && !button->menu()) {
00158             done(buttonId);
00159         }
00160     }
00161 private:
00162     QCheckBox* dontAskAgainCheckBox;
00163     KSharedConfig::Ptr dontAskConfig;
00164 
00165 public Q_SLOTS:
00166     void slotAppSelected(QAction* action)
00167     {
00168         selectedService = action->data().value<KService::Ptr>();
00169         //showService(selectedService);
00170         done(OpenDefault);
00171     }
00172 };
00173 
00174 
00175 BrowserOpenOrSaveQuestion::BrowserOpenOrSaveQuestion(QWidget* parent, const KUrl& url, const QString& mimeType)
00176     : d(new BrowserOpenOrSaveQuestionPrivate(parent, url, mimeType))
00177 {
00178 }
00179 
00180 BrowserOpenOrSaveQuestion::~BrowserOpenOrSaveQuestion()
00181 {
00182     delete d;
00183 }
00184 
00185 static KAction* createAppAction(const KService::Ptr& service, QObject* parent)
00186 {
00187     QString actionName(service->name().replace('&', "&&"));
00188     actionName = i18nc("@action:inmenu", "Open &with %1", actionName);
00189 
00190     KAction *act = new KAction(parent);
00191     act->setIcon(KIcon(service->icon()));
00192     act->setText(actionName);
00193     act->setData(QVariant::fromValue(service));
00194     return act;
00195 }
00196 
00197 BrowserOpenOrSaveQuestion::Result BrowserOpenOrSaveQuestion::askOpenOrSave()
00198 {
00199     d->questionLabel->setText(i18nc("@info", "Open '%1'?", d->url.pathOrUrl()));
00200     d->questionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
00201     d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, false);
00202 
00203     KGuiItem openWithDialogItem(i18nc("@label:button", "&Open with..."), "document-open");
00204 
00205     // I thought about using KFileItemActions, but we don't want a submenu, nor the slots....
00206     // and we want no menu at all if there's only one offer.
00207     // TODO: we probably need a setTraderConstraint(), to exclude the current application?
00208     const KService::List apps = KFileItemActions::associatedApplications(QStringList() << d->mimeType,
00209                                                                          QString() /* TODO trader constraint */);
00210     if (apps.isEmpty()) {
00211         d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, openWithDialogItem);
00212     } else {
00213         KService::Ptr offer = apps.first();
00214         KGuiItem openItem(i18nc("@label:button", "&Open with %1", offer->name()), offer->icon());
00215         d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, openItem);
00216         if (d->features & ServiceSelection) {
00217             // OpenDefault shall use this service
00218             d->selectedService = apps.first();
00219             d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, true);
00220             KMenu* menu = new KMenu(d);
00221             if (apps.count() > 1) {
00222                 // Provide an additional button with a menu of associated apps
00223                 KGuiItem openWithItem(i18nc("@label:button", "&Open with"), "document-open");
00224                 d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenWith, openWithItem);
00225                 d->setButtonMenu(BrowserOpenOrSaveQuestionPrivate::OpenWith, menu, KDialog::InstantPopup);
00226                 QObject::connect(menu, SIGNAL(triggered(QAction*)), d, SLOT(slotAppSelected(QAction*)));
00227                 for (KService::List::const_iterator it = apps.begin(); it != apps.end(); ++it) {
00228                     KAction* act = createAppAction(*it, d);
00229                     menu->addAction(act);
00230                 }
00231                 KAction* openWithDialogAction = new KAction(d);
00232                 openWithDialogAction->setIcon(KIcon("document-open"));
00233                 openWithDialogAction->setText(openWithDialogItem.text());
00234                 menu->addAction(openWithDialogAction);
00235             } else {
00236                 // Only one associated app, already offered by the other menu -> add "Open With..." button
00237                 d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenWith, openWithDialogItem);
00238             }
00239         } else {
00240             kDebug() << "Not using new feature ServiceSelection; port the caller to BrowserOpenOrSaveQuestion::setFeature(ServiceSelection)";
00241             //kDebug() << kBacktrace();
00242         }
00243     }
00244 
00245     // KEEP IN SYNC with kdebase/runtime/keditfiletype/filetypedetails.cpp!!!
00246     const QString dontAskAgain = QLatin1String("askSave") + d->mimeType;
00247 
00248     const int choice = d->executeDialog(dontAskAgain);
00249     return choice == BrowserOpenOrSaveQuestionPrivate::Save ? Save
00250         : (choice == BrowserOpenOrSaveQuestionPrivate::Cancel ? Cancel : Open);
00251 }
00252 
00253 KService::Ptr BrowserOpenOrSaveQuestion::selectedService() const
00254 {
00255     return d->selectedService;
00256 }
00257 
00258 bool BrowserOpenOrSaveQuestionPrivate::autoEmbedMimeType(int flags)
00259 {
00260     // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
00261     // NOTE: Keep this function in sync with
00262     // kdebase/runtime/keditfiletype/filetypedetails.cpp
00263     //       FileTypeDetails::updateAskSave()
00264 
00265     // Don't ask for:
00266     // - html (even new tabs would ask, due to about:blank!)
00267     // - dirs obviously (though not common over HTTP :),
00268     // - images (reasoning: no need to save, most of the time, because fast to see)
00269     // e.g. postscript is different, because takes longer to read, so
00270     // it's more likely that the user might want to save it.
00271     // - multipart/* ("server push", see kmultipart)
00272     // KEEP IN SYNC!!!
00273     if (flags != (int)BrowserRun::AttachmentDisposition && mime && (
00274             mime->is("text/html") ||
00275             mime->is("application/xml") ||
00276             mime->is("inode/directory") ||
00277             mimeType.startsWith(QLatin1String("image")) ||
00278             mime->is("multipart/x-mixed-replace") ||
00279             mime->is("multipart/replace")))
00280         return true;
00281     return false;
00282 }
00283 
00284 BrowserOpenOrSaveQuestion::Result BrowserOpenOrSaveQuestion::askEmbedOrSave(int flags)
00285 {
00286     if (d->autoEmbedMimeType(flags))
00287         return Embed;
00288 
00289     // don't use KStandardGuiItem::open() here which has trailing ellipsis!
00290     d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, KGuiItem(i18nc("@label:button", "&Open"), "document-open"));
00291     d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, false);
00292 
00293     d->questionLabel->setText(i18nc("@info", "Open '%1'?", d->url.pathOrUrl()));
00294     d->questionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
00295 
00296     const QString dontAskAgain = QLatin1String("askEmbedOrSave")+ d->mimeType; // KEEP IN SYNC!!!
00297     // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
00298 
00299     const int choice = d->executeDialog(dontAskAgain);
00300     return choice == BrowserOpenOrSaveQuestionPrivate::Save ? Save
00301         : (choice == BrowserOpenOrSaveQuestionPrivate::Cancel ? Cancel : Embed);
00302 }
00303 
00304 void BrowserOpenOrSaveQuestion::setFeatures(Features features)
00305 {
00306     d->features = features;
00307 }
00308 
00309 void BrowserOpenOrSaveQuestion::setSuggestedFileName(const QString& suggestedFileName)
00310 {
00311     if (suggestedFileName.isEmpty()) {
00312         return;
00313     }
00314 
00315     d->fileNameLabel->setText(i18nc("@label File name", "Name: %1", suggestedFileName));
00316     d->fileNameLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
00317     d->fileNameLabel->setWhatsThis(i18nc("@info:whatsthis", "This is the file name suggested by the server"));
00318     d->fileNameLabel->show();
00319 
00320     // If the current mime-type is the default mime-type, then attempt to
00321     // determine the "real" mimetype from the file name.
00322     if (d->mimeType == KMimeType::defaultMimeType()) {
00323         const KMimeType::Ptr mimePtr = KMimeType::findByUrl(suggestedFileName);
00324         d->mimeType = mimePtr->name();
00325     }
00326 }
00327 
00328 #include "browseropenorsavequestion.moc"

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

Skip menu "kdelibs"
  • 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
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal