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