summaryrefslogtreecommitdiffstats
path: root/kio/kfile/kopenwith.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kio/kfile/kopenwith.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kio/kfile/kopenwith.cpp')
-rw-r--r--kio/kfile/kopenwith.cpp851
1 files changed, 851 insertions, 0 deletions
diff --git a/kio/kfile/kopenwith.cpp b/kio/kfile/kopenwith.cpp
new file mode 100644
index 000000000..f1a71341b
--- /dev/null
+++ b/kio/kfile/kopenwith.cpp
@@ -0,0 +1,851 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1997 Torben Weis <weis@stud.uni-frankfurt.de>
+ Copyright (C) 1999 Dirk Mueller <mueller@kde.org>
+ Portions copyright (C) 1999 Preston Brown <pbrown@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qdialog.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qstyle.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <kbuttonbox.h>
+#include <kcombobox.h>
+#include <kdesktopfile.h>
+#include <kdialog.h>
+#include <kglobal.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmimemagic.h>
+#include <krun.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+#include <kuserprofile.h>
+#include <kurlcompletion.h>
+#include <kurlrequester.h>
+#include <dcopclient.h>
+#include <kmimetype.h>
+#include <kservicegroup.h>
+#include <klistview.h>
+#include <ksycoca.h>
+#include <kstdguiitem.h>
+
+#include "kopenwith.h"
+#include "kopenwith_p.h"
+
+#include <kdebug.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#define SORT_SPEC (QDir::DirsFirst | QDir::Name | QDir::IgnoreCase)
+
+
+// ----------------------------------------------------------------------
+
+KAppTreeListItem::KAppTreeListItem( KListView* parent, const QString & name,
+ const QPixmap& pixmap, bool parse, bool dir, const QString &p, const QString &c )
+ : QListViewItem( parent, name )
+{
+ init(pixmap, parse, dir, p, c);
+}
+
+
+// ----------------------------------------------------------------------
+
+KAppTreeListItem::KAppTreeListItem( QListViewItem* parent, const QString & name,
+ const QPixmap& pixmap, bool parse, bool dir, const QString &p, const QString &c )
+ : QListViewItem( parent, name )
+{
+ init(pixmap, parse, dir, p, c);
+}
+
+
+// ----------------------------------------------------------------------
+
+void KAppTreeListItem::init(const QPixmap& pixmap, bool parse, bool dir, const QString &_path, const QString &_exec)
+{
+ setPixmap(0, pixmap);
+ parsed = parse;
+ directory = dir;
+ path = _path; // relative path
+ exec = _exec;
+}
+
+
+/* Ensures that directories sort before non-directories */
+int KAppTreeListItem::compare(QListViewItem *i, int col, bool ascending) const
+{
+ KAppTreeListItem *other = dynamic_cast<KAppTreeListItem *>(i);
+
+ // Directories sort first
+ if (directory && !other->directory)
+ return -1;
+
+ else if (!directory && other->directory)
+ return 1;
+
+ else // both directories or both not
+ return QListViewItem::compare(i, col, ascending);
+}
+
+// ----------------------------------------------------------------------
+// Ensure that case is ignored
+QString KAppTreeListItem::key(int column, bool /*ascending*/) const
+{
+ return text(column).upper();
+}
+
+void KAppTreeListItem::activate()
+{
+ if ( directory )
+ setOpen(!isOpen());
+}
+
+void KAppTreeListItem::setOpen( bool o )
+{
+ if( o && !parsed ) { // fill the children before opening
+ ((KApplicationTree *) parent())->addDesktopGroup( path, this );
+ parsed = true;
+ }
+ QListViewItem::setOpen( o );
+}
+
+bool KAppTreeListItem::isDirectory()
+{
+ return directory;
+}
+
+// ----------------------------------------------------------------------
+
+KApplicationTree::KApplicationTree( QWidget *parent )
+ : KListView( parent ), currentitem(0)
+{
+ addColumn( i18n("Known Applications") );
+ setRootIsDecorated( true );
+
+ addDesktopGroup( QString::null );
+ cleanupTree();
+
+ connect( this, SIGNAL( currentChanged(QListViewItem*) ),
+ SLOT( slotItemHighlighted(QListViewItem*) ) );
+ connect( this, SIGNAL( selectionChanged(QListViewItem*) ),
+ SLOT( slotSelectionChanged(QListViewItem*) ) );
+}
+
+// ----------------------------------------------------------------------
+
+bool KApplicationTree::isDirSel()
+{
+ if (!currentitem) return false; // if currentitem isn't set
+ return currentitem->isDirectory();
+}
+
+// ----------------------------------------------------------------------
+
+static QPixmap appIcon(const QString &iconName)
+{
+ QPixmap normal = KGlobal::iconLoader()->loadIcon(iconName, KIcon::Small, 0, KIcon::DefaultState, 0L, true);
+ // make sure they are not larger than 20x20
+ if (normal.width() > 20 || normal.height() > 20)
+ {
+ QImage tmp = normal.convertToImage();
+ tmp = tmp.smoothScale(20, 20);
+ normal.convertFromImage(tmp);
+ }
+ return normal;
+}
+
+void KApplicationTree::addDesktopGroup( const QString &relPath, KAppTreeListItem *item)
+{
+ KServiceGroup::Ptr root = KServiceGroup::group(relPath);
+ if (!root || !root->isValid()) return;
+
+ KServiceGroup::List list = root->entries();
+
+ KAppTreeListItem * newItem;
+ for( KServiceGroup::List::ConstIterator it = list.begin();
+ it != list.end(); it++)
+ {
+ QString icon;
+ QString text;
+ QString relPath;
+ QString exec;
+ bool isDir = false;
+ KSycocaEntry *p = (*it);
+ if (p->isType(KST_KService))
+ {
+ KService *service = static_cast<KService *>(p);
+
+ if (service->noDisplay())
+ continue;
+
+ icon = service->icon();
+ text = service->name();
+ exec = service->exec();
+ }
+ else if (p->isType(KST_KServiceGroup))
+ {
+ KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
+
+ if (serviceGroup->noDisplay() || serviceGroup->childCount() == 0)
+ continue;
+
+ icon = serviceGroup->icon();
+ text = serviceGroup->caption();
+ relPath = serviceGroup->relPath();
+ isDir = true;
+ }
+ else
+ {
+ kdWarning(250) << "KServiceGroup: Unexpected object in list!" << endl;
+ continue;
+ }
+
+ QPixmap pixmap = appIcon( icon );
+
+ if (item)
+ newItem = new KAppTreeListItem( item, text, pixmap, false, isDir,
+ relPath, exec );
+ else
+ newItem = new KAppTreeListItem( this, text, pixmap, false, isDir,
+ relPath, exec );
+ if (isDir)
+ newItem->setExpandable( true );
+ }
+}
+
+
+// ----------------------------------------------------------------------
+
+void KApplicationTree::slotItemHighlighted(QListViewItem* i)
+{
+ // i may be 0 (see documentation)
+ if(!i)
+ return;
+
+ KAppTreeListItem *item = (KAppTreeListItem *) i;
+
+ currentitem = item;
+
+ if( (!item->directory ) && (!item->exec.isEmpty()) )
+ emit highlighted( item->text(0), item->exec );
+}
+
+
+// ----------------------------------------------------------------------
+
+void KApplicationTree::slotSelectionChanged(QListViewItem* i)
+{
+ // i may be 0 (see documentation)
+ if(!i)
+ return;
+
+ KAppTreeListItem *item = (KAppTreeListItem *) i;
+
+ currentitem = item;
+
+ if( ( !item->directory ) && (!item->exec.isEmpty() ) )
+ emit selected( item->text(0), item->exec );
+}
+
+// ----------------------------------------------------------------------
+
+void KApplicationTree::resizeEvent( QResizeEvent * e)
+{
+ setColumnWidth(0, width()-QApplication::style().pixelMetric(QStyle::PM_ScrollBarExtent)
+ -2*QApplication::style().pixelMetric(QStyle::PM_DefaultFrameWidth));
+ KListView::resizeEvent(e);
+}
+
+// Prune empty directories from the tree
+void KApplicationTree::cleanupTree()
+{
+ QListViewItem *item=firstChild();
+ while(item!=0)
+ {
+ if(item->isExpandable())
+ {
+ QListViewItem *temp=item->itemBelow();
+ if(item->text(0)!=i18n("Applications"))
+ item->setOpen(false);
+ item=temp;
+ continue;
+ }
+ item=item->itemBelow();
+ }
+}
+
+/***************************************************************
+ *
+ * KOpenWithDlg
+ *
+ ***************************************************************/
+class KOpenWithDlgPrivate
+{
+public:
+ KOpenWithDlgPrivate() : saveNewApps(false) { };
+ QPushButton* ok;
+ bool saveNewApps;
+ KService::Ptr curService;
+};
+
+KOpenWithDlg::KOpenWithDlg( const KURL::List& _urls, QWidget* parent )
+ :QDialog( parent, "openwith", true )
+{
+ setCaption( i18n( "Open With" ) );
+ QString text;
+ if( _urls.count() == 1 )
+ {
+ text = i18n("<qt>Select the program that should be used to open <b>%1</b>. "
+ "If the program is not listed, enter the name or click "
+ "the browse button.</qt>").arg( _urls.first().fileName() );
+ }
+ else
+ // Should never happen ??
+ text = i18n( "Choose the name of the program with which to open the selected files." );
+ setServiceType( _urls );
+ init( text, QString() );
+}
+
+KOpenWithDlg::KOpenWithDlg( const KURL::List& _urls, const QString&_text,
+ const QString& _value, QWidget *parent)
+ :QDialog( parent, "openwith", true )
+{
+ QString caption = KStringHandler::csqueeze( _urls.first().prettyURL() );
+ if (_urls.count() > 1)
+ caption += QString::fromLatin1("...");
+ setCaption(caption);
+ setServiceType( _urls );
+ init( _text, _value );
+}
+
+KOpenWithDlg::KOpenWithDlg( const QString &serviceType, const QString& value,
+ QWidget *parent)
+ :QDialog( parent, "openwith", true )
+{
+ setCaption(i18n("Choose Application for %1").arg(serviceType));
+ QString text = i18n("<qt>Select the program for the file type: <b>%1</b>. "
+ "If the program is not listed, enter the name or click "
+ "the browse button.</qt>").arg(serviceType);
+ qServiceType = serviceType;
+ init( text, value );
+ if (remember)
+ remember->hide();
+}
+
+KOpenWithDlg::KOpenWithDlg( QWidget *parent)
+ :QDialog( parent, "openwith", true )
+{
+ setCaption(i18n("Choose Application"));
+ QString text = i18n("<qt>Select a program. "
+ "If the program is not listed, enter the name or click "
+ "the browse button.</qt>");
+ qServiceType = QString::null;
+ init( text, QString::null );
+}
+
+void KOpenWithDlg::setServiceType( const KURL::List& _urls )
+{
+ if ( _urls.count() == 1 )
+ {
+ qServiceType = KMimeType::findByURL( _urls.first())->name();
+ if (qServiceType == QString::fromLatin1("application/octet-stream"))
+ qServiceType = QString::null;
+ }
+ else
+ qServiceType = QString::null;
+}
+
+void KOpenWithDlg::init( const QString& _text, const QString& _value )
+{
+ d = new KOpenWithDlgPrivate;
+ bool bReadOnly = kapp && !kapp->authorize("shell_access");
+ m_terminaldirty = false;
+ m_pTree = 0L;
+ m_pService = 0L;
+ d->curService = 0L;
+
+ QBoxLayout *topLayout = new QVBoxLayout( this, KDialog::marginHint(),
+ KDialog::spacingHint() );
+ label = new QLabel( _text, this );
+ topLayout->addWidget(label);
+
+ QHBoxLayout* hbox = new QHBoxLayout(topLayout);
+
+ QToolButton *clearButton = new QToolButton( this );
+ clearButton->setIconSet( BarIcon( "locationbar_erase" ) );
+ clearButton->setFixedSize( clearButton->sizeHint() );
+ connect( clearButton, SIGNAL( clicked() ), SLOT( slotClear() ) );
+ QToolTip::add( clearButton, i18n( "Clear input field" ) );
+
+ hbox->addWidget( clearButton );
+
+ if (!bReadOnly)
+ {
+ // init the history combo and insert it into the URL-Requester
+ KHistoryCombo *combo = new KHistoryCombo();
+ combo->setDuplicatesEnabled( false );
+ KConfig *kc = KGlobal::config();
+ KConfigGroupSaver ks( kc, QString::fromLatin1("Open-with settings") );
+ int max = kc->readNumEntry( QString::fromLatin1("Maximum history"), 15 );
+ combo->setMaxCount( max );
+ int mode = kc->readNumEntry(QString::fromLatin1("CompletionMode"),
+ KGlobalSettings::completionMode());
+ combo->setCompletionMode((KGlobalSettings::Completion)mode);
+ QStringList list = kc->readListEntry( QString::fromLatin1("History") );
+ combo->setHistoryItems( list, true );
+ edit = new KURLRequester( combo, this );
+ }
+ else
+ {
+ clearButton->hide();
+ edit = new KURLRequester( this );
+ edit->lineEdit()->setReadOnly(true);
+ edit->button()->hide();
+ }
+
+ edit->setURL( _value );
+ QWhatsThis::add(edit,i18n(
+ "Following the command, you can have several place holders which will be replaced "
+ "with the actual values when the actual program is run:\n"
+ "%f - a single file name\n"
+ "%F - a list of files; use for applications that can open several local files at once\n"
+ "%u - a single URL\n"
+ "%U - a list of URLs\n"
+ "%d - the directory of the file to open\n"
+ "%D - a list of directories\n"
+ "%i - the icon\n"
+ "%m - the mini-icon\n"
+ "%c - the comment"));
+
+ hbox->addWidget(edit);
+
+ if ( edit->comboBox() ) {
+ KURLCompletion *comp = new KURLCompletion( KURLCompletion::ExeCompletion );
+ edit->comboBox()->setCompletionObject( comp );
+ edit->comboBox()->setAutoDeleteCompletionObject( true );
+ }
+
+ connect ( edit, SIGNAL(returnPressed()), SLOT(slotOK()) );
+ connect ( edit, SIGNAL(textChanged(const QString&)), SLOT(slotTextChanged()) );
+
+ m_pTree = new KApplicationTree( this );
+ topLayout->addWidget(m_pTree);
+
+ connect( m_pTree, SIGNAL( selected( const QString&, const QString& ) ),
+ SLOT( slotSelected( const QString&, const QString& ) ) );
+ connect( m_pTree, SIGNAL( highlighted( const QString&, const QString& ) ),
+ SLOT( slotHighlighted( const QString&, const QString& ) ) );
+ connect( m_pTree, SIGNAL( doubleClicked(QListViewItem*) ),
+ SLOT( slotDbClick() ) );
+
+ terminal = new QCheckBox( i18n("Run in &terminal"), this );
+ if (bReadOnly)
+ terminal->hide();
+ connect(terminal, SIGNAL(toggled(bool)), SLOT(slotTerminalToggled(bool)));
+
+ topLayout->addWidget(terminal);
+
+ QBoxLayout* nocloseonexitLayout = new QHBoxLayout( 0, 0, KDialog::spacingHint() );
+ QSpacerItem* spacer = new QSpacerItem( 20, 0, QSizePolicy::Fixed, QSizePolicy::Minimum );
+ nocloseonexitLayout->addItem( spacer );
+
+ nocloseonexit = new QCheckBox( i18n("&Do not close when command exits"), this );
+ nocloseonexit->setChecked( false );
+ nocloseonexit->setDisabled( true );
+
+ // check to see if we use konsole if not disable the nocloseonexit
+ // because we don't know how to do this on other terminal applications
+ KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
+ QString preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
+
+ if (bReadOnly || preferredTerminal != "konsole")
+ nocloseonexit->hide();
+
+ nocloseonexitLayout->addWidget( nocloseonexit );
+ topLayout->addLayout( nocloseonexitLayout );
+
+ if (!qServiceType.isNull())
+ {
+ remember = new QCheckBox(i18n("&Remember application association for this type of file"), this);
+ // remember->setChecked(true);
+ topLayout->addWidget(remember);
+ }
+ else
+ remember = 0L;
+
+ // Use KButtonBox for the aligning pushbuttons nicely
+ KButtonBox* b = new KButtonBox( this );
+ b->addStretch( 2 );
+
+ d->ok = b->addButton( KStdGuiItem::ok() );
+ d->ok->setDefault( true );
+ connect( d->ok, SIGNAL( clicked() ), SLOT( slotOK() ) );
+
+ QPushButton* cancel = b->addButton( KStdGuiItem::cancel() );
+ connect( cancel, SIGNAL( clicked() ), SLOT( reject() ) );
+
+ b->layout();
+ topLayout->addWidget( b );
+
+ //edit->setText( _value );
+ // This is what caused "can't click on items before clicking on Name header".
+ // Probably due to the resizeEvent handler using width().
+ //resize( minimumWidth(), sizeHint().height() );
+ edit->setFocus();
+ slotTextChanged();
+}
+
+
+// ----------------------------------------------------------------------
+
+KOpenWithDlg::~KOpenWithDlg()
+{
+ delete d;
+ d = 0;
+}
+
+// ----------------------------------------------------------------------
+
+void KOpenWithDlg::slotClear()
+{
+ edit->setURL(QString::null);
+ edit->setFocus();
+}
+
+
+// ----------------------------------------------------------------------
+
+void KOpenWithDlg::slotSelected( const QString& /*_name*/, const QString& _exec )
+{
+ kdDebug(250)<<"KOpenWithDlg::slotSelected"<<endl;
+ KService::Ptr pService = d->curService;
+ edit->setURL( _exec ); // calls slotTextChanged :(
+ d->curService = pService;
+}
+
+
+// ----------------------------------------------------------------------
+
+void KOpenWithDlg::slotHighlighted( const QString& _name, const QString& )
+{
+ kdDebug(250)<<"KOpenWithDlg::slotHighlighted"<<endl;
+ qName = _name;
+ d->curService = KService::serviceByName( qName );
+ if (!m_terminaldirty)
+ {
+ // ### indicate that default value was restored
+ terminal->setChecked(d->curService->terminal());
+ QString terminalOptions = d->curService->terminalOptions();
+ nocloseonexit->setChecked( (terminalOptions.contains( "--noclose" ) > 0) );
+ m_terminaldirty = false; // slotTerminalToggled changed it
+ }
+}
+
+// ----------------------------------------------------------------------
+
+void KOpenWithDlg::slotTextChanged()
+{
+ kdDebug(250)<<"KOpenWithDlg::slotTextChanged"<<endl;
+ // Forget about the service
+ d->curService = 0L;
+ d->ok->setEnabled( !edit->url().isEmpty());
+}
+
+// ----------------------------------------------------------------------
+
+void KOpenWithDlg::slotTerminalToggled(bool)
+{
+ // ### indicate that default value was overridden
+ m_terminaldirty = true;
+ nocloseonexit->setDisabled( ! terminal->isChecked() );
+}
+
+// ----------------------------------------------------------------------
+
+void KOpenWithDlg::slotDbClick()
+{
+ if (m_pTree->isDirSel() ) return; // check if a directory is selected
+ slotOK();
+}
+
+void KOpenWithDlg::setSaveNewApplications(bool b)
+{
+ d->saveNewApps = b;
+}
+
+void KOpenWithDlg::slotOK()
+{
+ QString typedExec(edit->url());
+ QString fullExec(typedExec);
+
+ QString serviceName;
+ QString initialServiceName;
+ QString preferredTerminal;
+ m_pService = d->curService;
+ if (!m_pService) {
+ // No service selected - check the command line
+
+ // Find out the name of the service from the command line, removing args and paths
+ serviceName = KRun::binaryName( typedExec, true );
+ if (serviceName.isEmpty())
+ {
+ // TODO add a KMessageBox::error here after the end of the message freeze
+ return;
+ }
+ initialServiceName = serviceName;
+ kdDebug(250) << "initialServiceName=" << initialServiceName << endl;
+ int i = 1; // We have app, app-2, app-3... Looks better for the user.
+ bool ok = false;
+ // Check if there's already a service by that name, with the same Exec line
+ do {
+ kdDebug(250) << "looking for service " << serviceName << endl;
+ KService::Ptr serv = KService::serviceByDesktopName( serviceName );
+ ok = !serv; // ok if no such service yet
+ // also ok if we find the exact same service (well, "kwrite" == "kwrite %U"
+ if ( serv && serv->type() == "Application")
+ {
+ QString exec = serv->exec();
+ fullExec = exec;
+ exec.replace("%u", "", false);
+ exec.replace("%f", "", false);
+ exec.replace("-caption %c", "");
+ exec.replace("-caption \"%c\"", "");
+ exec.replace("%i", "");
+ exec.replace("%m", "");
+ exec = exec.simplifyWhiteSpace();
+ if (exec == typedExec)
+ {
+ ok = true;
+ m_pService = serv;
+ kdDebug(250) << k_funcinfo << "OK, found identical service: " << serv->desktopEntryPath() << endl;
+ }
+ }
+ if (!ok) // service was found, but it was different -> keep looking
+ {
+ ++i;
+ serviceName = initialServiceName + "-" + QString::number(i);
+ }
+ }
+ while (!ok);
+ }
+ if ( m_pService )
+ {
+ // Existing service selected
+ serviceName = m_pService->name();
+ initialServiceName = serviceName;
+ fullExec = m_pService->exec();
+ }
+
+ if (terminal->isChecked())
+ {
+ KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
+ preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
+ m_command = preferredTerminal;
+ // only add --noclose when we are sure it is konsole we're using
+ if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
+ m_command += QString::fromLatin1(" --noclose");
+ m_command += QString::fromLatin1(" -e ");
+ m_command += edit->url();
+ kdDebug(250) << "Setting m_command to " << m_command << endl;
+ }
+ if ( m_pService && terminal->isChecked() != m_pService->terminal() )
+ m_pService = 0L; // It's not exactly this service we're running
+
+ bool bRemember = remember && remember->isChecked();
+
+ if ( !bRemember && m_pService)
+ {
+ accept();
+ return;
+ }
+
+ if (!bRemember && !d->saveNewApps)
+ {
+ // Create temp service
+ m_pService = new KService(initialServiceName, fullExec, QString::null);
+ if (terminal->isChecked())
+ {
+ m_pService->setTerminal(true);
+ // only add --noclose when we are sure it is konsole we're using
+ if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
+ m_pService->setTerminalOptions("--noclose");
+ }
+ accept();
+ return;
+ }
+
+ // if we got here, we can't seem to find a service for what they
+ // wanted. The other possibility is that they have asked for the
+ // association to be remembered. Create/update service.
+
+ QString newPath;
+ QString oldPath;
+ QString menuId;
+ if (m_pService)
+ {
+ oldPath = m_pService->desktopEntryPath();
+ newPath = m_pService->locateLocal();
+ menuId = m_pService->menuId();
+ kdDebug(250) << "Updating exitsing service " << m_pService->desktopEntryPath() << " ( " << newPath << " ) " << endl;
+ }
+ else
+ {
+ newPath = KService::newServicePath(false /* hidden */, serviceName, &menuId);
+ kdDebug(250) << "Creating new service " << serviceName << " ( " << newPath << " ) " << endl;
+ }
+
+ int maxPreference = 1;
+ if (!qServiceType.isEmpty())
+ {
+ KServiceTypeProfile::OfferList offerList = KServiceTypeProfile::offers( qServiceType );
+ if (!offerList.isEmpty())
+ maxPreference = offerList.first().preference();
+ }
+
+ KDesktopFile *desktop = 0;
+ if (!oldPath.isEmpty() && (oldPath != newPath))
+ {
+ KDesktopFile orig(oldPath, true);
+ desktop = orig.copyTo(newPath);
+ }
+ else
+ {
+ desktop = new KDesktopFile(newPath);
+ }
+ desktop->writeEntry("Type", QString::fromLatin1("Application"));
+ desktop->writeEntry("Name", initialServiceName);
+ desktop->writePathEntry("Exec", fullExec);
+ if (terminal->isChecked())
+ {
+ desktop->writeEntry("Terminal", true);
+ // only add --noclose when we are sure it is konsole we're using
+ if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
+ desktop->writeEntry("TerminalOptions", "--noclose");
+ }
+ else
+ {
+ desktop->writeEntry("Terminal", false);
+ }
+ desktop->writeEntry("InitialPreference", maxPreference + 1);
+
+
+ if (bRemember || d->saveNewApps)
+ {
+ QStringList mimeList = desktop->readListEntry("MimeType", ';');
+ if (!qServiceType.isEmpty() && !mimeList.contains(qServiceType))
+ mimeList.append(qServiceType);
+ desktop->writeEntry("MimeType", mimeList, ';');
+
+ if ( !qServiceType.isEmpty() )
+ {
+ // Also make sure the "auto embed" setting for this mimetype is off
+ KDesktopFile mimeDesktop( locateLocal( "mime", qServiceType + ".desktop" ) );
+ mimeDesktop.writeEntry( "X-KDE-AutoEmbed", false );
+ mimeDesktop.sync();
+ }
+ }
+
+ // write it all out to the file
+ desktop->sync();
+ delete desktop;
+
+ KService::rebuildKSycoca(this);
+
+ m_pService = KService::serviceByMenuId( menuId );
+
+ Q_ASSERT( m_pService );
+
+ accept();
+}
+
+QString KOpenWithDlg::text() const
+{
+ if (!m_command.isEmpty())
+ return m_command;
+ else
+ return edit->url();
+}
+
+void KOpenWithDlg::hideNoCloseOnExit()
+{
+ // uncheck the checkbox because the value could be used when "Run in Terminal" is selected
+ nocloseonexit->setChecked( false );
+ nocloseonexit->hide();
+}
+
+void KOpenWithDlg::hideRunInTerminal()
+{
+ terminal->hide();
+ hideNoCloseOnExit();
+}
+
+void KOpenWithDlg::accept()
+{
+ KHistoryCombo *combo = static_cast<KHistoryCombo*>( edit->comboBox() );
+ if ( combo ) {
+ combo->addToHistory( edit->url() );
+
+ KConfig *kc = KGlobal::config();
+ KConfigGroupSaver ks( kc, QString::fromLatin1("Open-with settings") );
+ kc->writeEntry( QString::fromLatin1("History"), combo->historyItems() );
+ kc->writeEntry(QString::fromLatin1("CompletionMode"),
+ combo->completionMode());
+ // don't store the completion-list, as it contains all of KURLCompletion's
+ // executables
+ kc->sync();
+ }
+
+ QDialog::accept();
+}
+
+
+///////////////
+
+#ifndef KDE_NO_COMPAT
+bool KFileOpenWithHandler::displayOpenWithDialog( const KURL::List& urls )
+{
+ KOpenWithDlg l( urls, i18n("Open with:"), QString::null, 0L );
+ if ( l.exec() )
+ {
+ KService::Ptr service = l.service();
+ if ( !!service )
+ return KRun::run( *service, urls );
+
+ kdDebug(250) << "No service set, running " << l.text() << endl;
+ return KRun::run( l.text(), urls );
+ }
+ return false;
+}
+#endif
+
+#include "kopenwith.moc"
+#include "kopenwith_p.moc"
+