Warning, file /office/calligra/libs/kross/KoScriptManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /***************************************************************************
0002  * KoScriptManager.cpp
0003  * This file is part of the KDE project
0004  * copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
0005  * copyright (C) 2006-2007 Sebastian Sauer <mail@dipe.org>
0006  *
0007  * This program is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Library General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2 of the License, or (at your option) any later version.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Library General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Library General Public License
0018  * along with this program; see the file COPYING.  If not, write to
0019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  ***************************************************************************/
0022 
0023 #include "KoScriptManager.h"
0024 
0025 #include "KoScriptManagerAdd.h"
0026 #include "KoKrossDebug.h"
0027 
0028 #include <kross/core/manager.h>
0029 #include <kross/core/actioncollection.h>
0030 #include <kross/ui/model.h>
0031 #include <kross/ui/view.h>
0032 
0033 #include <KoIcon.h>
0034 
0035 #include <klocalizedstring.h>
0036 
0037 #include <QStandardPaths>
0038 #include <QBoxLayout>
0039 
0040 /******************************************************************************
0041  * KoScriptManagerCollection
0042  */
0043 
0044 /*
0045 /// \internal class that inherits \a KNewStuffSecure to implement the GHNS-functionality.
0046 class KoScriptManagerNewStuff : public KNewStuffSecure
0047 {
0048     public:
0049         KoScriptManagerNewStuff(KoScriptManagerCollection *collection, const QString& type, QWidget *parentWidget = 0)
0050             : KNewStuffSecure(type, parentWidget)
0051             , m_collection(collection) {}
0052         virtual ~KoScriptManagerNewStuff() {}
0053     private:
0054         KoScriptManagerCollection *m_collection;
0055         virtual void installResource() { m_collection->module()->installPackage(m_tarName); }
0056 };
0057 */
0058 
0059 class KoScriptManagerView : public Kross::ActionCollectionView
0060 {
0061 public:
0062     KoScriptManagerView(KoScriptManagerCollection *collection) : Kross::ActionCollectionView(collection)
0063     {
0064         setDragEnabled(true);
0065         setAcceptDrops(true);
0066 
0067         Kross::ActionCollectionModel::Mode modelmode = Kross::ActionCollectionModel::Mode(Kross::ActionCollectionModel::Icons | Kross::ActionCollectionModel::ToolTips | Kross::ActionCollectionModel::UserCheckable);
0068         Kross::ActionCollectionModel *model = new Kross::ActionCollectionModel(this, Kross::Manager::self().actionCollection(), modelmode);
0069         setModel(model);
0070         //selectionModel();
0071     }
0072 
0073     ~KoScriptManagerView() override {}
0074 
0075     Kross::ActionCollectionModel *model() const
0076     {
0077             return static_cast<Kross::ActionCollectionModel*>(Kross::ActionCollectionView::model());
0078     }
0079 
0080     void slotAdd() override
0081     {
0082         Kross::ActionCollection *collection = model()->rootCollection();
0083         if (itemSelection().count() == 1) {
0084             collection = Kross::ActionCollectionModel::collection(itemSelection().indexes().first());
0085         }
0086         KoScriptManagerAddWizard wizard(this, collection);
0087         int result = wizard.exec();
0088         Q_UNUSED(result);
0089     }
0090     void slotRemove() override
0091     {
0092         if (itemSelection().isEmpty()) {
0093             return;
0094         }
0095         // get the actions/collections, indexes will change when things are removed
0096         QList<Kross::Action*> actions;
0097         QList<Kross::ActionCollection*> collections;
0098         foreach (const QModelIndex &idx, itemSelection().indexes()) {
0099             Kross::Action *a =  model()->action(idx);
0100             if (a) {
0101                 actions << a;
0102             } else {
0103                 Kross::ActionCollection *c = model()->collection(idx);
0104                 if (c) {
0105                     collections << c;
0106                 }
0107             }
0108         }
0109         foreach (Kross::Action *action, actions) {
0110             QModelIndex idx = model()->indexForAction(action);
0111             if (idx.isValid()) {
0112                 //debugKoKross<<"action:"<<action->name();
0113                 delete action;
0114             }
0115         }
0116         foreach (Kross::ActionCollection *collection, collections) {
0117             QModelIndex idx = model()->indexForCollection(collection);
0118             if (idx.isValid()) {
0119                 //debugKoKross<<"collection:"<<collection->name();
0120                 delete collection;
0121             }
0122         }
0123     }
0124 };
0125 
0126 KoScriptManagerCollection::KoScriptManagerCollection(QWidget *parent)
0127     : QWidget(parent),
0128     m_modified(false)
0129 {
0130     QHBoxLayout *mainlayout = new QHBoxLayout();
0131     mainlayout->setMargin(0);
0132     setLayout(mainlayout);
0133 
0134     m_view = new KoScriptManagerView(this);
0135     mainlayout->addWidget(m_view);
0136 
0137     QWidget *btnwidget = new QWidget(this);
0138     QVBoxLayout *btnlayout = new QVBoxLayout();
0139     btnlayout->setMargin(0);
0140     btnwidget->setLayout(btnlayout);
0141     mainlayout->addWidget(btnwidget);
0142 
0143     //KActionCollection *collection = m_view->actionCollection();
0144 
0145     m_view->createButton(btnwidget, "run");
0146     m_view->createButton(btnwidget, "stop");
0147 
0148     QFrame *hr1 = new QFrame(btnwidget);
0149     hr1->setFrameStyle(QFrame::HLine | QFrame::Sunken);
0150     btnlayout->addWidget(hr1, 0);
0151 
0152     m_view->createButton(btnwidget, "edit");
0153     m_view->createButton(btnwidget, "add");
0154     m_view->createButton(btnwidget, "remove");
0155 
0156     btnlayout->addStretch(1);
0157     m_view->expandAll();
0158 }
0159 
0160 KoScriptManagerCollection::~KoScriptManagerCollection()
0161 {
0162 }
0163 
0164 /*
0165 bool KoScriptManagerCollection::isModified() const
0166 {
0167     return d->modified;
0168 }
0169 */
0170 
0171 #if 0
0172 bool KoScriptManagerCollection::slotInstall() {
0173     KFileDialog* filedialog = new KFileDialog(
0174         QUrl("kfiledialog:///KrossInstallPackage"), // startdir
0175         "*.tar.gz *.tgz *.bz2", // filter
0176         0, // custom widget
0177         0 // parent
0178     );
0179     filedialog->setCaption(i18n("Install Script Package"));
0180     return filedialog->exec() ? module()->installPackage(filedialog->selectedUrl().path()) : false;
0181 }
0182 void KoScriptManagerView::slotUninstall() {
0183     foreach(QModelIndex index, d->selectionmodel->selectedIndexes())
0184         if(index.isValid())
0185             if(! uninstallPackage( static_cast< Action* >(index.internalPointer()) ))
0186                 break;
0187 }
0188 void KoScriptManagerView::slotNewScripts() {
0189     const QString appname = KApplication::kApplication()->objectName();
0190     const QString type = QString("%1/script").arg(appname);
0191     krossdebug( QString("ScriptManagerView::slotNewScripts %1").arg(type) );
0192     if(! d->newstuff) {
0193         d->newstuff = new KoScriptManagerNewStuff(this, type);
0194         connect(d->newstuff, SIGNAL(installFinished()), this, SLOT(slotNewScriptsInstallFinished()));
0195     }
0196     KNS::Engine *engine = new KNS::Engine(d->newstuff, type, this);
0197     KNS::DownloadDialog *d = new KNS::DownloadDialog(engine, this);
0198     d->setCategory(type);
0199     KNS::ProviderLoader *p = new KNS::ProviderLoader(this);
0200     QObject::connect(p, SIGNAL(providersLoaded(Provider::List*)), d, SLOT(slotProviders(Provider::List*)));
0201     p->load(type, QString("http://download.kde.org/khotnewstuff/%1scripts-providers.xml").arg(appname));
0202     d->exec();
0203 }
0204 void KoScriptManagerView::slotNewScriptsInstallFinished() {
0205     // Delete KNewStuff's configuration entries. These entries reflect what has
0206     // already been installed. As we cannot yet keep them in sync after uninstalling
0207     // scripts, we deactivate the check marks entirely.
0208     KGlobal::config()->deleteGroup("KNewStuffStatus");
0209 }
0210 #endif
0211 
0212 #if 0
0213 bool KoScriptManagerModule::installPackage(const QString& scriptpackagefile)
0214 {
0215     KTar archive( scriptpackagefile );
0216     if(! archive.open(QIODevice::ReadOnly)) {
0217         KMessageBox::sorry(0, i18n("Could not read the package \"%1\".", scriptpackagefile));
0218         return false;
0219     }
0220 
0221     const KArchiveDirectory* archivedir = archive.directory();
0222     const KArchiveEntry* entry = archivedir->entry("install.rc");
0223     if(! entry || ! entry->isFile()) {
0224         KMessageBox::sorry(0, i18n("The package \"%1\" does not contain a valid install.rc file.", scriptpackagefile));
0225         return false;
0226     }
0227 
0228     QString xml = static_cast< const KArchiveFile* >(entry)->data();
0229     QDomDocument domdoc;
0230     if(! domdoc.setContent(xml)) {
0231         KMessageBox::sorry(0, i18n("Failed to parse the install.rc file at package \"%1\".", scriptpackagefile));
0232         return false;
0233     }
0234 
0235     QString destination = KGlobal::dirs()->saveLocation("appdata", "scripts/", true);
0236     if(destination.isNull()) {
0237         KMessageBox::sorry(0, i18n("Failed to determinate location where the package \"%1\" should be installed to.", scriptpackagefile));
0238         return false;
0239     }
0240 
0241     QString packagename = QFileInfo(scriptpackagefile).baseName();
0242     destination += packagename; // add the packagename to the name of the destination-directory.
0243 
0244     QDir packagepath(destination);
0245     if( packagepath.exists() ) {
0246         if( KMessageBox::warningContinueCancel(0,
0247             i18n("A script package with the name \"%1\" already exists. Replace this package?", packagename),
0248             i18n("Replace")) != KMessageBox::Continue )
0249                 return false;
0250         if(! KIO::NetAccess::del(destination, 0) ) {
0251             KMessageBox::sorry(0, i18n("Could not uninstall this script package. You may not have sufficient permissions to delete the folder \"%1\".", destination));
0252             return false;
0253         }
0254     }
0255 
0256     krossdebug( QString("Copy script-package to destination directory: %1").arg(destination) );
0257     archivedir->copyTo(destination, true);
0258 
0259     QDomNodeList nodelist = domdoc.elementsByTagName("ScriptAction");
0260     int nodelistcount = nodelist.count();
0261     for(int i = 0; i < nodelistcount; ++i) {
0262         QDomElement element = nodelist.item(i).toElement();
0263         const QString name = element.attribute("name");
0264         Action* action = new Action(Manager::self().actionCollection(), name, packagepath);
0265         action->fromDomElement(element);
0266         //connect(action, SIGNAL(failed(QString,QString)), this, SLOT(executionFailed(QString,QString)));
0267         //connect(action, SIGNAL(success()), this, SLOT(executionSuccessful()));
0268         //connect(action, SIGNAL(activated(Kross::Action*)), SIGNAL(executionStarted(Kross::Action*)));
0269     }
0270 
0271     //d->modified = true;
0272     return true;
0273 }
0274 
0275 bool KoScriptManagerModule::uninstallPackage(Action* action)
0276 {
0277     const QString name = action->objectName();
0278     QString file = action->file();
0279     QFileInfo fi(file);
0280     if(file.isNull() || ! fi.exists()) {
0281         KMessageBox::sorry(0, i18n("Could not uninstall the script package \"%1\" since the script is not installed.",action->objectName()));
0282         return false;
0283     }
0284     const QString scriptpackagepath = fi.absolutePath();
0285     krossdebug( QString("Uninstall script-package with destination directory: %1").arg(scriptpackagepath) );
0286     if(! KIO::NetAccess::del(scriptpackagepath, 0) ) {
0287         KMessageBox::sorry(0, i18n("Could not uninstall the script package \"%1\". You may not have sufficient permissions to delete the folder \"%1\".",action->objectName()).arg(scriptpackagepath));
0288         return false;
0289     }
0290     delete action; action = 0; // removes the action from d->actions as well
0291     d->modified = true;
0292     return true;
0293 }
0294 #endif
0295 
0296 KoScriptManagerDialog::KoScriptManagerDialog()
0297     : KoDialog()
0298 {
0299     setCaption(i18n("Script Manager"));
0300     setButtons(KoDialog::Ok | KoDialog::Cancel);
0301     setButtonText(KoDialog::Ok, i18n("Save"));
0302     setButtonIcon(KoDialog::Ok, koIcon("document-save"));
0303     m_collection = new KoScriptManagerCollection(mainWidget());
0304     setMainWidget(m_collection);
0305     resize(QSize(520, 380).expandedTo(minimumSizeHint()));
0306     connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
0307 }
0308 
0309 KoScriptManagerDialog::~KoScriptManagerDialog()
0310 {
0311 }
0312 
0313 void KoScriptManagerDialog::slotAccepted()
0314 {
0315     const QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
0316     if (! dir.isEmpty()) {
0317         const QString scriptsDir = dir + QStringLiteral("/scripts/");
0318         QDir().mkpath(scriptsDir);
0319 
0320         const QString file = QFileInfo(scriptsDir, "scripts.rc").absoluteFilePath();
0321         QFile f(file);
0322         if (f.open(QIODevice::WriteOnly))
0323             if (Kross::Manager::self().actionCollection()->writeXml(&f))
0324                 debugKoKross<<"Successfully saved file:"<<file;
0325         f.close();
0326     }
0327 }