--- khtml/misc/knsplugininstaller.cpp	(revision 0)
+++ khtml/misc/knsplugininstaller.cpp	(revision 0)
@@ -0,0 +1,672 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 2005 Benoit Canet <bcanet@dental-on-line.fr>
+ *           with some advices from Aurelien Gateau <agateau@dental-on-line.fr>
+ *
+ * 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 Steet, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#include "knsplugininstaller.moc"
+
+#include <kdebug.h>
+#include <kdiroperator.h> 
+#include <klistview.h>
+#include <klocale.h>
+#include <kstddirs.h>
+#include <ktempfile.h> 
+#include <netaccess.h>
+
+#include <qbuttongroup.h>
+#include <qdir.h>
+#include <qiodevice.h>
+#include <qfile.h>
+#include <qlabel.h>
+#include <qlayout.h> 
+#include <qmap.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+#include <sys/utsname.h>
+
+// Use 6031 for debugging (render_frame)
+#define DEBUG_NUMBER 6031 
+
+/*
+ * Utility class to associate a list item with a pluginInfo object
+ */
+class PluginListItem : public QListViewItem
+{
+
+public:
+    PluginListItem(KNSPluginInfo pluginInfo, QListView *parent)
+    : QListViewItem(parent, pluginInfo.pluginName())
+    , m_pluginInfo(pluginInfo) {}
+    KNSPluginInfo pluginInfo() const { return m_pluginInfo; }
+
+private:
+    KNSPluginInfo m_pluginInfo;
+
+};
+
+
+// public methods 
+
+KNSPluginInstallEngine::KNSPluginInstallEngine(KMimeType::Ptr mime) : QObject()
+{
+    m_mime = mime;
+
+    // Fill the architecture map 
+    m_archMap["i386"] = "ia32";
+    m_archMap["i486"] = "ia32";
+    m_archMap["i586"] = "ia32";
+    m_archMap["i686"] = "ia32";
+}
+
+KNSPluginInstallEngine::~KNSPluginInstallEngine()
+{
+}
+
+bool KNSPluginInstallEngine::pluginAvailable()
+{
+
+    if(m_pluginList.count())
+        return true;
+    
+    // check if pluginsListFile is present in kde config
+    if(!loadConfig())
+        return false;
+
+    // load the xml configuration file 
+    if(!loadXmlConfig())
+        return false;
+    
+    return findPlugin();
+}
+
+bool KNSPluginInstallEngine::isActive() 
+{
+    // check if we have a configuration key in the kde registry
+    QString pluginsListFile;
+    KConfig cfg("kcmnspluginrc", true);
+    cfg.setGroup("Misc");
+    pluginsListFile = cfg.readPathEntry("PluginsListFile");
+    return !pluginsListFile.isEmpty();
+}
+
+const QValueList<KNSPluginInfo>& KNSPluginInstallEngine::pluginList() const
+{
+    return m_pluginList;
+}
+
+// private methods 
+bool KNSPluginInstallEngine::loadConfig()
+{
+    QString pluginsListFile;
+    KConfig cfg("kcmnspluginrc", true);
+    cfg.setGroup("Misc");
+    pluginsListFile = cfg.readPathEntry("PluginsListFile");
+    if(!pluginsListFile.isEmpty())
+    {
+        m_pluginsListFileURL = KURL(pluginsListFile);
+        kdDebug(DEBUG_NUMBER) << "config loaded "<<endl;
+        return true;
+    }
+    return false;
+}
+
+bool KNSPluginInstallEngine::loadXmlConfig()
+{
+
+    // load the Xml configuration file 
+    if(m_pluginsXmlConfig.isEmpty())
+    {
+        QString tmpFile;
+        if(KIO::NetAccess::download(m_pluginsListFileURL, tmpFile, NULL)) {
+            QFile f(tmpFile);
+            if(!f.open(IO_ReadOnly))
+                return false;
+            QTextStream stream(&f);
+            stream.setEncoding(QTextStream::UnicodeUTF8);
+            m_pluginsXmlConfig = stream.read();
+            f.close();
+            KIO::NetAccess::removeTempFile(tmpFile);
+        } else
+            return false;
+    }
+    kdDebug(DEBUG_NUMBER) << "xml config loaded :" << endl;
+    return true;
+}
+
+bool KNSPluginInstallEngine::findPlugin()
+{
+
+    // get system infos
+    // TODO/FIX : correct this to work with x86-64 machines
+    utsname sysinfo;
+    if(uname(&sysinfo))
+        return false;
+    QString sysname(sysinfo.sysname);
+    QString machine(sysinfo.machine);
+    QString arch = m_archMap[machine]; 
+    
+    // Parse the document
+    QDomDocument doc("xmlConfig");
+    doc.setContent(m_pluginsXmlConfig);
+    QDomNodeList archList = doc.elementsByTagName(QString("arch"));
+    QDomNode archNode, osNode , pluginNode, node;
+    QDomElement e;
+
+    // look for the correct architecture
+    bool found = false;
+    unsigned int i;
+    for(i=0; i < archList.count() ; i++) {
+        archNode = archList.item(i);
+        e = archNode.toElement();
+        if( e.attribute("architecture") == arch) {
+            kdDebug(DEBUG_NUMBER) << "found correct architecture :" << arch << endl;
+            found = true;
+            break;
+        }
+    }
+
+    if(!found)
+        return false;
+    
+    // look for the correct os 
+    found = false;
+    osNode = archNode.firstChild();
+    while(!osNode.isNull()) {
+        e = osNode.toElement();
+        if( e.tagName() == "os" && e.attribute("name") == sysname) {
+            kdDebug(DEBUG_NUMBER) << "found correct os :" << sysname << endl;
+            found = true;
+            break;
+        }
+        osNode=osNode.nextSibling();
+    }
+
+    if(!found)
+        return false;
+   
+    // Look for a plugin with the given mimetype
+    pluginNode = osNode.firstChild();
+    while(!pluginNode.isNull()) {
+        e = pluginNode.toElement();
+        if( e.tagName() == "plugin" && m_mime->is(e.attribute("mimetype")) ) {
+            kdDebug(DEBUG_NUMBER) << "found correct plugin :" << e.attribute("mimetype") << endl;
+            KNSPluginInfo pluginInfo(pluginNode);
+                if(pluginInfo.isValid())
+                    m_pluginList.append(pluginInfo);
+        }
+        pluginNode=pluginNode.nextSibling();
+    }
+
+    if(m_pluginList.count())
+        return true;
+    else
+        return false;
+}
+
+
+void KNSPluginInstallEngine::startInstall(KNSPluginInfo info)
+{
+    m_toInstallPluginInfo = info;
+    // create a temporary dowload file 
+    KTempFile tempFile(locateLocal("tmp", "plugin") , QString(".tar.gz"));
+    m_tmpPluginFileName = tempFile.name();
+    tempFile.unlink();
+    tempFile.close();
+    // start the download job
+    m_downloadJob  = KIO::copy(info.pluginURL(), "file://"+m_tmpPluginFileName, false );
+    // connect signals 
+    connect(m_downloadJob, SIGNAL(percent (KIO::Job *, unsigned long)), this , SLOT(slotDownLoadProgress(KIO::Job *, unsigned long)));
+    connect(m_downloadJob, SIGNAL(result(KIO::Job *)), this, SLOT(slotDownloadResult(KIO::Job *)) );
+    kdDebug(DEBUG_NUMBER) << "download plugin " << m_tmpPluginFileName << endl;
+} 
+
+void KNSPluginInstallEngine::slotDownLoadProgress(KIO::Job *, unsigned long percent)
+{ 
+    // propagate the download progression
+    emit installProgress( ((int)percent)/3 );
+}
+
+void KNSPluginInstallEngine::slotDownloadResult(KIO::Job *job)
+{ 
+    // test if the download job suceed
+    if(job->error()) {
+        kdDebug(DEBUG_NUMBER) << "download error" << m_tmpPluginFileName << endl;
+        emit installFailed();
+     }
+     else {
+        kdDebug(DEBUG_NUMBER) << "download completed" << m_tmpPluginFileName << endl;
+        // the download succeed copy the plugins files 
+        
+       // test the existance of the homedir
+       QDir dir(QDir::homeDirPath());
+       if(!dir.exists()) {
+           emit installFailed();
+           return;
+        }
+
+       // test and create firefox plugins directory
+       if(!dir.exists(".mozilla"))
+           dir.mkdir(".mozilla");
+       if(!dir.exists(".mozilla/plugins"))
+           dir.mkdir(".mozilla/plugins");
+       // destination kurl
+       KURL destURL("file://"+QDir::homeDirPath()+"/.mozilla/plugins");
+
+       // construct the source kurlList
+       KURL::List urlList;
+       QStringList pluginFileList = m_toInstallPluginInfo.pluginFileList();
+
+       QStringList::iterator it;
+       for( it = pluginFileList.begin(); it != pluginFileList.end(); ++it ) {
+           urlList.append( KURL("tar://"+m_tmpPluginFileName+"/"+(*it)) );
+        }
+       m_installFileJob  = KIO::copy(urlList , destURL, false );
+       connect(m_installFileJob, SIGNAL(percent (KIO::Job *, unsigned long)), this , SLOT(slotCopyProgress(KIO::Job *, unsigned long)));
+       connect(m_installFileJob, SIGNAL(result(KIO::Job *)), this, SLOT(slotCopyResult(KIO::Job *)) );
+    }
+    kdDebug(DEBUG_NUMBER) << "COPY FILE " << m_tmpPluginFileName << endl;
+
+    // zero the download job pointer
+    m_downloadJob = NULL;
+}
+
+void KNSPluginInstallEngine::slotCopyProgress(KIO::Job *, unsigned long percent)
+{
+    // propagate the download progression
+    emit installProgress( ((int)percent)/3 + 33 );
+} 
+ 
+void KNSPluginInstallEngine::slotCopyResult(KIO::Job *job)
+{
+    // test if the download job suceed
+    if(job->error()) {
+        kdDebug(DEBUG_NUMBER) << "download error" << m_tmpPluginFileName << endl;
+        emit installFailed();
+    }
+    else {
+       // start the plugins scan
+       m_scanProc = new QProcess( this );
+       m_scanProc->addArgument( "nspluginscan" );
+       m_scanProc->addArgument( "--verbose" );
+
+       connect( m_scanProc, SIGNAL(readyReadStdout()),
+               this, SLOT(readScanProcFromStdout()) );
+       connect( m_scanProc, SIGNAL(processExited()),
+               this, SLOT(endScanProc()) );
+       if ( !m_scanProc->start() ) {
+            emit installFailed();
+       }
+    }
+}
+
+void KNSPluginInstallEngine::readScanProcFromStdout()
+{
+    // Monitor the scan progress
+    QString progress = m_scanProc->readLineStdout();
+    int percent;
+    bool ok;
+    percent = progress.toInt(&ok);
+    if(!ok)
+        emit installFailed();
+    emit installProgress( (percent)/3 + 66 );
+}
+
+
+void KNSPluginInstallEngine::endScanProc()
+{
+    // end of scan
+    if(m_scanProc->normalExit()) {
+        emit installProgress( 100 );
+        emit installCompleted();
+    } else
+        emit installFailed();
+}
+
+KNSPluginWizard::KNSPluginWizard(QWidget *parent, const char *name, KMimeType::Ptr mime)
+: KWizard(parent, name, true)
+, m_installEngine(mime)
+{
+    setCaption(i18n("KDE plugin wizard"));
+    setModal(true);
+
+    // read the plugin installer configuration
+    m_installEngine.pluginAvailable();
+
+    // init the wizzard Pages
+    initConfirmationPage();
+    initLicencePage();
+    initInstallationProgressPage();
+    initFinishPage();
+    initPagesButtonStates();
+
+    // connect signals and slots
+    connectSignals();
+
+    //set correct default installation status
+    m_installationComplete = false;
+
+};
+
+
+KNSPluginWizard::~KNSPluginWizard()
+{
+};
+
+void KNSPluginWizard::initConfirmationPage() 
+{
+
+        m_confirmationVBox = new QVBox(this);
+        new QLabel(i18n("The following plugins are available."), m_confirmationVBox);
+        m_pluginListView = new KListView(m_confirmationVBox);        
+        m_pluginListView->addColumn(i18n("Name"));
+        m_pluginListView->setSelectionMode(QListView::Single);
+        new QLabel(i18n("Click on next to install the selected plugin."), m_confirmationVBox);
+        addPage (m_confirmationVBox, i18n("Plugin installation confirmation"));
+        
+        bool selected = false;
+  
+        // Fill the plugin list
+        QValueList<KNSPluginInfo>::iterator it;
+        QValueList<KNSPluginInfo> pluginList = m_installEngine.pluginList();
+        for( it = pluginList.begin(); it != pluginList.end(); ++it ) {
+            PluginListItem *item = new PluginListItem((*it) , m_pluginListView);
+            if(!selected) {
+                selected = true;
+                m_pluginListView->setSelected(item, true);
+            }
+            kdDebug(DEBUG_NUMBER) << "New Plugin List item"<< endl;
+            setNextEnabled(m_confirmationVBox, true);
+        }
+}
+
+void KNSPluginWizard::initLicencePage()
+{
+    m_licenceVBox = new QVBox(this);
+    m_licencePageLabel = new QLabel(m_licenceVBox);
+    m_licencePageText = new KTextEdit(m_licenceVBox);
+    m_licencePageText->setReadOnly(true);
+    
+    // invisible buttonGroup
+    QButtonGroup *buttonGroup = new QButtonGroup(this);
+    m_agreementButtonGroup = buttonGroup;
+    buttonGroup->hide();
+    buttonGroup->setExclusive(true);
+    
+    m_licencePageAgree = new QRadioButton ( i18n("I agree."), m_licenceVBox);
+    
+    m_licencePageDisagree = new QRadioButton ( i18n("I do not agree (plugin will not be installed)."), m_licenceVBox);
+
+    buttonGroup->insert(m_licencePageAgree);
+    buttonGroup->insert(m_licencePageDisagree);
+    m_licencePageDisagree->setChecked(true);
+    
+    addPage (m_licenceVBox, i18n("Plugin licence"));
+
+
+    connect(buttonGroup, SIGNAL(clicked(int)), this, SLOT(slotAgreementClicked(int)));
+}
+
+void KNSPluginWizard::initInstallationProgressPage() {
+
+    m_installationProgressWidget = new QWidget(this);
+    QVBoxLayout *layout = new QVBoxLayout(m_installationProgressWidget);
+    layout->addWidget(new QLabel(i18n("Installation in progress."), m_installationProgressWidget));
+    layout->addItem(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Expanding ));
+    m_installationProgressBar = new KProgress(m_installationProgressWidget);
+    m_installationProgressBar->setTotalSteps(100);
+    layout->addWidget(m_installationProgressBar);
+    
+    addPage( m_installationProgressWidget, i18n("Plugin installation"));
+    
+}
+
+void KNSPluginWizard::initFinishPage()
+{
+    m_finishWidget = new QWidget(this);
+    QVBoxLayout *layout = new QVBoxLayout(m_finishWidget);
+    layout->addItem(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Expanding ));
+    m_finishLabel = new QLabel(m_finishWidget);
+    layout->addWidget(m_finishLabel);
+    layout->addItem(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Expanding ));
+    
+    addPage(m_finishWidget, i18n("Installation status"));
+    
+}
+
+
+void KNSPluginWizard::initPagesButtonStates()
+{
+    // set buttons states for the confirmation page
+    setNextEnabled(m_confirmationVBox, true);
+    setFinishEnabled(m_confirmationVBox, false);
+    setHelpEnabled(m_confirmationVBox, false);
+
+    // set buttons states for the licence page
+    setNextEnabled(m_licenceVBox    , false);
+    setBackEnabled(m_licenceVBox  , false);
+    setFinishEnabled(m_licenceVBox  , false);
+    setHelpEnabled(m_licenceVBox    , false);
+    
+    // for the installation page
+    setNextEnabled(m_installationProgressWidget     , false);
+    setBackEnabled(m_installationProgressWidget     , false);
+    setFinishEnabled(m_installationProgressWidget   , false);
+    setHelpEnabled(m_installationProgressWidget     , false);
+
+    // for the finish page 
+    setNextEnabled(m_finishWidget     , false);
+    setBackEnabled(m_finishWidget     , false);
+    setFinishEnabled(m_finishWidget   , true);
+    setHelpEnabled(m_finishWidget     , false);
+}
+
+
+
+void KNSPluginWizard::connectSignals() {
+    connect(&m_installEngine, SIGNAL(installProgress(int)), m_installationProgressBar, SLOT(setProgress(int)) );
+    connect(&m_installEngine, SIGNAL(installCompleted()), this, SLOT(slotInstallationCompleted()) );
+     connect(&m_installEngine, SIGNAL(installFailed()), this, SLOT(slotInstallationFailed()) );
+     
+
+}
+
+void KNSPluginWizard::showPage(QWidget *page)
+{
+
+    // if the licence page is shown set the label and the licence content
+    if(page == m_licenceVBox && m_licencePageLabel->text().isEmpty()) {
+        KNSPluginInfo info =  static_cast<PluginListItem *>(m_pluginListView->selectedItem())->pluginInfo();
+        m_licencePageLabel->setText(i18n("To install ")+info.pluginName()+i18n(" you need to agree to the following"));
+        QString licence;
+        licence = info.licence();
+        QString tmpFile;
+        if(info.licenceURL().isValid()) 
+            // retrieve the licence if we have an url
+            if(KIO::NetAccess::download(info.licenceURL(), tmpFile, NULL)) {
+                    QFile f(tmpFile);
+                    if(f.open(IO_ReadOnly)) {
+                        QTextStream stream(&f);
+                        stream.setEncoding(QTextStream::UnicodeUTF8);
+                        licence  = stream.read();
+                        f.close();
+                        KIO::NetAccess::removeTempFile(tmpFile);
+                    }
+             } 
+        // else display the licence found in the xml config
+        m_licencePageText->setText(licence);
+
+    }
+    
+    // if the installation page is shown start the download
+    if(page == m_installationProgressWidget) {
+        KNSPluginInfo info =  static_cast<PluginListItem *>(m_pluginListView->selectedItem())->pluginInfo();
+        m_installEngine.startInstall(info);
+
+    }
+
+    // If we must display the finish page
+    if(page == m_finishWidget) {
+        if(m_installationComplete)  {
+            m_finishLabel->setText(i18n("Installation completed. Reload the page."));
+
+        } else
+            m_finishLabel->setText(i18n("Installation failed"));
+
+    }
+
+    
+    KWizard::showPage(page);
+}
+
+int KNSPluginWizard::exec()
+{
+    if(!m_installEngine.pluginList().count())
+        return QDialog::Rejected;
+
+    return KWizard::exec();
+}
+
+
+bool KNSPluginWizard::pluginAvailable()
+{
+    return m_installEngine.pluginAvailable();
+}
+
+void KNSPluginWizard::slotAgreementClicked(int id)
+{
+    if( id == m_agreementButtonGroup->id(m_licencePageAgree) ) {
+        setNextEnabled(m_licenceVBox, true);
+   
+    } else {
+        setNextEnabled(m_licenceVBox, false);
+    }
+       
+}
+
+void KNSPluginWizard::slotInstallationCompleted() 
+{
+    m_installationComplete = true;
+    // enable next button 
+    setNextEnabled(m_installationProgressWidget, true);
+    next();
+}
+void KNSPluginWizard::slotInstallationFailed()
+{
+    m_installationComplete = false;
+    showPage(m_finishWidget);
+}
+
+
+// KNSPlugin info copy constructor
+
+KNSPluginInfo::KNSPluginInfo()
+{
+
+}
+
+// KNSPlugin info constructor par an xml dom fragment
+KNSPluginInfo::KNSPluginInfo(QDomNode pluginNode)
+{
+    QDomElement e;
+    QDomNode node;
+
+    // Read plugin informations
+    node = pluginNode.firstChild();
+    while(!node.isNull()) {
+        e = node.toElement();
+        if( e.tagName() == "pluginname") {
+            kdDebug(DEBUG_NUMBER) << "found name " << e.text() << endl;
+            m_pluginName = e.text();
+        }
+        
+        if( e.tagName() == "pluginurl") {
+            kdDebug(DEBUG_NUMBER) << "found plugin url " << e.text() << endl;
+            m_pluginURL = KURL(e.text());
+        }
+
+        if( e.tagName() == "licence") {
+            kdDebug(DEBUG_NUMBER) << "found licence " << e.text() << endl;
+            m_licence = e.text();
+        }            
+        
+        if( e.tagName() == "licenceurl") {
+            kdDebug(DEBUG_NUMBER) << "found licenceurl " << e.text() << endl;
+            m_licenceURL = KURL(e.text());
+        }            
+        
+        if( e.tagName() == "pluginfile") {
+            kdDebug(DEBUG_NUMBER) << "found pluginfile " << e.text() << endl;
+            m_pluginFileList.append(e.text());
+        }
+        node = node.nextSibling();
+    }
+}
+
+
+KNSPluginInfo::~KNSPluginInfo()
+{
+
+}
+
+
+bool KNSPluginInfo::isValid() const
+{
+    // tell if the pluginInfo is a valid One
+    if( m_pluginName.isEmpty() || ( m_licence.isEmpty() && !m_licenceURL.isValid() ) || !m_pluginURL.isValid() || m_pluginFileList.empty() ) {
+        kdDebug(DEBUG_NUMBER) << "invalid plugin info" << endl;
+        return false;
+
+    }
+    
+    else {
+
+        kdDebug(DEBUG_NUMBER) << "valid plugin info" << endl;
+        return true;
+    }
+}
+
+// Accesors
+QString KNSPluginInfo::pluginName() const
+{
+    return m_pluginName;
+}
+
+QString KNSPluginInfo::licence() const
+{
+    return m_licence;
+}
+
+KURL KNSPluginInfo::licenceURL() const
+{
+    return m_licenceURL;
+}
+
+KURL KNSPluginInfo::pluginURL() const
+{
+    return m_pluginURL;
+}
+
+const QStringList& KNSPluginInfo::pluginFileList() const
+{
+    return m_pluginFileList;
+}
--- khtml/misc/Makefile.am	(revision 558891)
+++ khtml/misc/Makefile.am	(working copy)
@@ -22,14 +22,14 @@
 noinst_LTLIBRARIES = libkhtmlmisc.la
 libkhtmlmisc_la_SOURCES = \
 	decoder.cpp    loader.cpp loader_jpeg.cpp guess_ja.cpp\
-	htmlhashes.cpp helper.cpp arena.cpp stringit.cpp
+	htmlhashes.cpp helper.cpp arena.cpp stringit.cpp knsplugininstaller.cpp
 libkhtmlmisc_la_LIBADD = $(LIBJPEG)
 libkhtmlmisc_la_LDFLAGS = $(USER_LDFLAGS)
 libkhtmlmisc_la_METASOURCES = AUTO
 
 noinst_HEADERS = \
 	decoder.h khtmllayout.h loader_jpeg.h loader.h guess_ja.h\
-	stringit.h htmlhashes.h helper.h shared.h arena.h 
+	stringit.h htmlhashes.h helper.h shared.h arena.h knsplugininstaller.h
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/dcop -I$(top_srcdir)/kio -I$(top_srcdir)/libltdl \
            -I$(top_srcdir)/khtml -I$(top_srcdir)/kutils $(all_includes)
--- khtml/misc/knsplugininstaller.h	(revision 0)
+++ khtml/misc/knsplugininstaller.h	(revision 0)
@@ -0,0 +1,269 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 2005 Benoit Canet <bcanet@dental-on-line.fr>
+ *           with some advices from Aurelien Gateau <agateau@dental-on-line.fr>
+ *
+ * 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 Steet, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KNSPLUGININSTALLER_H
+#define KNSPLUGININSTALLER_H
+
+#include <job.h>
+#include <ktextedit.h>
+#include <kmimetype.h>
+#include <kprogress.h> 
+#include <kurl.h>
+#include <kwizard.h>
+
+#include <qbuttongroup.h>
+#include <qdom.h>
+#include <qlabel.h>
+#include <qobject.h>
+#include <qprocess.h>
+#include <qradiobutton.h>
+#include <qvaluelist.h>
+#include <qvbox.h>
+#include <qwidget.h>
+
+class QStringList;
+
+/*
+ * This class contains all the infos needed to install a given plugin
+ * Takes and parse a QDomNode in its constructor
+ */
+class KNSPluginInfo 
+{
+
+public:
+
+    /*
+     * Construct the plugin info object
+     */
+    KNSPluginInfo();
+    KNSPluginInfo(QDomNode pluginNode);
+    ~KNSPluginInfo();
+
+    /*
+     * Check the validity of the plugin info object
+     */
+    bool isValid() const;
+
+    //Accessor methods
+    QString pluginName() const;
+    QString licence() const;
+    KURL licenceURL() const;
+    KURL pluginURL() const;
+    const QStringList& pluginFileList() const;
+   
+private:
+ 
+    // plugin info
+    QString m_pluginName;
+    QString m_licence;
+    KURL m_licenceURL;
+    KURL m_pluginURL;
+    QStringList m_pluginFileList;
+    
+    
+};
+
+
+/*
+ * This class contain all the the methods used to perform a plugin installation
+ *
+ */
+class KNSPluginInstallEngine : public QObject
+{
+    Q_OBJECT
+public:
+
+    /*
+     * Construct the class
+     */
+    KNSPluginInstallEngine(KMimeType::Ptr mime);
+    ~KNSPluginInstallEngine();
+    
+    /*
+     * Check if the installer engine and wizzard is activated
+     */
+    static bool isActive();
+    /**
+     * Check the availability of a plugin 
+     */
+    bool pluginAvailable();
+    /*
+     * Return the list of plugins Available
+     */
+    const QValueList<KNSPluginInfo>& pluginList() const;
+    void startInstall(KNSPluginInfo info);
+
+    
+
+private:
+
+    // methods used to check the kde config and detect if an adequate plugin is available
+ 
+    /*
+     * load kde KNSPluginInstaller config
+     */
+    bool loadConfig();
+    /*
+     * retrieve the xml configuration file
+     */
+    bool loadXmlConfig();
+    /*
+     * parse the xml configuration file
+     */
+    bool findPlugin();
+    
+
+    QMap<QString, QString> m_archMap;
+    QString m_pluginsXmlConfig;
+    QValueList<KNSPluginInfo> m_pluginList;
+    KMimeType::Ptr m_mime;
+    KURL m_pluginsListFileURL;
+    QString m_tmpPluginFileName;
+    KIO::CopyJob *m_downloadJob;
+    KIO::CopyJob *m_installFileJob;
+    KNSPluginInfo m_toInstallPluginInfo;
+    QProcess *m_scanProc;
+    
+signals:
+    // Signals used to communicate with the wizzard 
+    void installProgress(int percent);
+    void installCompleted();
+    void installFailed();
+   
+private slots:
+    // Used to monitor the plugin downloading
+    void slotDownLoadProgress(KIO::Job *job, unsigned long percent);
+    void slotDownloadResult(KIO::Job *job);
+    
+    // Used to monitor the plugin installation
+    void slotCopyProgress(KIO::Job *job, unsigned long percent);
+    void slotCopyResult(KIO::Job *job);
+
+    // Used to monitor the plugins scan
+    void readScanProcFromStdout();
+    void endScanProc();
+
+
+
+};
+
+/*
+ * This class is a wizzard used to install a plugin 
+ */
+class KNSPluginWizard : public KWizard
+{
+    Q_OBJECT
+public:
+        
+    /**
+    * Construct a KNSpluginInstaller
+    */
+    KNSPluginWizard(QWidget *parent, const char *name,  KMimeType::Ptr mime);
+    ~KNSPluginWizard();
+
+
+    /**
+     * Lauch the wizzard
+     */
+    int exec();
+    /*
+     * Check the availability of a plugin
+     */
+    bool pluginAvailable();
+
+
+private:
+    // methods used in the constructor to init the wizzard pages
+    void initConfirmationPage();
+    void initLicencePage();
+    void initInstallationProgressPage();
+    void initFinishPage();
+
+    // in this method we disable or enable the wizzard pages buttons
+    void initPagesButtonStates();
+    
+    /*
+     * Connect signals
+     */
+    void connectSignals();
+    
+    /*
+     * Overiden method called when a page is shown
+     */
+    void showPage(QWidget *page);
+
+
+    // Plugin installation engine
+    KNSPluginInstallEngine m_installEngine;
+
+    // pages widgets
+    QVBox *m_confirmationVBox;
+    QVBox *m_licenceVBox;
+    QWidget *m_installationProgressWidget;
+    QWidget *m_finishWidget;
+    
+    // plugin list
+    KListView *m_pluginListView;
+    
+    // licence stuff
+    QLabel *m_licencePageLabel;
+    KTextEdit *m_licencePageText;
+    QRadioButton *m_licencePageAgree;
+    QRadioButton *m_licencePageDisagree;
+    QButtonGroup *m_agreementButtonGroup;
+
+    // installation progress bar
+    KProgress *m_installationProgressBar;
+
+    // Finish Label 
+    QLabel *m_finishLabel;
+
+    // installation status
+    bool m_installationComplete;
+ 
+private slots:
+    /*
+     * Check if the user Agree or disagree with the licence
+     */
+    void slotAgreementClicked(int id);
+    /*
+     * Called when the installation is completed
+     */
+    void slotInstallationCompleted();
+    /*
+     * Called when the installation has failed
+     */
+    void slotInstallationFailed();
+
+signals:
+    /*
+     * Emited when the installation has complete - TODO connect this signal to reload the page
+     */
+    void pluginInstallCompleted();
+};
+
+
+
+   
+
+#endif
--- khtml/rendering/render_frames.cpp	(revision 558891)
+++ khtml/rendering/render_frames.cpp	(working copy)
@@ -36,6 +36,7 @@
 #include "misc/htmltags.h"
 #include "khtmlview.h"
 #include "khtml_part.h"
+#include "misc/knsplugininstaller.h"
 
 #include <kapplication.h>
 #include <kmessagebox.h>
@@ -937,17 +938,30 @@
         if (!mimeName.isEmpty() && part->docImpl() && !part->pluginPageQuestionAsked( serviceType ) )
         {
             part->setPluginPageQuestionAsked( serviceType );
-            // Prepare the URL to show in the question (host only if http, to make it short)
-            KURL pluginPageURL( embed->pluginPage );
-            QString shortURL = pluginPageURL.protocol() == "http" ? pluginPageURL.host() : pluginPageURL.prettyURL();
-            int res = KMessageBox::questionYesNo( m_view,
-                                                  i18n("No plugin found for '%1'.\nDo you want to download one from %2?").arg(mimeName).arg(shortURL),
-                                                  i18n("Missing Plugin"), i18n("Download"), i18n("Do Not Download"), QString("plugin-")+serviceType);
-            if ( res == KMessageBox::Yes )
+            bool pluginAvailable;
+            pluginAvailable = false;
+            // check if a pluginList file is in the config
+            if(KNSPluginInstallEngine::isActive())
             {
-                // Display vendor download page
-                ext->createNewWindow( pluginPageURL );
-                return;
+                KNSPluginWizard pluginWizard(m_view, "pluginInstaller", mime);
+                if(pluginWizard.pluginAvailable()) {
+                    pluginAvailable = true;
+                    pluginWizard.exec();
+                }
+            } 
+            if(!pluginAvailable) {
+                // Prepare the URL to show in the question (host only if http, to make it short)
+                KURL pluginPageURL( embed->pluginPage );
+                QString shortURL = pluginPageURL.protocol() == "http" ? pluginPageURL.host() : pluginPageURL.prettyURL();
+                int res = KMessageBox::questionYesNo( m_view,
+                                                      i18n("No plugin found for '%1'.\nDo you want to download one from %2?").arg(mimeName).arg(shortURL),
+                                                      i18n("Missing Plugin"), i18n("Download"), i18n("Do Not Download"), QString("plugin-")+serviceType);
+                if ( res == KMessageBox::Yes )
+                {
+                    // Display vendor download page
+                    ext->createNewWindow( pluginPageURL );
+                    return;
+                }
             }
         }
     }
@@ -1007,4 +1021,5 @@
   }
 }
 
+
 #include "render_frames.moc"
