• Skip to content
  • Skip to link menu
KDE 4.6 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         textVLayout->addWidget(mimeTypeLabel);
00102 
00103         hLayout->addLayout(textVLayout,5);
00104 
00105         mainLayout->addStretch(15);
00106         dontAskAgainCheckBox = new QCheckBox(mainWidget());
00107         dontAskAgainCheckBox->setText(i18nc("@label:checkbox", "Remember action for files of this type"));
00108         mainLayout->addWidget(dontAskAgainCheckBox);
00109     }
00110 
00111     bool autoEmbedMimeType(int flags);
00112 
00113     int executeDialog(const QString& dontShowAgainName)
00114     {
00115         KConfigGroup cg(dontAskConfig, "Notification Messages"); // group name comes from KMessageBox
00116         const QString dontAsk = cg.readEntry(dontShowAgainName, QString()).toLower();
00117         if (dontAsk == "yes" || dontAsk == "true") {
00118             return Save;
00119         } else if (dontAsk == "no" || dontAsk == "false") {
00120             return OpenDefault;
00121         }
00122 
00123         KNotification::event("messageQuestion", // why does KMessageBox uses Information for questionYesNoCancel?
00124                              questionLabel->text(), // also include mimetype?
00125                              QPixmap(),
00126                              window());
00127         const int result = exec();
00128 
00129         if (dontAskAgainCheckBox->isChecked()) {
00130             cg.writeEntry(dontShowAgainName, result == Save);
00131             cg.sync();
00132         }
00133         return result;
00134     }
00135 
00136     void showService(KService::Ptr selectedService)
00137     {
00138         KGuiItem openItem(i18nc("@label:button", "&Open with %1", selectedService->name()), selectedService->icon());
00139         setButtonGuiItem(OpenWith, openItem);
00140     }
00141 
00142     KUrl url;
00143     QString mimeType;
00144     KMimeType::Ptr mime;
00145     KService::Ptr selectedService;
00146     KSqueezedTextLabel* questionLabel;
00147     BrowserOpenOrSaveQuestion::Features features;
00148     QLabel* fileNameLabel;
00149 
00150 protected:
00151     virtual void slotButtonClicked(int buttonId)
00152     {
00153         if (buttonId != OpenDefault)
00154             selectedService = 0;
00155         KPushButton* button = KDialog::button(KDialog::ButtonCode(buttonId));
00156         if (button && !button->menu()) {
00157             done(buttonId);
00158         }
00159     }
00160 private:
00161     QCheckBox* dontAskAgainCheckBox;
00162     KSharedConfig::Ptr dontAskConfig;
00163 
00164 public Q_SLOTS:
00165     void slotAppSelected(QAction* action)
00166     {
00167         selectedService = action->data().value<KService::Ptr>();
00168         //showService(selectedService);
00169         done(OpenDefault);
00170     }
00171 };
00172 
00173 
00174 BrowserOpenOrSaveQuestion::BrowserOpenOrSaveQuestion(QWidget* parent, const KUrl& url, const QString& mimeType)
00175     : d(new BrowserOpenOrSaveQuestionPrivate(parent, url, mimeType))
00176 {
00177 }
00178 
00179 BrowserOpenOrSaveQuestion::~BrowserOpenOrSaveQuestion()
00180 {
00181     delete d;
00182 }
00183 
00184 static KAction* createAppAction(const KService::Ptr& service, QObject* parent)
00185 {
00186     QString actionName(service->name().replace('&', "&&"));
00187     actionName = i18nc("@action:inmenu", "Open &with %1", actionName);
00188 
00189     KAction *act = new KAction(parent);
00190     act->setIcon(KIcon(service->icon()));
00191     act->setText(actionName);
00192     act->setData(QVariant::fromValue(service));
00193     return act;
00194 }
00195 
00196 BrowserOpenOrSaveQuestion::Result BrowserOpenOrSaveQuestion::askOpenOrSave()
00197 {
00198     d->questionLabel->setText(i18nc("@info", "Open '%1'?", d->url.pathOrUrl()));
00199     d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, false);
00200 
00201     KGuiItem openWithDialogItem(i18nc("@label:button", "&Open with..."), "document-open");
00202 
00203     // I thought about using KFileItemActions, but we don't want a submenu, nor the slots....
00204     // and we want no menu at all if there's only one offer.
00205     // TODO: we probably need a setTraderConstraint(), to exclude the current application?
00206     const KService::List apps = KFileItemActions::associatedApplications(QStringList() << d->mimeType,
00207                                                                          QString() /* TODO trader constraint */);
00208     if (apps.isEmpty()) {
00209         d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, openWithDialogItem);
00210     } else {
00211         KService::Ptr offer = apps.first();
00212         KGuiItem openItem(i18nc("@label:button", "&Open with %1", offer->name()), offer->icon());
00213         d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, openItem);
00214         if (d->features & ServiceSelection) {
00215             // OpenDefault shall use this service
00216             d->selectedService = apps.first();
00217             d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, true);
00218             KMenu* menu = new KMenu(d);
00219             if (apps.count() > 1) {
00220                 // Provide an additional button with a menu of associated apps
00221                 KGuiItem openWithItem(i18nc("@label:button", "&Open with"), "document-open");
00222                 d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenWith, openWithItem);
00223                 d->setButtonMenu(BrowserOpenOrSaveQuestionPrivate::OpenWith, menu, KDialog::InstantPopup);
00224                 QObject::connect(menu, SIGNAL(triggered(QAction*)), d, SLOT(slotAppSelected(QAction*)));
00225                 for (KService::List::const_iterator it = apps.begin(); it != apps.end(); ++it) {
00226                     KAction* act = createAppAction(*it, d);
00227                     menu->addAction(act);
00228                 }
00229                 KAction* openWithDialogAction = new KAction(d);
00230                 openWithDialogAction->setIcon(KIcon("document-open"));
00231                 openWithDialogAction->setText(openWithDialogItem.text());
00232                 menu->addAction(openWithDialogAction);
00233             } else {
00234                 // Only one associated app, already offered by the other menu -> add "Open With..." button
00235                 d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenWith, openWithDialogItem);
00236             }
00237         } else {
00238             kDebug() << "Not using new feature ServiceSelection; port the caller to BrowserOpenOrSaveQuestion::setFeature(ServiceSelection)";
00239             //kDebug() << kBacktrace();
00240         }
00241     }
00242 
00243     // KEEP IN SYNC with kdebase/runtime/keditfiletype/filetypedetails.cpp!!!
00244     const QString dontAskAgain = QLatin1String("askSave") + d->mimeType;
00245 
00246     const int choice = d->executeDialog(dontAskAgain);
00247     return choice == BrowserOpenOrSaveQuestionPrivate::Save ? Save
00248         : (choice == BrowserOpenOrSaveQuestionPrivate::Cancel ? Cancel : Open);
00249 }
00250 
00251 KService::Ptr BrowserOpenOrSaveQuestion::selectedService() const
00252 {
00253     return d->selectedService;
00254 }
00255 
00256 bool BrowserOpenOrSaveQuestionPrivate::autoEmbedMimeType(int flags)
00257 {
00258     // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
00259     // NOTE: Keep this function in sync with
00260     // kdebase/runtime/keditfiletype/filetypedetails.cpp
00261     //       FileTypeDetails::updateAskSave()
00262 
00263     // Don't ask for:
00264     // - html (even new tabs would ask, due to about:blank!)
00265     // - dirs obviously (though not common over HTTP :),
00266     // - images (reasoning: no need to save, most of the time, because fast to see)
00267     // e.g. postscript is different, because takes longer to read, so
00268     // it's more likely that the user might want to save it.
00269     // - multipart/* ("server push", see kmultipart)
00270     // KEEP IN SYNC!!!
00271     if (flags != (int)BrowserRun::AttachmentDisposition && mime && (
00272             mime->is("text/html") ||
00273             mime->is("application/xml") ||
00274             mime->is("inode/directory") ||
00275             mimeType.startsWith(QLatin1String("image")) ||
00276             mime->is("multipart/x-mixed-replace") ||
00277             mime->is("multipart/replace")))
00278         return true;
00279     return false;
00280 }
00281 
00282 BrowserOpenOrSaveQuestion::Result BrowserOpenOrSaveQuestion::askEmbedOrSave(int flags)
00283 {
00284     if (d->autoEmbedMimeType(flags))
00285         return Embed;
00286 
00287     // don't use KStandardGuiItem::open() here which has trailing ellipsis!
00288     d->setButtonGuiItem(BrowserOpenOrSaveQuestionPrivate::OpenDefault, KGuiItem(i18nc("@label:button", "&Open"), "document-open"));
00289     d->showButton(BrowserOpenOrSaveQuestionPrivate::OpenWith, false);
00290 
00291     d->questionLabel->setText(i18nc("@info", "Open '%1'?", d->url.pathOrUrl()));
00292 
00293     const QString dontAskAgain = QLatin1String("askEmbedOrSave")+ d->mimeType; // KEEP IN SYNC!!!
00294     // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC
00295 
00296     const int choice = d->executeDialog(dontAskAgain);
00297     return choice == BrowserOpenOrSaveQuestionPrivate::Save ? Save
00298         : (choice == BrowserOpenOrSaveQuestionPrivate::Cancel ? Cancel : Embed);
00299 }
00300 
00301 void BrowserOpenOrSaveQuestion::setFeatures(Features features)
00302 {
00303     d->features = features;
00304 }
00305 
00306 void BrowserOpenOrSaveQuestion::setSuggestedFileName(const QString& suggestedFileName)
00307 {
00308     if (!suggestedFileName.isEmpty()) {
00309         d->fileNameLabel->setText(i18nc("@label File name", "Name: %1", suggestedFileName));
00310         d->fileNameLabel->setWhatsThis(i18nc("@info:whatsthis", "This is the file name suggested by the server"));
00311         d->fileNameLabel->show();
00312     }
00313 }
00314 
00315 #include "browseropenorsavequestion.moc"

KParts

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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