kio Library API Documentation

kopenwith.cpp

00001 /*  This file is part of the KDE libraries
00002 
00003     Copyright (C) 1997 Torben Weis <weis@stud.uni-frankfurt.de>
00004     Copyright (C) 1999 Dirk A. Mueller <dmuell@gmx.net>
00005     Portions copyright (C) 1999 Preston Brown <pbrown@kde.org>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to
00019     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020     Boston, MA 02111-1307, USA.
00021 */
00022 
00023 #include <qfile.h>
00024 #include <qdir.h>
00025 #include <qdialog.h>
00026 #include <qimage.h>
00027 #include <qpixmap.h>
00028 #include <qlabel.h>
00029 #include <qlayout.h>
00030 #include <qpushbutton.h>
00031 #include <qtoolbutton.h>
00032 #include <qcheckbox.h>
00033 #include <qtooltip.h>
00034 #include <qstyle.h>
00035 #include <qwhatsthis.h>
00036 
00037 #include <kapplication.h>
00038 #include <kbuttonbox.h>
00039 #include <kcombobox.h>
00040 #include <kdesktopfile.h>
00041 #include <kdialog.h>
00042 #include <kglobal.h>
00043 #include <klineedit.h>
00044 #include <klocale.h>
00045 #include <kiconloader.h>
00046 #include <kmimemagic.h>
00047 #include <krun.h>
00048 #include <kstandarddirs.h>
00049 #include <kstringhandler.h>
00050 #include <kuserprofile.h>
00051 #include <kurlcompletion.h>
00052 #include <kurlrequester.h>
00053 #include <dcopclient.h>
00054 #include <kmimetype.h>
00055 #include <kservicegroup.h>
00056 #include <klistview.h>
00057 #include <ksycoca.h>
00058 #include <kstdguiitem.h>
00059 
00060 #include "kopenwith.h"
00061 #include "kopenwith_p.h"
00062 
00063 #include <kdebug.h>
00064 #include <assert.h>
00065 #include <stdlib.h>
00066 
00067 template class QPtrList<QString>;
00068 
00069 #define SORT_SPEC (QDir::DirsFirst | QDir::Name | QDir::IgnoreCase)
00070 
00071 
00072 // ----------------------------------------------------------------------
00073 
00074 KAppTreeListItem::KAppTreeListItem( KListView* parent, const QString & name,
00075                                     const QPixmap& pixmap, bool parse, bool dir, const QString &p, const QString &c )
00076     : QListViewItem( parent, name )
00077 {
00078     init(pixmap, parse, dir, p, c);
00079 }
00080 
00081 
00082 // ----------------------------------------------------------------------
00083 
00084 KAppTreeListItem::KAppTreeListItem( QListViewItem* parent, const QString & name,
00085                                     const QPixmap& pixmap, bool parse, bool dir, const QString &p, const QString &c )
00086     : QListViewItem( parent, name )
00087 {
00088     init(pixmap, parse, dir, p, c);
00089 }
00090 
00091 
00092 // ----------------------------------------------------------------------
00093 
00094 void KAppTreeListItem::init(const QPixmap& pixmap, bool parse, bool dir, const QString &_path, const QString &_exec)
00095 {
00096     setPixmap(0, pixmap);
00097     parsed = parse;
00098     directory = dir;
00099     path = _path; // relative path
00100     exec = _exec;
00101 }
00102 
00103 
00104 // ----------------------------------------------------------------------
00105 // Ensure that dirs are sorted in front of files and case is ignored
00106 
00107 QString KAppTreeListItem::key(int column, bool /*ascending*/) const
00108 {
00109     if (directory)
00110         return QString::fromLatin1(" ") + text(column).upper();
00111     else
00112         return text(column).upper();
00113 }
00114 
00115 void KAppTreeListItem::activate()
00116 {
00117     if ( directory )
00118         setOpen(!isOpen());
00119 }
00120 
00121 void KAppTreeListItem::setOpen( bool o )
00122 {
00123     if( o && !parsed ) { // fill the children before opening
00124         ((KApplicationTree *) parent())->addDesktopGroup( path, this );
00125         parsed = true;
00126     }
00127     QListViewItem::setOpen( o );
00128 }
00129 
00130 bool KAppTreeListItem::isDirectory()
00131 {
00132     return directory;
00133 }
00134 
00135 // ----------------------------------------------------------------------
00136 
00137 KApplicationTree::KApplicationTree( QWidget *parent )
00138     : KListView( parent ), currentitem(0)
00139 {
00140     addColumn( i18n("Known Applications") );
00141     setRootIsDecorated( true );
00142 
00143     addDesktopGroup( QString::null );
00144 
00145     connect( this, SIGNAL( currentChanged(QListViewItem*) ),
00146             SLOT( slotItemHighlighted(QListViewItem*) ) );
00147     connect( this, SIGNAL( selectionChanged(QListViewItem*) ),
00148             SLOT( slotSelectionChanged(QListViewItem*) ) );
00149 }
00150 
00151 // ----------------------------------------------------------------------
00152 
00153 bool KApplicationTree::isDirSel()
00154 {
00155     if (!currentitem) return false; // if currentitem isn't set
00156     return currentitem->isDirectory();
00157 }
00158 
00159 // ----------------------------------------------------------------------
00160 
00161 static QPixmap appIcon(const QString &iconName)
00162 {
00163     QPixmap normal = KGlobal::iconLoader()->loadIcon(iconName, KIcon::Small, 0, KIcon::DefaultState, 0L, true);
00164     // make sure they are not larger than 20x20
00165     if (normal.width() > 20 || normal.height() > 20)
00166     {
00167        QImage tmp = normal.convertToImage();
00168        tmp = tmp.smoothScale(20, 20);
00169        normal.convertFromImage(tmp);
00170     }
00171     return normal;
00172 }
00173 
00174 void KApplicationTree::addDesktopGroup( const QString &relPath, KAppTreeListItem *item)
00175 {
00176    KServiceGroup::Ptr root = KServiceGroup::group(relPath);
00177    if (!root || !root->isValid()) return;
00178 
00179    KServiceGroup::List list = root->entries();
00180 
00181    KAppTreeListItem * newItem;
00182    for( KServiceGroup::List::ConstIterator it = list.begin();
00183        it != list.end(); it++)
00184    {
00185       QString icon;
00186       QString text;
00187       QString relPath;
00188       QString exec;
00189       bool isDir = false;
00190       KSycocaEntry *p = (*it);
00191       if (p->isType(KST_KService))
00192       {
00193          KService *service = static_cast<KService *>(p);
00194 
00195          if (service->noDisplay())
00196             continue;
00197 
00198          icon = service->icon();
00199          text = service->name();
00200          exec = service->exec();
00201       }
00202       else if (p->isType(KST_KServiceGroup))
00203       {
00204          KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00205 
00206          if (serviceGroup->noDisplay())
00207             continue;
00208 
00209          icon = serviceGroup->icon();
00210          text = serviceGroup->caption();
00211          relPath = serviceGroup->relPath();
00212          isDir = true;
00213          if ( text[0] == '.' ) // skip ".hidden" like kicker does
00214            continue;
00215       }
00216       else
00217       {
00218          kdWarning(250) << "KServiceGroup: Unexpected object in list!" << endl;
00219          continue;
00220       }
00221 
00222       QPixmap pixmap = appIcon( icon );
00223 
00224       if (item)
00225          newItem = new KAppTreeListItem( item, text, pixmap, false, isDir,
00226                                          relPath, exec );
00227       else
00228          newItem = new KAppTreeListItem( this, text, pixmap, false, isDir,
00229                                          relPath, exec );
00230       if (isDir)
00231          newItem->setExpandable( true );
00232    }
00233 }
00234 
00235 
00236 // ----------------------------------------------------------------------
00237 
00238 void KApplicationTree::slotItemHighlighted(QListViewItem* i)
00239 {
00240     // i may be 0 (see documentation)
00241     if(!i)
00242         return;
00243 
00244     KAppTreeListItem *item = (KAppTreeListItem *) i;
00245 
00246     currentitem = item;
00247 
00248     if( (!item->directory ) && (!item->exec.isEmpty()) )
00249         emit highlighted( item->text(0), item->exec );
00250 }
00251 
00252 
00253 // ----------------------------------------------------------------------
00254 
00255 void KApplicationTree::slotSelectionChanged(QListViewItem* i)
00256 {
00257     // i may be 0 (see documentation)
00258     if(!i)
00259         return;
00260 
00261     KAppTreeListItem *item = (KAppTreeListItem *) i;
00262 
00263     currentitem = item;
00264 
00265     if( ( !item->directory ) && (!item->exec.isEmpty() ) )
00266         emit selected( item->text(0), item->exec );
00267 }
00268 
00269 // ----------------------------------------------------------------------
00270 
00271 void KApplicationTree::resizeEvent( QResizeEvent * e)
00272 {
00273     setColumnWidth(0, width()-QApplication::style().pixelMetric(QStyle::PM_ScrollBarExtent)
00274                          -2*QApplication::style().pixelMetric(QStyle::PM_DefaultFrameWidth));
00275     KListView::resizeEvent(e);
00276 }
00277 
00278 
00279 /***************************************************************
00280  *
00281  * KOpenWithDlg
00282  *
00283  ***************************************************************/
00284 class KOpenWithDlgPrivate
00285 {
00286 public:
00287     KOpenWithDlgPrivate() : saveNewApps(false) { };
00288     QPushButton* ok;
00289     bool saveNewApps;
00290     KService::Ptr curService;
00291 };
00292 
00293 KOpenWithDlg::KOpenWithDlg( const KURL::List& _urls, QWidget* parent )
00294              :QDialog( parent, 0L, true )
00295 {
00296     setCaption( i18n( "Open With" ) );
00297     QString text;
00298     if( _urls.count() == 1 )
00299     {
00300         text = i18n("<qt>Select the program that should be used to open <b>%1</b>. "
00301                      "If the program is not listed, enter the name or click "
00302                      "the browse button.</qt>").arg( _urls.first().fileName() );
00303     }
00304     else
00305         // Should never happen ??
00306         text = i18n( "Choose the name of the program with which to open the selected files." );
00307     setServiceType( _urls );
00308     init( text, QString() );
00309 }
00310 
00311 KOpenWithDlg::KOpenWithDlg( const KURL::List& _urls, const QString&_text,
00312                             const QString& _value, QWidget *parent)
00313              :QDialog( parent, 0L, true )
00314 {
00315   QString caption = KStringHandler::csqueeze( _urls.first().prettyURL() );
00316   if (_urls.count() > 1)
00317       caption += QString::fromLatin1("...");
00318   setCaption(caption);
00319   setServiceType( _urls );
00320   init( _text, _value );
00321 }
00322 
00323 KOpenWithDlg::KOpenWithDlg( const QString &serviceType, const QString& value,
00324                             QWidget *parent)
00325              :QDialog( parent, 0L, true )
00326 {
00327     setCaption(i18n("Choose Application for %1").arg(serviceType));
00328   QString text = i18n("<qt>Select the program for the file type: <b>%1</b>. "
00329                       "If the program is not listed, enter the name or click "
00330                       "the browse button.</qt>").arg(serviceType);
00331   qServiceType = serviceType;
00332   init( text, value );
00333   if (remember)
00334       remember->hide();
00335 }
00336 
00337 KOpenWithDlg::KOpenWithDlg( QWidget *parent)
00338              :QDialog( parent, 0L, true )
00339 {
00340   setCaption(i18n("Choose Application"));
00341   QString text = i18n("<qt>Select a program. "
00342                       "If the program is not listed, enter the name or click "
00343                       "the browse button.</qt>");
00344   qServiceType = QString::null;
00345   init( text, QString::null );
00346 }
00347 
00348 void KOpenWithDlg::setServiceType( const KURL::List& _urls )
00349 {
00350   if ( _urls.count() == 1 )
00351   {
00352     qServiceType = KMimeType::findByURL( _urls.first())->name();
00353     if (qServiceType == QString::fromLatin1("application/octet-stream"))
00354       qServiceType = QString::null;
00355   }
00356   else
00357       qServiceType = QString::null;
00358 }
00359 
00360 void KOpenWithDlg::init( const QString& _text, const QString& _value )
00361 {
00362   d = new KOpenWithDlgPrivate;
00363   bool bReadOnly = kapp && !kapp->authorize("shell_access");
00364   m_terminaldirty = false;
00365   m_pTree = 0L;
00366   m_pService = 0L;
00367   d->curService = 0L;
00368 
00369   QBoxLayout *topLayout = new QVBoxLayout( this, KDialog::marginHint(),
00370           KDialog::spacingHint() );
00371   label = new QLabel( _text, this );
00372   topLayout->addWidget(label);
00373 
00374   QHBoxLayout* hbox = new QHBoxLayout(topLayout);
00375 
00376   QToolButton *clearButton = new QToolButton( this );
00377   clearButton->setIconSet( BarIcon( "locationbar_erase" ) );
00378   clearButton->setFixedSize( clearButton->sizeHint() );
00379   connect( clearButton, SIGNAL( clicked() ), SLOT( slotClear() ) );
00380   QToolTip::add( clearButton, i18n( "Clear input field" ) );
00381 
00382   hbox->addWidget( clearButton );
00383 
00384   if (!bReadOnly)
00385   {
00386     // init the history combo and insert it into the URL-Requester
00387     KHistoryCombo *combo = new KHistoryCombo();
00388     combo->setDuplicatesEnabled( false );
00389     KConfig *kc = KGlobal::config();
00390     KConfigGroupSaver ks( kc, QString::fromLatin1("Open-with settings") );
00391     int max = kc->readNumEntry( QString::fromLatin1("Maximum history"), 15 );
00392     combo->setMaxCount( max );
00393     int mode = kc->readNumEntry(QString::fromLatin1("CompletionMode"),
00394                 KGlobalSettings::completionMode());
00395     combo->setCompletionMode((KGlobalSettings::Completion)mode);
00396     QStringList list = kc->readListEntry( QString::fromLatin1("History") );
00397     combo->setHistoryItems( list, true );
00398     edit = new KURLRequester( combo, this );
00399   }
00400   else
00401   {
00402     clearButton->hide();
00403     edit = new KURLRequester( this );
00404     edit->lineEdit()->setReadOnly(true);
00405     edit->button()->hide();
00406   }
00407 
00408   edit->setURL( _value );
00409   QWhatsThis::add(edit,i18n(
00410     "Following the command, you can have several place holders which will be replaced "
00411     "with the actual values when the actual program is run:\n"
00412     "%f - a single file name\n"
00413     "%F - a list of files; use for applications that can open several local files at once\n"
00414     "%u - a single URL\n"
00415     "%U - a list of URLs\n"
00416     "%d - the directory of the file to open\n"
00417     "%D - a list of directories\n"
00418     "%i - the icon\n"
00419     "%m - the mini-icon\n"
00420     "%c - the comment"));
00421 
00422   hbox->addWidget(edit);
00423 
00424   if ( edit->comboBox() ) {
00425     KURLCompletion *comp = new KURLCompletion( KURLCompletion::ExeCompletion );
00426     edit->comboBox()->setCompletionObject( comp );
00427     edit->comboBox()->setAutoDeleteCompletionObject( true );
00428   }
00429 
00430   connect ( edit, SIGNAL(returnPressed()), SLOT(slotOK()) );
00431   connect ( edit, SIGNAL(textChanged(const QString&)), SLOT(slotTextChanged()) );
00432 
00433   m_pTree = new KApplicationTree( this );
00434   topLayout->addWidget(m_pTree);
00435 
00436   connect( m_pTree, SIGNAL( selected( const QString&, const QString& ) ),
00437            SLOT( slotSelected( const QString&, const QString& ) ) );
00438   connect( m_pTree, SIGNAL( highlighted( const QString&, const QString& ) ),
00439            SLOT( slotHighlighted( const QString&, const QString& ) ) );
00440   connect( m_pTree, SIGNAL( doubleClicked(QListViewItem*) ),
00441            SLOT( slotDbClick() ) );
00442 
00443   terminal = new QCheckBox( i18n("Run in &terminal"), this );
00444   if (bReadOnly)
00445      terminal->hide();
00446   connect(terminal, SIGNAL(toggled(bool)), SLOT(slotTerminalToggled(bool)));
00447 
00448   topLayout->addWidget(terminal);
00449 
00450   QBoxLayout* nocloseonexitLayout = new QHBoxLayout( 0, 0, KDialog::spacingHint() );
00451   QSpacerItem* spacer = new QSpacerItem( 20, 0, QSizePolicy::Fixed, QSizePolicy::Minimum );
00452   nocloseonexitLayout->addItem( spacer );
00453 
00454   nocloseonexit = new QCheckBox( i18n("&Do not close when command exits"), this );
00455   nocloseonexit->setChecked( false );
00456   nocloseonexit->setDisabled( true );
00457 
00458   // check to see if we use konsole if not disable the nocloseonexit
00459   // because we don't know how to do this on other terminal applications
00460   KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
00461   QString preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
00462 
00463   if (bReadOnly || preferredTerminal != "konsole")
00464      nocloseonexit->hide();
00465 
00466   nocloseonexitLayout->addWidget( nocloseonexit );
00467   topLayout->addLayout( nocloseonexitLayout );
00468 
00469   if (!qServiceType.isNull())
00470   {
00471     remember = new QCheckBox(i18n("&Remember application association for this type of file"), this);
00472     //    remember->setChecked(true);
00473     topLayout->addWidget(remember);
00474   }
00475   else
00476     remember = 0L;
00477 
00478   // Use KButtonBox for the aligning pushbuttons nicely
00479   KButtonBox* b = new KButtonBox( this );
00480   b->addStretch( 2 );
00481 
00482   d->ok = b->addButton( KStdGuiItem::ok() );
00483   d->ok->setDefault( true );
00484   connect(  d->ok, SIGNAL( clicked() ), SLOT( slotOK() ) );
00485 
00486   QPushButton* cancel = b->addButton(  KStdGuiItem::cancel() );
00487   connect(  cancel, SIGNAL( clicked() ), SLOT( reject() ) );
00488 
00489   b->layout();
00490   topLayout->addWidget( b );
00491 
00492   //edit->setText( _value );
00493   // This is what caused "can't click on items before clicking on Name header".
00494   // Probably due to the resizeEvent handler using width().
00495   //resize( minimumWidth(), sizeHint().height() );
00496   edit->setFocus();
00497   slotTextChanged();
00498 }
00499 
00500 
00501 // ----------------------------------------------------------------------
00502 
00503 KOpenWithDlg::~KOpenWithDlg()
00504 {
00505     delete d;
00506     d = 0;
00507 }
00508 
00509 // ----------------------------------------------------------------------
00510 
00511 void KOpenWithDlg::slotClear()
00512 {
00513     edit->setURL(QString::null);
00514     edit->setFocus();
00515 }
00516 
00517 
00518 // ----------------------------------------------------------------------
00519 
00520 void KOpenWithDlg::slotSelected( const QString& /*_name*/, const QString& _exec )
00521 {
00522     kdDebug(250)<<"KOpenWithDlg::slotSelected"<<endl;
00523     KService::Ptr pService = d->curService;
00524     edit->setURL( _exec ); // calls slotTextChanged :(
00525     d->curService = pService;
00526 }
00527 
00528 
00529 // ----------------------------------------------------------------------
00530 
00531 void KOpenWithDlg::slotHighlighted( const QString& _name, const QString& )
00532 {
00533     kdDebug(250)<<"KOpenWithDlg::slotHighlighted"<<endl;
00534     qName = _name;
00535     d->curService = KService::serviceByName( qName );
00536     if (!m_terminaldirty)
00537     {
00538         // ### indicate that default value was restored
00539         terminal->setChecked(d->curService->terminal());
00540         QString terminalOptions = d->curService->terminalOptions();
00541         nocloseonexit->setChecked( (terminalOptions.contains( "--noclose" ) > 0) );
00542         m_terminaldirty = false; // slotTerminalToggled changed it
00543     }
00544 }
00545 
00546 // ----------------------------------------------------------------------
00547 
00548 void KOpenWithDlg::slotTextChanged()
00549 {
00550     kdDebug(250)<<"KOpenWithDlg::slotTextChanged"<<endl;
00551     // Forget about the service
00552     d->curService = 0L;
00553     d->ok->setEnabled( !edit->url().isEmpty());
00554 }
00555 
00556 // ----------------------------------------------------------------------
00557 
00558 void KOpenWithDlg::slotTerminalToggled(bool)
00559 {
00560     // ### indicate that default value was overridden
00561     m_terminaldirty = true;
00562     nocloseonexit->setDisabled( ! terminal->isChecked() );
00563 }
00564 
00565 // ----------------------------------------------------------------------
00566 
00567 void KOpenWithDlg::slotDbClick()
00568 {
00569    if (m_pTree->isDirSel() ) return; // check if a directory is selected
00570    slotOK();
00571 }
00572 
00573 void KOpenWithDlg::setSaveNewApplications(bool b)
00574 {
00575   d->saveNewApps = b;
00576 }
00577 
00578 void KOpenWithDlg::slotOK()
00579 {
00580   QString fullExec(edit->url());
00581 
00582   QString serviceName;
00583   QString initialServiceName;
00584   QString preferredTerminal;
00585   m_pService = d->curService;
00586   if (!m_pService) {
00587     // No service selected - check the command line
00588 
00589     // Find out the name of the service from the command line, removing args and paths
00590     serviceName = KRun::binaryName( fullExec, true );
00591     if (serviceName.isEmpty())
00592     {
00593       // TODO add a KMessageBox::error here after the end of the message freeze
00594       return;
00595     }
00596     initialServiceName = serviceName;
00597     kdDebug(250) << "initialServiceName=" << initialServiceName << endl;
00598     int i = 1; // We have app, app-2, app-3... Looks better for the user.
00599     bool ok = false;
00600     // Check if there's already a service by that name, with the same Exec line
00601     do {
00602         kdDebug(250) << "looking for service " << serviceName << endl;
00603         KService::Ptr serv = KService::serviceByDesktopName( serviceName );
00604         ok = !serv; // ok if no such service yet
00605         // also ok if we find the exact same service (well, "kwrite" == "kwrite %U"
00606         if ( serv && serv->type() == "Application")
00607         {
00608             QString exec = serv->exec();
00609             exec.replace("%u", "", false);
00610             exec.replace("%f", "", false);
00611             exec.replace("-caption %c", "");
00612             exec.replace("-caption \"%c\"", "");
00613             exec.replace("%i", "");
00614             exec.replace("%m", "");
00615             exec = exec.simplifyWhiteSpace();
00616             if (exec == fullExec)
00617             {
00618                 ok = true;
00619                 m_pService = serv;
00620                 kdDebug(250) << k_funcinfo << "OK, found identical service: " << serv->desktopEntryPath() << endl;
00621             }
00622         }
00623         if (!ok) // service was found, but it was different -> keep looking
00624         {
00625             ++i;
00626             serviceName = initialServiceName + "-" + QString::number(i);
00627         }
00628     }
00629     while (!ok);
00630   }
00631   if ( m_pService )
00632   {
00633     // Existing service selected
00634     serviceName = m_pService->name();
00635     initialServiceName = serviceName;
00636   }
00637 
00638   if (terminal->isChecked())
00639   {
00640     KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
00641     preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
00642     m_command = preferredTerminal;
00643     // only add --noclose when we are sure it is konsole we're using
00644     if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
00645       m_command += QString::fromLatin1(" --noclose");
00646     m_command += QString::fromLatin1(" -e ");
00647     m_command += edit->url();
00648     kdDebug(250) << "Setting m_command to " << m_command << endl;
00649   }
00650   if ( m_pService && terminal->isChecked() != m_pService->terminal() )
00651       m_pService = 0L; // It's not exactly this service we're running
00652 
00653   bool bRemember = remember && remember->isChecked();
00654 
00655   if ( !bRemember && m_pService)
00656   {
00657     accept();
00658     return;
00659   }
00660 
00661   if (!bRemember && !d->saveNewApps)
00662   {
00663     // Create temp service
00664     m_pService = new KService(initialServiceName, fullExec, QString::null);
00665     if (terminal->isChecked())
00666     {
00667       m_pService->setTerminal(true);
00668       // only add --noclose when we are sure it is konsole we're using
00669       if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
00670          m_pService->setTerminalOptions("--noclose");
00671     }
00672     accept();
00673     return;
00674   }
00675 
00676   // if we got here, we can't seem to find a service for what they
00677   // wanted.  The other possibility is that they have asked for the
00678   // association to be remembered.  Create/update service.
00679 
00680   QString newPath;
00681   QString oldPath;
00682   QString menuId;
00683   if (m_pService)
00684   {
00685     oldPath = m_pService->desktopEntryPath();
00686     newPath = m_pService->locateLocal();
00687     menuId = m_pService->menuId();
00688     kdDebug(250) << "Updating exitsing service " << m_pService->desktopEntryPath() << " ( " << newPath << " ) " << endl;
00689   }
00690   else
00691   {
00692     newPath = KService::newServicePath(false /* hidden */, serviceName, &menuId);
00693     kdDebug(250) << "Creating new service " << serviceName << " ( " << newPath << " ) " << endl;
00694   }
00695 
00696   int maxPreference = 1;
00697   if (!qServiceType.isEmpty())
00698   {
00699     KServiceTypeProfile::OfferList offerList = KServiceTypeProfile::offers( qServiceType );
00700     if (!offerList.isEmpty())
00701       maxPreference = offerList.first().preference();
00702   }
00703 
00704   KDesktopFile *desktop = 0;
00705   if (!oldPath.isEmpty() && (oldPath != newPath))
00706   {
00707      KDesktopFile orig(oldPath, true);
00708      desktop = orig.copyTo(newPath);
00709   }
00710   else
00711   {
00712      desktop = new KDesktopFile(newPath);
00713   }
00714   desktop->writeEntry("Type", QString::fromLatin1("Application"));
00715   desktop->writeEntry("Name", initialServiceName);
00716   desktop->writePathEntry("Exec", fullExec);
00717   if (terminal->isChecked())
00718   {
00719     desktop->writeEntry("Terminal", true);
00720     // only add --noclose when we are sure it is konsole we're using
00721     if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
00722       desktop->writeEntry("TerminalOptions", "--noclose");
00723   }
00724   else
00725   {
00726     desktop->writeEntry("Terminal", false);
00727   }
00728   desktop->writeEntry("InitialPreference", maxPreference + 1);
00729 
00730 
00731   if (bRemember)
00732   {
00733     QStringList mimeList = desktop->readListEntry("MimeType", ';');
00734     if (!qServiceType.isEmpty() && !mimeList.contains(qServiceType))
00735       mimeList.append(qServiceType);
00736     desktop->writeEntry("MimeType", mimeList, ';');
00737 
00738     if ( !qServiceType.isEmpty() )
00739     {
00740       // Also make sure the "auto embed" setting for this mimetype is off
00741       KDesktopFile mimeDesktop( locateLocal( "mime", qServiceType + ".desktop" ) );
00742       mimeDesktop.writeEntry( "X-KDE-AutoEmbed", false );
00743       mimeDesktop.sync();
00744     }
00745   }
00746 
00747   // write it all out to the file
00748   desktop->sync();
00749   delete desktop;
00750 
00751   KService::rebuildKSycoca(this);
00752 
00753   m_pService = KService::serviceByMenuId( menuId );
00754 
00755   Q_ASSERT( m_pService );
00756 
00757   accept();
00758 }
00759 
00760 QString KOpenWithDlg::text() const
00761 {
00762     if (!m_command.isEmpty())
00763         return m_command;
00764     else
00765         return edit->url();
00766 }
00767 
00768 void KOpenWithDlg::hideNoCloseOnExit()
00769 {
00770     // uncheck the checkbox because the value could be used when "Run in Terminal" is selected
00771     nocloseonexit->setChecked( false );
00772     nocloseonexit->hide();
00773 }
00774 
00775 void KOpenWithDlg::hideRunInTerminal()
00776 {
00777     terminal->hide();
00778     hideNoCloseOnExit();
00779 }
00780 
00781 void KOpenWithDlg::accept()
00782 {
00783     KHistoryCombo *combo = static_cast<KHistoryCombo*>( edit->comboBox() );
00784     if ( combo ) {
00785         combo->addToHistory( edit->url() );
00786 
00787         KConfig *kc = KGlobal::config();
00788         KConfigGroupSaver ks( kc, QString::fromLatin1("Open-with settings") );
00789         kc->writeEntry( QString::fromLatin1("History"), combo->historyItems() );
00790     kc->writeEntry(QString::fromLatin1("CompletionMode"),
00791                combo->completionMode());
00792         // don't store the completion-list, as it contains all of KURLCompletion's
00793         // executables
00794         kc->sync();
00795     }
00796 
00797     QDialog::accept();
00798 }
00799 
00800 
00802 
00803 #ifndef KDE_NO_COMPAT
00804 bool KFileOpenWithHandler::displayOpenWithDialog( const KURL::List& urls )
00805 {
00806     KOpenWithDlg l( urls, i18n("Open with:"), QString::null, 0L );
00807     if ( l.exec() )
00808     {
00809       KService::Ptr service = l.service();
00810       if ( !!service )
00811         return KRun::run( *service, urls );
00812 
00813       kdDebug(250) << "No service set, running " << l.text() << endl;
00814       return KRun::run( l.text(), urls );
00815     }
00816     return false;
00817 }
00818 #endif
00819 
00820 #include "kopenwith.moc"
00821 #include "kopenwith_p.moc"
00822 
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:45:31 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003