[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/KDE/4.0/kdelibs/kio/kfile
From:       David Faure <faure () kde ! org>
Date:       2008-02-29 21:33:50
Message-ID: 1204320830.695282.15060.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 780728 by dfaure:

Backport reformattings and r780723:
Make KOpenWithDialog write to mimeapps.list when asked to remember an association \
between a mimetype and an existing application.

It still has to write a new .desktop file when the user types the name of a program \
without a .desktop file, or when checking "Run in terminal" (but in that case it's \
not a copy of another desktop file, so the previous fix to KConfig::copyTo is now \
                unrelated to this code).
CCBUG: 154595


 M  +134 -168  kopenwithdialog.cpp  


--- branches/KDE/4.0/kdelibs/kio/kfile/kopenwithdialog.cpp #780727:780728
@@ -39,7 +39,6 @@
 #include <krun.h>
 #include <kstandarddirs.h>
 #include <kstringhandler.h>
-#include <kmimetypetrader.h>
 #include <kurlcompletion.h>
 #include <kurlrequester.h>
 #include <kmimetype.h>
@@ -432,6 +431,8 @@
      */
     void setMimeType(const KUrl::List &_urls);
 
+    void addToMimeAppsList(const QString& serviceId);
+
     /**
      * Create a dialog that asks for a application to open a given
      * URL(s) with.
@@ -705,7 +706,7 @@
 
 void KOpenWithDialog::slotTextChanged()
 {
-    kDebug(250)<<"KOpenWithDialog::slotTextChanged";
+    kDebug(250)<<"KOpenWithDialog::slotTextChanged" << d->edit->url();
     // Forget about the service
     d->curService = 0L;
     enableButton(Ok, !d->edit->url().isEmpty());
@@ -736,188 +737,153 @@
   d->saveNewApps = b;
 }
 
-void KOpenWithDialogPrivate::_k_slotOK()
+static QString simplifiedExecLineFromService(const QString& fullExec)
 {
-  QString typedExec(edit->url().pathOrUrl());
-  QString fullExec(typedExec);
+    QString exec = fullExec;
+    exec.remove("%u", Qt::CaseInsensitive);
+    exec.remove("%f", Qt::CaseInsensitive);
+    exec.remove("-caption %c");
+    exec.remove("-caption \"%c\"");
+    exec.remove("%i");
+    exec.remove("%m");
+    return exec.simplified();
+}
 
-  QString serviceName;
-  QString initialServiceName;
-  QString preferredTerminal;
-  m_pService = curService;
-  if (!m_pService) {
-    // No service selected - check the command line
+void KOpenWithDialogPrivate::addToMimeAppsList(const QString& serviceId)
+{
+    KSharedConfig::Ptr profile = KSharedConfig::openConfig("mimeapps.list", \
KConfig::NoGlobals, "xdgdata-apps"); +    KConfigGroup addedApps(profile, "Added \
Associations"); +    QStringList apps = addedApps.readXdgListEntry(qMimeType);
+    apps.removeAll(serviceId);
+    apps.prepend(serviceId); // make it the preferred app
+    addedApps.writeXdgListEntry(qMimeType, apps);
+    addedApps.sync();
 
-    // 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;
-    kDebug(250) << "initialServiceName=" << initialServiceName;
-    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 {
-        kDebug(250) << "looking for service " << serviceName;
-        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->isApplication())
-        {
-            QString exec = serv->exec();
-            fullExec = exec;
-            exec.replace("%u", "", Qt::CaseInsensitive);
-            exec.replace("%f", "", Qt::CaseInsensitive);
-            exec.replace("-caption %c", "");
-            exec.replace("-caption \"%c\"", "");
-            exec.replace("%i", "");
-            exec.replace("%m", "");
-            exec = exec.simplified();
-            if (exec == typedExec)
-            {
-                ok = true;
-                m_pService = serv;
-                kDebug(250) << "OK, found identical service: " << serv->entryPath();
-            }
-        }
-        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();
-  }
+    // Also make sure the "auto embed" setting for this mimetype is off
+    KSharedConfig::Ptr fileTypesConfig = KSharedConfig::openConfig("filetypesrc", \
KConfig::NoGlobals); +    \
fileTypesConfig->group("EmbedSettings").writeEntry(QString("embed-")+qMimeType, \
false); +    fileTypesConfig->sync();
 
-  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().pathOrUrl();
-    kDebug(250) << "Setting m_command to " << m_command;
-  }
-  if ( m_pService && terminal->isChecked() != m_pService->terminal() )
-      m_pService = 0L; // It's not exactly this service we're running
+    kDebug(250) << "rebuilding ksycoca...";
 
-  bool bRemember = remember && remember->isChecked();
+    // kbuildsycoca is the one reading mimeapps.list, so we need to run it now
+    KBuildSycocaProgressDialog::rebuildKSycoca(q);
 
-  if ( !bRemember && m_pService)
-  {
-        q->accept();
-    return;
-  }
+    m_pService = KService::serviceByMenuId(serviceId);
+    Q_ASSERT( m_pService );
+}
 
-    if (!bRemember && !saveNewApps)
-  {
-    // Create temp service
-    m_pService = new KService(initialServiceName, fullExec, QString());
-    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");
-    }
-        q->accept();
-    return;
-  }
+void KOpenWithDialogPrivate::_k_slotOK()
+{
+    QString typedExec(edit->url().pathOrUrl());
+    if (typedExec.isEmpty())
+        return;
+    QString fullExec(typedExec);
 
-  // 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 serviceName;
+    QString initialServiceName;
+    QString preferredTerminal;
+    m_pService = curService;
+    if (!m_pService) {
+        // No service selected - check the command line
 
-  QString newPath;
-  QString oldPath;
-  QString menuId;
-  if (m_pService)
-  {
-    oldPath = m_pService->entryPath();
-    newPath = m_pService->locateLocal();
-    menuId = m_pService->menuId();
-    kDebug(250) << "Updating exitsing service " << m_pService->entryPath() << " ( " \
                << newPath << " ) ";
-  }
-  else
-  {
-    newPath = KService::newServicePath(false /* hidden */, serviceName, &menuId);
-    kDebug(250) << "Creating new service " << serviceName << " ( " << newPath << " ) \
                ";
-  }
+        // 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;
+        kDebug(250) << "initialServiceName=" << initialServiceName;
+        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 {
+            kDebug(250) << "looking for service" << serviceName;
+            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->isApplication()) {
+                fullExec = serv->exec();
+                if (typedExec == simplifiedExecLineFromService(fullExec)) {
+                    ok = true;
+                    m_pService = serv;
+                    kDebug(250) << "OK, found identical service: " << \
serv->entryPath(); +                }
+            }
+            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();
+    }
 
-  int maxPreference = 1;
-  if (!qMimeType.isEmpty())
-  {
-    // Find max highest preference from either initial preference or from profile
-    const KServiceOfferList offerList = KMimeTypeTrader::self()->weightedOffers( \
                qMimeType );
-    if (!offerList.isEmpty())
-      maxPreference = offerList.first().preference();
-  }
+    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().pathOrUrl();
+        kDebug(250) << "Setting m_command to" << m_command;
+    }
+    if ( m_pService && terminal->isChecked() != m_pService->terminal() )
+        m_pService = 0; // It's not exactly this service we're running
 
-  KDesktopFile *desktop = 0;
-  if (!oldPath.isEmpty() && (oldPath != newPath))
-  {
-     KDesktopFile orig( oldPath );
-     desktop = orig.copyTo( newPath );
-  }
-  else
-  {
-     desktop = new KDesktopFile(newPath);
-  }
-  KConfigGroup cg = desktop->desktopGroup();
-  cg.writeEntry("Type", "Application");
-  cg.writeEntry("Name", initialServiceName);
-  cg.writePathEntry("Exec", fullExec);
-  if (terminal->isChecked())
-  {
-    cg.writeEntry("Terminal", true);
-    // only add --noclose when we are sure it is konsole we're using
-    if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
-      cg.writeEntry("TerminalOptions", "--noclose");
-  }
-  else
-  {
-    cg.writeEntry("Terminal", false);
-  }
-  cg.writeEntry("InitialPreference", maxPreference + 1);
 
-
-    if (bRemember || saveNewApps) {
-        // Add mimetype to the service desktop file
-        QStringList mimeList = cg.readXdgListEntry("MimeType");
-        if (!qMimeType.isEmpty() && !mimeList.contains(qMimeType))
-            mimeList.append(qMimeType);
-        cg.writeXdgListEntry("MimeType", mimeList);
-
-        if ( !qMimeType.isEmpty() ) {
-            // Also make sure the "auto embed" setting for this mimetype is off
-            KSharedConfig::Ptr fileTypesConfig = \
                KSharedConfig::openConfig("filetypesrc", KConfig::NoGlobals);
-            fileTypesConfig->group("EmbedSettings").writeEntry(QString("embed-")+qMimeType, \
                false);
-            fileTypesConfig->sync();
+    const bool bRemember = remember && remember->isChecked();
+    kDebug(250) << "bRemember=" << bRemember << "service found=" << m_pService;
+    if (m_pService) {
+        if (bRemember) {
+            // Associate this app with qMimeType in mimeapps.list
+            Q_ASSERT(!qMimeType.isEmpty()); // we don't show the remember checkbox \
otherwise +            addToMimeAppsList(m_pService->storageId());
         }
-    }
+    } else {
+        const bool createDesktopFile = bRemember || saveNewApps;
+        if (!createDesktopFile) {
+            // Create temp service
+            m_pService = new KService(initialServiceName, fullExec, QString());
+            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");
+            }
+        } else {
+            // If we got here, we can't seem to find a service for what they wanted. \
Create one.  
-    // write it all out to the file
-    cg.sync();
-    delete desktop;
+            QString menuId;
+            QString newPath = KService::newServicePath(false /* ignored argument */, \
serviceName, &menuId); +            kDebug(250) << "Creating new service" << \
serviceName << "(" << newPath << ")";  
-    KBuildSycocaProgressDialog::rebuildKSycoca(q);
+            KDesktopFile desktopFile(newPath);
+            KConfigGroup cg = desktopFile.desktopGroup();
+            cg.writeEntry("Type", "Application");
+            cg.writeEntry("Name", initialServiceName);
+            cg.writePathEntry("Exec", fullExec);
+            cg.writeEntry("NoDisplay", true); // don't make it appear in the K menu
+            if (terminal->isChecked()) {
+                cg.writeEntry("Terminal", true);
+                // only add --noclose when we are sure it is konsole we're using
+                if (preferredTerminal == "konsole" && nocloseonexit->isChecked())
+                    cg.writeEntry("TerminalOptions", "--noclose");
+            }
+            cg.writeXdgListEntry("MimeType", QStringList() << qMimeType);
+            cg.sync();
 
-    m_pService = KService::serviceByMenuId( menuId );
-    Q_ASSERT( m_pService );
-
+            addToMimeAppsList(menuId);
+        }
+    }
     q->accept();
 }
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic