• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

kopenwith.cpp

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

kio

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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