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