kio Library API Documentation

kopenwith.cpp

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