• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kio/kfile
 

kio/kfile

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

kio/kfile

Skip menu "kio/kfile"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kio/kfile

Skip menu "kio/kfile"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kio/kfile by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |