diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ find_package( Qt5 5.8.0 COMPONENTS QuickControls2 WebEngine ) set_package_properties( Qt5QuickControls2 PROPERTIES TYPE RUNTIME PURPOSE "Needed by the player's context area" ) -find_package( Qt5 5.8.0 REQUIRED COMPONENTS Core DBus Gui QuickWidgets Qml Script ScriptTools Sql Svg Test Widgets Xml ) +find_package( Qt5 5.8.0 REQUIRED COMPONENTS Core DBus Gui QuickWidgets Qml Sql Svg Test Widgets Xml ) set_package_properties( Qt5WebEngine PROPERTIES TYPE OPTIONAL PURPOSE "Needed by the wikipedia applet" ) find_package( KF5 REQUIRED COMPONENTS Archive Codecs CoreAddons DBusAddons Declarative DNSSD GlobalAccel GuiAddons I18n IconThemes KCMUtils KIO NewStuff Notifications NotifyConfig Package Solid TextEditor ThreadWeaver WindowSystem ) diff --git a/cmake/modules/bindingstest/QtScriptBindingsTest.cpp b/cmake/modules/bindingstest/QtScriptBindingsTest.cpp deleted file mode 100644 --- a/cmake/modules/bindingstest/QtScriptBindingsTest.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2009 Ian Monroe - * released under public domain or: - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include - -#define FAIL 0xA - -int main(int argc, char **argv) -{ - QApplication app( argc, argv, false ); - - QStringList allowedBindings; - allowedBindings << "qt.core" << "qt.gui" << "qt.sql" << "qt.xml" << "qt.network"; - QScriptEngine engine; - foreach( QString binding, allowedBindings ) - { - QScriptValue error = engine.importExtension( binding ); - if( error.isUndefined() ) - { // undefined indiciates success - continue; - } - - qDebug() << "Extension" << binding << "not found:" << error.toString(); - qDebug() << "Available extensions:" << engine.availableExtensions(); - return FAIL; - } - return 0; -} diff --git a/src/ActionClasses.cpp b/src/ActionClasses.cpp --- a/src/ActionClasses.cpp +++ b/src/ActionClasses.cpp @@ -115,7 +115,6 @@ safePlug( ac, "cover_manager", this ); safePlug( ac, "queue_manager", this ); - safePlug( ac, "script_manager", this ); addSeparator(); diff --git a/src/App.h b/src/App.h --- a/src/App.h +++ b/src/App.h @@ -28,10 +28,6 @@ class TrayIcon; } -namespace ScriptConsoleNS{ - class ScriptConsole; -} - namespace KIO { class Job; } @@ -87,7 +83,6 @@ QPointer m_mainWindow; Amarok::TrayIcon *m_tray; MediaDeviceManager *m_mediaDeviceManager; - QPointer m_scriptConsole; QCommandLineParser *m_args; QString m_cwd; QStringList s_delayedAmarokUrls; diff --git a/src/App.cpp b/src/App.cpp --- a/src/App.cpp +++ b/src/App.cpp @@ -21,7 +21,6 @@ #include "KNotificationBackend.h" #include "MainWindow.h" #include "PluginManager.h" -#include "scripting/scriptmanager/ScriptManager.h" #include "TrayIcon.h" #include "amarokconfig.h" #include "aboutdialog/OcsData.h" @@ -56,7 +55,6 @@ #include "playlist/PlaylistModelStack.h" #include "playlistmanager/PlaylistManager.h" #include "services/ServicePluginManager.h" -#include "scripting/scriptconsole/ScriptConsole.h" #include "statemanagement/ApplicationController.h" #include "statemanagement/DefaultApplicationController.h" #include "statsyncing/Controller.h" @@ -212,8 +210,6 @@ AmarokConfig::self()->save(); #endif - ScriptManager::destroy(); - // this must be deleted before the connection to the Xserver is // severed, or we risk a crash when the QApplication is exited, // I asked Trolltech! *smug* @@ -398,11 +394,6 @@ Amarok::OSD::instance()->applySettings(); emit settingsChanged(); - - if( AmarokConfig::enableScriptConsole() && !m_scriptConsole ) - m_scriptConsole = ScriptConsoleNS::ScriptConsole::instance(); - else if( !AmarokConfig::enableScriptConsole() && m_scriptConsole ) - m_scriptConsole.data()->deleteLater(); } //SLOT @@ -419,11 +410,6 @@ delete m_tray; m_tray = 0; } - - if( AmarokConfig::enableScriptConsole() && !m_scriptConsole ) - m_scriptConsole = ScriptConsoleNS::ScriptConsole::instance(); - else if( !AmarokConfig::enableScriptConsole() && m_scriptConsole ) - m_scriptConsole.data()->deleteLater(); } //SLOT @@ -474,10 +460,6 @@ // Create engine, show TrayIcon etc. applySettingsFirstTime(); - // Must be created _after_ MainWindow. - PERF_LOG( "Starting ScriptManager" ) - ScriptManager::instance(); - PERF_LOG( "ScriptManager started" ) The::engineController()->setVolume( AmarokConfig::masterVolume() ); The::engineController()->setMuted( AmarokConfig::muteState() ); @@ -589,7 +571,6 @@ DEBUG_BLOCK The::playlistManager()->completePodcastDownloads(); - // Following signal is relayed to scripts, which may block quitting for a while emit prepareToQuit(); QApplication::quit(); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,7 +30,6 @@ add_subdirectory( core-impl/storage/sql ) add_subdirectory( context ) add_subdirectory( services ) -add_subdirectory( scripting/scripts ) add_subdirectory( aboutdialog/libattica-ocsclient ) add_subdirectory( transcoding ) add_subdirectory( kconf_update ) @@ -115,19 +114,6 @@ amarokurls/BookmarkMetaActions.cpp ) -##################################################################### -# SCRIPTABLESERVICE -##################################################################### -set(libscriptableservice_SRCS - services/scriptable/ScriptableService.cpp - services/scriptable/ScriptableServiceCollection.cpp - services/scriptable/ScriptableServiceCollectionTreeModel.cpp - services/scriptable/ScriptableServiceInfoParser.cpp - services/scriptable/ScriptableServiceManager.cpp - services/scriptable/ScriptableServiceMeta.cpp - services/scriptable/ScriptableServiceQueryMaker.cpp -) - ##################################################################### # CONFIGDIALOG ##################################################################### @@ -141,8 +127,6 @@ configdialog/dialogs/NotificationsConfig.cpp configdialog/dialogs/PlaybackConfig.cpp configdialog/dialogs/PluginsConfig.cpp - configdialog/dialogs/ScriptsConfig.cpp - configdialog/dialogs/ScriptSelector.cpp configdialog/dialogs/DatabaseConfig.cpp ) @@ -154,7 +138,6 @@ configdialog/dialogs/NotificationsConfig.ui configdialog/dialogs/PlaybackConfig.ui configdialog/dialogs/DatabaseConfig.ui - configdialog/dialogs/ScriptsConfig.ui ) set(libbrowserframework_SRCS @@ -283,7 +266,13 @@ context/AppletModel.cpp context/ContextDock.cpp context/ContextView.cpp - context/LyricsManager.cpp +) + +##################################################################### +# LYRICS +##################################################################### +set( liblyrics_SRCS + lyrics/LyricsManager.cpp ) ##################################################################### @@ -430,56 +419,6 @@ dbus/DBusQueryHelper.cpp ) - -##################################################################### -# SCRIPTING INTERFACE -##################################################################### -set(scriptengine_SRCS - scripting/scriptengine/AmarokBookmarkScript.cpp - scripting/scriptengine/AmarokCollectionScript.cpp - scripting/scriptengine/AmarokCollectionViewScript.cpp - scripting/scriptengine/AmarokEngineScript.cpp - scripting/scriptengine/AmarokEqualizerScript.cpp - scripting/scriptengine/AmarokInfoScript.cpp - scripting/scriptengine/AmarokKNotifyScript.cpp - scripting/scriptengine/AmarokLyricsScript.cpp - scripting/scriptengine/AmarokNetworkScript.cpp - scripting/scriptengine/AmarokOSDScript.cpp - scripting/scriptengine/AmarokPlaylistManagerScript.cpp - scripting/scriptengine/AmarokPlaylistScript.cpp - scripting/scriptengine/AmarokScript.cpp - scripting/scriptengine/AmarokScriptConfig.cpp - scripting/scriptengine/AmarokScriptableServiceScript.cpp - scripting/scriptengine/AmarokServicePluginManagerScript.cpp - scripting/scriptengine/AmarokStatusbarScript.cpp - scripting/scriptengine/AmarokStreamItemScript.cpp - scripting/scriptengine/AmarokWindowScript.cpp - scripting/scriptengine/AmarokScriptXml.cpp - scripting/scriptengine/ScriptImporter.cpp - scripting/scriptengine/ScriptingDefines.cpp - scripting/scriptengine/exporters/CollectionTypeExporter.cpp - scripting/scriptengine/exporters/MetaTypeExporter.cpp - scripting/scriptengine/exporters/PlaylistExporter.cpp - scripting/scriptengine/exporters/PlaylistProviderExporter.cpp - scripting/scriptengine/exporters/QueryMakerExporter.cpp - scripting/scriptengine/exporters/ScriptableBiasExporter.cpp -) - -set(scriptconsole_SRCS - scripting/scriptconsole/CompletionModel.cpp - scripting/scriptconsole/ScriptConsole.cpp - scripting/scriptconsole/ScriptEditorDocument.cpp - scripting/scriptconsole/ScriptConsoleItem.cpp -) - -if (PYTHONINTERP_FOUND) - execute_process(COMMAND "${PYTHON_EXECUTABLE}" ${CMAKE_SOURCE_DIR}/src/scripting/scriptengine/PHAACG2.py - ${CMAKE_SOURCE_DIR}/src/scripting/scriptengine - ${CMAKE_BINARY_DIR}/scriptconsole) - install(FILES ${CMAKE_BINARY_DIR}/scriptconsole/AutoComplete.txt - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scriptconsole) -endif() - ##################################################################### # PLAYLIST GENERATOR ##################################################################### @@ -583,11 +522,11 @@ # LIBAMAROK ##################################################################### set(amaroklib_LIB_SRCS - ${libscriptableservice_SRCS} ${libbrowserframework_SRCS} ${libcontextview_SRCS} ${libcollectionbrowser_SRCS} ${libconfigdialog_SRCS} + ${liblyrics_SRCS} ${libplaylist_SRCS} ${aggregatecollection_SRCS} ${libpodcasts_SRCS} @@ -605,8 +544,6 @@ ${libplaylistbrowser_SRCS} ${libplaylistmanager_SRCS} ${dbus_SRCS} - ${scriptengine_SRCS} - ${scriptconsole_SRCS} ${libstatusbar_SRCS} ${libamarokurl_SRCS} ${libsynchronization_SRCS} @@ -632,9 +569,6 @@ MediaDeviceMonitor.cpp PluginManager.cpp QStringx.cpp - scripting/scriptmanager/ScriptManager.cpp - scripting/scriptmanager/ScriptItem.cpp - scripting/scriptmanager/ScriptUpdater.cpp SvgHandler.cpp SvgTinter.cpp TrayIcon.cpp @@ -864,12 +798,9 @@ KF5::TextEditor KF5::ThreadWeaver KF5::WindowSystem - ${QT_QTSCRIPTTOOLS_LIBRARY} Qt5::Gui Qt5::Quick Qt5::QuickWidgets - Qt5::Script - Qt5::ScriptTools Qt5::Sql Qt5::Svg ${CMAKE_DL_LIBS} diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -47,6 +47,7 @@ #include "core/support/Components.h" #include "core/support/Debug.h" #include "core-impl/collections/support/CollectionManager.h" +#include "core-impl/collections/support/MemoryCollection.h" #include "covermanager/CoverManager.h" // for actions #include "dialogs/DiagnosticDialog.h" #include "dialogs/EqualizerDialog.h" @@ -63,7 +64,6 @@ #include "playlist/layouts/LayoutConfigAction.h" #include "playlistmanager/PlaylistManager.h" #include "playlistmanager/file/PlaylistFileProvider.h" -#include "services/scriptable/ScriptableService.h" #include "statsyncing/Controller.h" #include "toolbar/MainToolbar.h" #include "toolbar/SlimToolbar.h" @@ -284,9 +284,6 @@ m_browserDock->list()->addCategory( fileBrowser ); PERF_LOG( "Created FileBrowser" ) - serviceBrowser->setScriptableServiceManager( The::scriptableServiceManager() ); - PERF_LOG( "ScriptableServiceManager done" ) - PERF_LOG( "Creating Podcast Category" ) m_browserDock->list()->addCategory( The::podcastCategory() ); PERF_LOG( "Created Podcast Category" ) diff --git a/src/browsers/CollectionTreeView.cpp b/src/browsers/CollectionTreeView.cpp --- a/src/browsers/CollectionTreeView.cpp +++ b/src/browsers/CollectionTreeView.cpp @@ -41,7 +41,6 @@ #include "core-impl/collections/support/TrashCollectionLocation.h" #include "dialogs/TagDialog.h" #include "playlist/PlaylistModelStack.h" -#include "scripting/scriptengine/AmarokCollectionViewScript.h" #include #include @@ -434,7 +433,6 @@ foreach( QAction *action, actions ) { menu.addAction( action ); } - AmarokScript::AmarokCollectionViewScript::createScriptedActions( menu, indices ); menu.exec( event->globalPos() ); } diff --git a/src/browsers/servicebrowser/ServiceBrowser.h b/src/browsers/servicebrowser/ServiceBrowser.h --- a/src/browsers/servicebrowser/ServiceBrowser.h +++ b/src/browsers/servicebrowser/ServiceBrowser.h @@ -20,7 +20,6 @@ #include "browsers/BrowserCategoryList.h" -#include "services/scriptable/ScriptableServiceManager.h" #include "services/ServiceBase.h" #include @@ -62,12 +61,6 @@ public Q_SLOTS: - /** - * Set a scriptable service manager to handle scripted services. - * @param scriptableServiceManager The scriptable service manager to set. - */ - void setScriptableServiceManager( ScriptableServiceManager *scriptableServiceManager ); - void addService ( ServiceBase * ); private: @@ -80,8 +73,6 @@ static ServiceBrowser *s_instance; - ScriptableServiceManager *m_scriptableServiceManager; - QTimer m_filterTimer; QString m_currentFilter; diff --git a/src/browsers/servicebrowser/ServiceBrowser.cpp b/src/browsers/servicebrowser/ServiceBrowser.cpp --- a/src/browsers/servicebrowser/ServiceBrowser.cpp +++ b/src/browsers/servicebrowser/ServiceBrowser.cpp @@ -47,16 +47,6 @@ DEBUG_BLOCK } -//TODO: This should be moved to the ScriptableServiceManager instead -void -ServiceBrowser::setScriptableServiceManager( ScriptableServiceManager * scriptableServiceManager ) -{ - m_scriptableServiceManager = scriptableServiceManager; - m_scriptableServiceManager->setParent( this ); - connect ( m_scriptableServiceManager, &ScriptableServiceManager::addService, - this, &ServiceBrowser::addService ); -} - void ServiceBrowser::resetService( const QString &name ) { diff --git a/src/configdialog/ConfigDialog.cpp b/src/configdialog/ConfigDialog.cpp --- a/src/configdialog/ConfigDialog.cpp +++ b/src/configdialog/ConfigDialog.cpp @@ -27,7 +27,6 @@ #include "configdialog/dialogs/NotificationsConfig.h" #include "configdialog/dialogs/PlaybackConfig.h" #include "configdialog/dialogs/PluginsConfig.h" -#include "configdialog/dialogs/ScriptsConfig.h" #include "core/support/Amarok.h" #include "core/support/Debug.h" @@ -53,7 +52,6 @@ ConfigDialogBase *notify = new NotificationsConfig( this ); ConfigDialogBase *database = new DatabaseConfig( this, config ); ConfigDialogBase *plugins = new PluginsConfig( this ); - ConfigDialogBase *scripts = new ScriptsConfig( this ); //ConfigDialogBase* mediadevice = new MediadeviceConfig( this ); addPage( general, i18nc( "Miscellaneous settings", "General" ), "preferences-other-amarok", i18n( "Configure General Options" ) ); @@ -63,7 +61,6 @@ addPage( notify, i18n( "Notifications" ), "preferences-indicator-amarok", i18n( "Configure Notifications" ) ); addPage( database, i18n( "Database" ), "server-database", i18n( "Configure Database" ) ); addPage( plugins, i18n( "Plugins" ), "preferences-plugin", i18n( "Configure Plugins" ) ); - addPage( scripts, i18n( "Scripts" ), "preferences-plugin-script", i18n( "Configure Scripts" ) ); //addPage( mediadevice, i18n( "Media Devices" ), "preferences-multimedia-player-amarok", i18n( "Configure Portable Player Support" ) ); QPushButton *okButton = buttonBox()->button(QDialogButtonBox::Ok); diff --git a/src/configdialog/dialogs/ScriptSelector.h b/src/configdialog/dialogs/ScriptSelector.h deleted file mode 100644 --- a/src/configdialog/dialogs/ScriptSelector.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPTSELECTOR_H -#define SCRIPTSELECTOR_H - -#include -#include - -class KCategorizedView; -class QLineEdit; -class KPluginInfo; -class QScrollBar; - -class ScriptSelector : public KPluginSelector -{ - Q_OBJECT - - public: - explicit ScriptSelector( QWidget * parent ); - ~ScriptSelector(); - - QString currentItem() const; - void addScripts( QList pluginInfoList, - PluginLoadMethod pluginLoadMethod = ReadConfigFile, - const QString &categoryName = QString(), - const QString &categoryKey = QString(), - const KSharedConfig::Ptr &config = KSharedConfig::Ptr() ); - int verticalPosition(); - void setVerticalPosition( int position ); - QString filter(); - void setFilter( const QString &filter ); - - private: - KCategorizedView *m_listView; - QMap m_scripts; - int m_scriptCount; - QLineEdit *m_lineEdit; - - private Q_SLOTS: - void slotFiltered( const QString &filter ); - - Q_SIGNALS: - void filtered(bool); -}; - -#endif diff --git a/src/configdialog/dialogs/ScriptSelector.cpp b/src/configdialog/dialogs/ScriptSelector.cpp deleted file mode 100644 --- a/src/configdialog/dialogs/ScriptSelector.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptSelector.h" - -#include "core/support/Debug.h" - -#include -#include -#include -#include -#include - -// uber-hacky, this whole thing, make our own script selector? -ScriptSelector::ScriptSelector( QWidget * parent ) - : KPluginSelector( parent ) - , m_scriptCount( 0 ) -{ - m_lineEdit = this->findChild(); - if( m_lineEdit ) - { - m_lineEdit->setPlaceholderText( i18n( "Search Scripts" ) ); - connect( m_lineEdit, &QLineEdit::textChanged, this, &ScriptSelector::slotFiltered ); - } - - m_listView = this->findChild(); -} - -ScriptSelector::~ScriptSelector() -{} - -void -ScriptSelector::setVerticalPosition( int position ) -{ - m_listView->verticalScrollBar()->setSliderPosition( position ); -} - -int -ScriptSelector::verticalPosition() -{ - return m_listView->verticalScrollBar()->sliderPosition(); -} - -QString -ScriptSelector::filter() -{ - return m_lineEdit->text(); -} - -void -ScriptSelector::setFilter( const QString &filter ) -{ - m_lineEdit->setText( filter ); -} - -void -ScriptSelector::addScripts( QList pluginInfoList, - PluginLoadMethod pluginLoadMethod, - const QString &categoryName, - const QString &categoryKey, - const KSharedConfig::Ptr &config ) -{ - DEBUG_BLOCK - - qSort( pluginInfoList.begin(), pluginInfoList.end() - , []( const KPluginInfo &left, const KPluginInfo &right ){ return left.name() < right.name(); } ); - addPlugins( pluginInfoList, pluginLoadMethod, categoryName, categoryKey, config ); - foreach( const KPluginInfo &plugin, pluginInfoList ) - { - m_scriptCount++; - m_scripts[m_scriptCount] = plugin.pluginName(); - } -} - -QString -ScriptSelector::currentItem() const -{ - DEBUG_BLOCK - - QItemSelectionModel *selModel = m_listView->selectionModel(); - const QModelIndexList selIndexes = selModel->selectedIndexes(); - - if( !selIndexes.isEmpty() ) - { - QModelIndex currentIndex = selIndexes[0]; - if( currentIndex.isValid() ) - { - debug() << "row: " << currentIndex.row() + 1; //the index start from 1 - debug() << "name: "<< m_scripts[currentIndex.row() + 1]; - return m_scripts[currentIndex.row() + 1]; - } - } - - return QString(); -} - -void -ScriptSelector::slotFiltered( const QString &filter ) -{ - if( filter.isEmpty() ) - emit filtered( false ); - else - emit filtered( true ); -} - diff --git a/src/configdialog/dialogs/ScriptsConfig.h b/src/configdialog/dialogs/ScriptsConfig.h deleted file mode 100644 --- a/src/configdialog/dialogs/ScriptsConfig.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2010 Rick W. Chen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPTSCONFIG_H -#define AMAROK_SCRIPTSCONFIG_H - -#include "configdialog/ConfigDialogBase.h" - -#include - - -class KArchiveDirectory; -class KArchiveFile; -class ScriptSelector; -class QPushButton; -class QVBoxLayout; - -/** - * A widget that allows configuration of scripts - */ -class ScriptsConfig : public ConfigDialogBase -{ - Q_OBJECT - -public: - explicit ScriptsConfig( Amarok2ConfigDialog *parent ); - virtual ~ScriptsConfig(); - - void updateSettings() Q_DECL_OVERRIDE; - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; - -public Q_SLOTS: - void slotConfigChanged( bool changed ); - -private Q_SLOTS: - void slotManageScripts(); - void installLocalScript(); - void slotReloadScriptSelector(); - void slotUpdateScripts(); - void slotUninstallScript(); - void restoreScrollBar(); - -private: - const KArchiveFile *findSpecFile( const KArchiveDirectory *dir ) const; - void removeDir( const QString &dirPath ) const; - - bool m_configChanged; - ScriptSelector *m_selector; - QTimer *m_timer; - QVBoxLayout *m_verticalLayout; - QPushButton *m_uninstallButton; - QObject *m_parent; - ScriptSelector *m_oldSelector; -}; - -#endif // AMAROK_SCRIPTSCONFIG_H diff --git a/src/configdialog/dialogs/ScriptsConfig.cpp b/src/configdialog/dialogs/ScriptsConfig.cpp deleted file mode 100644 --- a/src/configdialog/dialogs/ScriptsConfig.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2010 Rick W. Chen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptsConfig" - -#include "ScriptsConfig.h" - -#include "amarokconfig.h" -#include "configdialog/ConfigDialog.h" -#include "core/support/Amarok.h" -#include "core/support/Debug.h" -#include "scripting/scriptmanager/ScriptManager.h" -#include "ScriptSelector.h" -#include "ui_ScriptsConfig.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -ScriptsConfig::ScriptsConfig( Amarok2ConfigDialog *parent ) - : ConfigDialogBase( parent ) - , m_configChanged( false ) - , m_parent( parent ) - , m_oldSelector( 0 ) -{ - DEBUG_BLOCK - Ui::ScriptsConfig gui; - gui.setupUi( this ); - - m_uninstallButton = gui.uninstallButton; - m_timer = new QTimer(this); - connect( m_timer, &QTimer::timeout, this, &ScriptsConfig::slotUpdateScripts ); - m_timer->setInterval( 200 ); - - // Load config - gui.kcfg_AutoUpdateScripts->setChecked( AmarokConfig::autoUpdateScripts() ); - gui.manageButton->setIcon( QIcon::fromTheme( "get-hot-new-stuff-amarok" ) ); - connect( gui.manageButton, &QAbstractButton::clicked, - this, &ScriptsConfig::slotManageScripts ); - connect( gui.installButton, &QAbstractButton::clicked, - this, &ScriptsConfig::installLocalScript ); - - m_selector = gui.scriptSelector; - m_verticalLayout = gui.verticalLayout; - slotReloadScriptSelector(); - - connect( gui.reloadButton, &QAbstractButton::clicked, m_timer, QOverload<>::of(&QTimer::start) ); - connect( gui.uninstallButton, &QAbstractButton::clicked, this, &ScriptsConfig::slotUninstallScript ); - - connect( ScriptManager::instance(), &ScriptManager::scriptsChanged, - this, &ScriptsConfig::slotReloadScriptSelector ); - - this->setEnabled( AmarokConfig::enableScripts() ); -} - -ScriptsConfig::~ScriptsConfig() -{} - -void -ScriptsConfig::slotManageScripts() -{ - QStringList updateScriptsList; - KNS3::DownloadDialog dialog("amarok.knsrc", this); - dialog.exec(); - - if( !dialog.installedEntries().isEmpty() || !dialog.changedEntries().isEmpty() ) - m_timer->start(); -} - -void -ScriptsConfig::updateSettings() -{ - DEBUG_BLOCK - if( m_configChanged ) - { - m_selector->save(); - ScriptManager::instance()->configChanged( true ); - } -} - -bool -ScriptsConfig::hasChanged() -{ - return m_configChanged; -} - -bool -ScriptsConfig::isDefault() -{ - return false; -} - -void -ScriptsConfig::slotConfigChanged( bool changed ) -{ - m_configChanged = changed; - if( changed ) - debug() << "config changed"; -} - -void -ScriptsConfig::installLocalScript() -{ - DEBUG_BLOCK - // where's this config stored anyway, use amarokconfig instead? - // the script can actually be updated if you get the folder name right - int response = KMessageBox::warningContinueCancel( this, i18n( "Manually installed scripts " - "cannot be automatically updated, continue?" ), QString(), KStandardGuiItem::cont() - , KStandardGuiItem::cancel(), "manualScriptInstallWarning" ); - if( response == KMessageBox::Cancel ) - return; - - QString filePath = QFileDialog::getOpenFileName( this, i18n( "Select Archived Script" ) ); - if( filePath.isEmpty() ) - return; - - QString fileName = QFileInfo( filePath ).fileName(); - QMimeDatabase db; - QMimeType mimeType = db.mimeTypeForFile( filePath ); - QScopedPointer archive; - if( mimeType.inherits( "application/zip" ) ) - archive.reset( new KZip( filePath ) ); - else - archive.reset( new KTar( filePath ) ); - - if( !archive || !archive->open( QIODevice::ReadOnly ) ) - { - KMessageBox::error( this, i18n( "Invalid Archive" ) ); - return; - } - - QString destination = QStandardPaths::writableLocation( QStandardPaths::GenericDataLocation ) + QString("amarok/scripts/") + fileName + '/'; - const KArchiveDirectory* const archiveDir = archive->directory(); - const QDir dir( destination ); - const KArchiveFile *specFile = findSpecFile( archiveDir ); - if( !specFile ) - { - KMessageBox::error( this, i18n( "Invalid Script File" ) ); - return; - } - - QTemporaryFile tempFile; - tempFile.open(); - QIODevice *device = specFile->createDevice(); - tempFile.write( device->readAll() ); - delete device; - tempFile.close(); - - KPluginInfo newScriptInfo( tempFile.fileName() ); - if( !newScriptInfo.isValid() ) - { - KMessageBox::error( this, i18n( "Invalid Script File" ) ); - return; - } - - if( ScriptManager::instance()->m_scripts.contains( newScriptInfo.pluginName() ) ) - { - QString existingVersion = ScriptManager::instance()->m_scripts[ newScriptInfo.pluginName() ]->info().version(); - QString message = i18n( "Another script with the name %1 already exists\nExisting Script's " - "Version: %1\nSelected Script's Version: %2", newScriptInfo.version() - , existingVersion, newScriptInfo.version() ); - KMessageBox::error( this, message ); - return; - } - - for( int i = 1; dir.exists( destination ); ++i ) - destination += i; - dir.mkpath( destination ); - archiveDir->copyTo( destination ); - KMessageBox::information( this, i18n( "The script %1 was successfully installed", newScriptInfo.name() ) ); - m_timer->start(); -} - -void -ScriptsConfig::slotReloadScriptSelector() -{ - DEBUG_BLOCK - m_oldSelector = m_selector; - m_selector = new ScriptSelector( this ); - QString key = QLatin1String( "Generic" ); - m_selector->addScripts( ScriptManager::instance()->scripts( key ), - KPluginSelector::ReadConfigFile, i18n("Generic"), key ); - - key = QLatin1String( "Lyrics" ); - m_selector->addScripts( ScriptManager::instance()->scripts( key ), - KPluginSelector::ReadConfigFile, i18n("Lyrics"), key ); - - key = QLatin1String( "Scriptable Service" ); - m_selector->addScripts( ScriptManager::instance()->scripts( key ), - KPluginSelector::ReadConfigFile, i18n("Scriptable Service"), key ); - connect( m_selector, &ScriptSelector::changed, this, &ScriptsConfig::slotConfigChanged ); - connect( m_selector, &ScriptSelector::filtered, m_uninstallButton, &QPushButton::setDisabled ); - connect( m_selector, &ScriptSelector::changed, - qobject_cast(m_parent), &Amarok2ConfigDialog::updateButtons ); - - m_verticalLayout->insertWidget( 0, m_selector ); - m_verticalLayout->removeWidget( m_oldSelector ); - - m_selector->setFilter( m_oldSelector->filter() ); - QTimer::singleShot( 0, this, &ScriptsConfig::restoreScrollBar ); -} - -void -ScriptsConfig::restoreScrollBar() -{ - if( !m_oldSelector ) - return; - m_selector->setVerticalPosition( m_oldSelector->verticalPosition() ); - m_oldSelector->deleteLater(); -} - -void -ScriptsConfig::slotUpdateScripts() -{ - m_timer->stop(); - ScriptManager::instance()->updateAllScripts(); -} - -void -ScriptsConfig::slotUninstallScript() -{ - DEBUG_BLOCK - if( !ScriptManager::instance()->m_scripts.contains( m_selector->currentItem() ) ) - return; - - ScriptItem *item = ScriptManager::instance()->m_scripts.value( m_selector->currentItem() ); - int response = KMessageBox::warningContinueCancel( this, i18n( "You are advised to only uninstall manually " - "installed scripts using this button." ) ); - if( response == KMessageBox::Cancel ) - return; - - QRegExp regex( "(.*apps/amarok/scripts/.+/).*script.spec" ); - regex.indexIn( item->info().entryPath() ); - qDebug() << "About to remove folder " << regex.cap( 1 ); - removeDir( regex.cap( 1 ) ); - m_timer->start(); -} - -const KArchiveFile* -ScriptsConfig::findSpecFile( const KArchiveDirectory *dir ) const -{ - foreach( const QString &entry, dir->entries() ) - { - if( dir->entry( entry )->isFile() ) - { - if( entry == "script.spec" ) - return static_cast( dir->entry( entry ) ); - } - else - { - if( entry != "." && entry != ".." ) - { - const KArchiveDirectory *subDir = static_cast( dir->entry( entry ) ); - if( subDir ) - { - const KArchiveFile *file = findSpecFile( subDir ); - if( !file ) - continue; - return file; - } - } - } - } - return 0; -} - -void -ScriptsConfig::removeDir( const QString &dirPath ) const -{ - QDir dir( dirPath ); - if( dir.exists( dirPath ) ) - { - foreach( const QFileInfo &info, dir.entryInfoList( QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files ) ) - { - if( info.isDir() ) - removeDir( info.absoluteFilePath() ); - else - QFile::remove( info.absoluteFilePath() ); - } - dir.rmdir( dirPath ); - } -} - diff --git a/src/configdialog/dialogs/ScriptsConfig.ui b/src/configdialog/dialogs/ScriptsConfig.ui deleted file mode 100644 --- a/src/configdialog/dialogs/ScriptsConfig.ui +++ /dev/null @@ -1,147 +0,0 @@ - - - Peter Zhou and Ian Monroe - ScriptsConfig - - - - 0 - 0 - 590 - 115 - - - - - 0 - 0 - - - - - - - - 0 - 0 - - - - - - - - - - Uninstall Script - - - - - - - Install Local Script - - - - - - - - - - - Automatically download and install updates for the built-in scripts from the Amarok website if available - - - Automatically download and install updates for the built-in scripts from the Amarok website if available - - - Automatically update built-in scripts - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Browse, install, and uninstall scripts - - - Manage Scripts - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - Script Console - - - - - - true - - - Enable the script console. - - - Enable the script console. - - - Enable Script Console - - - - - - - - - - - - QPushButton - QPushButton -
qpushbutton.h
-
- - ScriptSelector - QWidget -
configdialog/dialogs/ScriptSelector.h
- 1 -
-
- - -
diff --git a/src/context/LyricsManager.h b/src/context/LyricsManager.h deleted file mode 100644 --- a/src/context/LyricsManager.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Leo Franchi * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef LYRICS_MANAGER_H -#define LYRICS_MANAGER_H - -#include "amarok_export.h" - -#include -#include -#include - -class LyricsSubject; - -struct LyricsData -{ - QString text; - QString title; - QString artist; - QUrl site; - - void clear() - { - text.clear(); - title.clear(); - artist.clear(); - site.clear(); - } -}; - -class AMAROK_EXPORT LyricsObserver -{ - public: - LyricsObserver(); - explicit LyricsObserver( LyricsSubject* ); - virtual ~LyricsObserver(); - - /** - * A lyrics script has returned new lyrics. - */ - virtual void newLyrics( const LyricsData &lyrics ) { Q_UNUSED( lyrics ); } - /** - * A lyrics script has returned a list of suggested URLs for correct lyrics. - */ - virtual void newSuggestions( const QVariantList &suggestions ) { Q_UNUSED( suggestions ); } - /** - * A lyrics script has returned some generic message that they want to be displayed. - */ - virtual void lyricsMessage( const QString& key, const QString &val ) { Q_UNUSED( key ); Q_UNUSED( val ); } - - private: - LyricsSubject *m_subject; -}; - -class LyricsSubject -{ - public: - void attach( LyricsObserver *observer ); - void detach( LyricsObserver *observer ); - - protected: - LyricsSubject() {} - virtual ~LyricsSubject() {} - - void sendNewLyrics( const LyricsData &lyrics ); - void sendNewSuggestions( const QVariantList &suggestions ); - void sendLyricsMessage( const QString &key, const QString &val ); - - private: - QList m_observers; -}; - -class AMAROK_EXPORT LyricsManager : public LyricsSubject -{ - public: - static LyricsManager* self() - { - if( !s_self ) - s_self = new LyricsManager(); - - return s_self; - } - - void lyricsResult( const QString& lyrics, bool cached = false ); - void lyricsResultHtml( const QString& lyrics, bool cached = false ); - void lyricsError( const QString &error ); - void lyricsNotFound( const QString& notfound ); - - /** - * Sets the given lyrics for the track with the given URL. - * - * @param trackUrl The URL of the track. - * @param lyrics The new lyrics. - */ - void setLyricsForTrack( const QString &trackUrl, const QString &lyrics ) const; - - /** - * Tests if the given lyrics are empty. - * - * @param lyrics The lyrics which will be tested. - * - * @return true if the given lyrics are empty, otherwise false. - */ - bool isEmpty( const QString &lyrics ) const; - - private: - LyricsManager() : LyricsSubject() { s_self = this; } - - bool showCached(); - - static LyricsManager* s_self; -}; - -Q_DECLARE_METATYPE( LyricsData ); - -#endif diff --git a/src/context/LyricsManager.cpp b/src/context/LyricsManager.cpp deleted file mode 100644 --- a/src/context/LyricsManager.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Leo Franchi * - * Copyright (c) 2009 Seb Ruiz * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "LyricsManager" - -#include "LyricsManager.h" - -#include "EngineController.h" -#include "core/meta/Meta.h" -#include "core/support/Debug.h" -#include "core-impl/collections/support/CollectionManager.h" - -#include -#include - -#include - -//////////////////////////////////////////////////////////////// -//// CLASS LyricsObserver -/////////////////////////////////////////////////////////////// - -LyricsObserver::LyricsObserver() - : m_subject( 0 ) -{ - qRegisterMetaType("LyricsData"); -} - -LyricsObserver::LyricsObserver( LyricsSubject *s ) - : m_subject( s ) -{ - m_subject->attach( this ); -} - -LyricsObserver::~LyricsObserver() -{ - if( m_subject ) - m_subject->detach( this ); -} - -//////////////////////////////////////////////////////////////// -//// CLASS LyricsSubject -/////////////////////////////////////////////////////////////// - -void LyricsSubject::sendNewLyrics( const LyricsData &lyrics ) -{ - DEBUG_BLOCK - foreach( LyricsObserver* obs, m_observers ) - { - obs->newLyrics( lyrics ); - } -} - -void LyricsSubject::sendNewSuggestions( const QVariantList &sug ) -{ - DEBUG_BLOCK - foreach( LyricsObserver* obs, m_observers ) - { - obs->newSuggestions( sug ); - } -} - -void LyricsSubject::sendLyricsMessage( const QString &key, const QString &val ) -{ - DEBUG_BLOCK - foreach( LyricsObserver* obs, m_observers ) - { - obs->lyricsMessage( key, val ); - } -} - -void LyricsSubject::attach( LyricsObserver *obs ) -{ - if( !obs || m_observers.indexOf( obs ) != -1 ) - return; - m_observers.append( obs ); -} - -void LyricsSubject::detach( LyricsObserver *obs ) -{ - int index = m_observers.indexOf( obs ); - if( index != -1 ) m_observers.removeAt( index ); -} - -//////////////////////////////////////////////////////////////// -//// CLASS LyricsManager -/////////////////////////////////////////////////////////////// - -LyricsManager* LyricsManager::s_self = 0; - -void -LyricsManager::lyricsResult( const QString& lyricsXML, bool cached ) //SLOT -{ - DEBUG_BLOCK - Q_UNUSED( cached ); - - QXmlStreamReader xml( lyricsXML ); - while( xml.readNextStartElement() ) - { - if( xml.name() == QLatin1String("lyric") ) - { - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( !currentTrack ) - return; - - QString lyrics( xml.readElementText() ); - if( !isEmpty( lyrics ) ) - { - // overwrite cached lyrics (as either there were no lyircs available previously OR - // the user exlicitly agreed to overwrite the lyrics) - debug() << "setting cached lyrics..."; - currentTrack->setCachedLyrics( lyrics ); // TODO: setLyricsByPath? - } - else if( !isEmpty( currentTrack->cachedLyrics() ) ) - { - // we found nothing, so if we have cached lyrics, use it! - debug() << "using cached lyrics..."; - lyrics = currentTrack->cachedLyrics(); - } - else - { - lyricsError( i18n("Retrieved lyrics is empty") ); - return; - } - - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - LyricsData data = { lyrics, currentTrack->name(), artist, QUrl() }; - sendNewLyrics( data ); - return; - } - else if( xml.name() == QLatin1String("suggestions") ) - { - QVariantList suggestions; - while( xml.readNextStartElement() ) - { - if( xml.name() != QLatin1String("suggestion") ) - continue; - - const QXmlStreamAttributes &a = xml.attributes(); - - QString artist = a.value( QLatin1String("artist") ).toString(); - QString title = a.value( QLatin1String("title") ).toString(); - QString url = a.value( QLatin1String("url") ).toString(); - - if( !url.isEmpty() ) - suggestions << ( QStringList() << title << artist << url ); - xml.skipCurrentElement(); - } - - debug() << "got" << suggestions.size() << "suggestions"; - if( suggestions.isEmpty() ) - sendLyricsMessage( "notFound", "notfound" ); - else - sendNewSuggestions( suggestions ); - return; - } - xml.skipCurrentElement(); - } - - if( xml.hasError() ) - { - warning() << "errors occurred during reading lyrics xml result:" << xml.errorString(); - lyricsError( i18n("Lyrics data could not be parsed") ); - } -} - -void -LyricsManager::lyricsResultHtml( const QString& lyricsHTML, bool cached ) -{ - DEBUG_BLOCK - Q_UNUSED( cached ) - - // we don't need to deal with suggestions here, because - // we assume the script has called showLyrics if they could - // be suggestions. this is for HTML display only - - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( currentTrack && !isEmpty( lyricsHTML ) ) - { - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - LyricsData data = { lyricsHTML, currentTrack->name(), artist, QUrl() }; - sendNewLyrics( data ); - - // overwrite cached lyrics (as either there were no lyircs available previously OR - // the user exlicitly agreed to overwrite the lyrics) - currentTrack->setCachedLyrics( lyricsHTML ); - } -} - -void -LyricsManager::lyricsError( const QString &error ) -{ - DEBUG_BLOCK - if( !showCached() ) - { - sendLyricsMessage( "error", error ); - } -} - - -void -LyricsManager::lyricsNotFound( const QString& notfound ) -{ - DEBUG_BLOCK - if( !showCached() ) - sendLyricsMessage( "notfound", notfound ); -} - - -bool LyricsManager::showCached() -{ - DEBUG_BLOCK - //if we have cached lyrics there is absolutely no point in not showing these.. - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( currentTrack && !isEmpty( currentTrack->cachedLyrics() ) ) - { - // TODO: add some sort of feedback that we could not fetch new ones - // so we are showing a cached result - debug() << "showing cached lyrics!"; - - QString lyrics = currentTrack->cachedLyrics(); - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - LyricsData data = { lyrics, currentTrack->name(), artist, QUrl() }; - sendNewLyrics( data ); - return true; - } - return false; -} - -void LyricsManager::setLyricsForTrack( const QString &trackUrl, const QString &lyrics ) const -{ - DEBUG_BLOCK - - Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( QUrl( trackUrl ) ); - - if( track ) - track->setCachedLyrics( lyrics ); - else - debug() << QString("could not find a track for the given URL (%1) - ignoring.").arg( trackUrl ); -} - -bool LyricsManager::isEmpty( const QString &lyrics ) const -{ - QTextEdit testItem; - - // Set the text of the TextItem. - if( Qt::mightBeRichText( lyrics ) ) - testItem.setHtml( lyrics ); - else - testItem.setPlainText( lyrics ); - - // Get the plaintext content. - // We use toPlainText() to strip all Html formatting, - // so we can test if there's any text given. - QString testText = testItem.toPlainText().trimmed(); - - return testText.isEmpty(); -} diff --git a/src/context/applets/lyrics/plugin/LyricsEngine.h b/src/context/applets/lyrics/plugin/LyricsEngine.h --- a/src/context/applets/lyrics/plugin/LyricsEngine.h +++ b/src/context/applets/lyrics/plugin/LyricsEngine.h @@ -18,14 +18,13 @@ #ifndef AMAROK_LYRICS_ENGINE #define AMAROK_LYRICS_ENGINE -#include "context/LyricsManager.h" #include "core/meta/Meta.h" #include #include #include -class LyricsEngine : public QObject, public LyricsObserver +class LyricsEngine : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text NOTIFY lyricsChanged) @@ -39,12 +38,11 @@ public: explicit LyricsEngine( QObject* parent = Q_NULLPTR ); - // reimplemented from LyricsObserver - void newLyrics( const LyricsData &lyrics ) Q_DECL_OVERRIDE; - void newSuggestions( const QVariantList &suggest ) Q_DECL_OVERRIDE; - void lyricsMessage( const QString& key, const QString& val ) Q_DECL_OVERRIDE; + void newLyrics( const Meta::TrackPtr &track ); + void newSuggestions( const QVariantList &suggest ); + void lyricsMessage( const QString& key, const QString& val ); - QString text() const { return m_lyrics.text; } + QString text() const { return m_lyrics; } QVariantList suggestions() const { return m_suggestions; } bool fetching() const { return m_fetching; } qreal position() const; @@ -56,7 +54,6 @@ void setFont( const QString &font ); Q_INVOKABLE void refetchLyrics() const; - Q_INVOKABLE void fetchLyrics( const QString &artist, const QString &title, const QString &url ); Q_INVOKABLE QStringList availableFonts() const; Q_SIGNALS: @@ -73,11 +70,9 @@ void onTrackMetadataChanged( Meta::TrackPtr track ); private: - void setLyrics( const LyricsData &lyrics ); void clearLyrics(); - void refetchLyrics(); - LyricsData m_lyrics; + QString m_lyrics; QVariantList m_suggestions; bool m_fetching; bool m_isUpdateInProgress; diff --git a/src/context/applets/lyrics/plugin/LyricsEngine.cpp b/src/context/applets/lyrics/plugin/LyricsEngine.cpp --- a/src/context/applets/lyrics/plugin/LyricsEngine.cpp +++ b/src/context/applets/lyrics/plugin/LyricsEngine.cpp @@ -20,140 +20,69 @@ #include "LyricsEngine.h" #include "EngineController.h" -#include "scripting/scriptmanager/ScriptManager.h" #include "core/support/Amarok.h" #include "core/support/Debug.h" +#include "lyrics/LyricsManager.h" #include #include LyricsEngine::LyricsEngine( QObject* parent ) : QObject( parent ) - , LyricsObserver( LyricsManager::self() ) , m_fetching( false ) , m_isUpdateInProgress( false ) { EngineController* engine = The::engineController(); + LyricsManager* lyricsManager = LyricsManager::instance(); connect( engine, &EngineController::trackChanged, this, &LyricsEngine::update ); connect( engine, &EngineController::trackMetadataChanged, this, &LyricsEngine::onTrackMetadataChanged ); connect( engine, &EngineController::trackPositionChanged, this, &LyricsEngine::positionChanged ); + connect( lyricsManager, &LyricsManager::newLyrics, this, &LyricsEngine::newLyrics ); + connect( lyricsManager, &LyricsManager::newSuggestions, this, &LyricsEngine::newSuggestions ); } void LyricsEngine::onTrackMetadataChanged( Meta::TrackPtr track ) { DEBUG_BLOCK // Only update if the lyrics have changed. - QString artist = track->artist() ? track->artist()->name() : QString(); - if( m_lyrics.artist != artist || - m_lyrics.title != track->name() || - m_lyrics.text != track->cachedLyrics() ) + if( m_lyrics != track->cachedLyrics() ) update(); } void LyricsEngine::update() { - if( m_isUpdateInProgress ) - return; - - m_isUpdateInProgress = true; - - // -- get current title and artist - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( !currentTrack ) + Meta::TrackPtr track = The::engineController()->currentTrack(); + if( !track ) { - debug() << "no current track"; - m_lyrics.clear(); - emit lyricsChanged(); - m_isUpdateInProgress = false; + clearLyrics(); return; } - QString title = currentTrack->name(); - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - - // -- clean up title - const QString magnatunePreviewString = QLatin1String( "PREVIEW: buy it at www.magnatune.com" ); - if( title.contains(magnatunePreviewString, Qt::CaseSensitive) ) - title = title.remove( " (" + magnatunePreviewString + ')' ); - if( artist.contains(magnatunePreviewString, Qt::CaseSensitive) ) - artist = artist.remove( " (" + magnatunePreviewString + ')' ); - - if( title.isEmpty() && currentTrack ) - { - /* If title is empty, try to use pretty title. - The fact that it often (but not always) has "artist name" together, can be bad, - but at least the user will hopefully get nice suggestions. */ - QString prettyTitle = currentTrack->prettyName(); - int h = prettyTitle.indexOf( QLatin1Char('-') ); - if ( h != -1 ) - { - title = prettyTitle.mid( h + 1 ).trimmed(); - if( title.contains(magnatunePreviewString, Qt::CaseSensitive) ) - title = title.remove( " (" + magnatunePreviewString + ')' ); - - if( artist.isEmpty() ) - { - artist = prettyTitle.mid( 0, h ).trimmed(); - if( artist.contains(magnatunePreviewString, Qt::CaseSensitive) ) - artist = artist.remove( " (" + magnatunePreviewString + ')' ); - } - } - } - - LyricsData lyrics = { currentTrack->cachedLyrics(), title, artist, QUrl() }; - - // Check if the title, the artist and the lyrics are still the same. - if( !lyrics.text.isEmpty() && (lyrics.text == m_lyrics.text) ) + if( LyricsManager::instance()->isEmpty( track->cachedLyrics() ) ) { - debug() << "nothing changed:" << lyrics.title; - newLyrics( lyrics ); - m_isUpdateInProgress = false; + clearLyrics(); return; } - // don't rely on caching for streams - const bool cached = !LyricsManager::self()->isEmpty( lyrics.text ) - && !The::engineController()->isStream(); - - if( cached ) - { - newLyrics( lyrics ); - } - else - { - // no lyrics, and no lyrics script! - if( !ScriptManager::instance()->lyricsScriptRunning() ) - { - debug() << "no lyrics script running"; - clearLyrics(); - disconnect( ScriptManager::instance(), &ScriptManager::lyricsScriptStarted, this, 0 ); - connect( ScriptManager::instance(), &ScriptManager::lyricsScriptStarted, this, &LyricsEngine::update ); - m_isUpdateInProgress = false; - return; - } - - // fetch by lyrics script - clearLyrics(); - m_fetching = true; - emit fetchingChanged(); - ScriptManager::instance()->notifyFetchLyrics( lyrics.artist, lyrics.title, "", currentTrack ); - } - m_isUpdateInProgress = false; + newLyrics( track ); } -void LyricsEngine::newLyrics( const LyricsData &lyrics ) +void LyricsEngine::newLyrics( const Meta::TrackPtr &track ) { DEBUG_BLOCK - m_lyrics = lyrics; + if( track != The::engineController()->currentTrack() ) + return; + + m_lyrics = track->cachedLyrics(); emit lyricsChanged(); m_fetching = false; @@ -197,36 +126,7 @@ if( !currentTrack ) return; - ScriptManager::instance()->notifyFetchLyrics( m_lyrics.artist, m_lyrics.title, "", currentTrack ); -} - -void LyricsEngine::refetchLyrics() -{ - DEBUG_BLOCK - - auto currentTrack = The::engineController()->currentTrack(); - - if( currentTrack ) - ScriptManager::instance()->notifyFetchLyrics( currentTrack->artist()->name(), - currentTrack->name(), "", currentTrack ); - - m_fetching = true; - emit fetchingChanged(); -} - -void LyricsEngine::fetchLyrics(const QString& artist, const QString& title, const QString& url) -{ - DEBUG_BLOCK - - if( !QUrl( url ).isValid() ) - return; - - debug() << "clicked suggestion" << url; - - ScriptManager::instance()->notifyFetchLyrics( artist, title, url, Meta::TrackPtr() ); - - m_fetching = true; - emit fetchingChanged(); + LyricsManager::instance()->loadLyrics( currentTrack, true ); } qreal LyricsEngine::fontSize() const diff --git a/src/dialogs/DiagnosticDialog.cpp b/src/dialogs/DiagnosticDialog.cpp --- a/src/dialogs/DiagnosticDialog.cpp +++ b/src/dialogs/DiagnosticDialog.cpp @@ -19,7 +19,6 @@ #include "context/ContextView.h" #include "PluginManager.h" -#include "scripting/scriptmanager/ScriptManager.h" #include #include @@ -66,22 +65,6 @@ const QString DiagnosticDialog::generateReport( const KAboutData *aboutData ) { - // Get scripts -- we have to assemble 3 lists into one - KPluginInfo::List aScripts; - const auto aScriptManager = ScriptManager::instance(); - aScripts.append( aScriptManager->scripts( QLatin1String( "Generic" ) ) ); - aScripts.append( aScriptManager->scripts( QLatin1String( "Lyrics" ) ) ); - aScripts.append( aScriptManager->scripts( QLatin1String( "Scriptable Service" ) ) ); - - // Format the data to be readable - QString aScriptString; - foreach( KPluginInfo aInfo, aScripts ) - { - if( aInfo.isPluginEnabled() ) - aScriptString += " " + aInfo.name() + " (" + aInfo.version() + ")\n"; - } - - // Get plugins -- we have to assemble a list again. QList aPlugins; const auto aPluginManager = Plugins::PluginManager::instance(); @@ -127,10 +110,9 @@ aPhononBackend->property( "X-KDE-PhononBackendInfo-Version", QVariant::String ).toString(), // & Backend pulse // PulseAudio ) + i18n( - "Enabled Scripts:\n%1\n" - "Enabled Plugins:\n%2\n" - "Enabled Applets:\n%3\n", - aScriptString, aPluginString, appletString + "Enabled Plugins:\n%1\n" + "Enabled Applets:\n%2\n", + aPluginString, appletString ); } diff --git a/src/dialogs/deviceconfiguredialog.cpp b/src/dialogs/deviceconfiguredialog.cpp --- a/src/dialogs/deviceconfiguredialog.cpp +++ b/src/dialogs/deviceconfiguredialog.cpp @@ -23,7 +23,6 @@ #include "mediabrowser.h" #include "MediaDevice.h" #include "core/support/PluginManager.h" -#include "scripting/scriptmanager/ScriptManager.h" #include #include @@ -120,14 +119,8 @@ m_transcodeRemove->setText( i18n( "Remove transcoded files after transfer" ) ); m_transcodeRemove->setChecked( device->m_transcodeRemove ); - const ScriptManager *sm = ScriptManager::instance(); m_transcodeCheck->setEnabled( !sm->transcodeScriptRunning().isEmpty() ); transcodeGroup->setEnabled( !sm->transcodeScriptRunning().isEmpty() && device->m_transcode ); - if( sm->transcodeScriptRunning().isNull() ) - { - m_transcodeCheck->setToolTip( i18n( "For this feature, a script of type \"Transcode\" has to be running" ) ); - transcodeGroup->setToolTip( i18n( "For this feature, a script of type \"Transcode\" has to be running" ) ); - } device->addConfigElements( vbox ); } diff --git a/src/dynamic/BiasFactory.cpp b/src/dynamic/BiasFactory.cpp --- a/src/dynamic/BiasFactory.cpp +++ b/src/dynamic/BiasFactory.cpp @@ -29,7 +29,6 @@ #include "core/support/Debug.h" #include "core/collections/QueryMaker.h" #include "dynamic/Bias.h" -#include "scripting/scriptengine/exporters/ScriptableBiasExporter.h" #include #include diff --git a/src/lyrics/LyricsManager.h b/src/lyrics/LyricsManager.h new file mode 100644 --- /dev/null +++ b/src/lyrics/LyricsManager.h @@ -0,0 +1,73 @@ +/**************************************************************************************** + * Copyright (c) 2007 Leo Franchi * + * * + * This program is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License along with * + * this program. If not, see . * + ****************************************************************************************/ + +#ifndef LYRICS_MANAGER_H +#define LYRICS_MANAGER_H + +#include "amarok_export.h" +#include "core/meta/Meta.h" +#include "network/NetworkAccessManagerProxy.h" + +#include +#include +#include +#include + + +class AMAROK_EXPORT LyricsManager : public QObject +{ + Q_OBJECT + + public: + static LyricsManager* instance() + { + if( !s_self ) + s_self = new LyricsManager(); + + return s_self; + } + + /** + * Tests if the given lyrics are empty. + * + * @param lyrics The lyrics which will be tested. + * + * @return true if the given lyrics are empty, otherwise false. + */ + bool isEmpty( const QString &lyrics ) const; + + void newTrack( Meta::TrackPtr track ); + void lyricsResult( const QByteArray& lyrics, Meta::TrackPtr track ); + void lyricsLoaded( const QUrl &url, const QByteArray &data, NetworkAccessManagerProxy::Error err ); + void loadLyrics( Meta::TrackPtr track, bool overwrite = false ); + + signals: + void newLyrics( Meta::TrackPtr ); + void newSuggestions( QVariantList ); + void error( QString ); + + private: + LyricsManager(); + + void sanitizeTitle( QString &title ); + void sanitizeArtist( QString &artist ); + + static LyricsManager* s_self; + + QMap m_trackMap; +}; + +#endif diff --git a/src/lyrics/LyricsManager.cpp b/src/lyrics/LyricsManager.cpp new file mode 100644 --- /dev/null +++ b/src/lyrics/LyricsManager.cpp @@ -0,0 +1,275 @@ +/**************************************************************************************** + * Copyright (c) 2007 Leo Franchi * + * Copyright (c) 2009 Seb Ruiz * + * * + * This program is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License along with * + * this program. If not, see . * + ****************************************************************************************/ + +#define DEBUG_PREFIX "LyricsManager" + +#include "LyricsManager.h" + +#include "EngineController.h" +#include "core/meta/Meta.h" +#include "core/support/Debug.h" +#include "core-impl/collections/support/CollectionManager.h" + +#include +#include +#include + +#include + + +#define APIURL "http://lyrics.wikia.com/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles=" + + +LyricsManager* LyricsManager::s_self = 0; + +LyricsManager::LyricsManager() +{ + s_self = this; + connect( The::engineController(), &EngineController::trackChanged, this, &LyricsManager::newTrack ); +} + +void +LyricsManager::newTrack( Meta::TrackPtr track ) +{ + loadLyrics( track ); +} + +void +LyricsManager::lyricsResult( const QByteArray& lyricsXML, Meta::TrackPtr track ) //SLOT +{ + DEBUG_BLOCK + + QXmlStreamReader xml( lyricsXML ); + while( !xml.atEnd() ) + { + xml.readNext(); + + if( xml.name() == QStringLiteral("lyric") || xml.name() == QStringLiteral( "lyrics" ) ) + { + QString lyrics( xml.readElementText() ); + if( !isEmpty( lyrics ) ) + { + // overwrite cached lyrics (as either there were no lyircs available previously OR + // the user exlicitly agreed to overwrite the lyrics) + debug() << "setting cached lyrics..."; + track->setCachedLyrics( lyrics ); // TODO: setLyricsByPath? + emit newLyrics( track ); + } + else + { + ::error() << i18n("Retrieved lyrics is empty"); + return; + } + } + else if( xml.name() == QLatin1String("suggestions") ) + { + QVariantList suggestions; + while( xml.readNextStartElement() ) + { + if( xml.name() != QLatin1String("suggestion") ) + continue; + + const QXmlStreamAttributes &a = xml.attributes(); + + QString artist = a.value( QLatin1String("artist") ).toString(); + QString title = a.value( QLatin1String("title") ).toString(); + QString url = a.value( QLatin1String("url") ).toString(); + + if( !url.isEmpty() ) + suggestions << ( QStringList() << title << artist << url ); + + xml.skipCurrentElement(); + } + + debug() << "got" << suggestions.size() << "suggestions"; + + if( !suggestions.isEmpty() ) + emit newSuggestions( suggestions ); + + return; + } + } + + if( xml.hasError() ) + { + warning() << "errors occurred during reading lyrics xml result:" << xml.errorString(); + emit error( i18n("Lyrics data could not be parsed") ); + } +} + +void LyricsManager::loadLyrics( Meta::TrackPtr track, bool overwrite ) +{ + DEBUG_BLOCK + + if( !track ) + { + debug() << "no current track"; + return; + } + + // -- get current title and artist + QString title = track->name(); + QString artist = track->artist() ? track->artist()->name() : QString(); + + sanitizeTitle( title ); + sanitizeArtist( artist ); + + if( !isEmpty( track->cachedLyrics() ) && !overwrite ) + { + debug() << "Lyrics already cached."; + return; + } + + QUrl url( APIURL + artist + ':' + title ); + m_trackMap.insert( url, track ); + NetworkAccessManagerProxy::instance()->getData( url, this, &LyricsManager::lyricsLoaded ); +} + +void LyricsManager::lyricsLoaded( const QUrl& url, const QByteArray& data, NetworkAccessManagerProxy::Error err ) +{ + DEBUG_BLOCK + + if( err.code ) + { + warning() << "A network error occurred:" << err.description; + return; + } + + Meta::TrackPtr track = m_trackMap.take( url ); + if( !track ) + { + warning() << "No track belongs to this url:" << url.url(); + return; + } + + QDomDocument document; + document.setContent( data ); + auto list = document.elementsByTagName( QStringLiteral( "rev" ) ); + if( list.isEmpty() ) + { + if( track->album() && track->album()->albumArtist() ) + { + QString albumArtist = track->album()->albumArtist()->name(); + QString artist = track->artist() ? track->artist()->name() : QString(); + QString title = track->name(); + sanitizeTitle( title ); + sanitizeArtist( artist ); + sanitizeArtist( albumArtist ); + + //Try with album artist + if( url == QUrl( APIURL + artist + ':' + title ) && albumArtist != artist ) + { + debug() << "Try again with album artist."; + + QUrl newUrl( APIURL + albumArtist + ':' + title ); + m_trackMap.insert( newUrl, track ); + NetworkAccessManagerProxy::instance()->getData( newUrl, this, &LyricsManager::lyricsLoaded ); + return; + } + } + + debug() << "No lyrics found for track:" << track->name(); + return; + } + + QString rev = list.at( 0 ).toElement().text(); + if( rev.contains( QStringLiteral( "lyrics" ) ) ) + { + int lindex = rev.indexOf( QStringLiteral( "" ) ); + int rindex = rev.indexOf( QStringLiteral( "" ) ); + lyricsResult( (rev.mid( lindex, rindex - lindex ) + "" ).toUtf8(), track ); + } + else if( rev.contains( QStringLiteral( "lyric" ) ) ) + { + int lindex = rev.indexOf( QStringLiteral( "" ) ); + int rindex = rev.indexOf( QStringLiteral( "" ) ); + lyricsResult( (rev.mid( lindex, rindex - lindex ) + "" ).toUtf8(), track ); + } + else if( rev.contains( QStringLiteral( "#REDIRECT" ) ) ) + { + debug() << "Redirect:" << data; + + int lindex = rev.indexOf( QStringLiteral( "#REDIRECT [[" ) ) + 12; + int rindex = rev.indexOf( QStringLiteral( "]]" ) ); + QStringList list = rev.mid( lindex, rindex - lindex ).split( ':' ); + if( list.size() == 2 ) + { + list[0] = list[0].replace( '&', QStringLiteral( "%26" ) ); + list[1] = list[1].replace( '&', QStringLiteral( "%26" ) ); + QUrl newUrl( APIURL + list.join( ':' ) ); + m_trackMap.insert( newUrl, track ); + NetworkAccessManagerProxy::instance()->getData( newUrl, this, &LyricsManager::lyricsLoaded ); + } + } + else + warning() << "No lyrics found in data:" << data; +} + +void LyricsManager::sanitizeTitle( QString& title ) +{ + const QString magnatunePreviewString = QLatin1String( "PREVIEW: buy it at www.magnatune.com" ); + + if( title.contains(magnatunePreviewString, Qt::CaseSensitive) ) + title = title.remove( " (" + magnatunePreviewString + ')' ); + + title = title.remove( QStringLiteral( "(Live)" ) ); + title = title.remove( QStringLiteral( "(live)" ) ); + title = title.replace( '`', QStringLiteral( "'" ) ); + title = title.replace( '&', QStringLiteral( "%26" ) ); +} + +void LyricsManager::sanitizeArtist( QString& artist ) +{ + const QString magnatunePreviewString = QLatin1String( "PREVIEW: buy it at www.magnatune.com" ); + + if( artist.contains(magnatunePreviewString, Qt::CaseSensitive) ) + artist = artist.remove( " (" + magnatunePreviewString + ')' ); + + // strip "featuring " from the artist + int strip = artist.toLower().indexOf( " ft. "); + if ( strip != -1 ) + artist = artist.mid( 0, strip ); + + strip = artist.toLower().indexOf( " feat. " ); + if ( strip != -1 ) + artist = artist.mid( 0, strip ); + + strip = artist.toLower().indexOf( " featuring " ); + if ( strip != -1 ) + artist = artist.mid( 0, strip ); + + artist = artist.replace( '`', QStringLiteral( "'" ) ); + artist = artist.replace( '&', QStringLiteral( "%26" ) ); +} + +bool LyricsManager::isEmpty( const QString &lyrics ) const +{ + QTextEdit testItem; + + // Set the text of the TextItem. + if( Qt::mightBeRichText( lyrics ) ) + testItem.setHtml( lyrics ); + else + testItem.setPlainText( lyrics ); + + // Get the plaintext content. + // We use toPlainText() to strip all Html formatting, + // so we can test if there's any text given. + QString testText = testItem.toPlainText().trimmed(); + + return testText.isEmpty(); +} diff --git a/src/playlistmanager/PlaylistManager.h b/src/playlistmanager/PlaylistManager.h --- a/src/playlistmanager/PlaylistManager.h +++ b/src/playlistmanager/PlaylistManager.h @@ -52,7 +52,7 @@ /** * Facility for managing PlaylistProviders registered by other - * parts of the application, plugins and scripts. + * parts of the application and plugins. */ class AMAROK_EXPORT PlaylistManager : public QObject { diff --git a/src/scripting/scriptconsole/CompletionModel.h b/src/scripting/scriptconsole/CompletionModel.h deleted file mode 100644 --- a/src/scripting/scriptconsole/CompletionModel.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPTCONSOLE_COMPLETIONMODEL_H -#define SCRIPTCONSOLE_COMPLETIONMODEL_H - -#include -#include - -namespace KTextEditor { - class View; - class Document; -} - -namespace ScriptConsoleNS -{ - class AmarokScriptCodeCompletionModel : public KTextEditor::CodeCompletionModelControllerInterface - , public KTextEditor::CodeCompletionModel - { - public: - explicit AmarokScriptCodeCompletionModel( QObject *parent ); - virtual ~AmarokScriptCodeCompletionModel(); - - private: - QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; - void completionInvoked( KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType ); - void executeCompletionItem( KTextEditor::View *view, const KTextEditor::Range &range, const QModelIndex &index ) const; - KTextEditor::Range completionRange( KTextEditor::View *view, const KTextEditor::Cursor &position ); - bool shouldAbortCompletion( KTextEditor::View *view, const KTextEditor::Range &range, const QString ¤tCompletion ); - - QStringList m_completionList; - QStringList m_autoCompleteStrings; - }; -} - -#endif // SCRIPTCONSOLE_COMPLETIONMODEL_H diff --git a/src/scripting/scriptconsole/CompletionModel.cpp b/src/scripting/scriptconsole/CompletionModel.cpp deleted file mode 100644 --- a/src/scripting/scriptconsole/CompletionModel.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "CompletionModel.h" - -#include "core/support/Debug.h" - -#include -#include - -#include -#include - -using namespace ScriptConsoleNS; - -AmarokScriptCodeCompletionModel::AmarokScriptCodeCompletionModel( QObject *parent ) - : CodeCompletionModel( parent ) -{ - const QUrl url( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/scriptconsole/" ) ); - QFile file( url.path() + "AutoComplete.txt" ); - if( file.open( QFile::ReadOnly ) ) - { - QTextStream in( &file ); - while ( !in.atEnd() ) - m_autoCompleteStrings << in.readLine(); - } - else - debug() << "No autocomplete file found for the script console"; -} - -void -AmarokScriptCodeCompletionModel::completionInvoked( KTextEditor::View *view, const KTextEditor::Range &range, KTextEditor::CodeCompletionModel::InvocationType invocationType ) -{ - Q_UNUSED( invocationType ) - - beginResetModel(); - m_completionList.clear(); - const QString ¤tText = view->document()->text( range ); - foreach( const QString &completionItem, m_autoCompleteStrings ) - { - int index = completionItem.indexOf( currentText, Qt::CaseInsensitive ) + currentText.length(); - if( index != -1 && !QStringRef( &completionItem, index, completionItem.size()-index ).contains( '.' ) && completionItem != currentText ) - m_completionList << completionItem; - } - setRowCount( m_completionList.count() ); - endResetModel(); -} - -QVariant -AmarokScriptCodeCompletionModel::data( const QModelIndex &index, int role ) const -{ - if( !index.isValid() || role != Qt::DisplayRole || index.row() < 0 || index.row() >= rowCount() - || index.column() != KTextEditor::CodeCompletionModel::Name ) - return QVariant(); - return m_completionList[ index.row() ]; -} - -KTextEditor::Range -AmarokScriptCodeCompletionModel::completionRange(KTextEditor::View* view, const KTextEditor::Cursor& position) -{ - const QString& line = view->document()->line(position.line()); - KTextEditor::Range range(position, position); - // include everything non-space before - for( int i = position.column() - 1; i >= 0; --i ) - { - if( line.at( i ).isSpace() ) - break; - else - range.start().setColumn( i ); - } - // include everything non-space after - for( int i = position.column() + 1; i < line.length(); ++i ) - { - if( line.at( i ).isSpace() ) - break; - else - range.end().setColumn( i ); - } - return range; -} - -bool -AmarokScriptCodeCompletionModel::shouldAbortCompletion( KTextEditor::View *view, const KTextEditor::Range &range, const QString ¤tCompletion ) -{ - if(view->cursorPosition() < range.start() || view->cursorPosition() > range.end()) - return true; //Always abort when the completion-range has been left - - for( int i = 0; i < currentCompletion.length(); ++i ) - { - if( currentCompletion.at( i ).isSpace() ) - return true; - } - // else it's valid - return false; -} - -void -AmarokScriptCodeCompletionModel::executeCompletionItem( KTextEditor::View *view, const KTextEditor::Range &range, const QModelIndex &index ) const -{ - view->document()->replaceText( range, m_completionList.at( index.row() ) ); -} - -AmarokScriptCodeCompletionModel::~AmarokScriptCodeCompletionModel() -{ - DEBUG_BLOCK - m_completionList.clear(); -} diff --git a/src/scripting/scriptconsole/ScriptConsole.h b/src/scripting/scriptconsole/ScriptConsole.h deleted file mode 100644 --- a/src/scripting/scriptconsole/ScriptConsole.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPTCONSOLE_H -#define SCRIPTCONSOLE_H - -#include -#include -#include -#include -#include - -namespace KTextEditor{ - class Editor; - class View; -} -class QEvent; -class QListWidget; -class QListWidgetItem; -class QModelIndex; -class QScriptEngine; -class QSplitter; - -namespace ScriptConsoleNS -{ -class ScriptConsoleItem; -class ScriptListDockWidget; - - class ScriptConsole : public QMainWindow - { - Q_OBJECT - - public: - static ScriptConsole *instance(); - - private Q_SLOTS: - void slotAbortEvaluation(); - void slotExecuteNewScript(); - void slotNewScript(); - void setCurrentScriptItem( ScriptConsoleItem *item ); - void slotEvaluationSuspended(); - void slotEvaluationResumed(); - void slotEditScript( ScriptConsoleItem *item ); - - private: - explicit ScriptConsole( QWidget *parent ); - virtual ~ScriptConsole(); - - bool eventFilter( QObject *watched, QEvent *event ); - QDockWidget *getWidget( const QString &title, QScriptEngineDebugger::DebuggerWidget widget ); - void closeEvent( QCloseEvent *event ); - ScriptConsoleItem* createScriptItem( const QString &script ); - - QScriptEngineDebugger *m_debugger; - QPointer m_scriptItem; - QDockWidget *m_codeWidget; - QString m_savePath; - KTextEditor::Editor *m_editor; - ScriptListDockWidget *m_scriptListDock; - static QPointer s_instance; - }; - - class ScriptListDockWidget : public QDockWidget - { - Q_OBJECT - - public: - explicit ScriptListDockWidget( QWidget *parent ); - ~ScriptListDockWidget(); - void addScript( ScriptConsoleItem *script ); - void addItem( QListWidgetItem *item ); - - public Q_SLOTS: - void clear(); - void removeCurrentScript(); - void prev(); - void next(); - - Q_SIGNALS: - void edit( ScriptConsoleItem *item ); - void executeScript( ScriptConsoleItem *item ); - void currentItemChanged( ScriptConsoleItem *newItem ); - void newScript(); - - private Q_SLOTS: - void slotDoubleClicked( const QModelIndex &index ); - void slotCurrentItemChanged( QListWidgetItem *newItem, QListWidgetItem *oldItem ); - - private: - QListWidget *m_scriptListWidget; - const int ScriptRole = 1002; - }; -} - -#endif // SCRIPTCONSOLE_H diff --git a/src/scripting/scriptconsole/ScriptConsole.cpp b/src/scripting/scriptconsole/ScriptConsole.cpp deleted file mode 100644 --- a/src/scripting/scriptconsole/ScriptConsole.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptConsole.h" -#define DEBUG_PREFIX "ScriptConsole" - -#include "core/support/Amarok.h" -#include "core/support/Debug.h" -#include "MainWindow.h" -#include "ScriptEditorDocument.h" -#include "ScriptConsoleItem.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -using namespace AmarokScript; -using namespace ScriptConsoleNS; - -QPointer ScriptConsole::s_instance; - -ScriptConsole* -ScriptConsole::instance() -{ - if( !s_instance ) - s_instance = new ScriptConsole( The::mainWindow() ); - return s_instance.data(); -} - -//private - -ScriptConsole::ScriptConsole( QWidget *parent ) - : QMainWindow( parent, Qt::Window ) -{ - m_editor = KTextEditor::Editor::instance(); - if ( !m_editor ) - { - KMessageBox::error( 0, i18n("A KDE text-editor component could not be found.\n" - "Please check your KDE installation. Exiting the console!") ); - deleteLater(); - return; - } - m_scriptListDock = new ScriptListDockWidget( this ); - m_debugger = new QScriptEngineDebugger( this ); - - setDockNestingEnabled( true ); - setWindowTitle( i18n( "Script Console" ) ); - setObjectName( "scriptconsole" ); - - m_debugger->setAutoShowStandardWindow( false ); - m_codeWidget = getWidget( "Code", QScriptEngineDebugger::CodeWidget ); - addDockWidget( Qt::BottomDockWidgetArea, m_codeWidget ); - QList debugWidgets = QList() << getWidget( i18n( "Console" ), QScriptEngineDebugger::ConsoleWidget ) - << getWidget( i18n( "Error" ), QScriptEngineDebugger::ErrorLogWidget ) - << getWidget( i18n( "Debug Output" ), QScriptEngineDebugger::DebugOutputWidget ) - << getWidget( i18n( "Loaded Scripts" ), QScriptEngineDebugger::ScriptsWidget ) - << getWidget( i18n( "Breakpoints" ), QScriptEngineDebugger::BreakpointsWidget ) - << getWidget( i18n( "Stack" ), QScriptEngineDebugger::StackWidget ) - << getWidget( i18n( "Locals" ), QScriptEngineDebugger::LocalsWidget ); - foreach( QDockWidget *widget, debugWidgets ) - { - addDockWidget( Qt::BottomDockWidgetArea, widget ); - } - addDockWidget( Qt::BottomDockWidgetArea, m_scriptListDock ); - tabifyDockWidget( debugWidgets[0], debugWidgets[1] ); - tabifyDockWidget( debugWidgets[1], debugWidgets[2] ); - tabifyDockWidget( debugWidgets[3], debugWidgets[4] ); - tabifyDockWidget( debugWidgets[5], debugWidgets[6] ); - - QMenuBar *bar = new QMenuBar( this ); - setMenuBar( bar ); - bar->addMenu( m_debugger->createStandardMenu( this ) ); - QToolBar *toolBar = m_debugger->createStandardToolBar( this ); - QAction *action = new QAction( i18n( "Stop" ), this ); - action->setIcon( QApplication::style()->standardIcon( QStyle::SP_MediaStop ) ); - connect( action, &QAction::toggled, this, &ScriptConsole::slotAbortEvaluation ); - toolBar->addAction( action ); - action = new QAction( QIcon::fromTheme( "media-playback-start" ), i18n("Execute Script"), this ); - action->setShortcut( Qt::CTRL + Qt::Key_Enter ); - connect( action, &QAction::triggered, this, &ScriptConsole::slotExecuteNewScript ); - toolBar->addAction( action ); - action = new QAction( QIcon::fromTheme( "document-new" ), i18n( "&New Script" ), this ); - action->setShortcut( Qt::CTRL + Qt::Key_N ); - toolBar->addAction( action ); - connect( action, &QAction::triggered, this, &ScriptConsole::slotNewScript ); - action = new QAction( QIcon::fromTheme( "edit-delete" ), i18n( "&Delete Script" ), this ); - toolBar->addAction( action ); - connect( action, &QAction::triggered, m_scriptListDock, &ScriptListDockWidget::removeCurrentScript ); - action = new QAction( i18n( "&Clear All Scripts" ), this ); - toolBar->addAction( action ); - connect( action, &QAction::triggered, m_scriptListDock, &ScriptListDockWidget::clear ); - action = new QAction( i18n("Previous Script"), this ); - action->setShortcut( QKeySequence::MoveToPreviousPage ); - connect( action, &QAction::triggered, m_scriptListDock, &ScriptListDockWidget::prev ); - toolBar->addAction( action ); - action = new QAction( i18n("Next Script"), this ); - action->setShortcut( QKeySequence::MoveToNextPage ); - connect( action, &QAction::triggered, m_scriptListDock, &ScriptListDockWidget::next ); - toolBar->addAction( action ); - - addToolBar( toolBar ); - - QMenu *viewMenu = new QMenu( this ); - viewMenu->setTitle( i18n( "&View" ) ); - foreach( QDockWidget *dockWidget, findChildren() ) - { - if( dockWidget->parentWidget() == this ) - viewMenu->addAction( dockWidget->toggleViewAction() ); - } - menuBar()->addMenu( viewMenu ); - - addDockWidget( Qt::BottomDockWidgetArea, m_scriptListDock ); - connect( m_scriptListDock, &ScriptListDockWidget::edit, this, &ScriptConsole::slotEditScript ); - connect( m_scriptListDock, &ScriptListDockWidget::currentItemChanged, this, &ScriptConsole::setCurrentScriptItem ); - - QListWidgetItem *item = new QListWidgetItem( "The Amarok Script Console allows you to easily execute" - "JavaScript with access to all functions\nand methods you would" - "have in an Amarok script.\nInformation on scripting for Amarok is" - "available at:\nhttp://community.kde.org/Amarok/Development#Scripting" - "\nExecute code: CTRL-Enter\nBack in code history: Page Up" - "\nForward in code history: Page Down" - "See the debugger manual at: " - , 0 ); - item->setFlags( Qt::NoItemFlags ); - m_scriptListDock->addItem( item ); - - QSettings settings( "KDE", "Amarok" ); - settings.beginGroup( "ScriptConsole" ); - restoreGeometry( settings.value("geometry").toByteArray() ); - m_savePath = settings.value("savepath").toString(); - settings.endGroup(); - - if( m_savePath.isEmpty() ) - m_savePath = Amarok::saveLocation("scriptconsole"); - - slotNewScript(); - connect( m_debugger, &QScriptEngineDebugger::evaluationSuspended, this, &ScriptConsole::slotEvaluationSuspended ); - connect( m_debugger, &QScriptEngineDebugger::evaluationResumed, this, &ScriptConsole::slotEvaluationResumed ); - show(); - raise(); -} - -void -ScriptConsole::slotExecuteNewScript() -{ - if( m_scriptItem->document()->text().isEmpty() ) - return; - - QScriptSyntaxCheckResult syntaxResult = m_scriptItem->engine()->checkSyntax( m_scriptItem->document()->text() ); - if( QScriptSyntaxCheckResult::Valid != syntaxResult.state() ) - { - debug() << "Syntax error: " << syntaxResult.errorLineNumber() << syntaxResult.errorMessage(); - KTextEditor::View *view = dynamic_cast( m_codeWidget->widget() ); - ScriptEditorDocument::highlight( view, syntaxResult.errorLineNumber(), QColor( 255, 0, 0 ) ); - int response = KMessageBox::warningContinueCancel( this, i18n( "Syntax error at line %1, continue anyway?\nError: %2", - syntaxResult.errorLineNumber(), syntaxResult.errorMessage() ), - i18n( "Syntax Error" ) ); - if( response == KMessageBox::Cancel ) - return; - } - - m_scriptItem->document()->save(); - m_codeWidget->setWidget( m_debugger->widget( QScriptEngineDebugger::CodeWidget ) ); - m_scriptItem->start( false ); -} - -void -ScriptConsole::closeEvent( QCloseEvent *event ) -{ - QSettings settings( "KDE", "Amarok" ); - settings.beginGroup( "ScriptConsole" ); - settings.setValue( "geometry", saveGeometry() ); - settings.setValue( "savepath", m_savePath ); - settings.endGroup(); - QMainWindow::closeEvent( event ); - deleteLater(); -} - -void -ScriptConsole::slotEditScript( ScriptConsoleItem *item ) -{ - if( m_scriptItem->running() && KMessageBox::warningContinueCancel( this, i18n( "This will stop this script! Continue?" ), QString(), KStandardGuiItem::cont() - , KStandardGuiItem::cancel(), "stopRunningScriptWarning" ) == KMessageBox::Cancel ) - return; - - item->pause(); - setCurrentScriptItem( item ); -} - -ScriptConsoleItem* -ScriptConsole::createScriptItem( const QString &script ) -{ - if( ( m_savePath.isEmpty() || !QDir( m_savePath ).exists() ) - && ( m_savePath = QFileDialog::getExistingDirectory(this, i18n( "Choose where to save your scripts" ), "~", - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks) ).isEmpty() ) - return 0; - - QString scriptPath; - QString scriptName; - do - { - scriptName = QString( "Script-%1" ).arg( qrand() ); - scriptPath = QString( "%1/%2" ).arg( m_savePath, scriptName ); - } while ( QDir( scriptPath ).exists() ); - QDir().mkdir( scriptPath ); - - ScriptEditorDocument *document = new ScriptEditorDocument( this, m_editor->createDocument( 0 ) ); - document->setText( script ); - ScriptConsoleItem *scriptItem = new ScriptConsoleItem( this, scriptName, "Generic", scriptPath, document ); - return scriptItem; -} - -ScriptConsole::~ScriptConsole() -{ - m_debugger->detach(); -} - -void -ScriptConsole::slotEvaluationSuspended() -{ - if( !m_scriptItem ) - { - slotNewScript(); - return; - } - debug() << "Is Evaluating() " << m_scriptItem->engine()->isEvaluating(); - debug() << "Exception isValid()" << m_scriptItem->engine()->uncaughtException().isValid(); - if( m_scriptItem->engine() && m_scriptItem->engine()->uncaughtException().isValid() ) - return; - - KTextEditor::View *view = m_scriptItem->createEditorView( m_codeWidget ); - view->installEventFilter( this ); - view->document()->installEventFilter( this ); - m_codeWidget->setWidget( view ); -} - -void -ScriptConsole::slotEvaluationResumed() -{ - debug() << "Is Evaluating() " << m_scriptItem->engine()->isEvaluating(); - debug() << "Exception isValid()" << m_scriptItem->engine()->uncaughtException().isValid(); - if( !m_scriptItem->engine() || !m_scriptItem->engine()->isEvaluating() ) - return; - - KTextEditor::View *view = m_scriptItem->createEditorView( m_codeWidget ); - view->installEventFilter( this ); - m_codeWidget->setWidget( view ); -} - -void -ScriptConsole::slotAbortEvaluation() -{ - m_scriptItem->pause(); -} - -QDockWidget* -ScriptConsole::getWidget( const QString &title, QScriptEngineDebugger::DebuggerWidget widget ) -{ - QDockWidget *debugWidget = new QDockWidget( title, this ); - debugWidget->setWidget( m_debugger->widget( widget ) ); - return debugWidget; -} - -void -ScriptConsole::setCurrentScriptItem( ScriptConsoleItem *item ) -{ - if( !item || m_scriptItem.data() == item ) - return; - m_debugger->detach(); - m_debugger->attachTo( item->engine() ); - m_scriptItem = item; - if( item->engine() && item->engine()->isEvaluating() ) - { - m_codeWidget->setWidget( m_debugger->widget( QScriptEngineDebugger::CodeWidget ) ); - } - else - { - KTextEditor::View *view = item->createEditorView( m_codeWidget ); - view->installEventFilter( this ); - m_codeWidget->setWidget( view ); - } -} - -void -ScriptConsole::slotNewScript() -{ - ScriptConsoleItem *item = createScriptItem( "" ); - m_scriptListDock->addScript( item ); - setCurrentScriptItem( item ); -} - -bool -ScriptConsole::eventFilter( QObject *watched, QEvent *event ) -{ - Q_UNUSED( watched ) - if( event->type() == QEvent::KeyPress ) - { - QKeyEvent *keyEvent = static_cast( event ); - if( keyEvent == QKeySequence::MoveToNextPage ) - { - m_scriptListDock->next(); - return true; - } - else if( keyEvent == QKeySequence::MoveToPreviousPage ) - { - m_scriptListDock->prev(); - return true; - } - } - return false; -} - -ScriptListDockWidget::ScriptListDockWidget( QWidget *parent ) -: QDockWidget( i18n( "Scripts" ), parent ) -{ - QWidget *widget = new BoxWidget( true, this ); - setWidget( widget ); - m_scriptListWidget = new QListWidget( widget ); - m_scriptListWidget->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); - connect( m_scriptListWidget, &QListWidget::doubleClicked, - this, &ScriptListDockWidget::slotDoubleClicked ); - connect( m_scriptListWidget, &QListWidget::currentItemChanged, - this, &ScriptListDockWidget::slotCurrentItemChanged ); -} - -void -ScriptListDockWidget::addScript( ScriptConsoleItem *script ) -{ - if( !script ) - return; - - QListWidgetItem *item = new QListWidgetItem( script->name(), 0 ); - item->setData( ScriptRole, QVariant::fromValue( script ) ); - m_scriptListWidget->addItem( item ); - m_scriptListWidget->setCurrentItem( item ); -} - -void -ScriptListDockWidget::removeCurrentScript() -{ - QListWidgetItem *item = m_scriptListWidget->takeItem( m_scriptListWidget->currentRow() ); - ScriptConsoleItem *scriptItem = qvariant_cast( item->data( ScriptRole ) ); - switch( KMessageBox::warningYesNoCancel( this, i18n( "Remove script file from disk?" ), i18n( "Remove Script" ) ) ) - { - case KMessageBox::Cancel: - return; - case KMessageBox::Yes: - scriptItem->setClearOnDeletion( true ); - default: - break; - } - scriptItem->stop(); - scriptItem->deleteLater(); - delete item; -} - -void -ScriptListDockWidget::slotCurrentItemChanged( QListWidgetItem *newItem, QListWidgetItem *oldItem ) -{ - Q_UNUSED( oldItem ) - emit currentItemChanged( newItem ? qvariant_cast( newItem->data(ScriptRole) ) : 0 ); -} - -void -ScriptListDockWidget::slotDoubleClicked( const QModelIndex &index ) -{ - emit edit( qvariant_cast( index.data(ScriptRole) ) ); -} - -void -ScriptListDockWidget::clear() -{ - if( sender() && KMessageBox::warningContinueCancel( 0, i18n("Are you absolutely certain?") ) == KMessageBox::Cancel ) - return; - for( int i = 0; icount(); ++i ) - qvariant_cast( m_scriptListWidget->item( i )->data( ScriptRole ) )->deleteLater(); - m_scriptListWidget->clear(); - -} - -void -ScriptListDockWidget::addItem( QListWidgetItem *item ) -{ - m_scriptListWidget->addItem( item ); -} - -ScriptListDockWidget::~ScriptListDockWidget() -{ - clear(); -} - -void -ScriptListDockWidget::next() -{ - int currentRow = m_scriptListWidget->currentRow(); - m_scriptListWidget->setCurrentRow( currentRow > 1 ? currentRow - 1 : currentRow ); -} - -void -ScriptListDockWidget::prev() -{ - int currentRow = m_scriptListWidget->currentRow(); - m_scriptListWidget->setCurrentRow( currentRow + 1 < m_scriptListWidget->count() ? currentRow + 1 : currentRow ); -} diff --git a/src/scripting/scriptconsole/ScriptConsoleItem.h b/src/scripting/scriptconsole/ScriptConsoleItem.h deleted file mode 100644 --- a/src/scripting/scriptconsole/ScriptConsoleItem.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPT_CONSOLE_ITEM_H -#define SCRIPT_CONSOLE_ITEM_H - -#include "scripting/scriptmanager/ScriptItem.h" - -namespace KTextEditor{ - class View; -} -class QUrl; -class QIcon; -class QScriptContext; -class QScriptEngine; -class QScriptEngineDebugger; -class QWidget; - -namespace ScriptConsoleNS -{ - class ScriptEditorDocument; - - class ScriptConsoleItem : public ScriptItem - { - Q_OBJECT - - public: - ScriptConsoleItem( QObject *parent, const QString &name, const QString &path - , const QString &category, ScriptEditorDocument *document ); - virtual ~ScriptConsoleItem(); - ScriptEditorDocument* document() { return m_viewFactory; } - bool start( bool silent = false ); - KTextEditor::View *createEditorView( QWidget *parent ); - - /** - * Clear script files on disk upon object deletion - */ - void setClearOnDeletion( bool clearOnDelete ); - void pause(); - - private: - bool m_clearOnDelete; - ScriptEditorDocument *m_viewFactory; - QPointer m_view; - - void timerEvent(QTimerEvent* event); - void initializeScriptEngine(); - static KPluginInfo createSpecFile( const QString &name, const QString &category, const QString &path ); - QString handleError( QScriptEngine *engine ); - }; -} - -Q_DECLARE_METATYPE( ScriptConsoleNS::ScriptConsoleItem* ) - -#endif // SCRIPT_CONSOLE_ITEM_H diff --git a/src/scripting/scriptconsole/ScriptConsoleItem.cpp b/src/scripting/scriptconsole/ScriptConsoleItem.cpp deleted file mode 100644 --- a/src/scripting/scriptconsole/ScriptConsoleItem.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptConsoleItem" - -#include "ScriptConsoleItem.h" - -#include "amarokconfig.h" -#include "core/support/Debug.h" -#include "ScriptEditorDocument.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace ScriptConsoleNS; - -ScriptConsoleItem::ScriptConsoleItem( QObject *parent, const QString &name, const QString &category - , const QString &path, ScriptEditorDocument *document ) -: ScriptItem( parent, name, QString("%1/main.js").arg(path), createSpecFile( name, category, path ) ) -, m_clearOnDelete( false ) -, m_viewFactory( document ) -{ - document->setParent( this ); - document->save( url() ); - initializeScriptEngine(); -} - -ScriptConsoleItem::~ScriptConsoleItem() -{ - if( running() ) - stop(); - if( m_clearOnDelete || !AmarokConfig::saveSession() ) // TODO: implement session restore + user config option, export button - { - QFileInfo info( url().path() ); - QDir dir( info.path() ); - if( !dir.exists() ) - return; - dir.remove( "main.js" ); - dir.remove( "script.spec" ); - if( !dir.rmdir( dir.absolutePath() ) ) - debug() << "Directory %1 not removed, contains other files"; - } - if( m_view ) - m_view->deleteLater(); -} - -KPluginInfo -ScriptConsoleItem::createSpecFile( const QString &name, const QString &category, const QString &path ) -{ - QString specs = QString( "[Desktop Entry]" - "\nIcon=\"\"" - "\nType=script" - "\nServiceTypes=KPluginInfo" - "\nName= %1" - "\nX-KDE-PluginInfo-Name=%1" - "\nX-KDE-PluginInfo-Version=1.0" - "\nX-KDE-PluginInfo-Category=%2" - "\nX-KDE-PluginInfo-Depends=Amarok2.0" - "\nX-KDE-PluginInfo-EnabledByDefault=false\n" ).arg( name, category ); - - QString specPath = QString( "%1/script.spec" ).arg( path ); - QFile file( specPath ); - if( !file.open( QIODevice::WriteOnly ) ) - { - debug() << "Couldn't write to " + path; - return KPluginInfo(); - } - QTextStream stream( &file ); - stream << specs; - file.close(); - return KPluginInfo( specPath ); -} - -bool -ScriptConsoleItem::start( bool silent ) -{ - if( running() ) - return false; - if( !info().isValid() ) - { - debug() << "Invalid spec"; - return false; - } - m_viewFactory->save(); - Q_ASSERT( engine() ); - engine()->pushContext(); - return ScriptItem::start( silent ); -} - -KTextEditor::View* -ScriptConsoleItem::createEditorView( QWidget *parent ) -{ - if( !m_view ) - m_view = m_viewFactory->createView( parent ); - else - m_view->setParent( parent ); - return m_view.data(); -} - -void -ScriptConsoleItem::initializeScriptEngine() -{ - ScriptItem::initializeScriptEngine(); -} - -void -ScriptConsoleItem::timerEvent( QTimerEvent *event ) -{ - Q_UNUSED( event ) -} - - -void -ScriptConsoleItem::setClearOnDeletion( bool clearOnDelete ) -{ - m_clearOnDelete = clearOnDelete; -} - -QString -ScriptConsoleItem::handleError( QScriptEngine *engine ) -{ - QString errorString = QString( "Script Error: %1 (line: %2)" ) - .arg( engine->uncaughtException().toString(), - QString::number( engine->uncaughtExceptionLineNumber() ) ); - return errorString; -} - -void -ScriptConsoleItem::pause() -{ - if( !running() ) - return; - engine()->popContext(); - ScriptItem::pause(); -} diff --git a/src/scripting/scriptconsole/ScriptEditorDocument.h b/src/scripting/scriptconsole/ScriptEditorDocument.h deleted file mode 100644 --- a/src/scripting/scriptconsole/ScriptEditorDocument.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPT_EDITOR_DOCUMENT_H -#define SCRIPT_EDITOR_DOCUMENT_H - -#include "AmarokSharedPointer.h" - -#include -#include - -namespace KTextEditor -{ - class Attribute; - class Document; - class View; -} -class QUrl; -class QColor; -class QIcon; -class QWidget; - -namespace ScriptConsoleNS -{ - class AmarokScriptCodeCompletionModel; - - class ScriptEditorDocument : public QObject - { - Q_OBJECT - - public: - ScriptEditorDocument( QObject *parent, KTextEditor::Document* document ); - virtual ~ScriptEditorDocument(); - QString text() const; - KTextEditor::View *createView( QWidget *editor = 0 ); - void setText( const QString &text ); - void save( const QUrl &url ); - void save(); - void setReadWrite( bool readWrite ); - static void highlight( KTextEditor::View *view, int line, const QColor &color ); - - private: - KTextEditor::Document *m_document; - static QPointer s_completionModel; - }; -} - -#endif // SCRIPT_EDITOR_DOCUMENT_H diff --git a/src/scripting/scriptconsole/ScriptEditorDocument.cpp b/src/scripting/scriptconsole/ScriptEditorDocument.cpp deleted file mode 100644 --- a/src/scripting/scriptconsole/ScriptEditorDocument.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptEditorDocument.h" - -#include "CompletionModel.h" -#include "ScriptConsole.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace ScriptConsoleNS; - -QPointer ScriptEditorDocument::s_completionModel; - -ScriptEditorDocument::ScriptEditorDocument( QObject *parent, KTextEditor::Document* document ) -: QObject( parent ) -{ - m_document = document; - m_document->setParent( this ); - m_document->setHighlightingMode("JavaScript"); -} - -KTextEditor::View* -ScriptEditorDocument::createView( QWidget* parent ) -{ - KTextEditor::View *view = m_document->createView( parent ); - KTextEditor::CodeCompletionInterface *codeCompletionIf = qobject_cast( view ); - if( codeCompletionIf ) - { - if( !s_completionModel ) - s_completionModel = new AmarokScriptCodeCompletionModel( parent ); - codeCompletionIf->registerCompletionModel( s_completionModel.data() ); - codeCompletionIf->setAutomaticInvocationEnabled( true ); - } - KTextEditor::ConfigInterface *configIface = qobject_cast( view ); - if( configIface ) - configIface->setConfigValue( "line-numbers", true ); - return view; -} - -QString -ScriptEditorDocument::text() const -{ - return m_document->text(); -} - -void -ScriptEditorDocument::setText( const QString &text ) -{ - m_document->setText( text ); -} - -void -ScriptEditorDocument::save( const QUrl &url ) -{ - m_document->saveAs( url ); -} - -ScriptEditorDocument::~ScriptEditorDocument() -{} - -void -ScriptEditorDocument::save() -{ - m_document->save(); -} - -void -ScriptEditorDocument::setReadWrite( bool readWrite ) -{ - m_document->setReadWrite( readWrite ); -} - -void -ScriptEditorDocument::highlight( KTextEditor::View *view, int line, const QColor &color ) -{ - KTextEditor::MovingInterface *movingIf = qobject_cast( view->document() ); - if( !movingIf ) - return; - - KTextEditor::MovingRange *movingRange = movingIf->newMovingRange( KTextEditor::Range( line, 0, line, 500 ) ); - movingRange->setView( view ); - movingRange->setZDepth( -999 ); - //use highlightinterface::default styles? - KTextEditor::Attribute::Ptr attrb( new KTextEditor::Attribute() ); - attrb->setBackground( color ); - movingRange->setAttribute( attrb ); -} diff --git a/src/scripting/scriptengine/AmarokBookmarkScript.h b/src/scripting/scriptengine/AmarokBookmarkScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokBookmarkScript.h +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_BOOKMARK_SCRIPT_H -#define AMAROK_BOOKMARK_SCRIPT_H - -#include "amarokurls/BookmarkGroup.h" -#include "core/meta/Meta.h" - -#include -#include -#include - -class QScriptContext; -class QScriptEngine; -class QScriptValue; - -typedef QMap< QString, QString > StringMap; - -namespace AmarokScript -{ - // SCRIPTDOX Amarok.Bookmark - class AmarokBookmarkScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokBookmarkScript( QScriptEngine* scriptEngine ); - - /** - * @return bookmark for the current context view. - */ - Q_INVOKABLE AmarokUrlPtr contextView(); - - /** - * @return bookmark for the current playlist view. - */ - Q_INVOKABLE AmarokUrlPtr currentPlaylistView(); - - /** - * * @return bookmark for the current browser view. - */ - Q_INVOKABLE AmarokUrlPtr browserView(); - - /** - * Bookmark the current track at the currrent position. - */ - Q_INVOKABLE AmarokUrlPtr createCurrentTrackBookmark(); - }; - - class BookmarkPrototype : public QObject - { - Q_OBJECT - - Q_PROPERTY( int id READ id WRITE setId ) - Q_PROPERTY( BookmarkGroupPtr parent READ parent WRITE setParent ) - Q_PROPERTY( QString command READ command WRITE setCommand ) - Q_PROPERTY( QString name READ name WRITE setName ) - Q_PROPERTY( QString path READ path WRITE setPath ) - Q_PROPERTY( QString description READ description WRITE setDescription ) - Q_PROPERTY( bool isNull READ isNull ) - Q_PROPERTY( QString customValue READ customValue WRITE setCustomValue ) - Q_PROPERTY( QString url READ url ) - - public: - static QScriptValue bookmarkCtor( QScriptContext *context, QScriptEngine *engine ); - explicit BookmarkPrototype( AmarokUrlPtr bookmark ); - AmarokUrlPtr data() const { return m_url; } - - /** - * Save the bookmark to db. Must not be null. - */ - Q_INVOKABLE bool save(); - Q_INVOKABLE void initFromString( const QString & urlString ); - Q_INVOKABLE bool run(); - Q_INVOKABLE void removeFromDb(); - Q_INVOKABLE QString prettyCommand() const; - Q_INVOKABLE StringMap args() const; - - /** - * Sets the url argument named @param name to @param value. Overrides any possible - * previous value. - */ - Q_INVOKABLE void setArg( const QString &name, const QString &value ); - - private: - void setId( int id ); - int id() const; - void setParent( BookmarkGroupPtr parent ); - QString command() const; - void setCommand( const QString &command ); - void setName( const QString &name ); - QString name() const; - QString path() const; - void setPath( const QString &path ); - QString description() const; - BookmarkGroupPtr parent() const; - void setDescription( const QString &description ); - void setCustomValue( const QString &custom ); - QString customValue() const; - QString url() const; - bool isNull() const; - - AmarokUrlPtr m_url; - }; - - class BookmarkGroupPrototype : public QObject - { - Q_OBJECT - - Q_PROPERTY( int id READ id ) - Q_PROPERTY( BookmarkGroupPtr parent READ parent WRITE setParent ) - Q_PROPERTY( QString name READ name WRITE setName ) - Q_PROPERTY( QString description READ description WRITE setDescription ) - Q_PROPERTY( int childCount READ childCount ) - - public: - explicit BookmarkGroupPrototype( BookmarkGroupPtr group ); - static QScriptValue bookmarkGroupCtor( QScriptContext *context, QScriptEngine *engine ); - BookmarkGroupPtr data() const { return m_group; } - - /** - * Save the bookmark group to db. - */ - Q_INVOKABLE void save(); - Q_INVOKABLE BookmarkGroupList childGroups() const; - Q_INVOKABLE BookmarkList childBookmarks() const; - Q_INVOKABLE void clear(); - Q_INVOKABLE void deleteChildBookmark( AmarokUrlPtr bookmark ); - Q_INVOKABLE void deleteChildBookmarkgroup( BookmarkGroupPtr bookmarkGroup ); - - private: - int id() const; - QString name() const; - QString description() const; - int childCount() const; - void setName( const QString &name ); - void setDescription( const QString &description ); - BookmarkGroupPtr parent() const; - void setParent( BookmarkGroupPtr parent ); - - BookmarkGroupPtr m_group; - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokBookmarkScript.cpp b/src/scripting/scriptengine/AmarokBookmarkScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokBookmarkScript.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokBookmarkScript.h" - -#include "amarokconfig.h" -#include "amarokurls/AmarokUrl.h" -#include "amarokurls/BookmarkGroup.h" -#include "amarokurls/BookmarkModel.h" -#include "amarokurls/ContextUrlGenerator.h" -#include "amarokurls/NavigationUrlGenerator.h" -#include -#include "playlist/PlaylistViewUrlGenerator.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include - -Q_DECLARE_METATYPE( StringMap ) - -using namespace AmarokScript; - -AmarokBookmarkScript::AmarokBookmarkScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "Bookmark", scriptObject ); - qScriptRegisterMetaType( engine, toScriptValue, fromScriptValue ); - qScriptRegisterMetaType( engine, toScriptValue, fromScriptValue ); - engine->globalObject().setProperty( "BookmarkGroup", engine->newFunction( BookmarkGroupPrototype::bookmarkGroupCtor ) ); - engine->globalObject().setProperty( "Bookmark", engine->newFunction( BookmarkPrototype::bookmarkCtor ) ); - qScriptRegisterMetaType( engine, toScriptArray, fromScriptArray ); - qScriptRegisterMetaType( engine, toScriptArray, fromScriptArray ); -} - -AmarokUrlPtr -AmarokBookmarkScript::contextView() -{ - return AmarokUrlPtr( new AmarokUrl( ContextUrlGenerator::instance()->createContextBookmark() ) ); -} - -AmarokUrlPtr -AmarokBookmarkScript::currentPlaylistView() -{ - return AmarokUrlPtr( new AmarokUrl( Playlist::ViewUrlGenerator::instance()->createUrl() ) ); -} - -AmarokUrlPtr -AmarokBookmarkScript::browserView() -{ - return AmarokUrlPtr( new AmarokUrl( NavigationUrlGenerator::instance()->CreateAmarokUrl() ) ); -} - -AmarokUrlPtr -AmarokBookmarkScript::createCurrentTrackBookmark() -{ - return AmarokUrlPtr( new AmarokUrl( PlayUrlGenerator::instance()->createCurrentTrackBookmark() ) ); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// BookmarkGroupPrototype -////////////////////////////////////////////////////////////////////////////////////////////////// - -QScriptValue -BookmarkGroupPrototype::bookmarkGroupCtor( QScriptContext *context, QScriptEngine *engine ) -{ - BookmarkGroup *group = 0; - switch( context->argumentCount() ) - { - case 0: - return context->throwError( QScriptContext::SyntaxError, "Not enough arguments!!" ); - - case 1: - if( context->argument( 0 ).isString() ) - group = new BookmarkGroup( context->argument( 0 ).toString() ); - break; - - case 2: - if( context->argument( 0 ).isString() ) - { - QString name = context->argument( 0 ).toString(); - if( context->argument( 1 ).isString() ) - group = new BookmarkGroup( name, context->argument( 1 ).toString() ); - else if( dynamic_cast( context->argument(1).toQObject() ) ) - group = new BookmarkGroup( name, dynamic_cast( context->argument(1).toQObject() )->data() ); - } - break; - } - if( !group ) - return context->throwError( QScriptContext::TypeError, "Invalid arguments!" ); - return engine->newQObject( new BookmarkGroupPrototype( BookmarkGroupPtr( group ) ), QScriptEngine::ScriptOwnership, QScriptEngine::ExcludeSuperClassContents ); -} - -BookmarkGroupPrototype::BookmarkGroupPrototype( BookmarkGroupPtr group ) -:QObject( 0 ) -, m_group( group ) -{} - -BookmarkList -BookmarkGroupPrototype::childBookmarks() const -{ - return m_group->childBookmarks(); -} - -BookmarkGroupList -BookmarkGroupPrototype::childGroups() const -{ - return m_group->childGroups(); -} - -void -BookmarkGroupPrototype::clear() -{ - m_group->clear(); -} - -void BookmarkGroupPrototype::deleteChildBookmark( AmarokUrlPtr bookmark ) -{ - m_group->deleteChild( BookmarkViewItemPtr::staticCast( bookmark ) ); -} - -void -BookmarkGroupPrototype::deleteChildBookmarkgroup( BookmarkGroupPtr bookmarkGroup ) -{ - m_group->deleteChild( BookmarkViewItemPtr::staticCast( bookmarkGroup ) ); -} - -void -BookmarkGroupPrototype::save() -{ - m_group->save(); - BookmarkModel::instance()->reloadFromDb(); -} - -// private -int -BookmarkGroupPrototype::childCount() const -{ - return m_group->childCount(); -} - -QString -BookmarkGroupPrototype::description() const -{ - return m_group->description(); -} - -int -BookmarkGroupPrototype::id() const -{ - return m_group->id(); -} - -QString -BookmarkGroupPrototype::name() const -{ - return m_group->name(); -} - -BookmarkGroupPtr -BookmarkGroupPrototype::parent() const -{ - return m_group->parent(); -} - -void -BookmarkGroupPrototype::setDescription( const QString &description ) -{ - m_group->setDescription( description ); -} - -void -BookmarkGroupPrototype::setName( const QString &name ) -{ - m_group->rename( name ); -} - -void -BookmarkGroupPrototype::setParent( BookmarkGroupPtr parent ) -{ - m_group->reparent( parent ); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// BookmarkPrototype -////////////////////////////////////////////////////////////////////////////////////////////////// - -// public - -// script invokable -bool -BookmarkPrototype::save() -{ - bool success( m_url->saveToDb() ); - if( success ) - BookmarkModel::instance()->reloadFromDb(); - return success; -} - -QScriptValue -BookmarkPrototype::bookmarkCtor( QScriptContext *context, QScriptEngine *engine ) -{ - AmarokUrlPtr url; - switch( context->argumentCount() ) - { - case 0: - return context->throwError( QScriptContext::SyntaxError, "Not enough arguments!!" ); - - case 1: - if( context->argument( 0 ).isString() ) - url = new AmarokUrl( context->argument( 0 ).toString() ); - break; - - case 2: - if( context->argument( 0 ).isString() ) - { - BookmarkGroupPrototype *proto = dynamic_cast( context->argument(1).toQObject() ); - if( proto ) - url = new AmarokUrl( context->argument( 0 ).toString(), proto->data() ); - } - else - { - Meta::TrackPtr track = engine->fromScriptValue( context->argument( 0 ) ); - if( track && context->argument( 1 ).toVariant().canConvert( QVariant::LongLong ) ) - url = new AmarokUrl( PlayUrlGenerator::instance()->createTrackBookmark( track, context->argument(1).toVariant().toLongLong() ) ); - } - break; - } - if( !url ) - return context->throwError( QScriptContext::TypeError, "Invalid arguments!" ); - - return engine->newQObject( new BookmarkPrototype( url ), - QScriptEngine::ScriptOwnership, - QScriptEngine::ExcludeSuperClassContents ); -} - -BookmarkPrototype::BookmarkPrototype( AmarokUrlPtr bookmark ) -: QObject( 0 ) -, m_url( bookmark ) -{} - -void -BookmarkPrototype::initFromString( const QString &urlString ) -{ - m_url->initFromString( urlString ); -} - -StringMap -BookmarkPrototype::args() const -{ - return m_url->args(); -} - -void -BookmarkPrototype::setArg( const QString &name, const QString &value ) -{ - m_url->setArg( name, value ); -} - -QString -BookmarkPrototype::prettyCommand() const -{ - return m_url->prettyCommand(); -} - -void -BookmarkPrototype::removeFromDb() -{ - m_url->removeFromDb(); -} - -bool -BookmarkPrototype::run() -{ - return m_url->run(); -} - -// private - -QString -BookmarkPrototype::command() const -{ - return m_url->command(); -} - -void -BookmarkPrototype::setCommand( const QString &command ) -{ - m_url->setCommand( command ); -} - -QString -BookmarkPrototype::description() const -{ - return m_url->description(); -} - -void -BookmarkPrototype::setDescription( const QString &description ) -{ - m_url->setDescription( description ); -} - -int -BookmarkPrototype::id() const -{ - return m_url->id(); -} - -void -BookmarkPrototype::setId( int id ) -{ - m_url->setId( id ); -} - -QString -BookmarkPrototype::customValue() const -{ - return m_url->customValue(); -} - -void -BookmarkPrototype::setCustomValue( const QString &custom ) -{ - m_url->setCustomValue( custom ); -} - -bool -BookmarkPrototype::isNull() const -{ - return m_url->isNull(); -} - -QString -BookmarkPrototype::name() const -{ - return m_url->name(); -} - -void -BookmarkPrototype::setName( const QString &name ) -{ - return m_url->setName( name ); -} - - -BookmarkGroupPtr -BookmarkPrototype::parent() const -{ - return m_url->parent(); -} - -void -BookmarkPrototype::setParent( BookmarkGroupPtr parent ) -{ - m_url->reparent( parent ); -} - -QString -BookmarkPrototype::path() const -{ - return m_url->path(); -} - -void -BookmarkPrototype::setPath( const QString &path ) -{ - m_url->setPath( path ); -} - -QString -BookmarkPrototype::url() const -{ - return m_url->url(); -} diff --git a/src/scripting/scriptengine/AmarokCollectionScript.h b/src/scripting/scriptengine/AmarokCollectionScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokCollectionScript.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_COLLECTION_SCRIPT_H -#define AMAROK_COLLECTION_SCRIPT_H - -#include "ScriptingDefines.h" - -#include -#include - -class QScriptEngine; -namespace Collections -{ - class QueryMaker; - class Collection; - typedef QList CollectionList; -} - -namespace Playlists -{ - class PlaylistProvider; -} - -namespace AmarokScript -{ - /** - * Previously Amarok.Collection - */ - // SCRIPTDOX Amarok.CollectionManager - class AmarokCollectionScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokCollectionScript( AmarokScriptEngine* scriptEngine ); - - Q_INVOKABLE int totalAlbums() const; - Q_INVOKABLE int totalArtists() const; - Q_INVOKABLE int totalComposers() const; - Q_INVOKABLE int totalGenres() const; - Q_INVOKABLE int totalTracks() const; - - /** - * DEPRECATED - Use Amarok.CollectionManager.queryableCollections[0].actualLocation instead - * A list of locations that are part of the local collection - */ - Q_INVOKABLE QStringList collectionLocation() const; - - /** - * Directly query the Amarok SQLDB - */ - Q_INVOKABLE QStringList query( const QString& sql ) const; - - /** - * Escapes characters in string for use in an SQL statement. - */ - Q_INVOKABLE QString escape( const QString& sql ) const; - - /** - * Perform a full scan. - */ - Q_INVOKABLE void scanCollection() const; - - /** - * Perform an incremental scan. - */ - Q_INVOKABLE void scanCollectionChanges() const; - - /** - * Returns a query maker that queries all queryable collections. - */ - Q_INVOKABLE Collections::QueryMaker *queryMaker() const; - - /** - * Return a list of collections that are viewable in the collection browser. - */ - Q_INVOKABLE Collections::CollectionList viewableCollections() const; - - Q_SIGNALS: - /** - * Emitted when a new collection is added. - */ - void collectionAdded( Collections::Collection *newCollection ); - - /** - * This signal will be emitted after major changes to the collection - * e.g. new songs where added, or an album changed - * from compilation to non-compilation (and vice versa) - * it will not be emitted on minor changes (e.g. the tags of a song were changed) - * - * This means that previously done searches can no longer - * be considered valid. - */ - void collectionDataChanged( Collections::Collection *changedCollection ); - - /** - * Emitted when a collection is removed. - * @param collectionId The collectionID of the collection that was removed. - */ - void collectionRemoved( QString collectionId ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokCollectionScript.cpp b/src/scripting/scriptengine/AmarokCollectionScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokCollectionScript.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokCollectionScript.h" - -#include "amarokconfig.h" -#include "App.h" -#include -#include "core-impl/collections/support/CollectionManager.h" -#include "core-impl/storage/StorageManager.h" -#include "core/collections/Collection.h" -#include "core-impl/collections/db/sql/SqlCollectionLocation.h" -#include "core/collections/QueryMaker.h" - -#include - -#define SCRIPTING_DEPRECATED( x ) \ - AmarokScriptEngine *amarokScriptEngine = dynamic_cast(parent()); \ - if( amarokScriptEngine ) amarokScriptEngine->invokableDeprecatedCall( x ); - -using namespace AmarokScript; - -using Collections::Collection; -using Collections::CollectionList; -using Collections::QueryMaker; - -AmarokCollectionScript::AmarokCollectionScript( AmarokScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - //deprecate - engine->setDeprecatedProperty( "Amarok", "Collection", scriptObject ); - - engine->globalObject().property( "Amarok" ).setProperty( "CollectionManager", scriptObject ); - - CollectionManager *instance = CollectionManager::instance(); - connect( instance, &CollectionManager::collectionDataChanged, - this, &AmarokCollectionScript::collectionDataChanged ); - connect( instance, &CollectionManager::collectionAdded, - this, &AmarokCollectionScript::collectionAdded ); - connect( instance, &CollectionManager::collectionRemoved, - this, &AmarokCollectionScript::collectionRemoved ); -} - -int -AmarokCollectionScript::totalAlbums() const -{ - QStringList albums = query( "SELECT COUNT( id ) FROM albums;" ); - if( albums.size() < 1 ) - return 0; - QString total = albums[0]; - return total.toInt(); -} - -int -AmarokCollectionScript::totalArtists() const -{ - QStringList artists = query( "SELECT COUNT( id ) FROM artists;" ); - if( artists.size() < 1 ) - return 0; - QString total = artists[0]; - return total.toInt(); -} - -int -AmarokCollectionScript::totalComposers() const -{ - QStringList composers = query( "SELECT COUNT( id ) FROM composers;" ); - if( composers.size() < 1 ) - return 0; - QString total = composers[0]; - return total.toInt(); -} - -int -AmarokCollectionScript::totalGenres() const -{ - QStringList genres = query( "SELECT COUNT( id ) FROM genres;" ); - if( genres.size() < 1 ) - return 0; - QString total = genres[0]; - return total.toInt(); -} - -int -AmarokCollectionScript::totalTracks() const -{ - QStringList tracks = query( "SELECT COUNT( url ) FROM tracks;" ); - if( tracks.size() < 0 ) - return 0; - QString total = tracks[0]; - int final = total.toInt(); - return final; -} - -QStringList -AmarokCollectionScript::collectionLocation() const -{ - SCRIPTING_DEPRECATED( "collectionLocation" ) - Collections::CollectionLocation *location = CollectionManager::instance()->primaryCollection()->location(); - QStringList result = location->actualLocation(); - delete location; - return result; -} - -QStringList -AmarokCollectionScript::query( const QString& sql ) const -{ - return StorageManager::instance()->sqlStorage()->query( sql ); -} - -QString -AmarokCollectionScript::escape( const QString& sql ) const -{ - return StorageManager::instance()->sqlStorage()->escape( sql ); -} - -void -AmarokCollectionScript::scanCollection() const -{ - CollectionManager::instance()->startFullScan(); -} - -void -AmarokCollectionScript::scanCollectionChanges() const -{ - CollectionManager::instance()->checkCollectionChanges(); -} - -QueryMaker* -AmarokCollectionScript::queryMaker() const -{ - return CollectionManager::instance()->queryMaker(); -} - -CollectionList -AmarokCollectionScript::viewableCollections() const -{ - return CollectionManager::instance()->viewableCollections(); -} diff --git a/src/scripting/scriptengine/AmarokCollectionViewScript.h b/src/scripting/scriptengine/AmarokCollectionViewScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokCollectionViewScript.h +++ /dev/null @@ -1,244 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_COLLECTIONVIEW_SCRIPT_H -#define AMAROK_COLLECTIONVIEW_SCRIPT_H - -#include "browsers/BrowserDefines.h" -// #include "core/meta/forward_declarations.h" -#include "core/meta/Meta.h" - -#include -#include -#include -#include -#include -#include -#include - -class CollectionTreeItemModelBase; -class CollectionWidget; -class CollectionTreeItem; -namespace Collections -{ - class Collection; - class QueryMaker; -} -class QMenu; -class QScriptEngine; -typedef QList QActionList; - -namespace AmarokScript -{ - class AmarokScriptEngine; - class Selection; - class CollectionViewItem; - - // SCRIPTDOX Amarok.Window.CollectionView - /** - * Must call Importer.loadAmarokBinding( "collectionview" ); first; - */ - class AmarokCollectionViewScript : public QObject - { - Q_OBJECT - - Q_PROPERTY( QString filter READ filter WRITE setFilter ) - Q_PROPERTY( QScriptValue selection READ selectionScriptValue ) - Q_PROPERTY( bool showYears READ showYears WRITE setShowYears ) - Q_PROPERTY( bool showTrackNumbers READ showTrackNumbers WRITE setShowTrackNumbers ) - Q_PROPERTY( bool showCovers READ showCovers WRITE setShowCovers ) - - /** - * Set levels like: - * - * Importer.loadAmarokBinding("collectionview"); - * var cat = Amarok.Window.CollectionView.Category; - * Amarok.Window.CollectionView.levels = [cat.Album,cat.Artist,cat.Year]; - */ - Q_PROPERTY( QList levels READ levels WRITE setLevels ) - Q_PROPERTY( bool mergedView READ mergedView WRITE setMergedView ) - - public: - AmarokCollectionViewScript( AmarokScriptEngine *scriptEngine, const QString &scriptName ); - ~AmarokCollectionViewScript(); - static void createScriptedActions( QMenu &menu, const QModelIndexList &indices ); - QActionList actions(); - static Selection *selection(); - // SCRIPTDOX ENUM Amarok.CollectionView.Category - enum Category { - None = CategoryId::None, - Album = CategoryId::Album, - Artist = CategoryId::Artist, - AlbumArtist = CategoryId::AlbumArtist, - Composer = CategoryId::Composer, - Genre = CategoryId::Genre, - Year = CategoryId::Year, - Label = CategoryId::Label - }; - Q_ENUM( Category ) - - public Q_SLOTS: - void setLevel( int level, int type ); - - /** - * Set a function returning a QActionList here. - */ - void setAction( const QScriptValue &value ); - - Q_SIGNALS: - void filterChanged( QString ); - - private: - QString filter() const; - void setFilter( const QString &filter ); - QList levels() const; - void setLevels( const QList &levels ); - QScriptValue selectionScriptValue(); - void setShowYears( bool shown ); - void setShowTrackNumbers( bool shown ); - void setShowCovers( bool shown ); - bool showYears(); - bool showTrackNumbers(); - bool showCovers(); - bool mergedView() const; - void setMergedView( bool merged ); - - static QMap s_instances; - static QPointer s_selection; - QScriptValue m_actionFunction; - CollectionWidget *m_collectionWidget; - AmarokScriptEngine *m_engine; - QString m_scriptName; - const QMetaEnum m_categoryEnum; - - friend class AmarokWindowScript; - }; - - /** - * Represents an item from the CollectionTreeView - */ - class CollectionViewItem : public QObject - { - Q_OBJECT - - Q_PROPERTY( CollectionTreeItem* parent READ parent ) - Q_PROPERTY( int childCount READ childCount ) - Q_PROPERTY( QList children READ children ) - Q_PROPERTY( int row READ row ) - Q_PROPERTY( int level READ level ) - Q_PROPERTY( Collections::Collection* parentCollection READ parentCollection ) - Q_PROPERTY( bool isCollection READ isCollection ) - Q_PROPERTY( bool isDataItem READ isDataItem ) - Q_PROPERTY( bool isAlbumItem READ isAlbumItem ) - Q_PROPERTY( bool isTrackItem READ isTrackItem ) - Q_PROPERTY( bool isVariousArtistItem READ isVariousArtistItem ) - Q_PROPERTY( bool isNoLabelItem READ isNoLabelItem ) - - /** - * Returns true if all of this item's children have been loaded. - */ - Q_PROPERTY( bool childrenLoaded READ childrenLoaded ) - - public: - explicit CollectionViewItem( CollectionTreeItem *item, QObject *parent = 0 ); - CollectionTreeItem* data() const; - static QScriptValue toScriptValue( QScriptEngine *engine, CollectionTreeItem* const &item ); - - /** - * @return QueryMaker representing this item's descendant tracks ( or just the item if a track ) - */ - Q_INVOKABLE Collections::QueryMaker* queryMaker(); - - /** - * Add a filter representing this item to @param queryMaker. - * For example, for obtaining a specific collection's items in the merged view. - */ - Q_INVOKABLE void addFilter( Collections::QueryMaker *queryMaker ); - - /** - * Return the child item at @param row. - */ - Q_INVOKABLE CollectionTreeItem* child( int row ); - - /** - * Load children if they haven't already been loaded. - * Emit loaded( CollectionTreeItem* ) on completion. - */ - Q_INVOKABLE void loadChildren(); - - /** - * Return the track item represented by this collection item, - * invalid track if !isTrack - */ - Q_INVOKABLE Meta::TrackPtr track(); - - private Q_SLOTS: - void slotDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight ); - - Q_SIGNALS: - void loaded( CollectionTreeItem* ); - - private: - CollectionTreeItem* parent() const; - QList children() const; - int row() const; - int level() const; - bool isAlbumItem() const; - bool isTrackItem() const; - bool isVariousArtistItem() const; - bool isNoLabelItem() const; - bool isDataItem() const; - int childCount() const; - bool isCollection() const; - Collections::Collection* parentCollection() const; - bool childrenLoaded() const; - CollectionTreeItemModelBase *getModel(); - - CollectionTreeItem *m_item; - }; - - class Selection : public QObject - { - Q_OBJECT - - /** - * Whether the selected items belongs to a single collection. - */ - Q_PROPERTY( bool singleCollection READ singleCollection ) - - /** - * Get the selected lis tof items. - */ - Q_PROPERTY( QList selectedItems READ selectedItems ) - - public Q_SLOTS: - /** - * Get a QueryMaker for the selected items. - */ - Collections::QueryMaker* queryMaker(); - - private: - Selection( const QModelIndexList &indices ); - bool singleCollection() const; - QList selectedItems(); - - QModelIndexList m_indices; - - friend AmarokCollectionViewScript; - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokCollectionViewScript.cpp b/src/scripting/scriptengine/AmarokCollectionViewScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokCollectionViewScript.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "CollectionViewScript" -#include "AmarokCollectionViewScript.h" - -#include "amarokconfig.h" -#include "core/support/Debug.h" -#include "browsers/CollectionTreeView.h" -#include "browsers/collectionbrowser/CollectionWidget.h" -#include "browsers/collectionbrowser/CollectionBrowserTreeView.h" -#include "browsers/CollectionTreeItem.h" -#include "browsers/CollectionTreeItemModelBase.h" -#include "core-impl/collections/support/CollectionManager.h" -#include "core-impl/collections/support/TextualQueryFilter.h" -#include "MainWindow.h" -#include "ScriptingDefines.h" -#include "widgets/SearchWidget.h" - -#include -#include -#include -#include - -Q_DECLARE_METATYPE( QAction* ) -Q_DECLARE_METATYPE( QList ) - -using namespace AmarokScript; - -QMap AmarokCollectionViewScript::s_instances; -QPointer AmarokCollectionViewScript::s_selection; - -AmarokCollectionViewScript::AmarokCollectionViewScript( AmarokScriptEngine *engine, const QString &scriptName ) - : QObject( engine ) - , m_collectionWidget( The::mainWindow()->collectionBrowser() ) - , m_engine( engine ) - , m_scriptName( scriptName ) - , m_categoryEnum( metaObject()->enumerator( metaObject()->indexOfEnumerator("Category") ) ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - QScriptValue windowObject = engine->globalObject().property( "Amarok" ).property( "Window" ); - Q_ASSERT( !windowObject.isUndefined() ); - windowObject.setProperty( "CollectionView", scriptObject ); - const QMetaEnum typeEnum = CollectionTreeItem::staticMetaObject.enumerator( CollectionTreeItem::staticMetaObject.indexOfEnumerator( "Type" ) ); - Q_ASSERT( typeEnum.isValid() ); - scriptObject.setProperty( "Type", engine->enumObject( typeEnum ) ); - Q_ASSERT( m_categoryEnum.isValid() ); - scriptObject.setProperty( "Category", engine->enumObject( m_categoryEnum ) ); - qScriptRegisterMetaType( engine, CollectionViewItem::toScriptValue, fromScriptValue ); - engine->registerArrayType< QList >(); - engine->registerArrayType(); - s_instances[m_scriptName] = this; - connect( The::mainWindow()->collectionBrowser()->searchWidget(), &SearchWidget::filterChanged, this, &AmarokCollectionViewScript::filterChanged ); -} - -AmarokCollectionViewScript::~AmarokCollectionViewScript() -{ - s_instances.remove( m_scriptName ); - if( s_instances.isEmpty() ) - delete s_selection.data(); -} - -void -AmarokCollectionViewScript::setFilter( const QString &filter ) -{ - return m_collectionWidget->setFilter( filter ); -} - -QString -AmarokCollectionViewScript::filter() const -{ - return m_collectionWidget->filter(); -} - -QActionList -AmarokCollectionViewScript::actions() -{ - QScriptValue actions = m_actionFunction.call( QScriptValue(), QScriptValueList() << selectionScriptValue() ); - QActionList actionList = m_engine->fromScriptValue( actions ); - debug() << "Received " << actionList.size() << " actions"; - return actionList; -} - -void -AmarokCollectionViewScript::setAction( const QScriptValue &value ) -{ - m_actionFunction = value; -} - -void -AmarokCollectionViewScript::createScriptedActions( QMenu &menu, const QModelIndexList &indices ) -{ - debug() << "Checking for scripted actions"; - if( s_selection ) - delete s_selection.data(); - if( s_instances.isEmpty() ) - return; - s_selection = new Selection( indices ); - - foreach( const QString &scriptName, s_instances.keys() ) - { - if( s_instances[scriptName] ) - { - debug() << "Adding actions for script " << scriptName; - menu.addSeparator(); - foreach( QAction *action, s_instances[scriptName]->actions() ) - { - if( !action ) - { - debug() << "Null action received from script " << scriptName; - continue; - } - action->setParent( &menu ); - menu.addAction( action ); - } - } - } -} - -QScriptValue -AmarokCollectionViewScript::selectionScriptValue() -{ - return m_engine->newQObject( s_selection.data(), QScriptEngine::QtOwnership, - QScriptEngine::ExcludeSuperClassContents ); -} - -Selection* -AmarokCollectionViewScript::selection() -{ - return s_selection.data(); -} - -void -AmarokCollectionViewScript::setShowCovers( bool shown ) -{ - CollectionWidget::instance()->slotShowCovers( shown ); -} - -void -AmarokCollectionViewScript::setShowTrackNumbers( bool shown ) -{ - CollectionWidget::instance()->slotShowTrackNumbers( shown ); -} - -void -AmarokCollectionViewScript::setShowYears( bool shown ) -{ - CollectionWidget::instance()->slotShowYears( shown ); -} - -bool -AmarokCollectionViewScript::showCovers() -{ - return AmarokConfig::showAlbumArt(); -} - -bool -AmarokCollectionViewScript::showTrackNumbers() -{ - return AmarokConfig::showTrackNumbers(); -} - -bool -AmarokCollectionViewScript::showYears() -{ - return AmarokConfig::showYears(); -} - -bool -AmarokCollectionViewScript::mergedView() const -{ - return m_collectionWidget->viewMode() == CollectionWidget::UnifiedCollection; -} - -void -AmarokCollectionViewScript::setMergedView( bool merged ) -{ - CollectionWidget::instance()->toggleView( merged ); -} - -QList -AmarokCollectionViewScript::levels() const -{ - QList levels; - foreach( CategoryId::CatMenuId level, m_collectionWidget->currentView()->levels() ) - levels << level; - return levels; -} - -void -AmarokCollectionViewScript::setLevel( int level, int type ) -{ - if( m_categoryEnum.valueToKey( type ) ) - return m_collectionWidget->currentView()->setLevel( level, CategoryId::CatMenuId( type ) ); - m_engine->currentContext()->throwError( QScriptContext::TypeError, "Invalid category!" ); -} - -void -AmarokCollectionViewScript::setLevels( const QList &levels ) -{ - QList catLevels; - foreach( int level, levels ) - { - if( !m_categoryEnum.valueToKey( level ) ) - { - m_engine->currentContext()->throwError( QScriptContext::TypeError, "Invalid category!" ); - return; - } - catLevels << CategoryId::CatMenuId( level ); - } - m_collectionWidget->setLevels( catLevels ); -} - -/////////////////////////////////////////////////////////// -// CollectionViewItem -/////////////////////////////////////////////////////////// - -CollectionTreeItem* -CollectionViewItem::child( int row ) -{ - return m_item->child( row ); -} - -int -CollectionViewItem::childCount() const -{ - return m_item->childCount(); -} - -QList -CollectionViewItem::children() const -{ - return m_item->children(); -} - -CollectionViewItem::CollectionViewItem( CollectionTreeItem *item, QObject *parent ) - : QObject( parent ) - , m_item( item ) -{} - -bool -CollectionViewItem::isTrackItem() const -{ - return m_item->isTrackItem(); -} - -int -CollectionViewItem::level() const -{ - return m_item->level(); -} - -CollectionTreeItem* -CollectionViewItem::parent() const -{ - return m_item->parent(); -} - -Collections::Collection* -CollectionViewItem::parentCollection() const -{ - return m_item->parentCollection(); -} - -int -CollectionViewItem::row() const -{ - return m_item->row(); -} - -bool -CollectionViewItem::isCollection() const -{ - return m_item->type() == CollectionTreeItem::Collection; -} - -CollectionTreeItem* -CollectionViewItem::data() const -{ - return m_item; -} - -QScriptValue -CollectionViewItem::toScriptValue( QScriptEngine *engine, CollectionTreeItem* const &item ) -{ - CollectionViewItem *proto = new CollectionViewItem( item, AmarokCollectionViewScript::selection() ); - QScriptValue val = engine->newQObject( proto, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - return val; -} - -Meta::TrackPtr -CollectionViewItem::track() -{ - return Meta::TrackPtr::dynamicCast( m_item->data() ); -} - -bool -CollectionViewItem::isAlbumItem() const -{ - return m_item->isAlbumItem(); -} - -bool -CollectionViewItem::isDataItem() const -{ - return m_item->isDataItem(); -} - -bool -CollectionViewItem::isNoLabelItem() const -{ - return m_item->isNoLabelItem(); -} - -bool -CollectionViewItem::isVariousArtistItem() const -{ - return m_item->isVariousArtistItem(); -} - -bool -CollectionViewItem::childrenLoaded() const -{ - return m_item->isTrackItem() || !m_item->requiresUpdate(); -} - -void -CollectionViewItem::loadChildren() -{ - if( !m_item->requiresUpdate() ) - return; - CollectionTreeItemModelBase *model = getModel(); - connect( model, &CollectionTreeItemModelBase::dataChanged, - this, &CollectionViewItem::slotDataChanged ); - model->ensureChildrenLoaded( m_item ); -} - -void -CollectionViewItem::slotDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight ) -{ - Q_UNUSED( bottomRight ) - if( static_cast( topLeft.internalPointer() ) != m_item ) - return; - emit loaded( m_item ); - Q_ASSERT( disconnect( qobject_cast(sender()), &QAbstractItemModel::dataChanged, this, 0 ) ); -} - -Collections::QueryMaker* -CollectionViewItem::queryMaker() -{ - Collections::QueryMaker *qm = 0; - if( The::mainWindow()->collectionBrowser()->viewMode() == CollectionWidget::NormalCollections ) - qm = m_item->queryMaker(); - else - qm = CollectionManager::instance()->queryMaker(); - addFilter( qm ); - return qm; -} - -void -CollectionViewItem::addFilter( Collections::QueryMaker *queryMaker ) -{ - if( !queryMaker ) - return; - CollectionTreeItemModelBase *model = getModel(); - for( CollectionTreeItem *tmp = m_item; tmp; tmp = tmp->parent() ) - tmp->addMatch( queryMaker, model->levelCategory( tmp->level() - 1 ) ); - Collections::addTextualFilter( queryMaker, model->currentFilter() ); -} - -CollectionTreeItemModelBase* -CollectionViewItem::getModel() -{ - QSortFilterProxyModel *proxyModel = dynamic_cast( The::mainWindow()->collectionBrowser()->currentView()->model() ); - return dynamic_cast( proxyModel ? proxyModel->sourceModel() : 0 ); -} - -/////////////////////////////////////////////////////////// -// Selection -/////////////////////////////////////////////////////////// - -bool -Selection::singleCollection() const -{ - return CollectionTreeView::onlyOneCollection( m_indices ); -} - -QList -Selection::selectedItems() -{ - QList collectionItems; - foreach( const QModelIndex &index, m_indices ) - collectionItems << static_cast( index.internalPointer() ); - return collectionItems; -} - -Selection::Selection( const QModelIndexList &indices ) - : QObject( 0 ) - , m_indices( indices ) -{} - -Collections::QueryMaker* -Selection::queryMaker() -{ - return The::mainWindow()->collectionBrowser()->currentView()->createMetaQueryFromItems( selectedItems().toSet(), true ); -} diff --git a/src/scripting/scriptengine/AmarokEngineScript.h b/src/scripting/scriptengine/AmarokEngineScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokEngineScript.h +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_ENGINE_SCRIPT_H -#define AMAROK_ENGINE_SCRIPT_H - -#include "core/meta/forward_declarations.h" - -#include -#include - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX Amarok.Engine - class AmarokEngineScript : public QObject - { - Q_OBJECT - Q_PROPERTY( bool randomMode READ randomMode WRITE setRandomMode ) - Q_PROPERTY( bool dynamicMode READ dynamicMode ) - Q_PROPERTY( bool repeatPlaylist READ repeatPlaylist WRITE setRepeatPlaylist ) - Q_PROPERTY( bool repeatTrack READ repeatTrack WRITE setRepeatTrack ) - Q_PROPERTY( int volume READ volume WRITE setVolume ) - Q_PROPERTY( int fadeoutLength READ fadeoutLength WRITE setFadeoutLength ) - - public: - explicit AmarokEngineScript( QScriptEngine* scriptEngine ); - - enum PlayerStatus - { - Playing = 0, - Paused = 1, - Stopped = 2, - Error = -1 // deprecated. reason: Amarok will try to resolve the error by itself and never stay in the error state. In the worst case it will stop - }; - - Q_INVOKABLE void Play() const; - Q_INVOKABLE void Stop( bool forceInstant = false ) const; - Q_INVOKABLE void Pause() const; - Q_INVOKABLE void Next() const; - Q_INVOKABLE void Prev() const; - Q_INVOKABLE void PlayPause() const; - Q_INVOKABLE void Seek( int ms ) const; - Q_INVOKABLE void SeekRelative( int ms ) const; - Q_INVOKABLE void SeekForward( int ms = 10000 ) const; - Q_INVOKABLE void SeekBackward( int ms = 10000 ) const; - Q_INVOKABLE int IncreaseVolume( int ticks = 100/25 ); - Q_INVOKABLE int DecreaseVolume( int ticks = 100/25 ); - Q_INVOKABLE void Mute(); - /** This function returns the track position in seconds */ - Q_INVOKABLE int trackPosition() const; - /** This function returns the track position in milliseconds */ - Q_INVOKABLE int trackPositionMs() const; - /** This function returns the current engine state. - @returns 0 when playing or buffering, 1 when paused, 2 when stopped or loading and -1 in case of an error. - */ - Q_INVOKABLE int engineState() const; - /** This function returns the current track. - The current track might even be valid when not in playing state. - */ - Q_INVOKABLE Meta::TrackPtr currentTrack() const; - - Q_SIGNALS: - void trackFinished(); // when playback stops altogether - - /** This signal will be emitted every time the current track changes. - It will not be emitted if e.g. the title of the current track changes. - For this you will need to connect to newMetaData signal. - */ - void trackChanged(); - - /** This signal will indicate newly received meta data. - The signal will be triggered as soon as the phonon backend parses new meta data or - the current track or album data is changed through Amarok. - @param metaData Not longer filled. Use currentTrack to get the current meta data. - @param newTrack Always false. Use trackChanged to find changed tracks. - */ - void newMetaData( const QHash &metaData, bool newTrack ); - - /** Will be emitted as soon as the user changes the track playback position. */ - void trackSeeked( int ); //return relative time in million second - - /** This signal will be emitted when the volume changes. - @param volume The relative volume between 0 (mute) and 100. - */ - void volumeChanged( int ); - - /** This signal is emitted when the engine state switches to play or pause. - Note: You could get two trackPlayPause(1) in a row if e.g. the state - changed to stopped in beetween (which you will notice if connecting to - the trackFinished signal) - @param state Is 0 when state changed to playing or 1 when the state switched to pause. - */ - void trackPlayPause( int state ); - - private Q_SLOTS: - void trackPositionChanged( qint64 ); - void slotNewMetaData(); - void slotPaused(); - void slotPlaying(); - - private: - bool randomMode() const; - bool dynamicMode() const; - bool repeatPlaylist() const; - bool repeatTrack() const; - void setRandomMode( bool enable ); - void setRepeatPlaylist( bool enable ); - void setRepeatTrack( bool enable ); - int volume() const; - void setVolume( int percent ); - int fadeoutLength() const; - - /** - * Set the fadeout length. Must be >= 400. - */ - void setFadeoutLength( int length ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokEngineScript.cpp b/src/scripting/scriptengine/AmarokEngineScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokEngineScript.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokEngineScript.h" - -#include "AmarokEqualizerScript.h" -#include "App.h" -#include "EngineController.h" -#include "amarokconfig.h" -#include "core/meta/Meta.h" -#include "playlist/PlaylistActions.h" -#include "playlist/PlaylistModel.h" - -#include - -using namespace AmarokScript; - -AmarokEngineScript::AmarokEngineScript( QScriptEngine* scriptEngine ) - : QObject( scriptEngine ) -{ - QScriptValue scriptObject = scriptEngine->newQObject( this, QScriptEngine::AutoOwnership - , QScriptEngine::ExcludeSuperClassContents ); - scriptEngine->globalObject().property( "Amarok" ).setProperty( "Engine", scriptObject ); - - EngineController *engine = The::engineController(); - connect( engine, &EngineController::trackPositionChanged, - this, &AmarokEngineScript::trackPositionChanged ); - connect( engine, &EngineController::trackChanged, this, &AmarokEngineScript::trackChanged ); - connect( engine, &EngineController::paused, this, &AmarokEngineScript::slotPaused ); - connect( engine, &EngineController::trackPlaying, this, &AmarokEngineScript::slotPlaying ); - connect( engine, &EngineController::stopped, this, &AmarokEngineScript::trackFinished ); - connect( engine, &EngineController::currentMetadataChanged, - this, &AmarokEngineScript::slotNewMetaData ); - connect( engine, &EngineController::trackMetadataChanged, - this, &AmarokEngineScript::slotNewMetaData ); - connect( engine, &EngineController::albumMetadataChanged, - this, &AmarokEngineScript::slotNewMetaData ); - connect( engine, &EngineController::volumeChanged, this, &AmarokEngineScript::volumeChanged ); - - new AmarokEqualizerScript( scriptEngine ); -} - -void -AmarokEngineScript::Play() const -{ - The::engineController()->play(); -} - -void -AmarokEngineScript::Stop( bool forceInstant ) const -{ - The::engineController()->stop( forceInstant ); -} - -void -AmarokEngineScript::Pause() const -{ - The::engineController()->pause(); -} - -void -AmarokEngineScript::Next() const -{ - The::playlistActions()->next(); -} -void -AmarokEngineScript::Prev() const -{ - The::playlistActions()->back(); -} - -void -AmarokEngineScript::PlayPause() const -{ - The::engineController()->playPause(); -} - -void -AmarokEngineScript::Seek( int ms ) const -{ - The::engineController()->seekTo( ms ); -} - -void -AmarokEngineScript::SeekRelative( int ms ) const -{ - The::engineController()->seekBy( ms ); -} - -void -AmarokEngineScript::SeekForward( int ms ) const -{ - The::engineController()->seekBy( ms ); -} - -void -AmarokEngineScript::SeekBackward( int ms ) const -{ - The::engineController()->seekBy( -ms ); -} - -int -AmarokEngineScript::IncreaseVolume( int ticks ) -{ - return The::engineController()->increaseVolume( ticks ); -} - -int -AmarokEngineScript::DecreaseVolume( int ticks ) -{ - return The::engineController()->decreaseVolume( ticks ); -} - -void -AmarokEngineScript::Mute() -{ - The::engineController()->toggleMute(); -} - -int -AmarokEngineScript::trackPosition() const -{ - return The::engineController()->trackPosition(); -} - -int -AmarokEngineScript::trackPositionMs() const -{ - return The::engineController()->trackPositionMs(); -} - -int -AmarokEngineScript::engineState() const -{ - - if( The::engineController()->isPlaying() ) - return Playing; - else if( The::engineController()->isPaused() ) - return Paused; - else - return Stopped; -} - -Meta::TrackPtr -AmarokEngineScript::currentTrack() const -{ - Meta::TrackPtr track = The::engineController()->currentTrack(); - return track; -} - -void -AmarokEngineScript::trackPositionChanged( qint64 pos ) -{ - emit trackSeeked( pos ); -} - -void -AmarokEngineScript::slotNewMetaData() -{ - emit newMetaData( QHash(), false ); -} - -void -AmarokEngineScript::slotPaused() -{ - emit trackPlayPause( Paused ); -} - -void -AmarokEngineScript::slotPlaying() -{ - emit trackPlayPause( Playing ); -} - -bool -AmarokEngineScript::randomMode() const -{ - return AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RandomTrack || - AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RandomAlbum; -} - -bool -AmarokEngineScript::dynamicMode() const -{ - return AmarokConfig::dynamicMode(); -} - -bool -AmarokEngineScript::repeatPlaylist() const -{ - return AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RepeatPlaylist; -} - -bool -AmarokEngineScript::repeatTrack() const -{ - return AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RepeatTrack; -} - -void -AmarokEngineScript::setRandomMode( bool enable ) -{ - if( enable ) - { - AmarokConfig::setTrackProgression( AmarokConfig::EnumTrackProgression::RandomTrack ); - The::playlistActions()->playlistModeChanged(); - } - else if( AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RandomTrack ) - { - AmarokConfig::setTrackProgression( AmarokConfig::EnumTrackProgression::Normal ); - The::playlistActions()->playlistModeChanged(); - } -} - -void -AmarokEngineScript::setRepeatPlaylist( bool enable ) -{ - if( enable ) - { - AmarokConfig::setTrackProgression( AmarokConfig::EnumTrackProgression::RepeatPlaylist ); - The::playlistActions()->playlistModeChanged(); - } - else if( AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RepeatPlaylist ) - { - AmarokConfig::setTrackProgression( AmarokConfig::EnumTrackProgression::Normal ); - The::playlistActions()->playlistModeChanged(); - } -} - -void -AmarokEngineScript::setRepeatTrack( bool enable ) -{ - if( enable ) - { - AmarokConfig::setTrackProgression( AmarokConfig::EnumTrackProgression::RepeatTrack ); - The::playlistActions()->playlistModeChanged(); - } - else if( AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RepeatTrack ) - { - AmarokConfig::setTrackProgression( AmarokConfig::EnumTrackProgression::Normal ); - The::playlistActions()->playlistModeChanged(); - } -} - -int -AmarokEngineScript::volume() const -{ - return The::engineController()->volume(); -} - -void -AmarokEngineScript::setVolume( int percent ) -{ - The::engineController()->setVolume( percent ); -} - -int -AmarokEngineScript::fadeoutLength() const -{ - return AmarokConfig::fadeoutLength(); -} - -void -AmarokEngineScript::setFadeoutLength( int length ) -{ - if( length < 400 ) - debug() << "Fadeout length must be >= 400"; - else - AmarokConfig::setFadeoutLength( length ); -} diff --git a/src/scripting/scriptengine/AmarokEqualizerScript.h b/src/scripting/scriptengine/AmarokEqualizerScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokEqualizerScript.h +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_EQUALIZER_SCRIPT_H -#define AMAROK_EQUALIZER_SCRIPT_H - -#include - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX Amarok.Engine.Equalizer - class AmarokEqualizerScript : public QObject - { - Q_OBJECT - - /** - * @return true if the current backend supports equalizer. - */ - Q_PROPERTY( bool enabled READ enabled ) - - /** - * @return true if the current backend supports equalizer. - */ - Q_PROPERTY( bool isSupported READ isSupported ) - - /** - * The currently set equalizer preset. - * Set to "" to disable. - */ - Q_PROPERTY( QString selectedPreset READ selectedPreset WRITE setEqualizerPreset ) - - /** - * @return list of user presets. - */ - Q_PROPERTY( QStringList userPresets READ userPresets ) - - /** - * Return a localized list of all presets. - */ - Q_PROPERTY( QStringList translatedGlobalPresetList READ translatedGlobalPresetList ) - - /** - * Return an untranslated list of all presets. - */ - Q_PROPERTY( QStringList globalPresetList READ globalPresetList ) - - /** - * @return list of all default Amarok presets. - */ - Q_PROPERTY( QStringList translatedDefaultPresetList READ translatedDefaultPresetList ) - - /** - * @return translated list of all default Amarok presets. - */ - Q_PROPERTY( QStringList defaultPresetList READ defaultPresetList ) - - /** - * The current equalizer gains values. - */ - Q_PROPERTY( QList gains READ gains WRITE setGains ) - - Q_PROPERTY( int maxGain READ maxGain ) - - Q_PROPERTY( QStringList bandFrequencies READ bandFrequencies ) - - public: - /** - * Will return a "user" preset if present. Else a "global". - */ - Q_INVOKABLE QList getPresetGains( const QString &presetName ); - - /** - * Returns true if the preset was deleted. - * @param presetName The untranslated preset name. - */ - Q_INVOKABLE bool deletePreset( const QString &presetName ); - - /** - * Save the @param presetGains as a preset with name @param name. - */ - Q_INVOKABLE void savePreset( const QString &name, const QList &presetGains ); - - Q_SIGNALS: - /** - * Emitted when preset with name @param name is applied or the equalizer is disabled. - * name is "" when disabled. - */ - void presetApplied( QString name ); - - /** - * Emitted when the current gains are changed. - */ - void gainsChanged( QList gains ); - - /** - * Emitted when preset @param name is added, removed or modified. - */ - void presetsChanged( QString name ); - - private Q_SLOTS: - void equalizerPresetApplied( int index ); - - private: - AmarokEqualizerScript( QScriptEngine* scriptEngine ); - bool enabled(); - void setEqualizerPreset( const QString &name ) const; - QStringList bandFrequencies() const; - bool isSupported() const; - QString selectedPreset() const; - QStringList userPresets() const; - QStringList translatedGlobalPresetList() const; - QStringList globalPresetList() const; - QStringList translatedDefaultPresetList() const; - QStringList defaultPresetList() const; - QList gains() const; - void setGains( QList gains ); - int maxGain() const; - - friend class AmarokEngineScript; - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokEqualizerScript.cpp b/src/scripting/scriptengine/AmarokEqualizerScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokEqualizerScript.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokEqualizerScript.h" - -#include "amarokconfig.h" -#include "EngineController.h" -#include "equalizer/EqualizerPresets.h" - -#include - -using namespace AmarokScript; - -AmarokEqualizerScript::AmarokEqualizerScript( QScriptEngine *scriptEngine ) -: QObject( scriptEngine ) -{ - QScriptValue scriptObject = scriptEngine->newQObject( this, QScriptEngine::AutoOwnership - , QScriptEngine::ExcludeSuperClassContents ); - scriptEngine->globalObject().property( "Amarok" ).property( "Engine" ).setProperty( "Equalizer", scriptObject ); - - EqualizerController *equalizer = The::engineController()->equalizerController(); - connect( equalizer, &EqualizerController::gainsChanged, this, &AmarokEqualizerScript::gainsChanged ); - connect( equalizer, &EqualizerController::presetsChanged, this, &AmarokEqualizerScript::presetsChanged ); - connect( equalizer, &EqualizerController::presetApplied, this, &AmarokEqualizerScript::equalizerPresetApplied ); -} - -// script invokable -bool -AmarokEqualizerScript::deletePreset( const QString &presetName ) -{ - return The::engineController()->equalizerController()->deletePreset( presetName ); -} - -void -AmarokEqualizerScript::savePreset( const QString &name, const QList &presetGains ) -{ - The::engineController()->equalizerController()->savePreset( name, presetGains ); -} - - -//private - -bool -AmarokEqualizerScript::enabled() -{ - return The::engineController()->equalizerController()->enabled(); -} - -QStringList -AmarokEqualizerScript::bandFrequencies() const -{ - return The::engineController()->equalizerController()->eqBandsFreq(); -} - -QStringList -AmarokEqualizerScript::defaultPresetList() const -{ - return EqualizerPresets::eqDefaultPresetsList(); -} - -void -AmarokEqualizerScript::equalizerPresetApplied( int index ) -{ - emit presetApplied( EqualizerPresets::eqGlobalList().value( index ) ); -} - -QList -AmarokEqualizerScript::gains() const -{ - return The::engineController()->equalizerController()->gains(); -} - -QList -AmarokEqualizerScript::getPresetGains( const QString &presetName ) -{ - return EqualizerPresets::eqCfgGetPresetVal( presetName ); -} - -QStringList -AmarokEqualizerScript::globalPresetList() const -{ - return EqualizerPresets::eqGlobalList(); -} - -bool -AmarokEqualizerScript::isSupported() const -{ - return The::engineController()->equalizerController()->isEqSupported(); -} - -int -AmarokEqualizerScript::maxGain() const -{ - return The::engineController()->equalizerController()->eqMaxGain(); -} - -QString -AmarokEqualizerScript::selectedPreset() const -{ - return The::engineController()->equalizerController()->equalizerPreset(); -} - -void -AmarokEqualizerScript::setEqualizerPreset( const QString &name ) const -{ - The::engineController()->equalizerController()->applyEqualizerPresetByName( name ); -} - -QStringList -AmarokEqualizerScript::translatedDefaultPresetList() const -{ - return EqualizerPresets::eqDefaultTranslatedPresetsList(); -} - -QStringList -AmarokEqualizerScript::translatedGlobalPresetList() const -{ - return EqualizerPresets::eqGlobalTranslatedList(); -} - -QStringList -AmarokEqualizerScript::userPresets() const -{ - return EqualizerPresets::eqUserList(); -} - -void -AmarokEqualizerScript::setGains( QList gains ) -{ - The::engineController()->equalizerController()->setGains( gains ); -} diff --git a/src/scripting/scriptengine/AmarokInfoScript.h b/src/scripting/scriptengine/AmarokInfoScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokInfoScript.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Ian Monroe * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) version 3 or * - * any later version accepted by the membership of KDE e.V. (or its successor approved * - * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of * - * version 3 of the license. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_INFO_SCRIPT_H -#define AMAROK_INFO_SCRIPT_H - -#include -#include - -class QScriptEngine; - -namespace AmarokScript -{ - class AmarokScriptEngine; - - // SCRIPTDOX Amarok.Info - class InfoScript : public QObject - { - Q_OBJECT - - public: - // SCRIPTDOX enum Amarok.Info.IconSizes - enum IconSizes { - Small=16, - SmallMedium=22, - Medium=32, - Large=48, - Huge=64, - Enormous=128 - }; - Q_ENUM( IconSizes ) - - InfoScript( const QUrl &scriptUrl, AmarokScriptEngine *engine ); - - /** - * The directory where the script's main.js file is located - */ - Q_INVOKABLE QString scriptPath() const; - - /** - * Return the location of the specified config - */ - Q_INVOKABLE QString scriptConfigPath( const QString& name ) const; - - /** - * Return the path to the standard icon with the given name. - * Icons will be searched in current icon theme and all its base themes. - * @param name The name of the icon, without extension. If an absolute - * path is supplied for this parameter, iconPath will return it - * directly. - * @param size Search icons whose size is @param size. - * See Info.IconSizes - */ - Q_INVOKABLE QString iconPath( const QString& name, int size ) const; - - /** - * The current Amarok version. - */ - Q_INVOKABLE QString version() const; - - private: - const QUrl m_scriptUrl; - }; - -} // namespace AmarokScript - -#endif diff --git a/src/scripting/scriptengine/AmarokInfoScript.cpp b/src/scripting/scriptengine/AmarokInfoScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokInfoScript.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Ian Monroe * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) version 3 or * - * any later version accepted by the membership of KDE e.V. (or its successor approved * - * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of * - * version 3 of the license. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokInfoScript.h" - -#include "core/support/Amarok.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include - -#include -#include - -using namespace AmarokScript; - -InfoScript::InfoScript( const QUrl &scriptUrl, AmarokScriptEngine *engine ) - : QObject( engine ) - , m_scriptUrl( scriptUrl ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "Info", scriptObject ); - - const QMetaEnum iconEnum = metaObject()->enumerator( metaObject()->indexOfEnumerator("IconSizes") ); - Q_ASSERT( iconEnum.isValid() ); - scriptObject.setProperty( "IconSizes", engine->enumObject( iconEnum ) ); -} - -QString -InfoScript::version() const -{ - return AMAROK_VERSION; -} - -QString -InfoScript::scriptPath() const -{ - return m_scriptUrl.adjusted(QUrl::RemoveFilename).path(); -} - -QString -InfoScript::iconPath( const QString& name, int size ) const -{ - //if size was positive it would refer to KIconLoader::Group - return KIconLoader::global()->iconPath( name, -size ); -} - -QString -InfoScript::scriptConfigPath( const QString& name ) const -{ - return Amarok::saveLocation( "scripts/" + name ); -} diff --git a/src/scripting/scriptengine/AmarokKNotifyScript.h b/src/scripting/scriptengine/AmarokKNotifyScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokKNotifyScript.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2011 Kevin Funk * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_KNOTIFY_SCRIPT_H -#define AMAROK_KNOTIFY_SCRIPT_H - -#include -#include - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX Amarok.Window.KNotify - /** - * KNotify is the notification subsystem within KDE, which alerts users to - * user-configured events within the KDE system. - */ - class AmarokKNotifyScript : public QObject - { - Q_OBJECT - /** - * Whether KNotify is enabled - */ - Q_PROPERTY( bool kNotifyEnabled READ kNotifyEnabled WRITE setKNotifyEnabled ) - - public: - explicit AmarokKNotifyScript( QScriptEngine* scriptEngine ); - - /** - * Show notifications for the currently playing track. - */ - Q_INVOKABLE void showCurrentTrack(); - - /** - * Show a custom KNotify notification - */ - Q_INVOKABLE void show(const QString &title, const QString &body, const QPixmap &pixmap = QPixmap() ); - - private: - void setKNotifyEnabled( bool enable ); - bool kNotifyEnabled(); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokKNotifyScript.cpp b/src/scripting/scriptengine/AmarokKNotifyScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokKNotifyScript.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2011 Kevin Funk * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokKNotifyScript.h" - -#include "amarokconfig.h" -#include "App.h" -#include "KNotificationBackend.h" - -#include - -#define kNotify Amarok::KNotificationBackend::instance() - -using namespace AmarokScript; - -AmarokKNotifyScript::AmarokKNotifyScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - QScriptValue windowObject = engine->globalObject().property( "Amarok" ).property( "Window" ); - windowObject.setProperty( "KNotify", scriptObject ); -} - -bool -AmarokKNotifyScript::kNotifyEnabled() -{ - return AmarokConfig::kNotifyEnabled(); -} - -void -AmarokKNotifyScript::setKNotifyEnabled( bool enable ) -{ - AmarokConfig::setKNotifyEnabled( enable ); -} - -void -AmarokKNotifyScript::show( const QString &title, const QString &body, const QPixmap &pixmap ) -{ - kNotify->show( title, body, pixmap ); -} - - -void -AmarokKNotifyScript::showCurrentTrack() -{ - kNotify->showCurrentTrack( true ); -} diff --git a/src/scripting/scriptengine/AmarokLyricsScript.h b/src/scripting/scriptengine/AmarokLyricsScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokLyricsScript.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Leo Franchi * - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_LYRICS_SCRIPT_H -#define AMAROK_LYRICS_SCRIPT_H - -#include "core/meta/forward_declarations.h" - -#include - -class QScriptEngine; -class QByteArray; - -namespace AmarokScript -{ - // SCRIPTDOX Amarok.Lyrics - class AmarokLyricsScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokLyricsScript( QScriptEngine* scriptEngine ); - - Q_INVOKABLE void showLyrics( const QString& lyrics ) const; - - Q_INVOKABLE void showLyricsHtml( const QString& lyrics ) const; - Q_INVOKABLE void showLyricsError( const QString& error ) const; - Q_INVOKABLE void showLyricsNotFound( const QString& msg ) const; - - Q_INVOKABLE QString escape( const QString& str ); - - Q_INVOKABLE void setLyricsForTrack( const QString& trackUrl , const QString& lyrics ) const; - Q_INVOKABLE QString toUtf8( const QByteArray& lyrics, const QString& encoding = "UTF-8" ); - Q_INVOKABLE QString QStringtoUtf8( const QString& lyrics, const QString& encoding = "UTF-8" ); - Q_INVOKABLE QByteArray fromUtf8( const QString& str, const QString& encoding ); - - Q_SIGNALS: - void fetchLyrics( const QString& artist, const QString& title, const QString&, Meta::TrackPtr ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokLyricsScript.cpp b/src/scripting/scriptengine/AmarokLyricsScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokLyricsScript.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Leo Franchi * - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "AmarokLyricsScript" - -#include "AmarokLyricsScript.h" - -#include "EngineController.h" -#include "scripting/scriptmanager/ScriptManager.h" -#include "context/LyricsManager.h" -#include "core/meta/Meta.h" -#include "core/support/Amarok.h" -#include "core/support/Debug.h" - -#include -#include -#include -#include - -using namespace AmarokScript; - - -AmarokLyricsScript::AmarokLyricsScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "Lyrics", scriptObject ); - connect( ScriptManager::instance(), &ScriptManager::fetchLyrics, - this, &AmarokLyricsScript::fetchLyrics ); -} - -void -AmarokLyricsScript::showLyrics( const QString &lyrics ) const -{ - DEBUG_BLOCK - Meta::TrackPtr track = The::engineController()->currentTrack(); - if( !track ) - return; - LyricsManager::self()->lyricsResult( lyrics, false ); -} - -void -AmarokLyricsScript::showLyricsHtml( const QString &lyrics ) const -{ - DEBUG_BLOCK - Meta::TrackPtr track = The::engineController()->currentTrack(); - if( !track ) - return; - LyricsManager::self()->lyricsResultHtml( lyrics, false ); -} - -void -AmarokLyricsScript::showLyricsError( const QString &error ) const -{ - DEBUG_BLOCK - LyricsManager::self()->lyricsError( error ); -} - - -void -AmarokLyricsScript::showLyricsNotFound( const QString &msg ) const -{ - DEBUG_BLOCK - LyricsManager::self()->lyricsNotFound( msg ); -} - - -QString -AmarokLyricsScript::escape( const QString &str ) -{ - return str.toHtmlEscaped(); -} - -void -AmarokLyricsScript::setLyricsForTrack( const QString &trackUrl, const QString &lyrics ) const -{ - LyricsManager::self()->setLyricsForTrack( trackUrl, lyrics ); -} - -QString -AmarokLyricsScript::toUtf8( const QByteArray &lyrics, const QString &encoding ) -{ - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - if( !codec ) - return QString(); - return codec->toUnicode( lyrics ); -} - -QString -AmarokLyricsScript::QStringtoUtf8( const QString &lyrics, const QString &encoding ) -{ - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - if( !codec ) - return QString(); - return codec->toUnicode( lyrics.toLatin1() ); -} - -QByteArray -AmarokLyricsScript::fromUtf8( const QString &str, const QString &encoding ) -{ - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - if( !codec ) - return QByteArray(); - - return codec->fromUnicode( str ); -} diff --git a/src/scripting/scriptengine/AmarokNetworkScript.h b/src/scripting/scriptengine/AmarokNetworkScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokNetworkScript.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Leo Franchi * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_NETWORK_SCRIPT_H -#define AMAROK_NETWORK_SCRIPT_H - -#include "network/NetworkAccessManagerProxy.h" - -#include - -#include -#include -#include -#include - -class QScriptContext; -class QScriptEngine; - -namespace AmarokScript -{ - class Downloader : public QObject - { - Q_OBJECT - - public: - explicit Downloader( QScriptEngine* scriptEngine ); - - private: - static QScriptValue dataDownloader_prototype_ctor( QScriptContext* context, QScriptEngine* engine ); - static QScriptValue stringDownloader_prototype_ctor( QScriptContext* context, QScriptEngine* engine ); - static QScriptValue init( QScriptContext* context, QScriptEngine* engine, bool stringResult ); - - QScriptEngine* m_scriptEngine; - }; - - // this internal class manages multiple downloads from a script. - // keeps track of each unique download - class AmarokDownloadHelper : public QObject - { - Q_OBJECT - - static AmarokDownloadHelper *s_instance; - - public: - AmarokDownloadHelper(); - - static AmarokDownloadHelper *instance(); - - // called by the wrapper class to register a new download - void newStringDownload( const QUrl &url, QScriptEngine* engine, QScriptValue obj, QString encoding = "UTF-8" ); - void newDataDownload( const QUrl &url, QScriptEngine* engine, QScriptValue obj ); - - private Q_SLOTS: - void resultString( const QUrl &url, QByteArray data, NetworkAccessManagerProxy::Error e ); - void resultData( const QUrl &url, QByteArray data, NetworkAccessManagerProxy::Error e ); - - void requestRedirected( const QUrl &sourceUrl, const QUrl &targetUrl ); - - private: - void cleanUp( const QUrl &url ); - - template - void newDownload( const QUrl &url, QScriptEngine* engine, QScriptValue obj, Function slot ) - { - m_values[ url ] = obj; - m_engines[ url ] = engine; - - The::networkAccessManager()->getData( url, this, slot ); - } - - /** - * Template function which updates the given @p sourceUrl to the given - * @p targetUrl. All entries in the given hash will be copied. - * The old entries will be removed. - * - * @param hash The hash which contains all elements. - * @param sourceUrl The old URL (= the old key). - * @param targetUrl The new URL (= the new key). - */ - template void updateUrl( QHash< QUrl, T > &hash, const QUrl &sourceUrl, const QUrl &targetUrl ) - { - // Get all entries with the source URL as key. - QList< T > data = hash.values( sourceUrl ); - - foreach( T entry, data ) - { - // Copy each entry to a new one with the - // new URL as key. - hash[ targetUrl ] = entry; - } - - // Remove all entries which are still pointing - // to the source URL. - hash.remove( sourceUrl ); - }; - - QHash m_engines; - QHash m_values; - QHash m_encodings; - }; -} - -Q_DECLARE_METATYPE( AmarokScript::Downloader* ) - -#endif diff --git a/src/scripting/scriptengine/AmarokNetworkScript.cpp b/src/scripting/scriptengine/AmarokNetworkScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokNetworkScript.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Leo Franchi * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "AmarokNetworkScript" - -#include "AmarokNetworkScript.h" - -#include "App.h" -#include "core/support/Debug.h" - -#include -#include - -#include - -using namespace AmarokScript; - -AmarokDownloadHelper *AmarokDownloadHelper::s_instance = 0; - -Downloader::Downloader( QScriptEngine* engine ) - : QObject( engine ) - , m_scriptEngine( engine ) -{ - engine->setDefaultPrototype( qMetaTypeId(), QScriptValue() ); - const QScriptValue stringCtor = engine->newFunction( stringDownloader_prototype_ctor ); - engine->globalObject().setProperty( "Downloader", stringCtor ); //kept for compat - engine->globalObject().setProperty( "StringDownloader", stringCtor ); //added for clarity - const QScriptValue dataCtor = engine->newFunction( dataDownloader_prototype_ctor ); - engine->globalObject().setProperty( "DataDownloader", dataCtor ); -} - -QScriptValue -Downloader::stringDownloader_prototype_ctor( QScriptContext* context, QScriptEngine* engine ) -{ - return init( context, engine, true ); -} - -QScriptValue -Downloader::dataDownloader_prototype_ctor( QScriptContext* context, QScriptEngine* engine ) -{ - if( engine->importedExtensions().contains( "qt.core" ) ) - return init( context, engine, false ); - else - { - context->throwError( i18nc("do not translate 'DataDownloader' or 'qt.core'", "qt.core must be loaded to use DataDownloader" ) ); - return engine->toScriptValue( false ); - } -} - -QScriptValue -Downloader::init( QScriptContext* context, QScriptEngine *engine, bool stringResult ) -{ - // from QtScript API docs - DEBUG_BLOCK - QScriptValue object; - - if( context->isCalledAsConstructor() ) - object = context->thisObject(); - else - { - object = engine->newObject(); - object.setPrototype( context->callee().property("prototype") ); - } - - if( context->argumentCount() < 2 ) - { - debug() << "ERROR! Constructor not called with enough arguments:" << context->argumentCount(); - return object; - } - - if( !context->argument( 1 ).isFunction() ) //TODO: check QUrl - { - debug() << "ERROR! Constructor not called with a Url and function!"; - return object; - } - - QUrl url = QUrl::fromEncoded( context->argument( 0 ).toString().toLatin1(), QUrl::StrictMode ); - - if( !url.isValid() ) - { - debug() << "ERROR! Constructor not called with a valid Url!"; - return object; - } - - // start download, and connect to it - if( stringResult ) - { - QString encoding = "UTF-8"; - if( context->argumentCount() == 3 ) // encoding specified - encoding = context->argument( 2 ).toString(); - AmarokDownloadHelper::instance()->newStringDownload( url, engine, context->argument( 1 ), encoding ); - } - else - AmarokDownloadHelper::instance()->newDataDownload( url, engine, context->argument( 1 ) ); - // connect to a local slot to extract the qstring - //qScriptConnect( job, SIGNAL(result(KJob*)), object, fetchResult( job ) ); - return object; -} - -/////// -// Class AmarokDownloadHelper -////// - -AmarokDownloadHelper::AmarokDownloadHelper() -{ - s_instance = this; - connect( The::networkAccessManager(), &NetworkAccessManagerProxy::requestRedirectedUrl, - this, &AmarokDownloadHelper::requestRedirected ); -} - -void -AmarokDownloadHelper::newStringDownload( const QUrl &url, QScriptEngine* engine, QScriptValue obj, QString encoding ) -{ - m_encodings[ url ] = encoding; - newDownload( url, engine, obj, &AmarokDownloadHelper::resultString ); -} - -void -AmarokDownloadHelper::newDataDownload( const QUrl &url, QScriptEngine* engine, QScriptValue obj ) -{ - newDownload( url, engine, obj, &AmarokDownloadHelper::resultData ); -} - -void -AmarokDownloadHelper::requestRedirected( const QUrl &sourceUrl, const QUrl &targetUrl ) -{ - DEBUG_BLOCK - - // Move all entries from "url" to "targetUrl". - updateUrl< QScriptEngine* >( m_engines, sourceUrl, targetUrl ); - updateUrl< QScriptValue >( m_values, sourceUrl, targetUrl ); - updateUrl< QString >( m_encodings, sourceUrl, targetUrl ); -} - -void -AmarokDownloadHelper::resultData( const QUrl &url, QByteArray data, NetworkAccessManagerProxy::Error e ) -{ - if( !m_values.contains( url ) ) - return; - - if( e.code != QNetworkReply::NoError ) - warning() << "Error fetching data:" << e.description; - - QScriptValue obj = m_values.value( url ); - QScriptEngine* engine = m_engines.value( url ); - cleanUp( url ); - - // now send the data to the associated script object - if( !obj.isFunction() ) - { - debug() << "script object is valid but not a function!!"; - return; - } - - if( !engine ) - { - debug() << "stored script engine is not valid!"; - return; - } - - QScriptValueList args; - args << engine->toScriptValue( data ); - obj.call( obj, args ); -} - - -void -AmarokDownloadHelper::resultString( const QUrl &url, QByteArray data, NetworkAccessManagerProxy::Error e ) -{ - if( !m_values.contains( url ) ) - return; - - if( e.code != QNetworkReply::NoError ) - warning() << "Error fetching string:" << e.description; - - QScriptValue obj = m_values.value( url ); - QScriptEngine* engine = m_engines.value( url ); - QString encoding = m_encodings.value( url ); - cleanUp( url ); - - QString str; - if( encoding.isEmpty() ) - { - str = QString( data ); - } - else - { - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - str = codec->toUnicode( data ); - } - - // now send the data to the associated script object - if( !obj.isFunction() ) - { - debug() << "script object is valid but not a function!!"; - return; - } - - if( !engine ) - { - debug() << "stored script engine is not valid!"; - return; - } - - QScriptValueList args; - args << engine->toScriptValue( str ); - obj.call( obj, args ); -} - -void -AmarokDownloadHelper::cleanUp( const QUrl &url ) -{ - m_values.remove( url ); - m_engines.remove( url ); - m_encodings.remove( url ); -} - -AmarokDownloadHelper* -AmarokDownloadHelper::instance() -{ - if( !s_instance ) - s_instance = new AmarokDownloadHelper(); - return s_instance; -} diff --git a/src/scripting/scriptengine/AmarokOSDScript.h b/src/scripting/scriptengine/AmarokOSDScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokOSDScript.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_OSD_SCRIPT_H -#define AMAROK_OSD_SCRIPT_H - -#include - -class QColor; -class QImage; -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX: Amarok.Window.OSD - class AmarokOSDScript : public QObject - { - Q_OBJECT - - Q_PROPERTY ( bool osdEnabled READ osdEnabled WRITE setOsdEnabled ) - - public: - explicit AmarokOSDScript( QScriptEngine* scriptEngine ); - - /** - * Show an OSD for the currently playing track, even if the OSD - * has been disabled by the user. - */ - Q_INVOKABLE void showCurrentTrack(); - - /** - * Forces an OSD update. - * OSD settings changes do not take effect until the next time - * the OSD is shown. - * To show an OSD with the current settings, call show(); - */ - Q_INVOKABLE void show(); - - /** - * Set the OSD duration - */ - Q_INVOKABLE void setDuration( int ms ); - - /** - * Set the OSD textcolor - */ - Q_INVOKABLE void setTextColor( const QColor &color ); - - /** - * Set the OSD's y-offset. - */ - Q_INVOKABLE void setOffset( int y ); - - /** - * Set the image to be shown in the OSD. - */ - Q_INVOKABLE void setImage( const QImage &image ); - - /** - * Set the screen on which to show the OSD. - */ - Q_INVOKABLE void setScreen( int screen ); - - /** - * Set the OSD text - */ - Q_INVOKABLE void setText( const QString &text ); - - /** - * Set the number of half-stars to be shown in the OSD. - * Amarok must be playing a track for the stars to show. - */ - Q_INVOKABLE void setRating( const short rating ); - - private: - void setOsdEnabled( bool enable ); - bool osdEnabled(); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokOSDScript.cpp b/src/scripting/scriptengine/AmarokOSDScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokOSDScript.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokOSDScript.h" - -#include "App.h" -#include "amarokconfig.h" -#include "widgets/Osd.h" - -#include - -using namespace AmarokScript; - -AmarokOSDScript::AmarokOSDScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - QScriptValue windowObject = engine->globalObject().property( "Amarok" ).property( "Window" ); - windowObject.setProperty( "OSD", scriptObject ); -} - -void -AmarokOSDScript::showCurrentTrack() -{ - Amarok::OSD::instance()->forceToggleOSD(); -} - -void -AmarokOSDScript::show() -{ - Amarok::OSD::instance()->show(); -} - -void -AmarokOSDScript::setDuration( int ms ) -{ - Amarok::OSD::instance()->setDuration( ms ); -} - -void -AmarokOSDScript::setTextColor( const QColor &color ) -{ - Amarok::OSD::instance()->setTextColor( color ); -} - -void -AmarokOSDScript::setOffset( int y ) -{ - Amarok::OSD::instance()->setYOffset( y ); -} - -void -AmarokOSDScript::setImage( const QImage &image ) -{ - Amarok::OSD::instance()->setImage( image ); -} - -void -AmarokOSDScript::setScreen( int screen ) -{ - Amarok::OSD::instance()->setScreen( screen ); -} - -void -AmarokOSDScript::setText( const QString &text ) -{ - Amarok::OSD::instance()->setText( text ); -} - -void -AmarokOSDScript::setRating( const short rating ) -{ - Amarok::OSD::instance()->setRating( rating ); -} - -void -AmarokOSDScript::setOsdEnabled( bool enable ) -{ - Amarok::OSD::instance()->setEnabled( enable ); - AmarokConfig::setOsdEnabled( enable ); -} - -bool -AmarokOSDScript::osdEnabled() -{ - return AmarokConfig::osdEnabled(); -} diff --git a/src/scripting/scriptengine/AmarokPlaylistManagerScript.h b/src/scripting/scriptengine/AmarokPlaylistManagerScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokPlaylistManagerScript.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_PLAYLISTMANAGER_SCRIPT_H -#define AMAROK_PLAYLISTMANAGER_SCRIPT_H - -#include "core/meta/forward_declarations.h" - -#include - -class QScriptEngine; -namespace Playlists -{ - class Playlist; - class PlaylistProvider; - - typedef AmarokSharedPointer PlaylistPtr; - typedef QList PlaylistList; - typedef QList PlaylistProviderList; -} - -namespace AmarokScript -{ - class AmarokScriptEngine; - - //ANM-TODO podcasts! - // SCRIPTDOX Amarok.PlaylistManager - class AmarokPlaylistManagerScript : public QObject - { - Q_OBJECT - - // SCRIPTDOX ENUM Amarok.PlaylistManager.PlaylistCategory - // enum PlaylistCategory { UserPlaylist, PodcastChannel }; - - /** - * @returns all available categories registered at that moment - */ - Q_PROPERTY( QList availableCategories READ availableCategories ) - - public: - explicit AmarokPlaylistManagerScript( AmarokScriptEngine* engine ); - - /** - * @returns playlists of a certain category from all registered PlaylistProviders - */ - Q_INVOKABLE Playlists::PlaylistList playlistsOfCategory( int playlistCategory ); - - /** - * @returns all PlaylistProviders that provide a certain playlist category. - **/ - Q_INVOKABLE Playlists::PlaylistProviderList providersForCategory( int playlistCategory ); - - // ANM-TODO synced playlists - /** - * Do all the work necessary to sync playlists, including the - * SyncedPlaylist creation and more. This sync is persistent. - * @arg playlist of the master playlist - * @arg playlist of the slave playlist - */ - //void setupSync( const Playlists::PlaylistPtr master, const Playlists::PlaylistPtr slave ); - - /** - * Return provider with name @param name and category @param category. - */ - Q_INVOKABLE Playlists::PlaylistProvider *playlistProvider( int category, QString name ); - - /** - * Saves a list of tracks to a new playlist. Used in the Playlist save button. - * @arg tracks list of tracks to save - * @arg name of playlist to save - * @arg toProvider If 0 (default) will save to the default UserPlaylistProvider ( SQLPlaylistProvider ) - */ - Q_INVOKABLE bool save( Meta::TrackList tracks, const QString &name = QString(), - Playlists::PlaylistProvider *toProvider = 0 ); - - /** - * Saves a playlist from a file to the database. - * @arg fromLocation Saved playlist file to load - */ - Q_INVOKABLE bool import( const QUrl &fromLocation ); - - /** - * Rename @param playlist to @param newName, return true if renaming was successful, - * false otherwise. - */ - Q_INVOKABLE bool rename( Playlists::PlaylistPtr playlist, const QString &newName ); - - Q_INVOKABLE bool deletePlaylists( Playlists::PlaylistList playlistList ); - - /** - * Retrieves the provider owning the given playlist. - * Will only return multiple providers if this is a synced playlist - * @arg playlist the playlist whose provider we want - */ - Q_INVOKABLE QList - getProvidersForPlaylist( const Playlists::PlaylistPtr playlist ); - - /** - * Checks if the provider to whom this playlist belongs supports writing - * @arg playlist the playlist we are testing for writability - * @return whether or not the playlist is writable - */ - Q_INVOKABLE bool isWritable( const Playlists::PlaylistPtr &playlist ); - - private: - QList availableCategories(); - - Q_SIGNALS: - void updated( int category ); - void categoryAdded( int category ); - void providerAdded( Playlists::PlaylistProvider *provider, int category ); - void providerRemoved( Playlists::PlaylistProvider *provider, int category ); - void playlistAdded( Playlists::PlaylistPtr playlist, int category ); - void playlistRemoved( Playlists::PlaylistPtr playlist, int category ); - void playlistUpdated( Playlists::PlaylistPtr playlist, int category ); - void renamePlaylist( Playlists::PlaylistPtr playlist ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokPlaylistManagerScript.cpp b/src/scripting/scriptengine/AmarokPlaylistManagerScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokPlaylistManagerScript.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokPlaylistManagerScript.h" - -#include "playlistmanager/PlaylistManager.h" -#include "scripting/scriptengine/exporters/PlaylistExporter.h" -#include "scripting/scriptengine/exporters/PlaylistProviderExporter.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include -#include - -using namespace AmarokScript; - -AmarokPlaylistManagerScript::AmarokPlaylistManagerScript( AmarokScriptEngine* engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "PlaylistManager", scriptObject ); - - const QMetaObject *metaObject = &PlaylistManager::staticMetaObject; - const QMetaEnum categoryEnum = metaObject->enumerator( metaObject->indexOfEnumerator("PlaylistCategory") ); - Q_ASSERT( categoryEnum.isValid() ); - scriptObject.setProperty( "PlaylistCategory", engine->enumObject( categoryEnum ) ); - - PlaylistPrototype::init( engine ); - PlaylistProviderPrototype::init( engine ); - - PlaylistManager *instance = PlaylistManager::instance(); - connect( instance, SIGNAL(categoryAdded(int)), SIGNAL(categoryAdded(int)) ); - connect( instance, SIGNAL(playlistAdded(Playlists::PlaylistPtr,int)), SIGNAL(playlistAdded(Playlists::PlaylistPtr,int)) ); - connect( instance, SIGNAL(playlistRemoved(Playlists::PlaylistPtr,int)), SIGNAL(playlistRemoved(Playlists::PlaylistPtr,int)) ); - connect( instance, SIGNAL(playlistUpdated(Playlists::PlaylistPtr,int)), SIGNAL(playlistUpdated(Playlists::PlaylistPtr,int)) ); - connect( instance, SIGNAL(providerAdded(Playlists::PlaylistProvider*,int)), SIGNAL(providerAdded(Playlists::PlaylistProvider*,int)) ); - connect( instance, SIGNAL(providerRemoved(Playlists::PlaylistProvider*,int)), SIGNAL(providerRemoved(Playlists::PlaylistProvider*,int)) ); - connect( instance, SIGNAL(renamePlaylist(Playlists::PlaylistPtr)), SIGNAL(renamePlaylist(Playlists::PlaylistPtr)) ); - connect( instance, SIGNAL(updated(int)), SIGNAL(updated(int)) ); -} - -// script invokable - -bool -AmarokPlaylistManagerScript::deletePlaylists( Playlists::PlaylistList playlistList ) -{ - return PlaylistManager::instance()->deletePlaylists( playlistList ); -} - -QList< Playlists::PlaylistProvider* > -AmarokPlaylistManagerScript::getProvidersForPlaylist( const Playlists::PlaylistPtr playlist ) -{ - return PlaylistManager::instance()->getProvidersForPlaylist( playlist ); -} - -bool -AmarokPlaylistManagerScript::import( const QUrl &fromLocation ) -{ - return PlaylistManager::instance()->import( fromLocation ); -} - -bool -AmarokPlaylistManagerScript::isWritable( const Playlists::PlaylistPtr &playlist ) -{ - return PlaylistManager::instance()->isWritable( playlist ); -} - -Playlists::PlaylistProvider* -AmarokPlaylistManagerScript::playlistProvider( int category, QString name ) -{ - return PlaylistManager::instance()->playlistProvider( category, name ); -} - -Playlists::PlaylistList -AmarokPlaylistManagerScript::playlistsOfCategory( int playlistCategory ) -{ - return PlaylistManager::instance()->playlistsOfCategory( playlistCategory ); -} - -PlaylistProviderList -AmarokPlaylistManagerScript::providersForCategory( int playlistCategory ) -{ - return PlaylistManager::instance()->providersForCategory( playlistCategory ); -} - -bool -AmarokPlaylistManagerScript::rename( Playlists::PlaylistPtr playlist, const QString &newName ) -{ - return PlaylistManager::instance()->rename( playlist, newName ); -} - -bool -AmarokPlaylistManagerScript::save( Meta::TrackList tracks, const QString &name, Playlists::PlaylistProvider *toProvider ) -{ - return PlaylistManager::instance()->save( tracks, name, toProvider ); -} - -// private - -QList -AmarokPlaylistManagerScript::availableCategories() -{ - return PlaylistManager::instance()->availableCategories(); -} diff --git a/src/scripting/scriptengine/AmarokPlaylistScript.h b/src/scripting/scriptengine/AmarokPlaylistScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokPlaylistScript.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_PLAYLIST_SCRIPT_H -#define AMAROK_PLAYLIST_SCRIPT_H - -#include "core/meta/forward_declarations.h" - -#include -#include -#include - -class QModelIndex; -class QUrl; - -namespace AmarokScript -{ - class AmarokScriptEngine; - - // SCRIPTDOX: Amarok.Playlist - class AmarokPlaylistScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokPlaylistScript( AmarokScriptEngine *engine ); - - /** - * Return the index of the currently playing track in the playlist. - */ - Q_INVOKABLE int activeIndex(); - - /** - * Return the number of tracks in the playlist. - */ - Q_INVOKABLE int totalTrackCount(); - - /** - * Save the current playlist in the default playlist path. - */ - Q_INVOKABLE QString saveCurrentPlaylist(); - - /** - * Load the track represented by the url and append to playlist. - */ - Q_INVOKABLE void addMedia( const QUrl &url ); - - /** - * Append @param track to playlist. - */ - Q_INVOKABLE void addTrack( Meta::TrackPtr track ); - - /** - * Load the list of tracks represented by the urls and append to playlist. - */ - Q_INVOKABLE void addMediaList( const QList &urls ); - - /** - * Append the list of tracks to playlist. - */ - Q_INVOKABLE void addTrackList( const Meta::TrackList &tracks ); - - /** - * Clear the current playlist. - */ - Q_INVOKABLE void clearPlaylist(); - - /** - * Play the track at the specified index in the playlist. - */ - Q_INVOKABLE void playByIndex( int index ); - - /** - * Prepend the the track represented by the passed url and start playing it. - */ - Q_INVOKABLE void playMedia( const QUrl &url ); - - /** - * Prepend @param track and start playing it. - */ - Q_INVOKABLE void playTrack( Meta::TrackPtr track ); - - /** - * Prepend the tracks represented by the passed urls and start playing them. - */ - Q_INVOKABLE void playMediaList( const QList &urls ); - - /** - * Prepend tracks in @param trackList and start playing them. - */ - Q_INVOKABLE void playTrackList( const Meta::TrackList &trackList ); - - /** - * Remove the currently playing track from the playlist. - */ - Q_INVOKABLE void removeCurrentTrack(); - - /** - * Remove the track at @param index from the playlist. - */ - Q_INVOKABLE void removeByIndex( int index ); - - /** - * Save the current playlist at the absolute path @param path. - */ - Q_INVOKABLE void savePlaylist( const QString& path ); - - /** - * Set whether to stop playing after the current track. - */ - Q_INVOKABLE void setStopAfterCurrent( bool on ); - - /* - * Indicates whether will stop playing after the current track. - */ - Q_INVOKABLE bool stopAfterCurrent(); - - /** - * Show/ Hide the playlist. - */ - Q_INVOKABLE void togglePlaylist(); - - /** - * Return a list of urls representing all the tracks in the playlist. - */ - Q_INVOKABLE QStringList filenames(); - - /** - * Return the track at the specified position in the playlist. - */ - Q_INVOKABLE Meta::TrackPtr trackAt( int row ); - - /** - * Get an unsorted list of indices of the currently selected tracks in the playlist. - */ - Q_INVOKABLE QList selectedIndexes(); - - /** - * Get an unsorted list of urls of the currently selected tracks in the playlist. - */ - Q_INVOKABLE QStringList selectedFilenames(); - - Q_SIGNALS: - /** - * Emitted when tracks are added to the playlist. - */ - void trackInserted( int start, int end ); - - /** - * Emitted when tracks are removed from the playlist. - */ - void trackRemoved( int start, int end ); - - private Q_SLOTS: - void slotTrackInserted( const QModelIndex&, int start, int end ); - void slotTrackRemoved( const QModelIndex&, int start, int end ); - - private: - AmarokScriptEngine* m_scriptEngine; - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokPlaylistScript.cpp b/src/scripting/scriptengine/AmarokPlaylistScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokPlaylistScript.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "AmarokScript::Playlist" - -#include "AmarokPlaylistScript.h" - -#include "App.h" -#include "EngineController.h" -#include "MainWindow.h" -#include "core/meta/Meta.h" -#include "core-impl/collections/support/CollectionManager.h" -#include "playlist/PlaylistActions.h" -#include "playlist/PlaylistController.h" -#include "playlist/PlaylistModelStack.h" -#include "playlist/view/listview/PrettyListView.h" -#include "playlist/PlaylistDock.h" -#include "ScriptingDefines.h" - -#include - -using namespace AmarokScript; - -AmarokPlaylistScript::AmarokPlaylistScript( AmarokScriptEngine *engine ) - : QObject( engine ) - , m_scriptEngine( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "Playlist", scriptObject ); - connect( The::playlist()->qaim(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT (slotTrackInserted(QModelIndex,int,int)) ); - connect( The::playlist()->qaim(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT (slotTrackRemoved(QModelIndex,int,int)) ); - engine->registerArrayType< QList >(); -} - -int -AmarokPlaylistScript::activeIndex() -{ - return The::playlist()->activeRow(); -} - -int -AmarokPlaylistScript::totalTrackCount() -{ - return The::playlist()->qaim()->rowCount(); -} - -QString -AmarokPlaylistScript::saveCurrentPlaylist() -{ - QString savePath = Amarok::defaultPlaylistPath(); - The::playlist()->exportPlaylist( savePath ); - return savePath; -} - -void -AmarokPlaylistScript::addMedia( const QUrl &url ) -{ - The::playlistController()->insertOptioned( url ); -} - -void -AmarokPlaylistScript::addTrack( Meta::TrackPtr track ) -{ - The::playlistController()->insertOptioned( track ); -} - -void -AmarokPlaylistScript::addMediaList( const QList &urls ) -{ - QList list; - foreach( const QUrl &url, urls ) - list << url; - The::playlistController()->insertOptioned( list ); -} - -void -AmarokPlaylistScript::addTrackList( const Meta::TrackList &tracks ) -{ - The::playlistController()->insertOptioned( tracks ); -} - -void -AmarokPlaylistScript::clearPlaylist() -{ - The::playlistController()->clear(); -} - -void -AmarokPlaylistScript::playByIndex( int index ) -{ - The::playlistActions()->play( index ); -} - -void -AmarokPlaylistScript::playMedia( const QUrl &url ) -{ - The::playlistController()->insertOptioned( url, Playlist::OnPlayMediaAction ); -} - -void -AmarokPlaylistScript::playTrack( Meta::TrackPtr track ) -{ - The::playlistController()->insertOptioned( track, Playlist::OnPlayMediaAction ); -} - -void -AmarokPlaylistScript::playMediaList( const QList &urls ) -{ - QList list; - foreach( const QUrl &url, urls ) - list << url; - The::playlistController()->insertOptioned( list, Playlist::OnPlayMediaAction ); -} - -void -AmarokPlaylistScript::playTrackList( const Meta::TrackList &trackList ) -{ - The::playlistController()->insertOptioned( trackList, Playlist::OnPlayMediaAction ); -} - -void -AmarokPlaylistScript::removeCurrentTrack() -{ - The::playlistController()->removeRow( activeIndex() ); -} - -void -AmarokPlaylistScript::removeByIndex( int index ) -{ - if( index < totalTrackCount() ) - The::playlistController()->removeRow( index ); -} - -void -AmarokPlaylistScript::savePlaylist( const QString& path ) -{ - The::playlist()->exportPlaylist( path ); -} - -void -AmarokPlaylistScript::setStopAfterCurrent( bool on ) -{ - if( on ) - The::playlistActions()->stopAfterPlayingTrack(); - else - The::playlistActions()->stopAfterPlayingTrack( 0 ); -} - -bool -AmarokPlaylistScript::stopAfterCurrent() -{ - return The::playlistActions()->willStopAfterTrack( The::playlist()->activeId() ); -} - -void -AmarokPlaylistScript::togglePlaylist() -{ - The::mainWindow()->showHide(); -} - -QStringList -AmarokPlaylistScript::filenames() -{ - QStringList fileNames; - for( int i=0; i < The::playlist()->qaim()->rowCount(); i++ ) - fileNames << The::playlist()->trackAt(i)->prettyUrl(); - return fileNames; -} - -Meta::TrackPtr -AmarokPlaylistScript::trackAt( int row ) -{ - DEBUG_BLOCK - Meta::TrackPtr track = The::playlist()->trackAt( row ); - return track; -} - -QList -AmarokPlaylistScript::selectedIndexes() -{ - DEBUG_BLOCK - - Playlist::PrettyListView* list = qobject_cast( The::mainWindow()->playlistDock()->currentView() ); - return list->selectedRows(); -} - -QStringList -AmarokPlaylistScript::selectedFilenames() -{ - DEBUG_BLOCK - - QStringList fileNames; - const QList indexes = selectedIndexes(); - - for( int i=0; i < indexes.size(); i++ ) - fileNames << The::playlist()->trackAt( indexes[i] )->prettyUrl(); - - return fileNames; -} - -void -AmarokPlaylistScript::slotTrackInserted( const QModelIndex&, int start, int end ) -{ - emit trackInserted( start, end ); -} - -void -AmarokPlaylistScript::slotTrackRemoved( const QModelIndex&, int start, int end ) -{ - emit trackRemoved( start, end ); -} diff --git a/src/scripting/scriptengine/AmarokScript.h b/src/scripting/scriptengine/AmarokScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScript.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Mark Kretschmann * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPT_H -#define AMAROK_SCRIPT_H - -#include -#include - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX: Amarok - class AmarokScript : public QObject - { - Q_OBJECT - - public: - AmarokScript( const QString &name, QScriptEngine *engine ); - - /** Shuts down Amarok completely. */ - Q_INVOKABLE void quitAmarok(); - - /** - * Print debug output to the shell. Only printed if amarok is started with --debug. - * @text The text to print. - */ - Q_INVOKABLE void debug( const QString& text ) const; - - /** - * Show an information dialog in Amarok. - * @text The text to display. - * @type Type of the dialog. See KMessageBox docs. - */ - Q_INVOKABLE int alert( const QString& text, const QString& type = "information" ) const; - - /** Signals Amarok that this script has ended. */ - Q_INVOKABLE void end(); - - /** - * Start another Amarok script. - * @name Name of the script to start. - */ - Q_INVOKABLE bool runScript( const QString& name ) const; - - /** - * Stop another Amarok script. - * @name Name of the script to stop. - */ - Q_INVOKABLE bool stopScript( const QString& name ) const; - - /** - * A list of names of the currently running scripts. - * Does not list scripts running in the scriptconsole! - */ - Q_INVOKABLE QStringList listRunningScripts() const; - - Q_SIGNALS: - /** - * Emitted when this script is uninstalled. - */ - void uninstalled(); - - // TODO: actaully emit this signal - void configured(); - - private: - QString m_name; - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokScript.cpp b/src/scripting/scriptengine/AmarokScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScript.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Mark Kretschmann * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokScript.h" - -#include "core/support/Amarok.h" -#include "App.h" -#include "core/support/Debug.h" -#include "scripting/scriptmanager/ScriptManager.h" - -#include - -#include - -AmarokScript::AmarokScript::AmarokScript( const QString &name, QScriptEngine *engine ) - : QObject( engine ) - , m_name( name ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().setProperty( "Amarok", scriptObject ); - if( ScriptManager::instance()->m_scripts.contains( name ) ) - connect( ScriptManager::instance()->m_scripts[name], &ScriptItem::uninstalled, this, &AmarokScript::uninstalled ); -} - -void -AmarokScript::AmarokScript::quitAmarok() -{ - pApp->quit(); -} - -void -AmarokScript::AmarokScript::debug( const QString& text ) const -{ - ::debug() << "SCRIPT" << m_name << ": " << text; -} - -int -AmarokScript::AmarokScript::alert( const QString& text, const QString& type ) const -{ - //Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 - if( type == "error" ) - { - KMessageBox::error( 0, text ); - return -1; - } - else if( type == "sorry" ) - { - KMessageBox::sorry( 0, text ); - return -1; - } - else if( type == "information" ) - { - KMessageBox::information( 0, text ); - return -1; - } - else if( type == "questionYesNo" ) - return KMessageBox::questionYesNo( 0, text ); - else if( type == "questionYesNoCancel" ) - return KMessageBox::questionYesNo( 0, text ); - else if( type == "warningYesNo" ) - return KMessageBox::warningYesNo( 0, text ); - else if( type == "warningContinueCancel" ) - return KMessageBox::warningContinueCancel( 0, text ); - else if( type == "warningYesNoCancel" ) - return KMessageBox::warningYesNoCancel( 0, text ); - - debug( "alert type not found!" ); - return -1; -} - -void -AmarokScript::AmarokScript::end() -{ - ScriptManager::instance()->stopScript( m_name ); -} - -bool -AmarokScript::AmarokScript::runScript( const QString& name ) const -{ - return ScriptManager::instance()->runScript( name, true ); -} - -bool -AmarokScript::AmarokScript::stopScript( const QString& name ) const -{ - return ScriptManager::instance()->stopScript( name ); -} - -QStringList -AmarokScript::AmarokScript::listRunningScripts() const -{ - return ScriptManager::instance()->listRunningScripts(); -} diff --git a/src/scripting/scriptengine/AmarokScriptConfig.h b/src/scripting/scriptengine/AmarokScriptConfig.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScriptConfig.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPT_CONFIG_H -#define AMAROK_SCRIPT_CONFIG_H - -#include - -#include - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX: Amarok.Script - class AmarokScriptConfig : public QObject - { - Q_OBJECT - - public: - AmarokScriptConfig( const QString& name, QScriptEngine *engine ); - - Q_INVOKABLE QVariant readConfig( const QString &name, const QVariant &defaultValue ) const; - Q_INVOKABLE void writeConfig( const QString &name, const QVariant &content ); - - private: - QString m_name; - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokScriptConfig.cpp b/src/scripting/scriptengine/AmarokScriptConfig.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScriptConfig.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokScriptConfig.h" - -#include "core/support/Amarok.h" - -#include -#include - -#include - -using namespace AmarokScript; - -AmarokScriptConfig::AmarokScriptConfig( const QString &name, QScriptEngine *engine ) - : QObject( engine ) - , m_name( name ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - //better name? - engine->globalObject().property( "Amarok" ).setProperty( "Script", scriptObject ); -} - -QVariant -AmarokScriptConfig::readConfig( const QString &name, const QVariant &defaultValue ) const -{ - return Amarok::config( m_name ).readEntry( name, defaultValue ); -} - -void -AmarokScriptConfig::writeConfig( const QString &name, const QVariant &content ) -{ - Amarok::config( m_name ).writeEntry( name, content ); -} diff --git a/src/scripting/scriptengine/AmarokScriptXml.h b/src/scripting/scriptengine/AmarokScriptXml.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScriptXml.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2017 Malte Veerman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef AMAROKSCRIPTXML_H -#define AMAROKSCRIPTXML_H - -#include - -class QDomDocument; -class QScriptEngine; -class QXmlStreamReader; - -namespace AmarokScript -{ - -class AmarokScriptXml : public QObject -{ - Q_OBJECT - -public: - explicit AmarokScriptXml( QScriptEngine *engine ); - ~AmarokScriptXml(); - - Q_INVOKABLE void setReaderData( const QString &data ); - Q_INVOKABLE bool setDomObjectData( const QString &data ); - Q_INVOKABLE QString readFirstStreamElementWithName( const QString &name ); - Q_INVOKABLE QString textOfFirstDomElementWithName( const QString &name ); - -private: - QXmlStreamReader *m_reader; - QDomDocument *m_domDocument; -}; - -} - -#endif // AMAROKSCRIPTXML_H diff --git a/src/scripting/scriptengine/AmarokScriptXml.cpp b/src/scripting/scriptengine/AmarokScriptXml.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScriptXml.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2017 Malte Veerman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "AmarokScriptXml.h" - -#include "core/support/Debug.h" - -#include -#include -#include - -using namespace AmarokScript; - -AmarokScriptXml::AmarokScriptXml( QScriptEngine *engine ) - : QObject( engine ) - , m_reader( Q_NULLPTR ) - , m_domDocument( new QDomDocument ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "Xml", scriptObject ); -} - -AmarokScriptXml::~AmarokScriptXml() -{ - delete m_domDocument; - - if( m_reader ) - delete m_reader; -} - -void AmarokScriptXml::setReaderData(const QString& data) -{ - if( m_reader ) - delete m_reader; - - m_reader = new QXmlStreamReader( data ); -} - -bool AmarokScriptXml::setDomObjectData(const QString& data) -{ - return m_domDocument->setContent( data ); -} - -QString AmarokScriptXml::readFirstStreamElementWithName(const QString& name) -{ - if( !m_reader ) - return QString(); - - while( m_reader->readNextStartElement() ) - { - if( m_reader->name() == name ) - return m_reader->readElementText(); - } - - return QString(); -} - -QString AmarokScriptXml::textOfFirstDomElementWithName(const QString& name) -{ - auto elements = m_domDocument->elementsByTagName( name ); - - if( !elements.isEmpty() ) - { - auto element = elements.at( 0 ); - return element.toElement().text(); - } - - return QString(); -} diff --git a/src/scripting/scriptengine/AmarokScriptableServiceScript.h b/src/scripting/scriptengine/AmarokScriptableServiceScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScriptableServiceScript.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPTABLE_SERVICE_SCRIPT_H -#define AMAROK_SCRIPTABLE_SERVICE_SCRIPT_H - -#include // for Q_DECLARE_METATYPE -#include -#include - -class StreamItem; -class QPixmap; -class QScriptContext; -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX: ScriptableServiceScript - /** - * Usage: First create the sciprtable service using a call to - * ScriptableServiceScript( string name, int levels, string shortDescription, string rootHtml, bool showSearchBar ) - */ - class ScriptableServiceScript : public QObject, public QScriptable - { - Q_OBJECT - - public: - explicit ScriptableServiceScript( QScriptEngine* engine ); - - void slotPopulate( QString name, int level, int parent_id, QString callbackData, QString filter ); - void slotRequestInfo( QString name, int level, QString callbackData ); - - void slotCustomize( const QString &name ); - - /** Script Invokable **/ - Q_INVOKABLE int insertItem( StreamItem* item ); - Q_INVOKABLE void setCurrentInfo( const QString &infoHtml ); - - Q_INVOKABLE int donePopulating() const; - - Q_INVOKABLE void setIcon( const QPixmap &icon ); - Q_INVOKABLE void setEmblem( const QPixmap &icon ); - Q_INVOKABLE void setScalableEmblem( const QString &emblemPath ); - - private: - QScriptEngine* m_scriptEngine; - int m_currentId; - QString m_serviceName; - static QScriptValue ScriptableServiceScript_prototype_ctor( QScriptContext *context, QScriptEngine *engine ); - static QScriptValue ScriptableServiceScript_prototype_populate( QScriptContext *context, QScriptEngine *engine ); - - Q_SIGNALS: - void populate( int, QString, QString ); - void fetchInfo( int, QString ); - void customize(); - }; -} - -Q_DECLARE_METATYPE( AmarokScript::ScriptableServiceScript* ) - -#endif diff --git a/src/scripting/scriptengine/AmarokScriptableServiceScript.cpp b/src/scripting/scriptengine/AmarokScriptableServiceScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokScriptableServiceScript.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "AmarokScriptableServiceScript" - -#include "AmarokScriptableServiceScript.h" - -#include "App.h" -#include "core/support/Debug.h" -#include "services/scriptable/ScriptableServiceManager.h" -#include "scripting/scriptengine/AmarokStreamItemScript.h" -#include "scripting/scriptmanager/ScriptManager.h" - -#include - -using namespace AmarokScript; - -ScriptableServiceScript::ScriptableServiceScript( QScriptEngine* engine ) - : QObject( engine ) - , m_scriptEngine( engine ) -{ - DEBUG_BLOCK - m_scriptEngine = engine; - engine->setDefaultPrototype( qMetaTypeId(), QScriptValue() ); - const QScriptValue ctor = engine->newFunction( ScriptableServiceScript_prototype_ctor ); - engine->globalObject().setProperty( "ScriptableServiceScript", ctor ); -} - -QScriptValue -ScriptableServiceScript::ScriptableServiceScript_prototype_ctor( QScriptContext *context, QScriptEngine *engine ) -{ - DEBUG_BLOCK - QString serviceName = context->argument(0).toString(); - int levels = context->argument(1).toInt32(); - QString shortDescription = context->argument(2).toString(); - QString rootHtml = context->argument(3).toString(); - bool showSearchBar = context->argument(4).toBoolean(); - if( !ScriptManager::instance()->m_scripts.contains( serviceName ) ) - { - error() << "The name of the scriptable script should be the same with the one in the script.spec file!"; - return engine->undefinedValue(); - } - QScriptValue obj = engine->newQObject( context->thisObject(), ScriptManager::instance()->m_scripts.value(serviceName)->service(), - QScriptEngine::AutoOwnership, QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().setProperty( "ScriptableServiceScript", obj ); - The::scriptableServiceManager()->initService( serviceName, levels, shortDescription, rootHtml, showSearchBar ); - return engine->undefinedValue(); -} - -QScriptValue -ScriptableServiceScript::ScriptableServiceScript_prototype_populate( QScriptContext *context, QScriptEngine *engine ) -{ - Q_UNUSED( context ); - debug() << "prototype populating here!"; - return engine->undefinedValue(); -} - -int -ScriptableServiceScript::insertItem( StreamItem* item ) -{ - return The::scriptableServiceManager()->insertItem( m_serviceName, item->level(), m_currentId, item->itemName(), item->infoHtml(), item->callbackData(), item->playableUrl(), - item->album(), item->artist(), item->genre(), item->composer(), item->year(), - item->coverUrl() ); -} - -int -ScriptableServiceScript::donePopulating() const -{ - DEBUG_BLOCK - - The::scriptableServiceManager()->donePopulating( m_serviceName, m_currentId ); - return -1; // Fixme: return the right thing. -} - -void -ScriptableServiceScript::slotPopulate( QString name, int level, int parent_id, QString callbackData, QString filter ) -{ - DEBUG_BLOCK - m_currentId = parent_id; - m_serviceName = name; - emit( populate( level, callbackData, filter ) ); -} - -void -ScriptableServiceScript::slotRequestInfo( QString name, int level, QString callbackData ) -{ - DEBUG_BLOCK - m_serviceName = name; - emit( fetchInfo( level, callbackData ) ); -} - -void -ScriptableServiceScript::slotCustomize( const QString &name ) -{ - DEBUG_BLOCK - m_serviceName = name; - emit( customize() ); -} - - -void -ScriptableServiceScript::setIcon( const QPixmap &icon ) -{ - The::scriptableServiceManager()->setIcon( m_serviceName, icon ); -} - -void -ScriptableServiceScript::setEmblem( const QPixmap &emblem ) -{ - The::scriptableServiceManager()->setEmblem( m_serviceName, emblem ); -} - -void -ScriptableServiceScript::setScalableEmblem ( const QString& emblemPath ) -{ - The::scriptableServiceManager()->setScalableEmblem( m_serviceName, emblemPath ); -} - -void -ScriptableServiceScript::setCurrentInfo( const QString &infoHtml ) -{ - The::scriptableServiceManager()->setCurrentInfo( m_serviceName, infoHtml ); -} diff --git a/src/scripting/scriptengine/AmarokServicePluginManagerScript.h b/src/scripting/scriptengine/AmarokServicePluginManagerScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokServicePluginManagerScript.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SERVICE_PLUGIN_MANAGER_SCRIPT_H -#define AMAROK_SERVICE_PLUGIN_MANAGER_SCRIPT_H - -#include -#include - - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX: Amarok.ServicePluginManager - class AmarokServicePluginManagerScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokServicePluginManagerScript( QScriptEngine* scriptEngine ); - - Q_INVOKABLE QStringList loadedServices(); - Q_INVOKABLE QStringList loadedServiceNames(); - Q_INVOKABLE QString serviceDescription( const QString &service ); - Q_INVOKABLE QString serviceMessages( const QString &service ); - Q_INVOKABLE QString sendMessage( const QString &service, const QString &message ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokServicePluginManagerScript.cpp b/src/scripting/scriptengine/AmarokServicePluginManagerScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokServicePluginManagerScript.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokServicePluginManagerScript.h" - -#include "App.h" -#include "services/ServicePluginManager.h" - -#include - -using namespace AmarokScript; - -AmarokServicePluginManagerScript::AmarokServicePluginManagerScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "ServicePluginManager", scriptObject ); -} - -QStringList -AmarokServicePluginManagerScript::loadedServices() -{ - return ServicePluginManager::instance()->loadedServices(); -} - -QStringList -AmarokServicePluginManagerScript::loadedServiceNames() -{ - return ServicePluginManager::instance()->loadedServiceNames(); -} - -QString -AmarokServicePluginManagerScript::serviceDescription( const QString &service ) -{ - return ServicePluginManager::instance()->serviceDescription( service ); -} - -QString -AmarokServicePluginManagerScript::serviceMessages( const QString &service ) -{ - return ServicePluginManager::instance()->serviceMessages( service ); -} - -QString -AmarokServicePluginManagerScript::sendMessage( const QString &service, const QString &message ) -{ - return ServicePluginManager::instance()->sendMessage( service, message ); -} diff --git a/src/scripting/scriptengine/AmarokStatusbarScript.h b/src/scripting/scriptengine/AmarokStatusbarScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokStatusbarScript.h +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_STATUSBAR_SCRIPT_H -#define AMAROK_STATUSBAR_SCRIPT_H - -#include - -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX: Amarok.Window.Statusbar - class AmarokStatusbarScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokStatusbarScript( QScriptEngine* scriptEngine ); - - Q_INVOKABLE void longMessage( const QString &text ); - Q_INVOKABLE void shortMessage( const QString &text ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokStatusbarScript.cpp b/src/scripting/scriptengine/AmarokStatusbarScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokStatusbarScript.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokStatusbarScript.h" - -#include "core/interfaces/Logger.h" -#include "core/support/Components.h" - -#include - -using namespace AmarokScript; - -AmarokStatusbarScript::AmarokStatusbarScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - QScriptValue windowObject = engine->globalObject().property( "Amarok" ).property( "Window" ); - windowObject.setProperty( "Statusbar", scriptObject ); -} - -void -AmarokStatusbarScript::longMessage( const QString &text ) -{ - Amarok::Components::logger()->longMessage( text ); -} - -void -AmarokStatusbarScript::shortMessage( const QString &text ) -{ - Amarok::Components::logger()->shortMessage( text ); -} diff --git a/src/scripting/scriptengine/AmarokStreamItemScript.h b/src/scripting/scriptengine/AmarokStreamItemScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokStreamItemScript.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_STREAMITEM_SCRIPT_H -#define AMAROK_STREAMITEM_SCRIPT_H - -#include // for Q_DECLARE_METATYPE -#include - -class QScriptEngine; - -//namespace AmarokScript{ - - // SCRIPTDOX: Amarok.StreamItem - class StreamItem : public QObject - { - Q_OBJECT - - Q_PROPERTY( QString itemName WRITE setItemName READ itemName ) - Q_PROPERTY( QString infoHtml WRITE setInfoHtml READ infoHtml ) - Q_PROPERTY( QString playableUrl WRITE setPlayableUrl READ playableUrl ) - Q_PROPERTY( QString callbackData WRITE setCallbackData READ callbackData ) - Q_PROPERTY( int level WRITE setLevel READ level ) - - Q_PROPERTY( QString album WRITE setAlbum READ album ) - Q_PROPERTY( QString artist WRITE setArtist READ artist ) - Q_PROPERTY( QString genre WRITE setGenre READ genre ) - Q_PROPERTY( QString composer WRITE setComposer READ composer ) - Q_PROPERTY( int year WRITE setYear READ year ) - Q_PROPERTY( QString coverUrl WRITE setCoverUrl READ coverUrl ) - - public: - explicit StreamItem( QScriptEngine *engine ); - - QString itemName() const; - QString infoHtml() const; - QString playableUrl() const; - QString callbackData() const; - int level() const; - - QString album() const; - QString artist() const; - QString genre() const; - QString composer() const; - int year() const; - QString coverUrl(); - - private: - void setItemName( QString name ); - void setInfoHtml( QString infoHtml ); - void setPlayableUrl( QString playableUrl ); - void setCallbackData( QString callbackData ); - void setLevel( int level ); - - void setAlbum( QString album ); - void setArtist( QString artist ); - void setGenre( QString genre ); - void setComposer( QString composer ); - void setYear( int year ); - void setCoverUrl( QString url ); - - QString m_name; - QString m_infoHtml; - QString m_playableUrl; - QString m_callbackData; - int m_level; - - //these are not required but can be used to override what is shown in the playlist and elsewhere. - QString m_album; - QString m_artist; - QString m_genre; - QString m_composer; - int m_year; - QString m_coverUrl; - - }; -//} - -Q_DECLARE_METATYPE( StreamItem* ) - -#endif // AMAROK_STREAMITEM_SCRIPT_H diff --git a/src/scripting/scriptengine/AmarokStreamItemScript.cpp b/src/scripting/scriptengine/AmarokStreamItemScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokStreamItemScript.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokStreamItemScript.h" - -#include "core/support/Debug.h" - -#include - -//using namespace AmarokScript; - -StreamItem::StreamItem( QScriptEngine *engine ) - : QObject( engine ) - , m_year( 0 ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "StreamItem", scriptObject ); - engine->setDefaultPrototype( qMetaTypeId(), QScriptValue() ); -} - -QString -StreamItem::itemName() const -{ - return m_name; -} - -QString -StreamItem::infoHtml() const -{ - return m_infoHtml; -} - -QString -StreamItem::playableUrl() const -{ - return m_playableUrl; -} - -QString -StreamItem::callbackData() const -{ - return m_callbackData; -} - -int -StreamItem::level() const -{ - return m_level; -} - - -QString -StreamItem::album() const -{ - return m_album; -} - -QString -StreamItem::artist() const -{ - return m_artist; -} - -QString -StreamItem::genre() const -{ - return m_genre; -} - -QString -StreamItem::composer() const -{ - return m_composer; -} - -int -StreamItem::year() const -{ - return m_year; -} - -QString -StreamItem::coverUrl() -{ - return m_coverUrl; -} - - -void -StreamItem::setItemName( QString name ) -{ - m_name = name; -} - -void -StreamItem::setInfoHtml( QString infoHtml ) -{ - m_infoHtml = infoHtml; -} - -void -StreamItem::setPlayableUrl( QString playableUrl ) -{ - m_playableUrl = playableUrl; -} - -void -StreamItem::setCallbackData( QString callbackData ) -{ - m_callbackData = callbackData; -} - -void -StreamItem::setLevel( int level ) -{ - m_level = level; -} - -void -StreamItem::setAlbum( QString album ) -{ - m_album = album; -} - -void -StreamItem::setArtist( QString artist ) -{ - m_artist = artist; -} - -void -StreamItem::setGenre( QString genre ) -{ - m_genre = genre; -} - -void -StreamItem::setComposer( QString composer ) -{ - m_composer = composer; -} - -void -StreamItem::setYear( int year ) -{ - m_year = year; -} - -void -StreamItem::setCoverUrl( QString url ) -{ - m_coverUrl = url; -} diff --git a/src/scripting/scriptengine/AmarokWindowScript.h b/src/scripting/scriptengine/AmarokWindowScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokWindowScript.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2013-2014 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_WINDOW_SCRIPT_H -#define AMAROK_WINDOW_SCRIPT_H - -#include -#include -#include -#include -#include -#include -#include - -class EventFilter; -class QMenu; -class QMainWindow; -class QMenu; -class QScriptEngine; - -namespace AmarokScript -{ - class AmarokScriptEngine; - // SCRIPTDOX: Amarok.Window - class AmarokWindowScript : public QObject - { - Q_OBJECT - - Q_PROPERTY( bool isTrayIconShown READ isTrayIconShown ) - Q_PROPERTY( QString activeBrowserName READ activeBrowserName ) - Q_PROPERTY( QMainWindow* mainWindow READ mainWindow ) - /** - * Convenience method for mainWindow.styleSheet and setStyleSheet - */ - Q_PROPERTY( QString styleSheet READ styleSheet WRITE setStyleSheet ) - Q_PROPERTY( QFont font READ font WRITE setFont ) - Q_PROPERTY( QPalette palette READ palette WRITE setPalette ) - - public: - explicit AmarokWindowScript( AmarokScriptEngine* scriptEngine ); - - Q_INVOKABLE void addToolsMenu( const QString &name ); - Q_INVOKABLE void addSettingsMenu( const QString &name ); - Q_INVOKABLE bool addToolsAction( QString id, QString actionName, QString icon = "amarok" ); - Q_INVOKABLE void addToolsSeparator(); - Q_INVOKABLE bool addSettingsAction( QString id, QString actionName, QString icon = "amarok" ); - Q_INVOKABLE bool addCustomAction( QString menuName, QString id, QString actionName, QString icon = "amarok" ); - Q_INVOKABLE void addSettingsSeparator(); - Q_INVOKABLE void showTrayIcon( bool show ); - - /** - * Show tooltips with the widget's name on mouseover. - * @param showDelay the duration after which toolTip appears. - * @param copyDelay the duration after - * - * Must restart Amarok afetr invoking this function to revert tooltips - * to normal. - */ - Q_INVOKABLE void showToolTip(); - - Q_SIGNALS: - void prepareToQuit(); - void newPalette( QPalette ); - - private: - /** - * adds an action with the given ID and title to the given menu - * - * @param menu the menu to which the action will be added - * @param id the ID of the action - * @param actionName the title of the action - * @param menuProperty the name of the menu property for the script engine - * @param icon the icon for the action - * - * @return true if adding the action was successful, false otherwise - */ - bool addMenuAction( QMenu *menu, QString id, QString actionName, QString menuProperty, QString icon ); - - QString activeBrowserName(); - bool isTrayIconShown(); - QMainWindow* mainWindow(); - void setStyleSheet( const QString &styleSheet ); - QString styleSheet() const; - QFont font() const; - void setFont( const QFont &font ); - QPalette palette() const; - void setPalette( const QPalette & palette ); - - QMap m_customMenus; - QPointer m_toolsMenu; - QPointer m_settingsMenu; - AmarokScriptEngine* m_scriptEngine; - }; -} - -Q_DECLARE_METATYPE( QMainWindow* ) -Q_DECLARE_METATYPE( QPalette ) - -#endif diff --git a/src/scripting/scriptengine/AmarokWindowScript.cpp b/src/scripting/scriptengine/AmarokWindowScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokWindowScript.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "AmarokWindowScript.h" - -#include "ActionClasses.h" -#include "amarokconfig.h" -#include "core/support/Amarok.h" -#include "App.h" -#include "browsers/collectionbrowser/CollectionWidget.h" -#include "core/support/Debug.h" -#include "MainWindow.h" -#include "PaletteHandler.h" -#include "ScriptingDefines.h" - -#include -#include - -#include -#include - -using namespace AmarokScript; - -class ToolTipEventFilter : public QObject -{ - public: - static ToolTipEventFilter *instance(); - - private: - ToolTipEventFilter(); - bool eventFilter( QObject *object, QEvent *event ); - - static QPointer s_instance; -}; - -QPointer ToolTipEventFilter::s_instance; - -ToolTipEventFilter* -ToolTipEventFilter::instance() -{ - if( !s_instance ) - s_instance = new ToolTipEventFilter(); - return s_instance.data(); -} - -ToolTipEventFilter::ToolTipEventFilter() -: QObject( The::mainWindow() ) -{} - -bool -ToolTipEventFilter::eventFilter( QObject *object, QEvent *event ) -{ - if( event->type() == QEvent::ToolTip ) - QApplication::clipboard()->setText( object->objectName() ); - return false; -} - -// AmarokWindowScript - -AmarokWindowScript::AmarokWindowScript( AmarokScriptEngine* scriptEngine ) - : QObject( scriptEngine ) - , m_toolsMenu( The::mainWindow()->ToolsMenu() ) - , m_settingsMenu( The::mainWindow()->SettingsMenu() ) - , m_scriptEngine( scriptEngine ) -{ - QScriptValue windowObject = scriptEngine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - scriptEngine->globalObject().property( "Amarok" ).setProperty( "Window", windowObject ); - - windowObject.setProperty( "ToolsMenu", scriptEngine->newObject() ); - windowObject.setProperty( "SettingsMenu", scriptEngine->newObject() ); - - connect( pApp, &App::prepareToQuit, this, &AmarokWindowScript::prepareToQuit ); -} - -void -AmarokWindowScript::addToolsMenu( const QString &name ) -{ - if( m_customMenus.contains( name ) ) - return; - - QMenu *menu = new QMenu( name ); - m_customMenus.insert( name, menu ); - m_toolsMenu->addMenu( menu ); - QScriptValue scriptMenu = m_scriptEngine->newQObject( menu ); - m_scriptEngine->globalObject().property( "Amarok" ).property( "Window" ).setProperty( name, scriptMenu ); -} - -void -AmarokWindowScript::addSettingsMenu( const QString &name ) -{ - if( m_customMenus.contains( name ) ) - return; - - QMenu *menu = new QMenu( name ); - m_customMenus.insert( name, menu ); - m_settingsMenu->addMenu( menu ); - QScriptValue scriptMenu = m_scriptEngine->newQObject( menu ); - m_scriptEngine->globalObject().property( "Amarok" ).property( "Window" ).setProperty( name, scriptMenu ); -} - -bool -AmarokWindowScript::addToolsAction( QString id, QString actionName, QString icon ) -{ - return addMenuAction( m_toolsMenu, id, actionName, "ToolsMenu", icon ); -} - -void -AmarokWindowScript::addToolsSeparator() -{ - m_toolsMenu->addSeparator(); -} - -bool -AmarokWindowScript::addSettingsAction( QString id, QString actionName, QString icon ) -{ - return addMenuAction( m_settingsMenu, id, actionName, "SettingsMenu", icon ); -} - -bool -AmarokScript::AmarokWindowScript::addCustomAction(QString menuName, QString id, QString actionName, QString icon) -{ - if( !m_customMenus.contains( menuName ) ) - return false; - - return addMenuAction( m_customMenus.value( menuName ), id, actionName, menuName, icon ); -} - -void -AmarokWindowScript::addSettingsSeparator() -{ - m_settingsMenu->addSeparator(); -} - -bool -AmarokWindowScript::addMenuAction( QMenu *menu, QString id, QString actionName, QString menuProperty, QString icon ) -{ - KActionCollection* const ac = Amarok::actionCollection(); - if( ac->action( id ) ) - return false; - - QAction *action = new QAction( QIcon::fromTheme( icon ), actionName, this ); - ac->addAction( id, action ); - - // don't forget to read the shortcut settings from the config file so - // the shortcuts for the actions are updated - ac->readSettings(); - - // add the action to the given menu - menu->addAction( ac->action( id ) ); - - QScriptValue newMenu = m_scriptEngine->newQObject( action ); - m_scriptEngine->globalObject().property( "Amarok" ).property( "Window" ).property( menuProperty ).setProperty( id, newMenu ); - return true; -} - -void -AmarokWindowScript::showTrayIcon( bool show ) -{ - AmarokConfig::setShowTrayIcon( show ); - pApp->applySettings(); -} - -QString -AmarokWindowScript::activeBrowserName() -{ - return The::mainWindow()->activeBrowserName(); -} - -bool -AmarokWindowScript::isTrayIconShown() -{ - return AmarokConfig::showTrayIcon(); -} - -QMainWindow* -AmarokWindowScript::mainWindow() -{ - return The::mainWindow(); -} - -QPalette -AmarokWindowScript::palette() const -{ - return The::paletteHandler()->palette(); -} - -void -AmarokWindowScript::setPalette( const QPalette &palette ) -{ - The::paletteHandler()->setPalette( palette ); -} - -void -AmarokWindowScript::setStyleSheet( const QString &styleSheet ) -{ - The::mainWindow()->setStyleSheet( styleSheet ); -} - -QString -AmarokWindowScript::styleSheet() const -{ - return The::mainWindow()->styleSheet(); -} - -QFont -AmarokWindowScript::font() const -{ - return The::mainWindow()->font(); -} - -void -AmarokWindowScript::setFont( const QFont &font ) -{ - The::mainWindow()->setFont( font ); - The::mainWindow()->collectionBrowser()->update(); -} - -void -AmarokWindowScript::showToolTip() -{ - foreach( QWidget *widget, The::mainWindow()->findChildren() ) - { - widget->setToolTip( widget->objectName() ); - widget->installEventFilter( ToolTipEventFilter::instance() ); - } -} diff --git a/src/scripting/scriptengine/PHAACG2.py b/src/scripting/scriptengine/PHAACG2.py deleted file mode 100755 --- a/src/scripting/scriptengine/PHAACG2.py +++ /dev/null @@ -1,111 +0,0 @@ -# Copyright 2013 Anmol Ahuja -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# TODOs: -# NO enums like in AmarokInfoScript.cpp handled, global func not handled -# handle enums in scriptdox -# Handle multiple classes in a file -# Handle docs in script dox - -import os -import sys -import re - -prototype = {} -scriptMap = {} -autoComplete = [] - -def addElement( scriptMap, name, classDoc = '' ): - #if not scriptMap.has_key( name ): - scriptMap[name] = ["\nclass " + name + "{\n"] - -def generatePseudoHeader( rootDir, fileName ): - global prototype - global scriptMap - global autoComplete - - headerPath = os.path.join(rootDir, fileName+".h") - - className = None - with open( headerPath, 'r' ) as f: - contents = f.read() - match = re.search( r'//[\s]*SCRIPTDOX[\s:]*(.*)', contents ) - if match is None: - return - s = [item for item in match.group(1).split(' ') if item] - if 'PROTOTYPE' in s: - className = s[2].strip() - prototype[ s[1] ] = className - else: - className = s[0].strip() - autoComplete.append( className ) - addElement( scriptMap, className )#, classDoc ) - classBeg = contents.index(match.group(0)) - if True: - properties = re.findall( r"(Q_PROPERTY\(\s*[\w:<>]*\s*([\w:<>\*]*).*\))", contents, re.MULTILINE ) - for qProperty in properties: - if 'PROTOTYPE' not in s: - autoComplete.append( className + "." + qProperty[1] ) - scriptMap[className].append( qProperty[0] ) - #re.findall( r"public slots:[\s\n]*(.*)[\n\s]*(protected|private|public|slots|};|signals):" #huh, works without |signals?! - # , contents, re.MULTILINE|re.DOTALL ) - accessMap = {} - for access in ( 'private slots:', 'protected slots:', 'public slots:', 'private:', 'public:', 'protected:', 'signals:', '};' ): - indexFromBeg = contents[classBeg:].find( access ) + classBeg - if indexFromBeg is not -1: - accessMap[ indexFromBeg ] = access - - sortedKeys = sorted( accessMap.keys() ) - for access in ('public slots:', 'signals:'): - if( access in contents ): - accessIndex = contents[classBeg:].find( access ) + classBeg - selections = contents[ accessIndex : sortedKeys[sortedKeys.index(accessIndex)] ] - functions = filter( None, re.findall( r'(.*;)', selections ) ) - if 'PROTOTYPE' not in s: - for function in functions: - reg = re.search( r'.*[\s\n](.*)[\s\n]*\(', function.strip()) - if reg: - funcName = reg.group(1).replace('*','').replace('&','') - autoComplete.append( className+"."+ funcName + '(' ) - scriptMap[className].append( selections ) - -def traverseDir( dirPath, opDir ): - for root, subFolder, files in os.walk(dirPath): - for fileName in files: - if fileName.endswith( ".cpp" ): - generatePseudoHeader( root, fileName[:-4] ) - #substitute prototypes - for scriptClass in scriptMap: - for line in scriptMap[scriptClass]: - re.sub( r"\b("+'|'.join(prototype.keys())+r')\b', lambda word: prototype[word.group()], line ) - - f = open( os.path.join( opDir, "PseudoHeader.h" ), 'w' ) - for scriptClass in scriptMap: - f.write( '\n'.join(scriptMap[scriptClass]) + '};\n' ) - f.close() - - autoComplete.sort() - f = open( os.path.join( opDir, "AutoComplete.txt" ), 'w' ) - f.write( '\n'.join(autoComplete) ) - f.close() - -def main(): - scriptPath = sys.argv[1] - if not os.path.exists(sys.argv[2]): - os.makedirs(sys.argv[2]) - traverseDir( sys.argv[1], sys.argv[2] ) - -if __name__ == "__main__": - main() diff --git a/src/scripting/scriptengine/ScriptImporter.h b/src/scripting/scriptengine/ScriptImporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/ScriptImporter.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPT_IMPORTER_H -#define SCRIPT_IMPORTER_H - - -#include -#include -#include -#include - -class QScriptEngine; -class QStringList; - -namespace AmarokScript -{ - class AmarokScriptEngine; - - // SCRIPTDOX: Importer - class ScriptImporter : public QObject - { - Q_OBJECT - - public: - ScriptImporter( AmarokScriptEngine *scriptEngine, const QUrl &url ); - - Q_INVOKABLE QStringList availableBindings() const; - Q_INVOKABLE bool loadAmarokBinding( const QString &name ); - Q_INVOKABLE void loadExtension( const QString &src ); - Q_INVOKABLE bool loadQtBinding( const QString &binding ); - Q_INVOKABLE bool include( const QString &relativeFile ); - - private: - const QUrl m_scriptUrl; - AmarokScriptEngine *m_scriptEngine; - QSet m_importedBindings; - }; -} - -#endif diff --git a/src/scripting/scriptengine/ScriptImporter.cpp b/src/scripting/scriptengine/ScriptImporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/ScriptImporter.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptImporter.h" - -#include "App.h" -#include "AmarokBookmarkScript.h" -#include "AmarokCollectionViewScript.h" -#include "config.h" -#include "core/support/Debug.h" -#include "ScriptingDefines.h" -#include "AmarokPlaylistManagerScript.h" -#include "scripting/scriptmanager/ScriptManager.h" - -#include - -#include -#include - -using namespace AmarokScript; - -ScriptImporter::ScriptImporter( AmarokScriptEngine *scriptEngine, const QUrl &url ) - : QObject( scriptEngine ) - , m_scriptUrl( url ) - , m_scriptEngine( scriptEngine ) -{ - QScriptValue scriptObject = scriptEngine->newQObject( this, QScriptEngine::AutoOwnership - , QScriptEngine::ExcludeSuperClassContents ); - scriptEngine->globalObject().setProperty( "Importer", scriptObject ); -} - -void -ScriptImporter::loadExtension( const QString& src ) -{ - DEBUG_BLOCK - m_scriptEngine->importExtension( "amarok/" + src ); -} - -bool -ScriptImporter::loadQtBinding( const QString& binding ) -{ - Q_UNUSED( binding ) - - error() << __PRETTY_FUNCTION__ << "Loading Qt bindings in scripts not available in Qt5!"; - return false; -} - -bool -ScriptImporter::include( const QString& relativeFilename ) -{ - QUrl includeUrl = KIO::upUrl(m_scriptUrl); - includeUrl = includeUrl.adjusted(QUrl::StripTrailingSlash); - includeUrl.setPath(includeUrl.path() + '/' + ( relativeFilename )); - QFile file( includeUrl.toLocalFile() ); - if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - warning() << "cannot open the include file!"; - return false; - } - m_scriptEngine->currentContext()->setActivationObject( - m_scriptEngine->currentContext()->parentContext()->activationObject() ); - m_scriptEngine->evaluate( file.readAll(), relativeFilename ); - return true; -} - -QStringList -ScriptImporter::availableBindings() const -{ - return m_scriptEngine->availableExtensions(); -} - -bool -ScriptImporter::loadAmarokBinding( const QString &name ) -{ - if( name == "bookmarks" ) - new AmarokBookmarkScript( m_scriptEngine ); - else if( name == "collectionview" ) - new AmarokCollectionViewScript( m_scriptEngine, ScriptManager::instance()->scriptNameForEngine( m_scriptEngine ) ); - else if( name == "playlistmanager" ) - new AmarokPlaylistManagerScript( m_scriptEngine ); - else - { - warning() << "\"" << name << "\" doesn't exist!"; - return false; - } - return true; -} diff --git a/src/scripting/scriptengine/ScriptingDefines.h b/src/scripting/scriptengine/ScriptingDefines.h deleted file mode 100644 --- a/src/scripting/scriptengine/ScriptingDefines.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROKSCRIPT_SCRIPTING_DEFINES_H -#define AMAROKSCRIPT_SCRIPTING_DEFINES_H - -#include -#include -#include -#include -#include - -class QMetaEnum; - -namespace AmarokScript -{ - template - void fromScriptValue( const QScriptValue &obj, type &object ) - { - const WrapperType *wrapper = dynamic_cast( obj.toQObject() ); - if( wrapper ) - object = wrapper->data(); - else - object = 0; - } - - template - QScriptValue toScriptValue( QScriptEngine *engine, type const &object ) - { - WrapperType *wrapper = new WrapperType( object ); - return engine->newQObject( wrapper, QScriptEngine::ScriptOwnership, - QScriptEngine::ExcludeSuperClassContents ); - } - - template - QScriptValue toScriptArray( QScriptEngine *engine, const Container &container ) - { - QScriptValue scriptArray = engine->newArray(); - typename Container::const_iterator begin = container.begin(); - typename Container::const_iterator end = container.end(); - typename Container::const_iterator it; - for( it = begin; it != end; ++it ) - scriptArray.setProperty( quint32(it - begin), engine->toScriptValue(*it) ); - return scriptArray; - } - - template - void fromScriptArray( const QScriptValue &value, Container &container ) - { - quint32 len = value.property( "length" ).toUInt32(); - for( quint32 i = 0; i < len; ++i ) - { - QScriptValue item = value.property( i ); - typedef typename Container::value_type ContainerValue; - container.push_back( qscriptvalue_cast(item) ); - } - } - - template - QScriptValue toScriptMap( QScriptEngine *engine, const Map &map ) - { - QScriptValue scriptMap = engine->newObject(); - for( typename Map::const_iterator it( map.begin() ); it != map.end(); ++it ) - scriptMap.setProperty( it.key(), engine->toScriptValue( it.value() ) ); - return scriptMap; - } - - template - void fromScriptMap( const QScriptValue &value, Map &map ) - { - QScriptValueIterator it( value ); - while( it.hasNext() ) - { - it.next(); - map[it.name()] = qscriptvalue_cast( it.value() ); - } - } - - /** - * SCRIPTDOX _ - */ - class AmarokScriptEngine : public QScriptEngine - { - Q_OBJECT - - public: - explicit AmarokScriptEngine( QObject *parent ); - virtual ~AmarokScriptEngine(); - - void setDeprecatedProperty( const QString &parent, const QString &name, const QScriptValue &property ); - // exposing the metaobject directly also exposes >900 other values - QScriptValue enumObject( const QMetaEnum &metaEnum ); - - template - void registerArrayType() - { - qScriptRegisterMetaType( this, toScriptArray, fromScriptArray ); - } - template - void registerMapType() - { - qScriptRegisterMetaType( this, toScriptMap, fromScriptMap ); - } - - // SCRIPTDOX exclude - Q_INVOKABLE void invokableDeprecatedCall( const QString &call ); - - /** - * @param function The function to invoke after time @param time in milliseconds. - * @param thisObject [Optional] The this object this function is invoked with. - * @param args [Optional] An array containing arguments this function is to be invoked with. - */ - Q_INVOKABLE void setTimeout( const QScriptValue &function, int time, - const QScriptValue &thisObject = QScriptValue(), - const QScriptValue &args = QScriptValue() ); - - private Q_SLOTS: - void slotTimeout(); - - Q_SIGNALS: - void deprecatedCall(QString); - - private: - const QString internalObject; - QHash m_callbacks; - }; -} - -#endif // AMAROKSCRIPT_SCRIPTING_DEFINES_H diff --git a/src/scripting/scriptengine/ScriptingDefines.cpp b/src/scripting/scriptengine/ScriptingDefines.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/ScriptingDefines.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptingDefines.h" - -#include "core/support/Debug.h" - -#include -#include - -using namespace AmarokScript; - -AmarokScriptEngine::AmarokScriptEngine( QObject *parent ) -: QScriptEngine(parent) -, internalObject( "UndocumentedAmarokScriptingInternals" ) -{ - QScriptValue scriptObject = newQObject( this, QtOwnership, - ExcludeChildObjects | ExcludeSuperClassContents ); - globalObject().setProperty( internalObject, scriptObject, QScriptValue::ReadOnly ); - QScriptValue setTimeoutObject = scriptObject.property( "setTimeout" ); - Q_ASSERT( !setTimeoutObject.isUndefined() ); - Q_ASSERT( !globalObject().property( internalObject ).property( "invokableDeprecatedCall" ).isUndefined() ); - globalObject().setProperty( "setTimeout", setTimeoutObject ); -} - -void -AmarokScriptEngine::setDeprecatedProperty( const QString &parent, const QString &name, const QScriptValue &property ) -{ - const QString objName = QString( "%1%2" ).arg( name, QString::number( qrand() ) ); - globalObject().property( internalObject ).setProperty( objName, property, QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration ); - const QString command = QString( "Object.defineProperty( %1, \"%2\", {get : function(){ var iobj= %3; iobj.invokableDeprecatedCall(\"" - " %1.%2 \"); return iobj.%4; },\ - enumerable : true,\ - configurable : false} );" ) - .arg( parent, name, internalObject, objName ); - evaluate( command ); -} - -void -AmarokScriptEngine::invokableDeprecatedCall( const QString &call ) -{ - warning() << "Deprecated function " + call; - emit deprecatedCall( call ); -} - -void -AmarokScriptEngine::setTimeout( const QScriptValue &function, int time, const QScriptValue &thisObject, const QScriptValue &args ) -{ - QTimer *timer = new QTimer( this ); - timer->setSingleShot( true ); - timer->setInterval( time ); - m_callbacks[timer] = QScriptValueList() << function << thisObject << args; - connect( timer, &QTimer::timeout, this, &AmarokScriptEngine::slotTimeout ); - timer->start(); -} - -void -AmarokScriptEngine::slotTimeout() -{ - QObject *timer = sender(); - if( !timer ) - return; - - QScriptValueList args; - QScriptValue thisObject; - if( m_callbacks[timer].size() > 1 ) - { - thisObject = m_callbacks[timer][1]; - if( m_callbacks[timer].size() == 3 ) - for ( quint32 i = 0; i < m_callbacks[timer][2].property("length").toUInt32(); ++i ) - args << m_callbacks[timer][2].property( i ); - } - m_callbacks[timer][0].call( thisObject, args ); - m_callbacks.remove( timer ); - timer->deleteLater(); -} - -QScriptValue -AmarokScriptEngine::enumObject( const QMetaEnum &metaEnum ) -{ - QScriptValue enumObj = newObject(); - for( int i = 0; i< metaEnum.keyCount(); ++i ) - enumObj.setProperty( metaEnum.key(i), QScriptEngine::toScriptValue( metaEnum.value(i) ) ); - return enumObj; -} - - -AmarokScriptEngine::~AmarokScriptEngine() -{} - diff --git a/src/scripting/scriptengine/exporters/CollectionTypeExporter.h b/src/scripting/scriptengine/exporters/CollectionTypeExporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/CollectionTypeExporter.h +++ /dev/null @@ -1,240 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef COLLECTIONTYPE_EXPORTER_H -#define COLLECTIONTYPE_EXPORTER_H - -#include "amarok_export.h" -#include "core/meta/forward_declarations.h" -#include "core/collections/Collection.h" -#include "core/collections/CollectionLocation.h" - -#include -#include -#include -#include -#include - -namespace Collections -{ - class Collection; - class QueryMaker; -} -class QScriptEngine; -class QScriptValue; - -namespace AmarokScript -{ - // SCRIPTDOX PROTOTYPE Collections::Collection Collection - #ifdef DEBUG - class AMAROK_EXPORT - #else - class - #endif - CollectionPrototype : public QObject - { - Q_OBJECT - - /** - * Indicates whether user can choose track file path within this collection. - */ - Q_PROPERTY( bool isOrganizable READ isOrganizable ) - - /** - * Indicates whether this collection can be written to (tracks added, removed). - */ - Q_PROPERTY( bool isWritable READ isWritable ) - - /** - * A unique identifier for this collection - */ - Q_PROPERTY( QString collectionId READ collectionId ) - - /** - * A user visible name for this collection. - */ - Q_PROPERTY( QString prettyName READ toString ) - - /** - * The used space on this collection. - */ - Q_PROPERTY( float usedCapacity READ usedCapacity ) - - /** - * The total storage capacity the collection. - */ - Q_PROPERTY( float totalCapacity READ totalCapacity ) - - /** - * Indicates whether this collection still exists. - */ - Q_PROPERTY( bool isValid READ isValid ) - - /** - * An icon representing this collection. - */ - Q_PROPERTY( QIcon icon READ icon ) - - /** - * Indicates whether this collection can be queried using a - * QueryMaker object - */ - Q_PROPERTY( bool isQueryable READ isQueryable ) - - /** - * Indicates whether the collection is viewable in the browser. - */ - Q_PROPERTY( bool isViewable READ isViewable ) - - /** - * Indicated whether tracks may be transcoded when copying tracks to this collection. - */ - Q_PROPERTY( bool supportsTranscode READ supportsTranscode ) - - /** - * A displayable string representation of the collection's location. use the return - * value of this method to display the collection location to the user. - * @return a string representation of the collection location - */ - Q_PROPERTY( QString prettyLocation READ prettyLocation ) - - /** - * Returns a list of machine usable string*s representingthe collection location. - * For example, a local collection would return a list of paths where tracks are - * stored, while an Ampache collection would return a list with one string - * containing the URL of an ampache server. Empty for collections like iPod collection and - * MTP devices. - */ - Q_PROPERTY( QStringList actualLocation READ actualLocation ) - - public: - static void init( QScriptEngine *engine ); - CollectionPrototype( Collections::Collection *collection ); - Collections::Collection* data() const { return m_collection.data(); } - - /** - * Copy a list of tracks to the destination collection - */ - Q_INVOKABLE void copyTracks( const Meta::TrackList &tracks, Collections::Collection *targetCollection ); - - /** - * Copy a single track to the destination collection - */ - Q_INVOKABLE void copyTracks( const Meta::TrackPtr track, Collections::Collection *targetCollection ); - - /** - * Convenience method for copying tracks based on QueryMaker results, - * takes ownership of the @param qm (The querymaker is rendered invalid - * after copying). - * @see copyTracks( Meta::TrackList, CollectionLocation* ) - */ - Q_INVOKABLE void queryAndCopyTracks( Collections::QueryMaker *queryMaker, Collections::Collection *targetCollection ); - - /** - * Copy an array of tracks to the destination collection. - */ - Q_INVOKABLE void moveTracks( const Meta::TrackList &tracks, Collections::Collection *targetCollection ); - - /** - * Move a single track to the destination collection. - */ - Q_INVOKABLE void moveTracks( const Meta::TrackPtr track, Collections::Collection *targetCollection ); - - /** - * Convenience method for moving tracks based on QueryMaker results, - * takes ownership of the @param qm (The querymaker is rendered invalid - * after moving). - * @see moveTracks( Meta::TrackList, CollectionLocation* ) - */ - Q_INVOKABLE void queryAndMoveTracks( Collections::QueryMaker *queryMaker, Collections::Collection *targetCollection ); - - /** - * Remove an array of tracks from collection. - */ - Q_INVOKABLE void removeTracks( const Meta::TrackList &trackList ); - - /** - * Remove single track from collection. - */ - Q_INVOKABLE void removeTracks( const Meta::TrackPtr track ); - - /** - * Convenience method for removing tracks selected by QueryMaker, - * takes ownership of the @param qm (The querymaker is rendered invalid - * after the removal). - * @see removeTracks( Meta::TrackList ) - */ - Q_INVOKABLE void queryAndRemoveTracks( Collections::QueryMaker *qm ); - - /** - * A querymaker object for querying the collection. - */ - Q_INVOKABLE Collections::QueryMaker *queryMaker(); - - private: - QPointer m_collection; - - bool isOrganizable() const; - bool isWritable() const; - QString collectionId() const; - QString toString() const; - float usedCapacity() const; - float totalCapacity() const; - bool isValid() const; - QIcon icon() const; - bool isQueryable() const; - bool isViewable() const ; - bool supportsTranscode() const; - QString prettyLocation() const; - QStringList actualLocation() const; - - Meta::TrackList removeInvalidTracks( const Meta::TrackList &tracks ); - - Q_SIGNALS: - /** - * This signal will be emitted after major changes to the collection - * e.g. new songs where added, or an album changed - * from compilation to non-compilation (and vice versa) - * it will not be emitted on minor changes (e.g. the tags of a song were changed) - * - * This means that previously done searches can no longer - * be considered valid. - */ - void updated(); - - /** - * Emitted when this collection is removed. - */ - void removed(); - - /** - * Emitted when a copy operation from/ to this collection has finished. - */ - void finishCopy(); - - /** - * Emitted when a removal operation on this collection has finished. - */ - void finishRemove(); - - /** - * Emitted when a copy/ move operation from/ to this collection was aborted. - */ - void aborted(); - }; -} - -#endif diff --git a/src/scripting/scriptengine/exporters/CollectionTypeExporter.cpp b/src/scripting/scriptengine/exporters/CollectionTypeExporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/CollectionTypeExporter.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "CollectionTypeExporter.h" - -#include "core/meta/Meta.h" -#include "core-impl/collections/support/CollectionManager.h" -#include "core/collections/Collection.h" -#include "core/collections/CollectionLocation.h" -#include "core/capabilities/TranscodeCapability.h" -#include "core/transcoding/TranscodingController.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include -#include -#include - -using namespace AmarokScript; - -using Collections::Collection; -using Collections::QueryMaker; - -#define GET_COLLECTION( returnVal ) Collection *collection = m_collection.data(); if( !collection ) return returnVal; - -void -CollectionPrototype::init( QScriptEngine *engine ) -{ - qScriptRegisterMetaType( engine, toScriptValue, fromScriptValue ); - qScriptRegisterMetaType( engine, toScriptArray, fromScriptArray ); -} - -//script invokable - -void -CollectionPrototype::copyTracks( const Meta::TrackPtr track, Collection* targetCollection ) -{ - copyTracks( Meta::TrackList() << track, targetCollection ); -} - -void -CollectionPrototype::copyTracks( const Meta::TrackList &tracks, Collection* targetCollection ) -{ - GET_COLLECTION() - if( !targetCollection ) - return; - collection->location()->prepareCopy( removeInvalidTracks( tracks ), targetCollection->location() ); -} - -void -CollectionPrototype::queryAndCopyTracks( QueryMaker *queryMaker, Collection* targetCollection ) -{ - GET_COLLECTION() - if( !queryMaker || !targetCollection ) - return; - collection->location()->prepareCopy( queryMaker, targetCollection->location() ); -} - -void -CollectionPrototype::moveTracks( const Meta::TrackPtr track, Collection *targetCollection ) -{ - moveTracks( Meta::TrackList() << track, targetCollection ); -} - -void -CollectionPrototype::moveTracks( const Meta::TrackList &tracks, Collection *targetCollection ) -{ - GET_COLLECTION() - if( !targetCollection ) - return; - collection->location()->prepareMove( removeInvalidTracks( tracks ), targetCollection->location() ); -} - -void -CollectionPrototype::queryAndMoveTracks( QueryMaker *queryMaker, Collection *targetCollection ) -{ - GET_COLLECTION() - if( !queryMaker || !targetCollection ) - return; - collection->location()->prepareMove( queryMaker, targetCollection->location() ); -} - -void -CollectionPrototype::removeTracks( const Meta::TrackList &list ) -{ - GET_COLLECTION() - collection->location()->prepareRemove( removeInvalidTracks( list ) ); -} - -void CollectionPrototype::removeTracks( const Meta::TrackPtr track ) -{ - removeTracks( Meta::TrackList() << track ); -} - -void -CollectionPrototype::queryAndRemoveTracks( QueryMaker* queryMaker ) -{ - GET_COLLECTION() - if( !queryMaker ) - return; - collection->location()->prepareRemove( queryMaker ); -} - -QueryMaker* -CollectionPrototype::queryMaker() -{ - GET_COLLECTION( 0 ); - return collection->queryMaker(); -} - -//private methods - -QIcon -CollectionPrototype::icon() const -{ - GET_COLLECTION( QIcon() ) - return collection->icon(); -} - -QString -CollectionPrototype::collectionId() const -{ - GET_COLLECTION( QString() ); - return collection->collectionId(); -} - -bool -CollectionPrototype::isOrganizable() const -{ - GET_COLLECTION( false ); - return collection->isOrganizable(); -} - -bool -CollectionPrototype::isWritable() const -{ - GET_COLLECTION( false ); - return collection->isWritable(); -} - -QString -CollectionPrototype::toString() const -{ - GET_COLLECTION( QString() ); - return collection->prettyName(); -} - -float -CollectionPrototype::totalCapacity() const -{ - GET_COLLECTION( 0.0 ) - return collection->totalCapacity(); -} - -float -CollectionPrototype::usedCapacity() const -{ - GET_COLLECTION( 0.0 ) - return collection->usedCapacity(); -} - -bool -CollectionPrototype::isValid() const -{ - GET_COLLECTION( false ) - return true; -} - -bool -CollectionPrototype::isQueryable() const -{ - if( CollectionManager::instance()->collectionStatus( collectionId() ) & - CollectionManager::CollectionQueryable ) - return true; - return false; -} - -bool -CollectionPrototype::isViewable() const -{ - if( CollectionManager::instance()->collectionStatus( collectionId() ) & - CollectionManager::CollectionViewable ) - return true; - return false; -} - -bool -CollectionPrototype::supportsTranscode() const -{ - GET_COLLECTION( false ) - if( !collection->has() ) - return false; - Transcoding::Controller *tcC = Amarok::Components::transcodingController(); - if( tcC && !tcC->availableEncoders().isEmpty() ) - return true; - return false; -} - -//private - -CollectionPrototype::CollectionPrototype( Collection *collection ) -: QObject( 0 ) //script owned -, m_collection( collection ) -{ - connect( collection, SIGNAL(updated()), SIGNAL(updated()) ); - connect( collection->location(), SIGNAL(aborted()), SIGNAL(aborted()) ); - connect( collection->location(), SIGNAL(finishCopy()), SIGNAL(finishCopy()) ); - connect( collection->location(), SIGNAL(finishRemove()), SIGNAL(finishRemove()) ); - connect( collection, SIGNAL(remove()), SIGNAL(removed()) ); -} - -Meta::TrackList -CollectionPrototype::removeInvalidTracks(const Meta::TrackList& tracks) -{ - Meta::TrackList cleaned; - foreach( const Meta::TrackPtr &track, tracks ) - { - if( track ) - cleaned << track; - } - return cleaned; -} - -QString -CollectionPrototype::prettyLocation() const -{ - GET_COLLECTION( QString() ) - return collection->location()->prettyLocation(); -} - -QStringList -CollectionPrototype::actualLocation() const -{ - GET_COLLECTION( QStringList() ) - return collection->location()->actualLocation(); -} - -#undef GET_COLLECTION diff --git a/src/scripting/scriptengine/exporters/MetaTypeExporter.h b/src/scripting/scriptengine/exporters/MetaTypeExporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/MetaTypeExporter.h +++ /dev/null @@ -1,209 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2013-14 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef METATYPE_EXPORTER_H -#define METATYPE_EXPORTER_H - -#include "amarok_export.h" -#include "core/meta/Meta.h" -#include "core/meta/Observer.h" - -#include -#include -#include - -class QScriptContext; -class QScriptEngine; -class QScriptValue; - -typedef QMap StringMap; -namespace Meta -{ - typedef QHash FieldHash; -} - -namespace AmarokScript -{ - // SCRIPTDOX PROTOTYPE Meta::TrackPtr Track - /** - * Represents track objects. - * Create new tracks using: - * new Track( ) - * - * Tracks are loaded asynchronously. If you wish to read or write a track's metadata, you must ensure that it has loaded. - * This can my done as follows: - * - * function myFunction( track ) - * { - * // do stuff here - * } - * var track = new Track( new QUrl("file:///my/track/url/MyTrack.ext") ); - * if( !track.isLoaded ) - * track.loaded.connect( myFunction ); - * else - * myFunction( track ); - * - */ - #ifdef DEBUG - class AMAROK_EXPORT - #else - class - #endif - MetaTrackPrototype : public QObject, public Meta::Observer - { - Q_OBJECT - - Q_PROPERTY( QString title WRITE setTitle READ title ) - Q_PROPERTY( int sampleRate READ sampleRate ) - Q_PROPERTY( int bitrate READ bitrate ) - Q_PROPERTY( double score WRITE setScore READ score ) - Q_PROPERTY( int rating WRITE setRating READ rating ) - Q_PROPERTY( bool inCollection READ inCollection ) - Q_PROPERTY( QString type READ type ) - Q_PROPERTY( int length READ length ) - Q_PROPERTY( int fileSize READ fileSize ) - Q_PROPERTY( int trackNumber WRITE setTrackNumber READ trackNumber ) - Q_PROPERTY( int discNumber WRITE setDiscNumber READ discNumber ) - Q_PROPERTY( int playCount READ playCount ) - Q_PROPERTY( bool playable READ playable ) - Q_PROPERTY( QString album WRITE setAlbum READ album ) - Q_PROPERTY( QString artist WRITE setArtist READ artist ) - Q_PROPERTY( QString composer WRITE setComposer READ composer ) - Q_PROPERTY( QString genre WRITE setGenre READ genre ) - Q_PROPERTY( int year WRITE setYear READ year ) - Q_PROPERTY( QString comment WRITE setComment READ comment ) - Q_PROPERTY( QString path READ path ) - Q_PROPERTY( bool isValid READ isValid ) - Q_PROPERTY( bool isEditable READ isEditable ) - Q_PROPERTY( QString lyrics WRITE setLyrics READ lyrics ) - Q_PROPERTY( QString imageUrl WRITE setImageUrl READ imageUrl ) - Q_PROPERTY( QString url READ url ) - Q_PROPERTY( double bpm READ bpm ) // setter not yet available in Meta::Track - Q_PROPERTY( Meta::FieldHash tags READ tags ) - - /** - * Tracks may be loaded asynchronously, indicates whether the track has been loaded and its full metadata available . - * Connect to the trackLoaded signal to be notified when it is. - */ - Q_PROPERTY( bool isLoaded READ isLoaded ) - Q_PROPERTY( QImage embeddedCover READ embeddedCover WRITE setEmbeddedCover ) - - public: - static void init( QScriptEngine *engine ); - Meta::TrackPtr data() const { return m_track; } - MetaTrackPrototype( const Meta::TrackPtr &track ); - static QScriptValue trackCtor( QScriptContext *context, QScriptEngine *engine ); - static QScriptValue toScriptTagMap( QScriptEngine *engine, const Meta::FieldHash &map ); - static void fromScriptTagMap( const QScriptValue &value, Meta::FieldHash &map ); - - /** - * Returns the image for the album, usually the cover image, if it has one, - * or an undefined value otherwise. - */ - Q_INVOKABLE QScriptValue imagePixmap( int size = 1 ) const; - - /** - * Asynchronously write the passed tags to the track. - * Fields like title, artist, etc. except for lyrics are already written to tags - * depending on user preferences. Use this to override preferences or for - * external tracks. - * - * @param changes The tags you'd like to write to the track. The existing tag for - * that field will be deleted. - * @param respectConfig Whether to respect the user's preferences of writing tags to tracks. - * - * For example, - * var tags = {}; - * tags["lyrics"] = "My lyrics"; - * tags["title"]= "My Song"; - * track.changeTags( tags ); - */ - Q_INVOKABLE void changeTags( const Meta::FieldHash &changes, bool respectConfig = true ); - - Q_SIGNALS: - /** - * Emitted when a track has finished loading. - */ - void loaded( Meta::TrackPtr ); - - private: - Meta::TrackPtr m_track; - - void metadataChanged( Meta::TrackPtr track ) override; - void metadataChanged( Meta::ArtistPtr artist ) override { Q_UNUSED( artist ) } - void metadataChanged( Meta::AlbumPtr album ) override { Q_UNUSED( album ) } - void metadataChanged( Meta::GenrePtr genre ) override { Q_UNUSED( genre ) } - void metadataChanged( Meta::ComposerPtr composer ) override { Q_UNUSED( composer ) } - void metadataChanged( Meta::YearPtr year ) override { Q_UNUSED( year ) } - - QScriptEngine *m_engine; - - int sampleRate() const; - int bitrate() const; - double score() const; - int rating() const; - bool inCollection() const; - QString type() const; - qint64 length() const; - int fileSize() const; - int trackNumber() const; - int discNumber() const; - int playCount() const; - bool playable() const; - QString album() const; - QString artist() const; - QString composer() const; - QString genre() const; - int year() const; - QString comment() const; - QString path() const; - bool isValid() const; - bool isEditable(); - QString lyrics() const; - QString title() const; - QString imageUrl() const; - QString url() const; - double bpm() const; - bool isLoaded() const; - Meta::FieldHash tags() const; - QImage embeddedCover() const; - - void setScore( double score ); - void setRating( int rating ); - void setTrackNumber( int number ); - void setDiscNumber( int number ); - void setAlbum( const QString &album ); - void setArtist( const QString &artist ); - void setComposer( const QString &composer ); - void setGenre( const QString &genre ); - void setYear( int year ); - void setComment( const QString &comment ); - void setLyrics( const QString &lyrics ); - void setTitle( const QString& name ); - void setImageUrl( const QString& imageUrl ); - - /** - * Check if the track has loaded and is local. - */ - bool isLoadedAndLocal() const; - void setEmbeddedCover( const QImage &image ); - }; -} - -Q_DECLARE_METATYPE( Meta::FieldHash ) - -#endif diff --git a/src/scripting/scriptengine/exporters/MetaTypeExporter.cpp b/src/scripting/scriptengine/exporters/MetaTypeExporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/MetaTypeExporter.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008 Ian Monroe * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "MetaTypeExporter.h" - -#include "core/support/Debug.h" -#include "core/meta/Meta.h" -#include "core/meta/support/MetaConstants.h" -#include "core/meta/Statistics.h" -#include "core/meta/TrackEditor.h" -#include "core-impl/collections/support/CollectionManager.h" -#include "core-impl/collections/support/jobs/WriteTagsJob.h" -#include "core-impl/meta/proxy/MetaProxy.h" -#include "MetaTagLib.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include -#include - -#include -#include - -Q_DECLARE_METATYPE( StringMap ) - -using namespace AmarokScript; - -#define CHECK_TRACK( X ) if( !m_track ){ warning() << "Invalid track!"; return X; }; -#define GET_TRACK_EC( X ) CHECK_TRACK() \ - Meta::TrackEditorPtr ec = m_track->editor(); \ - if( ec ) \ - { \ - X; \ - } - -void -MetaTrackPrototype::init( QScriptEngine *engine ) -{ - qScriptRegisterMetaType( engine, toScriptValue, fromScriptValue ); - qScriptRegisterMetaType( engine, toScriptArray, fromScriptArray ); - qScriptRegisterMetaType( engine, toScriptMap, fromScriptMap ); - qScriptRegisterMetaType( engine, toScriptTagMap, fromScriptTagMap ); - engine->globalObject().setProperty( "Track", engine->newFunction( trackCtor ) ); -} - -QScriptValue -MetaTrackPrototype::trackCtor( QScriptContext *context, QScriptEngine *engine ) -{ - if( context->argumentCount() < 1 ) - return context->throwError( QScriptContext::SyntaxError, "Not enough arguments! Pass the track url." ); - - QUrl url( qscriptvalue_cast( context->argument( 0 ) ) ); - if( !url.isValid() ) - return context->throwError( QScriptContext::TypeError, "Invalid QUrl" ); - - MetaProxy::TrackPtr proxyTrack( new MetaProxy::Track( url ) ); - proxyTrack->setTitle( url.fileName() ); // set temporary name - return engine->newQObject( new MetaTrackPrototype( Meta::TrackPtr( proxyTrack.data() ) ) - , QScriptEngine::ScriptOwnership - , QScriptEngine::ExcludeSuperClassContents ); -} - -MetaTrackPrototype::MetaTrackPrototype( const Meta::TrackPtr &track ) -: QObject( 0 ) -, m_track( track ) -{ -} - -Meta::FieldHash -MetaTrackPrototype::tags() const -{ - if( !isLoadedAndLocal() ) - return Meta::FieldHash(); - - return Meta::Tag::readTags( m_track->playableUrl().path() ); -} - -int -MetaTrackPrototype::sampleRate() const -{ - CHECK_TRACK( 0 ) - return m_track->sampleRate(); -} - -int -MetaTrackPrototype::bitrate() const -{ - CHECK_TRACK( 0 ) - return m_track->bitrate(); -} - -double -MetaTrackPrototype::score() const -{ - CHECK_TRACK( 0.0 ) - return m_track->statistics()->score(); -} - -int -MetaTrackPrototype::rating() const -{ - CHECK_TRACK( 0 ) - return m_track->statistics()->rating(); -} - -bool -MetaTrackPrototype::inCollection() const -{ - CHECK_TRACK( false ) - return m_track->inCollection(); -} - -QString -MetaTrackPrototype::type() const -{ - CHECK_TRACK( QString() ) - return m_track->type(); -} - -qint64 -MetaTrackPrototype::length() const -{ - CHECK_TRACK( 0 ) - return m_track->length(); -} - -int -MetaTrackPrototype::fileSize() const -{ - CHECK_TRACK( 0 ) - return m_track->filesize(); -} - -int -MetaTrackPrototype::trackNumber() const -{ - CHECK_TRACK( 0 ) - return m_track->trackNumber(); -} - -int -MetaTrackPrototype::discNumber() const -{ - CHECK_TRACK( 0 ) - return m_track->discNumber(); -} - -int -MetaTrackPrototype::playCount() const -{ - CHECK_TRACK( 0 ) - return m_track->statistics()->playCount(); -} - -bool -MetaTrackPrototype::playable() const -{ - CHECK_TRACK( false ) - return m_track->isPlayable(); -} - -QString -MetaTrackPrototype::album() const -{ - CHECK_TRACK( QString() ) - return m_track->album() ? m_track->album()->prettyName() : QString(); -} - -QString -MetaTrackPrototype::artist() const -{ - CHECK_TRACK( QString() ) - return m_track->artist() ? m_track->artist()->prettyName() : QString(); -} - -QString -MetaTrackPrototype::composer() const -{ - CHECK_TRACK( QString() ) - return m_track->composer() ? m_track->composer()->prettyName() : QString(); -} - -QString -MetaTrackPrototype::genre() const -{ - CHECK_TRACK( QString() ) - return m_track->genre() ? m_track->genre()->prettyName() : QString(); -} - -int -MetaTrackPrototype::year() const -{ - CHECK_TRACK( 0 ) - return m_track->year() ? m_track->year()->year() : 0; -} - -QString -MetaTrackPrototype::comment() const -{ - CHECK_TRACK( QString() ) - return m_track->comment(); -} - -QString -MetaTrackPrototype::path() const -{ - CHECK_TRACK( QString() ) - return m_track->playableUrl().path(); -} - -QString -MetaTrackPrototype::title() const -{ - CHECK_TRACK ( QString() ) - return m_track->prettyName(); -} - -QString -MetaTrackPrototype::imageUrl() const -{ - CHECK_TRACK( QString() ) - return m_track->album() ? m_track->album()->imageLocation().toDisplayString() : QString(); -} - -QString -MetaTrackPrototype::url() const -{ - CHECK_TRACK( QString() ) - return m_track->playableUrl().url(); -} - -double -MetaTrackPrototype::bpm() const -{ - CHECK_TRACK( 0.0 ) - return m_track->bpm(); -} - -bool -MetaTrackPrototype::isLoaded() const -{ - MetaProxy::TrackPtr proxyTrack = MetaProxy::TrackPtr::dynamicCast( m_track ); - if( proxyTrack && !proxyTrack->isResolved() ) - { - const_cast( this )->Observer::subscribeTo( m_track ); - return false; - } - return true; -} - -QScriptValue -MetaTrackPrototype::imagePixmap( int size ) const -{ - CHECK_TRACK( QScriptValue() ) - return m_track->album() ? m_engine->toScriptValue( m_track->album()->image( size ) ) : QScriptValue(); -} - -bool -MetaTrackPrototype::isValid() const -{ - return m_track; -} - -bool -MetaTrackPrototype::isEditable() -{ - CHECK_TRACK( false ) - return m_track->editor(); // converts to bool nicely -} - -QString -MetaTrackPrototype::lyrics() const -{ - CHECK_TRACK( QString() ) - return m_track->cachedLyrics(); -} - -void -MetaTrackPrototype::setScore( double score ) -{ - CHECK_TRACK() - m_track->statistics()->setScore( score ); -} - -void -MetaTrackPrototype::setRating( int rating ) -{ - CHECK_TRACK() - m_track->statistics()->setRating( rating ); -} - -void -MetaTrackPrototype::setTrackNumber( int number ) -{ - GET_TRACK_EC( ec->setTrackNumber( number ) ) -} - -void -MetaTrackPrototype::setDiscNumber( int number ) -{ - GET_TRACK_EC( ec->setDiscNumber( number ) ) -} - -void -MetaTrackPrototype::setAlbum( const QString &album ) -{ - GET_TRACK_EC( ec->setAlbum( album ) ) -} - -void -MetaTrackPrototype::setArtist( const QString &artist ) -{ - GET_TRACK_EC( ec->setArtist( artist ) ) -} - -void -MetaTrackPrototype::setComposer( const QString &composer ) -{ - GET_TRACK_EC( ec->setComposer( composer ) ) -} - -void -MetaTrackPrototype::setGenre( const QString &genre ) -{ - GET_TRACK_EC( ec->setGenre( genre ) ) -} - -void -MetaTrackPrototype::setYear( int year ) -{ - GET_TRACK_EC( ec->setYear( year ) ) -} - -void -MetaTrackPrototype::setComment( const QString &comment ) -{ - GET_TRACK_EC( ec->setComment( comment ) ) -} - -void -MetaTrackPrototype::setLyrics( const QString &lyrics ) -{ - CHECK_TRACK() - m_track->setCachedLyrics( lyrics ); -} - -void -MetaTrackPrototype::setTitle( const QString& title ) -{ - GET_TRACK_EC( ec->setTitle( title ) ) -} - -void -MetaTrackPrototype::setImageUrl( const QString& imageUrl ) -{ - CHECK_TRACK() - if( m_track->album() ) - m_track->album()->setImage( QImage(imageUrl) ); -} - -void -MetaTrackPrototype::metadataChanged( Meta::TrackPtr track ) -{ - Observer::unsubscribeFrom( track ); - debug() << "Loaded track: " << track->prettyName(); - emit loaded( track ); -} - -void -MetaTrackPrototype::fromScriptTagMap( const QScriptValue &value, Meta::FieldHash &map ) -{ - QScriptValueIterator it( value ); - while( it.hasNext() ) - { - it.next(); - map[Meta::fieldForName( it.name() )] = it.value().toVariant(); - } -} - -QScriptValue -MetaTrackPrototype::toScriptTagMap( QScriptEngine *engine, const Meta::FieldHash &map ) -{ - QScriptValue scriptMap = engine->newObject(); - for( typename Meta::FieldHash::const_iterator it( map.constBegin() ); it != map.constEnd(); ++it ) - scriptMap.setProperty( Meta::nameForField( it.key() ), engine->toScriptValue( it.value() ) ); - return scriptMap; -} - -void -MetaTrackPrototype::changeTags( const Meta::FieldHash &changes, bool respectConfig ) -{ - if( !isLoadedAndLocal() ) - return; - - if( changes.isEmpty() ) - return; - WriteTagsJob *job = new WriteTagsJob( m_track->playableUrl().path(), changes, respectConfig ); - connect( job, &WriteTagsJob::done, job, &QObject::deleteLater ); - ThreadWeaver::Queue::instance()->enqueue( QSharedPointer(job) ); -} - -QImage -MetaTrackPrototype::embeddedCover() const -{ - if( isLoadedAndLocal() ) - return QImage(); - - return Meta::Tag::embeddedCover( m_track->playableUrl().path() ); -} - -void -MetaTrackPrototype::setEmbeddedCover( const QImage &image ) -{ - if( image.isNull() ) - return; -} - -bool -MetaTrackPrototype::isLoadedAndLocal() const -{ - CHECK_TRACK( false ); - if( !isLoaded() ) - { - debug() << "Track for url " << m_track->prettyUrl() << " not loaded yet!"; - return false; - } - if( !m_track->playableUrl().isLocalFile() ) - { - debug() << m_track->prettyName() + " is not a local file!"; - return false; - } - - return true; -} - -#undef GET_TRACK -#undef CHECK_TRACK -#undef GET_TRACK_EC - diff --git a/src/scripting/scriptengine/exporters/PlaylistExporter.h b/src/scripting/scriptengine/exporters/PlaylistExporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/PlaylistExporter.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef PLAYLIST_EXPORTER_H -#define PLAYLIST_EXPORTER_H - -#include "core/meta/forward_declarations.h" -#include "core/playlists/Playlist.h" - -#include -#include -#include - -class QScriptValue; -class QScriptEngine; - -namespace AmarokScript -{ - class AmarokScriptEngine; - - // SCRIPTDOX PROTOTYPE Playlists::Playlist Playlist - class PlaylistPrototype : public QObject, public Playlists::PlaylistObserver - { - Q_OBJECT - - /** - * Indicates whether this playlist object is valid. - */ - Q_PROPERTY( bool isValid READ isValid ) - - Q_PROPERTY( QString name READ toString WRITE setName ) - - /** - * @returns a unique identifier for a playlist. - */ - Q_PROPERTY( QUrl uidUrl READ uidUrl ) - - /** - * Returns the number of tracks this playlist contains. -1 if tracks are not - * yet loaded (call {@link #triggerFullLoad triggerFullLoad} or {@link #triggerQuickLoad triggerQuickLoad} in this case). - * If you get non-negative number, all tracks have been already loaded. - */ - Q_PROPERTY( int trackCount READ trackCount ) - - /** - * @returns the provider this playlist belongs to. - */ - Q_PROPERTY( Playlists::PlaylistProvider* provider READ provider ) - - public: - static void init( QScriptEngine *engine ); - explicit PlaylistPrototype( Playlists::PlaylistPtr playlist ); - Playlists::PlaylistPtr data() const { return m_playlist; } - - /** - * Returns loaded tracks in this playlist. Note that the list may be incomplete, - * to be sure, check that trackCount() is non-negative. Otherwise you have to call - * {@link #triggerFullLoad triggerFullLoad} or {@link #triggerQuickLoad triggerQuickLoad}. - */ - Q_INVOKABLE Meta::TrackList tracks(); - - /** - * Trigger asynchronous loading of this playlist. - * Postpone the finished() signal until the all constituent tracks have resolved - * and their full metadata is available. Also use this flag when you need to immediately play - * the tracks. - * Note: This means you'll just get the finished signal a bit later. - */ - Q_INVOKABLE void triggerFullLoad(); - - /** - * Trigger asynchronous loading of this playlist. - * Don't wait for constituent tracks to fully load before emitting the finished signal. - */ - Q_INVOKABLE void triggerQuickLoad(); - - /** - * Add the track to a certain position in the playlist - * - * @param position place to add this track. The default value -1 appends to - * the end. - * - * @note if the position is larger then the size of the playlist append to the - * end without generating an error. - */ - Q_INVOKABLE void addTrack( Meta::TrackPtr track, int position = -1 ); - - /** - * Remove track at the specified position - */ - Q_INVOKABLE void removeTrack( int position ); - - Q_INVOKABLE QString toString() const; - - private: - void trackAdded( Playlists::PlaylistPtr playlist, Meta::TrackPtr track, int position ) override; - void trackRemoved( Playlists::PlaylistPtr playlist, int position ) override; - - bool isValid() const; - QUrl uidUrl() const; - void setName( const QString &name ); - int trackCount() const; - Playlists::PlaylistProvider *provider() const; - - QScriptEngine *m_engine; - Playlists::PlaylistPtr m_playlist; - - Q_SIGNALS: - void loaded( Meta::TrackList tracks ); - void addedTrack( Meta::TrackPtr track, int position ); - void removedTrack( int position ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/exporters/PlaylistExporter.cpp b/src/scripting/scriptengine/exporters/PlaylistExporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/PlaylistExporter.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "PlaylistExporter.h" - -#include "core/collections/QueryMaker.h" -#include "core/meta/Meta.h" -#include "core/playlists/PlaylistProvider.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include -#include - -using namespace AmarokScript; - -void -PlaylistPrototype::init( QScriptEngine *engine ) -{ - qScriptRegisterMetaType( engine, - toScriptValue, - fromScriptValue ); - qScriptRegisterMetaType( engine, toScriptArray, fromScriptArray ); -} - -// script invokable - -void -PlaylistPrototype::triggerFullLoad() -{ - TrackLoader *loader = new TrackLoader( TrackLoader::FullMetadataRequired ); - loader->init( Playlists::PlaylistList() << m_playlist ); - connect( loader, SIGNAL(finished(Meta::TrackList)), SIGNAL(loaded(Meta::TrackList)) ); -} - -void -PlaylistPrototype::triggerQuickLoad() -{ - TrackLoader *loader = new TrackLoader(); - connect( loader, SIGNAL(finished(Meta::TrackList)), SIGNAL(loaded(Meta::TrackList)) ); -} - -void -PlaylistPrototype::trackAdded( Playlists::PlaylistPtr playlist, Meta::TrackPtr track, int position ) -{ - Q_UNUSED( playlist ) - emit addedTrack( track, position ); -} - -void -PlaylistPrototype::trackRemoved( Playlists::PlaylistPtr playlist, int position ) -{ - Q_UNUSED( playlist ) - emit removedTrack( position ); -} - -void -PlaylistPrototype::addTrack( Meta::TrackPtr track, int position ) -{ - if( m_playlist ) - m_playlist->addTrack( track, position ); -} - -Playlists::PlaylistProvider* -PlaylistPrototype::provider() const -{ - if( m_playlist ) - return m_playlist->provider(); - return 0; -} - -void -PlaylistPrototype::removeTrack( int position ) -{ - if( m_playlist ) - m_playlist->removeTrack( position ); -} - -Meta::TrackList -PlaylistPrototype::tracks() -{ - if( m_playlist ) - return m_playlist->tracks(); - return Meta::TrackList(); -} - -// private - -PlaylistPrototype::PlaylistPrototype( Playlists::PlaylistPtr playlist ) -: QObject( 0 ) -, m_playlist( playlist ) -{ - PlaylistObserver::subscribeTo( playlist ); -} - -bool -PlaylistPrototype::isValid() const -{ - return m_playlist; -} - -QString -PlaylistPrototype::toString() const -{ - if( !m_playlist ) - return QString( "Invalid" ); - return m_playlist->name(); -} - -void -PlaylistPrototype::setName( const QString &name ) -{ - if( m_playlist ) - m_playlist->setName( name ); -} - -QUrl -PlaylistPrototype::uidUrl() const -{ - if( !m_playlist ) - return QUrl(); - return m_playlist->uidUrl(); -} - -int -PlaylistPrototype::trackCount() const -{ - return m_playlist->trackCount(); -} diff --git a/src/scripting/scriptengine/exporters/PlaylistProviderExporter.h b/src/scripting/scriptengine/exporters/PlaylistProviderExporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/PlaylistProviderExporter.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef PLAYLISTPROVIDER_TYPE_EXPORTER_H -#define PLAYLISTPROVIDER_TYPE_EXPORTER_H - -#include "core/meta/forward_declarations.h" -#include "core/playlists/PlaylistProvider.h" - -#include -#include -#include -#include - -class QScriptEngine; -class QScriptValue; - - -namespace Playlists -{ - class Playlist; - - typedef AmarokSharedPointer PlaylistPtr; - typedef QList PlaylistList; -} - -class QIcon; - -namespace AmarokScript -{ - // SCRIPTDOX PROTOTYPE Playlists::PlaylistProvider PlaylistProvider - class PlaylistProviderPrototype : public QObject - { - Q_OBJECT - - /** - * Return true if this provider supports modification. - * i.e. whether addPlaylist(), renamePlaylist(), deletePlaylists() can - * be triggered. - */ - Q_PROPERTY( bool isWritable READ isWritable ) - - /** - * A user presentable name for this collection. Same as its {@link #toString toString}. - */ - Q_PROPERTY( QString prettyName READ toString ) - - /** - * Indicates whether this provider still exists. - */ - Q_PROPERTY( bool isValid READ isValid ) - - /** - * A nice icon for this playlist provider. - */ - Q_PROPERTY( QIcon icon READ icon ) - - /** - * @returns An integer that identifies the category of the offered playlists. - * Use the Amarok.PlaylistManager.PlaylistCategory enum. - */ - Q_PROPERTY( int category READ category ) - - /** - * @returns the number of playlists this provider has or a negative value if it - * can not determine that before loading them all. - */ - Q_PROPERTY( int playlistCount READ playlistCount ) - - public: - static void init( QScriptEngine *engine ); - explicit PlaylistProviderPrototype( Playlists::PlaylistProvider *provider ); - Playlists::PlaylistProvider* data() const { return m_provider.data(); } - - Q_INVOKABLE QString toString() const; - - /** - * @returns a list of playlists of this provider. If playlistCount is negative, - * this list may be incomplete. - */ - Q_INVOKABLE Playlists::PlaylistList playlists(); - - /** - * Copy a playlist to the provider. - */ - Q_INVOKABLE Playlists::PlaylistPtr addPlaylist( Playlists::PlaylistPtr playlist ); - - /** - * Rename a playlist of this provider. - */ - Q_INVOKABLE void renamePlaylist( Playlists::PlaylistPtr playlist, const QString &newName ); - - /** - * Deletes a list of playlists. - * @returns true if successful, false otherwise. - */ - Q_INVOKABLE bool deletePlaylists( const Playlists::PlaylistList &playlistlist ); - - /** - * UserPlaylistProvider function - */ - Q_INVOKABLE Playlists::PlaylistPtr save( const Meta::TrackList &tracks, const QString &name = QString() ); - - - private: - QPointer m_provider; - - bool isValid() const; - virtual bool isWritable() const; - QIcon icon() const; - int category() const; - int playlistCount() const; - - Q_SIGNALS: - void updated(); - void playlistAdded( Playlists::PlaylistPtr playlist ); - void playlistRemoved( Playlists::PlaylistPtr playlist ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/exporters/PlaylistProviderExporter.cpp b/src/scripting/scriptengine/exporters/PlaylistProviderExporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/PlaylistProviderExporter.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "PlaylistProviderExporter.h" - -#include "playlistmanager/PlaylistManager.h" -#include "core/playlists/PlaylistProvider.h" -#include "core-impl/playlists/providers/user/UserPlaylistProvider.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include - -#include -#include - -using namespace AmarokScript; - -PlaylistProviderPrototype::PlaylistProviderPrototype( Playlists::PlaylistProvider *provider ) -: QObject( 0 ) -, m_provider( provider ) -{} - -void -PlaylistProviderPrototype::init( QScriptEngine *engine ) -{ - qScriptRegisterMetaType( engine, toScriptValue, - fromScriptValue ); - qScriptRegisterMetaType< PlaylistProviderList >( engine, toScriptArray, fromScriptArray ); -} - -// script invokable - -Playlists::PlaylistPtr -PlaylistProviderPrototype::addPlaylist(Playlists::PlaylistPtr playlist) -{ - if( m_provider ) - return m_provider->addPlaylist( playlist ); - return Playlists::PlaylistPtr(); -} - -int -PlaylistProviderPrototype::category() const -{ - if( m_provider ) - return m_provider->category(); - return -1; -} - -bool -PlaylistProviderPrototype::deletePlaylists( const Playlists::PlaylistList &playlistlist ) -{ - return m_provider && m_provider->deletePlaylists( playlistlist ); -} - -Playlists::PlaylistList -PlaylistProviderPrototype::playlists() -{ - if( m_provider ) - return m_provider->playlists(); - return Playlists::PlaylistList(); -} - -void -PlaylistProviderPrototype::renamePlaylist( Playlists::PlaylistPtr playlist, const QString &newName ) -{ - if( m_provider ) - m_provider->renamePlaylist( playlist, newName ); -} - -Playlists::PlaylistPtr -PlaylistProviderPrototype::save( const Meta::TrackList &tracks, const QString &name ) -{ - Playlists::UserPlaylistProvider* playlist = dynamic_cast( m_provider.data() ); - if( playlist ) - return playlist->save( tracks, name ); - return Playlists::PlaylistPtr(); -} - -QString PlaylistProviderPrototype::toString() const -{ - if( m_provider ) - return m_provider->prettyName(); - return QString( "Invalid" ); -} - -// private - -bool -PlaylistProviderPrototype::isValid() const -{ - return m_provider; -} - -QIcon -PlaylistProviderPrototype::icon() const -{ - if( m_provider ) - return m_provider->icon(); - return QIcon(); -} - -bool -PlaylistProviderPrototype::isWritable() const -{ - return m_provider && m_provider->isWritable(); -} - -int -PlaylistProviderPrototype::playlistCount() const -{ - if( m_provider ) - return m_provider->playlistCount(); - return -1; -} diff --git a/src/scripting/scriptengine/exporters/QueryMakerExporter.h b/src/scripting/scriptengine/exporters/QueryMakerExporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/QueryMakerExporter.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef QUERYMAKER_EXPORTER_H -#define QUERYMAKER_EXPORTER_H - -#include "amarok_export.h" -#include "core/collections/QueryMaker.h" -#include "core/meta/Meta.h" - -#include -#include -#include - -namespace Collections -{ - class QueryMaker; -} -class QScriptEngine; -class QScriptValue; - -namespace AmarokScript -{ - // SCRIPTDOX PROTOTYPE Collections::QueryMaker QueryMaker - #ifdef DEBUG - class AMAROK_EXPORT - #else - class - #endif - QueryMakerPrototype : public QObject - { - Q_OBJECT - - /** - * Indicates whether this query maker object is valid. - */ - Q_PROPERTY( bool isValid READ isValid ) - - /** - * The current filter string. - */ - Q_PROPERTY( QString filter READ filter ) - - public: - static void init( QScriptEngine *engine ); - QueryMakerPrototype( Collections::QueryMaker *collection ); - ~QueryMakerPrototype(); - Collections::QueryMaker *data() const { return m_querymaker; } - - /** - * Starts the query. This method returns immediately. All processing is done in one or more - * separate worker thread(s). One of the newResultReady signals will be emitted at least once, - * followed by the queryDone() signal exactly once. - */ - Q_INVOKABLE void run(); - - /** - * Block until the query completes, returns the tracklist.. - */ - Q_INVOKABLE Meta::TrackList blockingRun(); - - /** - * Aborts a running query. - */ - Q_INVOKABLE void abort(); - - /** - * Add a filter query to this query maker. - */ - Q_INVOKABLE void addFilter( const QString &filter ); - - private: - QPointer m_querymaker; - QString m_filter; - Meta::TrackList m_result; - - bool isValid() const; - QString filter() const; - - private Q_SLOTS: - void slotResult( const Meta::TrackList &tracks ); - - Q_SIGNALS: - /** - * newResultReady will be emitted every time new results from the query maker are received. - * This signal can be emitted zero times (in case of no results) one (the usual case) or multiple times - * (e.g. in case when the result is received in several batches). - * The results will be terminated by a queryDone signal. - */ - void newResultReady( Meta::TrackList ); - - /** - * This signal is emitted after all the results have been submitted via zero or more newResultReady signals. - */ - void queryDone(); - }; -} - -#endif diff --git a/src/scripting/scriptengine/exporters/QueryMakerExporter.cpp b/src/scripting/scriptengine/exporters/QueryMakerExporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/QueryMakerExporter.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "QueryMakerExporter.h" - -#include "core-impl/collections/support/TextualQueryFilter.h" -#include "scripting/scriptengine/ScriptingDefines.h" - -#include -#include -#include - -using namespace AmarokScript; - -using Collections::QueryMaker; - -void -QueryMakerPrototype::init( QScriptEngine *engine ) -{ - qScriptRegisterMetaType( engine, toScriptValue, fromScriptValue ); -} - -// script invokable - -void -QueryMakerPrototype::addFilter( const QString &filter ) -{ - if( !m_querymaker ) - return; - Collections::addTextualFilter( m_querymaker.data(), filter ); - m_filter += filter + ' '; -} - -void -QueryMakerPrototype::run() -{ - if( !m_querymaker ) - return; - m_querymaker->setQueryType( Collections::QueryMaker::Track ); - m_querymaker->run(); -} - -Meta::TrackList -QueryMakerPrototype::blockingRun() -{ - if( !m_querymaker ) - return Meta::TrackList(); - QEventLoop loop; - connect( m_querymaker.data(), &Collections::QueryMaker::newTracksReady, this, &QueryMakerPrototype::slotResult ); - connect( m_querymaker.data(), &Collections::QueryMaker::queryDone, &loop, &QEventLoop::quit ); - run(); - loop.exec(); - return m_result; -} - -void -QueryMakerPrototype::abort() -{ - if( m_querymaker ) - m_querymaker->abortQuery(); -} - -//private - -QueryMakerPrototype::QueryMakerPrototype( QueryMaker *queryMaker ) -: QObject( 0 ) //engine ownership -, m_querymaker( queryMaker ) -{ - if( !queryMaker ) - return; - connect( queryMaker, &Collections::QueryMaker::newTracksReady, this, &QueryMakerPrototype::newResultReady ); - connect( queryMaker, &Collections::QueryMaker::queryDone, this, &QueryMakerPrototype::queryDone ); - queryMaker->setAutoDelete( true ); -} - -QString -QueryMakerPrototype::filter() const -{ - return m_filter; -} - -bool -QueryMakerPrototype::isValid() const -{ - return m_querymaker; -} - -void -QueryMakerPrototype::slotResult( const Meta::TrackList &tracks ) -{ - m_result << tracks; -} - -QueryMakerPrototype::~QueryMakerPrototype() -{ - if( m_querymaker ) - m_querymaker->deleteLater(); -} diff --git a/src/scripting/scriptengine/exporters/ScriptableBiasExporter.h b/src/scripting/scriptengine/exporters/ScriptableBiasExporter.h deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/ScriptableBiasExporter.h +++ /dev/null @@ -1,289 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef BIAS_EXPORTER_H -#define BIAS_EXPORTER_H - -#include "dynamic/Bias.h" -#include "dynamic/BiasFactory.h" - -#include -#include -#include -#include -#include - -class QScriptContext; -class QScriptEngine; - -namespace AmarokScript -{ - // SCRIPTDOX BiasFactory - class ScriptableBiasFactory : public QObject, public Dynamic::AbstractBiasFactory - { - Q_OBJECT - - /** - * Set whether this bias is enabled and visible in the dynamic playlist bias menu. - */ - Q_PROPERTY( bool enabled READ enabled WRITE setEnabled ) - - /** - * A user visible name for this bias - */ - Q_PROPERTY( QString name READ i18nName WRITE setI18nName ) // corresponds to i18name - - /** - * A unique identifier for this bias. - */ - Q_PROPERTY( QString identifier READ name WRITE setName ) - - /** - * A user visible description for this bias. - */ - Q_PROPERTY( QString description READ i18nDescription WRITE setI18nDescription ) - - /** - * Set a function returning widget appropriate for editing the bias, if needed. - * var obj = new ScriptableBias(); obj.widget = function( a ) { return new QLabel(\"dfdsf\"); }" - */ - Q_PROPERTY( QScriptValue widget READ widgetFunction WRITE setWidgetFunction ) - - Q_PROPERTY( QScriptValue fromXml READ fromXmlFunction WRITE setFromXmlFunction ) - - Q_PROPERTY( QScriptValue toXml READ toXmlFunction WRITE setToXmlFunction ) - - /** - * Set this to a function of signature: - * TrackSet ( const Meta::TrackList &playlist, int contextCount, int finalCount, QStringList universeUids ) - */ - Q_PROPERTY( QScriptValue matchingTracks READ matchingTracksFunction WRITE setMatchingTracksFunction ) - - /** - * bool trackMatches( int position, TrackList playlist, int contextCount ) - */ - Q_PROPERTY( QScriptValue trackMatches READ trackMatchesFunction WRITE setTrackMatchesFunction ) - - Q_PROPERTY( QScriptValue toStringFunction READ toStringFunction WRITE setToStringFunction ) - - Q_PROPERTY( QScriptValue init READ initFunction WRITE setInitFunction ) - - public: - static void init( QScriptEngine *engine ); - - QString i18nName() const override; - QString name() const override; - QString i18nDescription() const override; - QScriptValue initFunction() const; - QScriptValue fromXmlFunction() const; - QScriptValue matchingTracksFunction() const; - QScriptValue toXmlFunction() const; - QScriptValue toStringFunction() const; - QScriptValue trackMatchesFunction() const; - QScriptValue widgetFunction() const; - QScriptEngine *engine() const; - - public Q_SLOTS: - Dynamic::BiasPtr createBias() override; - - private: - static QScriptValue groupBiasCtor( QScriptContext *context, QScriptEngine *engine ); - static QScriptValue biasCtor( QScriptContext *context, QScriptEngine *engine ); - ScriptableBiasFactory( QScriptEngine *engine = 0, bool groupBias = false ); - ~ScriptableBiasFactory(); - - bool enabled() const; - void setEnabled( bool enabled ); - void setName( const QString &name ); - void setI18nName( const QString &i18nName ); - void setI18nDescription( const QString &description ); - void setInitFunction( const QScriptValue &value ); - void setWidgetFunction( const QScriptValue &value ); - void setFromXmlFunction( const QScriptValue &value ); - void setToXmlFunction( const QScriptValue &value ); - void setTrackMatchesFunction( const QScriptValue &value ); - void setMatchingTracksFunction( const QScriptValue &value ); - void setToStringFunction( const QScriptValue &value ); - - QScriptValue m_initFunction; - QString m_name; - QString m_i18nName; - QString m_description; - QScriptValue m_widgetFunction; - QScriptValue m_fromXmlFunction; - QScriptValue m_toXmlFunction; - QScriptValue m_matchingTracksFunction; - QScriptValue m_trackMatchesFunction; - QScriptValue m_toStringFunction; - bool m_groupBias; - QScriptEngine *m_engine; - bool m_enabled; - }; - - class ScriptableBias : public Dynamic::AbstractBias - { - Q_OBJECT - - public: - explicit ScriptableBias( ScriptableBiasFactory *biasProto ); - ~ScriptableBias() override; - QScriptValue scriptObject() { return m_biasObject; } - - public: - void fromXml( QXmlStreamReader *reader ) override; - void toXml(QXmlStreamWriter *writer) const override; - Dynamic::TrackSet matchingTracks( const Meta::TrackList &playlist, int contextCount, - int finalCount, const Dynamic::TrackCollectionPtr universe ) const override; - bool trackMatches( int position, const Meta::TrackList &playlist, int contextCount ) const override; - QString toString() const override; - QString name() const override; - void paintOperator( QPainter *painter, const QRect &rect, AbstractBias *bias ) override; - QWidget* widget( QWidget *parent = 0 ) override; - - private Q_SLOTS: - Dynamic::TrackSet slotMatchingTracks( const Meta::TrackList &playlist, int contextCount, - int finalCount, const Dynamic::TrackCollectionPtr universe ) const; - void removeBias(); - - public Q_SLOTS: - - /** This slot is called when the bias should discard cached results. - * This will be done in case a new playlist is requested for an updated - * collection. - */ - void invalidate() override; - - /** Call this function when this bias should be replaced by a new one. - * @param newBias The bias that replaces this bias. If you give - * an empty BiasPrt as argument the bias will be removed. - */ - void replace( Dynamic::BiasPtr newBias ) override; - - /** - * Call after an outstanding result is completed - */ - void ready( const Dynamic::TrackSet &trackSet ); - - private: - QPointer m_scriptBias; - QScriptEngine *m_engine; - QScriptValue m_biasObject; - }; - - /** - * A representation of a set of tracks, relative to a given universe set. - * Intersecting TrackSets from different universes is not a good idea. - */ - class TrackSetExporter : public QObject, public Dynamic::TrackSet - { - Q_OBJECT - - /** - * The number of songs contained in this trackSet. - */ - Q_PROPERTY( int count READ trackCount ) - - /** - * True if all of the tracks are included in the set. - */ - Q_PROPERTY( bool isFull READ isFull ) - - /** - * Returns true if the results of this track set are not yet available - */ - Q_PROPERTY( bool isOutstanding READ isOutstanding ) - - /** - * True if none of the tracks are included in the set. - */ - Q_PROPERTY( bool isEmpty READ isEmpty ) - - public: - static QScriptValue toScriptValue( QScriptEngine *engine, Dynamic::TrackSet const &trackSet ); - static void fromScriptValue( const QScriptValue &obj, Dynamic::TrackSet &trackSet ); - static QScriptValue trackSetConstructor( QScriptContext* context, QScriptEngine* engine ); - - /** - * Includes or excludes all tracks in the set. - * @param value If true set is set to "full". Else to "empty". - */ - Q_INVOKABLE void reset( bool value ); - - /** - * Returns true if the @param uid is included in the set - */ - Q_INVOKABLE bool containsUid( const QString& uid ) const; - - Q_INVOKABLE bool containsTrack( const Meta::TrackPtr track ) const; - - /** - * Returns the uids of a random track contains in this set - */ - Q_INVOKABLE Meta::TrackPtr getRandomTrack() const; - - /** - * Add the track @param track to the trackset. - */ - Q_INVOKABLE void uniteTrack( const Meta::TrackPtr &track ); - - /** - * Add the track @param track to the trackset. - */ - Q_INVOKABLE void uniteTrackSet( const Dynamic::TrackSet &trackSet ); - - /** - * Add the track @param track to the trackset. - */ - Q_INVOKABLE void uniteUids( const QStringList &uids ); - - /** - * Perform an intersection of the trackset with the set @param trackSet - */ - Q_INVOKABLE void intersectTrackSet( const Dynamic::TrackSet &trackSet ); - - /** - * Perform an intersection on this trackset with the tracksset represtente by @param uids - */ - Q_INVOKABLE void intersectUids( const QStringList &uids ); - - /** - * Subtraact the track @param track from this trackset. - */ - Q_INVOKABLE void subtractTrack( const Meta::TrackPtr &track ); - - /** - * Subtract the trackset @param trackSet from this trackset - */ - Q_INVOKABLE void subtractTrackSet( const Dynamic::TrackSet &trackSet ); - - /** - * Subtract the set represented by @param uids from this trackset - */ - Q_INVOKABLE void subtractUids( const QStringList &uids ); - - private: - static void init( QScriptEngine *engine ); - explicit TrackSetExporter( const Dynamic::TrackSet &trackSet ); - - friend class ScriptableBiasFactory; - }; -} - -Q_DECLARE_METATYPE( QXmlStreamReader* ) -Q_DECLARE_METATYPE( QXmlStreamWriter* ) -Q_DECLARE_METATYPE( AmarokScript::ScriptableBias* ) - -#endif diff --git a/src/scripting/scriptengine/exporters/ScriptableBiasExporter.cpp b/src/scripting/scriptengine/exporters/ScriptableBiasExporter.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/exporters/ScriptableBiasExporter.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Anmol Ahuja * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptableBias" - -#include "ScriptableBiasExporter.h" - -#include "core/support/Debug.h" -#include "core/meta/Meta.h" -#include "core-impl/collections/support/CollectionManager.h" - -#include -#include -#include -#include -#include -#include - -using namespace AmarokScript; - -void -ScriptableBiasFactory::init( QScriptEngine *engine ) -{ - TrackSetExporter::init( engine ); - engine->globalObject().setProperty( "BiasFactory", engine->newFunction( biasCtor ), - QScriptValue:: Undeletable | QScriptValue::ReadOnly ); - engine->globalObject().setProperty( "GroupBiasFactory", engine->newFunction( groupBiasCtor ), - QScriptValue:: Undeletable | QScriptValue::ReadOnly ); -} - -QScriptValue -ScriptableBiasFactory::biasCtor( QScriptContext *context, QScriptEngine *engine ) -{ - Q_UNUSED( context ) - const QScriptValue biasFactoryObject = engine->newQObject( new ScriptableBiasFactory( engine ) - , QScriptEngine::ScriptOwnership - , QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeChildObjects ); - return biasFactoryObject; -} - -QScriptValue -ScriptableBiasFactory::groupBiasCtor( QScriptContext *context, QScriptEngine *engine ) -{ - Q_UNUSED( context ) - ScriptableBiasFactory *factory = new ScriptableBiasFactory( engine, true ); - QScriptValue biasFactoryObject = engine->newQObject( factory - , QScriptEngine::ScriptOwnership - , QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeChildObjects ); - return biasFactoryObject; -} - -ScriptableBiasFactory::ScriptableBiasFactory( QScriptEngine *engine, bool groupBias ) -: QObject( engine ) -, m_groupBias( groupBias ) -, m_engine( engine ) -, m_enabled( false ) -{} - -ScriptableBiasFactory::~ScriptableBiasFactory() -{ - Dynamic::BiasFactory::instance()->removeBiasFactory( this ); -} - -Dynamic::BiasPtr -ScriptableBiasFactory::createBias() -{ - ScriptableBias *bias; - //if( m_groupBias ) - // return new ScriptableGroupBias( this ); - //else - bias = new ScriptableBias( this ); - Dynamic::BiasPtr biasPtr = Dynamic::BiasPtr( bias ); - QScriptValue biasObject = bias->scriptObject(); - if( m_initFunction.isFunction() ) - m_initFunction.call( biasObject, QScriptValueList() << biasObject ); - - return biasPtr; -} - -// private - -QScriptEngine* -ScriptableBiasFactory::engine() const -{ - return m_engine; -} - -void -ScriptableBiasFactory::setEnabled( bool enabled ) -{ - if( enabled ) - { - if( !m_enabled ) - Dynamic::BiasFactory::instance()->registerNewBiasFactory( this ); - } - else - Dynamic::BiasFactory::instance()->removeBiasFactory( this ); - m_enabled = enabled; -} - -bool -ScriptableBiasFactory::enabled() const -{ - return m_enabled; -} - -void -ScriptableBiasFactory::setName( const QString &name ) -{ - m_name = name; -} - -QString -ScriptableBiasFactory::name() const -{ - return m_name; -} - -QString -ScriptableBiasFactory::i18nName() const -{ - return m_i18nName; -} - -QString -ScriptableBiasFactory::i18nDescription() const -{ - return m_description; -} - -QScriptValue -ScriptableBiasFactory::initFunction() const -{ - return m_initFunction; -} - -void -ScriptableBiasFactory::setInitFunction( const QScriptValue &value ) -{ - m_initFunction = value; -} - -void -ScriptableBiasFactory::setI18nDescription( const QString &description ) -{ - m_description = description; -} - -void -ScriptableBiasFactory::setI18nName( const QString &i18nName ) -{ - m_i18nName = i18nName; -} - -QScriptValue -ScriptableBiasFactory::widgetFunction() const -{ - return m_widgetFunction; -} - -void -ScriptableBiasFactory::setWidgetFunction( const QScriptValue &value ) -{ - // throw exception? - //if( !value.isFunction() ) - m_widgetFunction = value; -} - -void -ScriptableBiasFactory::setFromXmlFunction( const QScriptValue &value ) -{ - m_fromXmlFunction = value; -} - -void -ScriptableBiasFactory::setToXmlFunction( const QScriptValue &value ) -{ - m_toXmlFunction = value; -} - -QScriptValue -ScriptableBiasFactory::fromXmlFunction() const -{ - return m_fromXmlFunction; -} - -QScriptValue -ScriptableBiasFactory::toXmlFunction() const -{ - return m_toXmlFunction; -} - -QScriptValue -ScriptableBiasFactory::matchingTracksFunction() const -{ - return m_matchingTracksFunction; -} - -void -ScriptableBiasFactory::setMatchingTracksFunction( const QScriptValue &value ) -{ - m_matchingTracksFunction = value; -} - -void -ScriptableBiasFactory::setTrackMatchesFunction( const QScriptValue &value ) -{ - m_trackMatchesFunction = value; -} - -QScriptValue -ScriptableBiasFactory::trackMatchesFunction() const -{ - return m_trackMatchesFunction; -} - -void -ScriptableBiasFactory::setToStringFunction( const QScriptValue &value ) -{ - m_toStringFunction = value; -} - -QScriptValue -ScriptableBiasFactory::toStringFunction() const -{ - return m_toStringFunction; -} - -/********************************************************************************* -// ScriptableBias -**********************************************************************************/ -void -ScriptableBias::toXml( QXmlStreamWriter *writer ) const -{ - if( m_scriptBias->toXmlFunction().isFunction() ) - m_scriptBias->fromXmlFunction().call( m_biasObject, - QScriptValueList() << m_engine->toScriptValue( writer ) ); - else - Dynamic::AbstractBias::toXml( writer ); -} - -void -ScriptableBias::fromXml( QXmlStreamReader *reader ) -{ - if( m_scriptBias->fromXmlFunction().isFunction() ) - m_scriptBias->fromXmlFunction().call( m_biasObject, - QScriptValueList() << m_engine->toScriptValue( reader ) ); - else - Dynamic::AbstractBias::fromXml( reader ); -} - -QWidget* -ScriptableBias::widget( QWidget *parent ) -{ - QWidget *widget = dynamic_cast( m_scriptBias->widgetFunction().call( m_biasObject, - m_scriptBias->engine()->newQObject( parent ) ).toQObject() ); - if( widget ) - return widget; - return Dynamic::AbstractBias::widget( parent ); -} - -void -ScriptableBias::invalidate() -{ - Dynamic::AbstractBias::invalidate(); -} - -Dynamic::TrackSet -ScriptableBias::matchingTracks( const Meta::TrackList &playlist, int contextCount, int finalCount, const Dynamic::TrackCollectionPtr universe ) const -{ - DEBUG_BLOCK - if( QThread::currentThread() == QCoreApplication::instance()->thread() ) - return slotMatchingTracks( playlist, contextCount, finalCount, universe ); - - Dynamic::TrackSet retVal; - Q_ASSERT( QMetaObject::invokeMethod( const_cast( this ), "slotMatchingTracks", Qt::BlockingQueuedConnection, - Q_RETURN_ARG( Dynamic::TrackSet, retVal), - Q_ARG( Meta::TrackList, playlist ), - Q_ARG( int, contextCount ), - Q_ARG( int, finalCount ), - Q_ARG( Dynamic::TrackCollectionPtr, universe ) - ) ); - debug() << "Returning trackSet, trackCount " << retVal.trackCount() << ", isOutstanding " << retVal.isOutstanding(); - return retVal; -} - -Dynamic::TrackSet -ScriptableBias::slotMatchingTracks( const Meta::TrackList &playlist, int contextCount, int finalCount, const Dynamic::TrackCollectionPtr universe ) const -{ - Q_ASSERT( QThread::currentThread() == QCoreApplication::instance()->thread() ); - if( m_scriptBias->matchingTracksFunction().isFunction() ) - { - QScriptValue trackSetVal = m_scriptBias->matchingTracksFunction().call( m_biasObject, - QScriptValueList() << m_engine->toScriptValue( playlist ) - << contextCount - << finalCount - << m_engine->toScriptValue( universe->uids() ) ); - TrackSetExporter *trackSetExporter = dynamic_cast( trackSetVal.toQObject() ); - if( trackSetExporter ) - return Dynamic::TrackSet( *trackSetExporter ); - } - debug() << "Invalid trackSet received"; - return Dynamic::TrackSet( universe, false ); -} - -QString -ScriptableBias::name() const -{ - QString name; - if( m_scriptBias ) - name = m_scriptBias->name(); - return name.isEmpty() ? Dynamic::AbstractBias::name() : name; -} - -void -ScriptableBias::ready( const Dynamic::TrackSet &trackSet ) -{ - debug() << "Received trackset, count: " << trackSet.trackCount() << "Is outstanding:" << trackSet.isOutstanding(); - emit resultReady( trackSet ); -} - -void -ScriptableBias::paintOperator( QPainter *painter, const QRect &rect, Dynamic::AbstractBias *bias ) -{ - Dynamic::AbstractBias::paintOperator( painter, rect, bias ); -} - -void -ScriptableBias::replace( Dynamic::BiasPtr newBias ) -{ - Dynamic::AbstractBias::replace( newBias ); -} - -QString -ScriptableBias::toString() const -{ - return m_scriptBias->toStringFunction().call( m_biasObject ).toString(); -} - -bool -ScriptableBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const -{ - if( m_scriptBias->trackMatchesFunction().isFunction() ) - return m_scriptBias->trackMatchesFunction().call( m_biasObject, - QScriptValueList() << position - << m_engine->toScriptValue( playlist ) - << contextCount - ).toBool(); - return true; -} - -ScriptableBias::ScriptableBias( ScriptableBiasFactory *biasProto ) -: m_scriptBias( biasProto ) -, m_engine( biasProto->engine() ) -{ - m_biasObject = m_engine->newQObject( this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater ); - connect( m_engine, &QObject::destroyed, this, &ScriptableBias::removeBias ); -} - -ScriptableBias::~ScriptableBias() -{} - -void -ScriptableBias::removeBias() -{ - replace( Dynamic::BiasPtr( new Dynamic::ReplacementBias( name() ) ) ); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// TrackSetExporter -///////////////////////////////////////////////////////////////////////////////////////// - -void -TrackSetExporter::init( QScriptEngine *engine ) -{ - qScriptRegisterMetaType( engine, toScriptValue, fromScriptValue ); - engine->globalObject().setProperty( "TrackSet", engine->newFunction( trackSetConstructor ), - QScriptValue:: Undeletable | QScriptValue::ReadOnly ); -} - -void -TrackSetExporter::fromScriptValue( const QScriptValue &obj, Dynamic::TrackSet &trackSet ) -{ - DEBUG_BLOCK - TrackSetExporter *trackSetProto = dynamic_cast( obj.toQObject() ); - if( !trackSetProto ) - trackSet = Dynamic::TrackSet( Dynamic::TrackCollectionPtr( new Dynamic::TrackCollection( QStringList() ) ), false ); - else - trackSet = *trackSetProto; -} - -QScriptValue -TrackSetExporter::toScriptValue( QScriptEngine *engine, const Dynamic::TrackSet &trackSet ) -{ - DEBUG_BLOCK - TrackSetExporter *trackProto = new TrackSetExporter( trackSet ); - QScriptValue val = engine->newQObject( trackProto, QScriptEngine::ScriptOwnership, - QScriptEngine::ExcludeSuperClassContents ); - return val; -} - -bool -TrackSetExporter::containsUid( const QString &uid ) const -{ - return Dynamic::TrackSet::contains( uid ); -} - - -QScriptValue -TrackSetExporter::trackSetConstructor( QScriptContext *context, QScriptEngine *engine ) -{ - DEBUG_BLOCK - - // if( !context->isCalledAsConstructor() ) throw exception? - Dynamic::TrackSet trackSet; - bool invalid = false; - switch( context->argumentCount() ) - { - case 0: - break; - - case 1: - { - TrackSetExporter *trackSetPrototype = dynamic_cast( context->argument( 0 ).toQObject() ); - if( trackSetPrototype ) - trackSet = Dynamic::TrackSet( *trackSetPrototype ); - else - invalid = true; - break; - } - - case 2: - if( context->argument( 1 ).isBool() ) - { - bool isFull = context->argument( 1 ).toBool(); - QScriptValue arg0 = context->argument( 0 ); - QStringList uidList; - Meta::TrackList trackList; - if( arg0.toVariant().canConvert() ) - { - uidList = arg0.toVariant().toStringList(); - Q_ASSERT( !arg0.toVariant().canConvert() ); - trackSet = Dynamic::TrackSet( Dynamic::TrackCollectionPtr( new Dynamic::TrackCollection( uidList ) ), isFull ); - } - else if( arg0.toVariant().canConvert() ) - { - debug() << "In Meta::Tracklist TrackSet ctor"; - trackList = qscriptvalue_cast( arg0 ); - foreach( const Meta::TrackPtr &track, trackList ) - { - if( track ) - uidList << track->uidUrl(); - } - trackSet = Dynamic::TrackSet( Dynamic::TrackCollectionPtr( new Dynamic::TrackCollection( uidList ) ), isFull ); - } - else - invalid = true; - } - else - invalid = true; - break; - - default: - invalid = true; - } - if( invalid ) - { - context->throwError( QScriptContext::SyntaxError, "Invalid arguments for TrackSet!" ); - return engine->undefinedValue(); - } - - const QScriptValue trackSetObject = engine->newQObject( new TrackSetExporter( trackSet ) - , QScriptEngine::ScriptOwnership - , QScriptEngine::ExcludeSuperClassContents ); - return trackSetObject; -} - -void -TrackSetExporter::reset( bool value ) -{ - Dynamic::TrackSet::reset( value ); -} - -void -TrackSetExporter::intersectTrackSet( const Dynamic::TrackSet &trackSet) -{ - Dynamic::TrackSet::intersect( trackSet ); -} - -void -TrackSetExporter::intersectUids( const QStringList &uids ) -{ - Dynamic::TrackSet::intersect( uids ); -} - -void -TrackSetExporter::subtractTrack( const Meta::TrackPtr &track ) -{ - Dynamic::TrackSet::subtract( track ); -} - -void -TrackSetExporter::subtractTrackSet( const Dynamic::TrackSet &trackSet ) -{ - Dynamic::TrackSet::subtract( trackSet ); -} - -void -TrackSetExporter::subtractUids( const QStringList &uids ) -{ - Dynamic::TrackSet::subtract( uids ); -} - -void -TrackSetExporter::uniteTrack( const Meta::TrackPtr &track ) -{ - Dynamic::TrackSet::unite( track ); -} - -void -TrackSetExporter::uniteTrackSet( const Dynamic::TrackSet &trackSet ) -{ - Dynamic::TrackSet::unite( trackSet ); -} - -void -TrackSetExporter::uniteUids( const QStringList &uids ) -{ - Dynamic::TrackSet::unite( uids ); -} - -Meta::TrackPtr -TrackSetExporter::getRandomTrack() const -{ - return CollectionManager::instance()->trackForUrl( QUrl( Dynamic::TrackSet::getRandomTrack() ) ); -} - -bool -TrackSetExporter::containsTrack( const Meta::TrackPtr track ) const -{ - return Dynamic::TrackSet::contains( track ); -} - -// private -TrackSetExporter::TrackSetExporter( const Dynamic::TrackSet &trackSet ) -: QObject( 0 ) -, TrackSet( trackSet ) -{} diff --git a/src/scripting/scriptmanager/ScriptItem.h b/src/scripting/scriptmanager/ScriptItem.h deleted file mode 100644 --- a/src/scripting/scriptmanager/ScriptItem.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2004-2010 Mark Kretschmann * - * Copyright (c) 2005 Seb Ruiz * - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPTITEM_H -#define AMAROK_SCRIPTITEM_H - -#include "amarok_export.h" -#include "scripting/scriptengine/AmarokScriptableServiceScript.h" -#include "scripting/scriptengine/ScriptingDefines.h" -#include "statusbar/PopupWidget.h" - -#include -#include - -#include - -namespace AmarokScript { - class AmarokScript; -} -class ScriptItem; -class QScriptContext; -class QScriptEngine; -class QTimerEvent; - -class ScriptTerminatorWidget : public PopupWidget -{ - Q_OBJECT -public: - explicit ScriptTerminatorWidget( const QString &message ); - -Q_SIGNALS: - void terminate(); -}; - -class ScriptItem : public QObject -{ - Q_OBJECT -public: - ScriptItem( QObject *parent, const QString &name, const QString &path, const KPluginInfo &info ); - virtual ~ScriptItem(); - - QString name() const { return m_name; } - AmarokScript::AmarokScriptEngine* engine() { return m_engine.data(); } - AmarokScript::ScriptableServiceScript* service() { return m_service.data(); } - QUrl url() const { return m_url; } - KPluginInfo info() const { return m_info; } - bool running() const { return m_running; } - QString specPath() const; - QString output() const { return m_output.join("\n"); } - - virtual bool start( bool silent ); - virtual void pause(); - void uninstall(); - -public Q_SLOTS: - void stop(); - - /** - * Warn the user about scripts calling deprecated API calls - */ - virtual void slotDeprecatedCall( const QString &call ); - -private Q_SLOTS: - virtual void timerEvent( QTimerEvent *event ); - -Q_SIGNALS: - void signalHandlerException(QScriptValue); - void evaluated( QString output ); - void uninstalled(); - -protected: - /** - * Initialize QScriptEngine and load wrapper classes - */ - virtual void initializeScriptEngine(); - virtual QString handleError( QScriptEngine *engine ); - -private: - QString m_name; - QUrl m_url; - KPluginInfo m_info; - QPointer m_engine; - /** Currently activated in the Script Manager */ - bool m_running; - bool m_evaluating; - QStringList m_log; - QPointer m_service; - QStringList m_output; - int m_runningTime; - int m_timerId; - QPointer m_popupWidget; -}; - -#endif /* AMAROK_SCRIPTITEM_H */ diff --git a/src/scripting/scriptmanager/ScriptItem.cpp b/src/scripting/scriptmanager/ScriptItem.cpp deleted file mode 100644 --- a/src/scripting/scriptmanager/ScriptItem.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2004-2010 Mark Kretschmann * - * Copyright (c) 2005-2007 Seb Ruiz * - * Copyright (c) 2006 Alexandre Pereira de Oliveira * - * Copyright (c) 2006 Martin Ellis * - * Copyright (c) 2007 Leo Franchi * - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2009 Jakob Kummerow * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptItem" - -#include "ScriptItem.h" - -#include "core/support/Amarok.h" -#include "core/support/Debug.h" -#include "core/support/Components.h" -#include "core/interfaces/Logger.h" -#include "MainWindow.h" -#include "amarokconfig.h" -#include "config.h" -#include "services/scriptable/ScriptableServiceManager.h" -#include "scripting/scriptengine/AmarokCollectionScript.h" -#include "scripting/scriptengine/AmarokScriptConfig.h" -#include "scripting/scriptengine/AmarokEngineScript.h" -#include "scripting/scriptengine/AmarokInfoScript.h" -#include "scripting/scriptengine/AmarokKNotifyScript.h" -#include "scripting/scriptengine/AmarokLyricsScript.h" -#include "scripting/scriptengine/AmarokNetworkScript.h" -#include "scripting/scriptengine/AmarokOSDScript.h" -#include "scripting/scriptengine/AmarokPlaylistScript.h" -#include "scripting/scriptengine/AmarokScript.h" -#include "scripting/scriptengine/AmarokScriptableServiceScript.h" -#include "scripting/scriptengine/AmarokServicePluginManagerScript.h" -#include "scripting/scriptengine/AmarokStatusbarScript.h" -#include "scripting/scriptengine/AmarokStreamItemScript.h" -#include "scripting/scriptengine/AmarokWindowScript.h" -#include "scripting/scriptengine/AmarokScriptXml.h" -#include "scripting/scriptengine/exporters/CollectionTypeExporter.h" -#include "scripting/scriptengine/exporters/MetaTypeExporter.h" -#include "scripting/scriptengine/exporters/QueryMakerExporter.h" -#include "scripting/scriptengine/exporters/ScriptableBiasExporter.h" -#include "scripting/scriptengine/ScriptImporter.h" -#include "scripting/scriptengine/ScriptingDefines.h" -#include "ScriptManager.h" - -#include -#include -#include -#include -#include -#include - -#include - -//////////////////////////////////////////////////////////////////////////////// -// ScriptTerminatorWidget -//////////////////////////////////////////////////////////////////////////////// - -ScriptTerminatorWidget::ScriptTerminatorWidget( const QString &message ) - : PopupWidget( 0 ) -{ - setFrameStyle( QFrame::StyledPanel | QFrame::Raised ); - - setContentsMargins( 4, 4, 4, 4 ); - - setMinimumWidth( 26 ); - setMinimumHeight( 26 ); - setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); - - QPalette p = QToolTip::palette(); - setPalette( p ); - - QLabel *alabel = new QLabel( message, this ); - alabel->setWordWrap( true ); - alabel->setTextFormat( Qt::RichText ); - alabel->setTextInteractionFlags( Qt::TextBrowserInteraction ); - alabel->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred ); - alabel->setPalette( p ); - - QPushButton *button = new QPushButton( i18n( "Terminate" ), this ); - button->setPalette(p);; - connect( button, &QAbstractButton::clicked, this, &ScriptTerminatorWidget::terminate ); - auto closeItem = KStandardGuiItem::close(); - button = new QPushButton( closeItem.icon(), closeItem.text(), this ); - button->setPalette(p); - connect( button, &QAbstractButton::clicked, this, &ScriptTerminatorWidget::hide ); - - reposition(); -} - -//////////////////////////////////////////////////////////////////////////////// -// ScriptItem -//////////////////////////////////////////////////////////////////////////////// - - -ScriptItem::ScriptItem( QObject *parent, const QString &name, const QString &path, const KPluginInfo &info ) -: QObject( parent ) -, m_name( name ) -, m_url( QUrl::fromLocalFile( path ) ) -, m_info( info ) -, m_running( false ) -, m_evaluating( false ) -, m_runningTime( 0 ) -, m_timerId( 0 ) -{} - -void -ScriptItem::pause() -{ - DEBUG_BLOCK - if( !m_engine ) - { - warning() << "Script has no script engine attached:" << m_name; - return; - } - - killTimer( m_timerId ); - if( m_popupWidget ) - { - m_popupWidget->hide(); - m_popupWidget->deleteLater();; - } - //FIXME: Sometimes a script can be evaluating and cannot be abort? or can be reevaluating for some reason? - if( m_engine->isEvaluating() ) - { - m_engine->abortEvaluation(); - m_evaluating = false; - return; - } - if( m_info.category() == "Scriptable Service" ) - The::scriptableServiceManager()->removeRunningScript( m_name ); - - if( m_info.isPluginEnabled() ) - { - debug() << "Disabling script" << m_info.pluginName(); - m_info.setPluginEnabled( false ); - m_info.save(); - } - - m_log << QString( "%1 Script ended" ).arg( QTime::currentTime().toString() ); - m_running = false; - m_evaluating = false; -} - -QString -ScriptItem::specPath() const -{ - QFileInfo info( m_url.path() ); - const QString specPath = QString( "%1/%2.spec" ).arg( info.path(), info.completeBaseName() ); - return specPath; -} - -void -ScriptItem::timerEvent( QTimerEvent* event ) -{ - Q_UNUSED( event ) - if( m_engine && m_engine->isEvaluating() ) - { - m_runningTime += 100; - if( m_runningTime >= 5000 ) - { - debug() << "5 seconds passed evaluating" << m_name; - m_runningTime = 0; - - if( !m_popupWidget ) - { - m_popupWidget = new ScriptTerminatorWidget( - i18n( "Script %1 has been evaluating for over" - " 5 seconds now, terminate?" - , m_name ) ); - connect( m_popupWidget.data(), &ScriptTerminatorWidget::terminate, - this, &ScriptItem::stop ); - } - m_popupWidget.data()->show(); - } - } - else - { - if( m_popupWidget ) - m_popupWidget->deleteLater(); - m_runningTime = 0; - } -} - -QString -ScriptItem::handleError( QScriptEngine *engine ) -{ - QString errorString = QString( "Script Error: %1 (line: %2)" ) - .arg( engine->uncaughtException().toString() ) - .arg( engine->uncaughtExceptionLineNumber() ); - error() << errorString; - engine->clearExceptions(); - stop(); - return errorString; -} - - -bool -ScriptItem::start( bool silent ) -{ - DEBUG_BLOCK - //load the wrapper classes - m_output.clear(); - initializeScriptEngine(); - - QFile scriptFile( m_url.path() ); - scriptFile.open( QIODevice::ReadOnly ); - m_running = true; - m_evaluating = true; - - m_log << QString( "%1 Script started" ).arg( QTime::currentTime().toString() ); - - m_timerId = startTimer( 100 ); - Q_ASSERT( m_engine ); - m_output << m_engine->evaluate( scriptFile.readAll() ).toString(); - debug() << "After Evaluation "<< m_name; - emit evaluated( m_output.join( "\n" ) ); - scriptFile.close(); - - if ( m_evaluating ) - { - m_evaluating = false; - if ( m_engine->hasUncaughtException() ) - { - m_log << handleError( m_engine.data() ); - if( !silent ) - { - debug() << "The Log For the script that is the borked: " << m_log; - } - return false; - } - if( m_info.category() == QLatin1String("Scriptable Service") ) - m_service->slotCustomize( m_name ); - } - else - stop(); - return true; -} - -void -ScriptItem::initializeScriptEngine() -{ - DEBUG_BLOCK - - if( m_engine ) - return; - - m_engine = new AmarokScript::AmarokScriptEngine( this ); - connect( m_engine.data(), &AmarokScript::AmarokScriptEngine::deprecatedCall, - this, &ScriptItem::slotDeprecatedCall ); - connect( m_engine.data(), &AmarokScript::AmarokScriptEngine::signalHandlerException, - this, &ScriptItem::signalHandlerException ); - m_engine.data()->setProcessEventsInterval( 50 ); - debug() << "starting script engine:" << m_name; - - // first create the Amarok global script object - new AmarokScript::AmarokScript( m_name, m_engine.data() ); - - // common utils - new AmarokScript::ScriptImporter( m_engine.data(), m_url ); - new AmarokScript::AmarokScriptConfig( m_name, m_engine.data() ); - new AmarokScript::AmarokScriptXml( m_engine.data() ); - new AmarokScript::InfoScript( m_url, m_engine.data() ); - //new AmarokNetworkScript( m_engine.data() ); - new AmarokScript::Downloader( m_engine.data() ); - - // backend - new AmarokScript::AmarokCollectionScript( m_engine.data() ); - new AmarokScript::AmarokEngineScript( m_engine.data() ); - - // UI - new AmarokScript::AmarokWindowScript( m_engine.data() ); - new AmarokScript::AmarokPlaylistScript( m_engine.data() ); - new AmarokScript::AmarokStatusbarScript( m_engine.data() ); - new AmarokScript::AmarokKNotifyScript( m_engine.data() ); - new AmarokScript::AmarokOSDScript( m_engine.data() ); - - AmarokScript::CollectionPrototype::init( m_engine.data() ); - AmarokScript::QueryMakerPrototype::init( m_engine.data() ); - - const QString &category = m_info.category(); - if( category.contains( QLatin1String("Lyrics") ) ) - { - new AmarokScript::AmarokLyricsScript( m_engine.data() ); - } - if( category.contains( QLatin1String("Scriptable Service") ) ) - { - new StreamItem( m_engine.data() ); - m_service = new AmarokScript::ScriptableServiceScript( m_engine.data() ); - new AmarokScript::AmarokServicePluginManagerScript( m_engine.data() ); - } - - AmarokScript::MetaTrackPrototype::init( m_engine.data() ); - AmarokScript::ScriptableBiasFactory::init( m_engine.data() ); -} - -void -ScriptItem::stop() -{ - pause(); - m_engine->deleteLater(); -} - - -void -ScriptItem::slotDeprecatedCall( const QString &call ) -{ - Q_UNUSED( call ) - disconnect( sender(), SIGNAL(deprecatedCall(QString)), this, 0 ); - if( !AmarokConfig::enableDeprecationWarnings() ) - return; - - QString message = i18nc( "%1 is the name of the offending script, %2 the name of the script author, and %3 the author's email" - , "The script %1 uses deprecated scripting API calls. Please contact the script" - " author, %2 at %3, and ask him to upgrade it before the next Amarok release." - , m_info.name(), m_info.author(), m_info.email() ); - Amarok::Components::logger()->longMessage( message ); -} - -void -ScriptItem::uninstall() -{ - emit uninstalled(); - deleteLater(); -} - -ScriptItem::~ScriptItem() -{ - stop(); -} diff --git a/src/scripting/scriptmanager/ScriptManager.h b/src/scripting/scriptmanager/ScriptManager.h deleted file mode 100644 --- a/src/scripting/scriptmanager/ScriptManager.h +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2004-2010 Mark Kretschmann * - * Copyright (c) 2005 Seb Ruiz * - * Copyright (c) 2008 Peter ZHOU * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPTMANAGER_H -#define AMAROK_SCRIPTMANAGER_H - -#include "amarok_export.h" -#include "core/meta/forward_declarations.h" -#include "ScriptItem.h" - -#include -#include - -#include - -namespace AmarokScript { - class AmarokScript; -} -class QScriptContext; -class QScriptEngine; -class QScriptValue; - -class AMAROK_EXPORT ScriptManager : public QObject -{ - Q_OBJECT - - public: - static ScriptManager* instance(); - static void destroy(); - - /** - * Runs the script with the given name. - * @param name The pluginName of the script. - * @return True if successful. - */ - bool runScript( const QString& name, bool silent = false ); - - /** - * Stops the script with the given name. - * @param name The name of the script. - * @return True if successful. - */ - bool stopScript( const QString& name ); - - void configChanged( bool changed ); - - KPluginInfo::List scripts( const QString &category ) const; - - /** Returns a list of all currently running scripts. Used by the DCOP handler. */ - QStringList listRunningScripts() const; - - /** Returns the path of the spec file of the given script */ - QString specForScript( const QString& name ) const; - - /** Returns whether or not there is a lyrics script running */ - bool lyricsScriptRunning() const; - - QString scriptNameForEngine( const QScriptEngine *engine ) const; - - /** Notifies any running lyric scripts to fetch desired lyric from given URL */ - void notifyFetchLyrics( const QString& artist, const QString& title, const QString& url, Meta::TrackPtr track ); - - void ServiceScriptPopulate( const QString &name, - int level, - int parent_id, - const QString &callbackString, - const QString &filter ); - - void ServiceScriptRequestInfo( const QString &name, int level, const QString &callbackString ); - - void ServiceScriptCustomize( const QString &name ); - - typedef QHash ScriptMap; - ScriptMap m_scripts; - QString m_lyricsScript; - - public Q_SLOTS: - /** Finds installed scripts, updates them, and loads them */ - void updateAllScripts(); - - Q_SIGNALS: - // needed so the lyrics script can connect to this - void fetchLyrics( const QString&, const QString&, const QString& url, Meta::TrackPtr ); - void lyricsScriptStarted(); - - /** - * Emitted when a script is added, removed or updated - */ - void scriptsChanged(); - - private Q_SLOTS: - bool slotRunScript( const QString &name, bool silent = false ); - void handleException( const QScriptValue &value ); - - void updaterFinished( const QString &scriptPath ); - void slotConfigChanged(); - - private: - explicit ScriptManager( QObject* parent ); - virtual ~ScriptManager(); - - /// \return false if loadScript failed. - bool loadScript( const QString& path ); - - ///////////////////////////////////////////////////////////////////////////////////// - // DATA MEMBERS - ///////////////////////////////////////////////////////////////////////////////////// - static ScriptManager* s_instance; - - bool m_configChanged; - QStringList m_changedScripts; - - // count returning ScriptUpdaters in a thread-safe way - QSemaphore m_updateSemaphore; - // memorize how many scripts were found and tried to be updated - int m_nScripts; - -}; - -#endif /* AMAROK_SCRIPTMANAGER_H */ diff --git a/src/scripting/scriptmanager/ScriptManager.cpp b/src/scripting/scriptmanager/ScriptManager.cpp deleted file mode 100644 --- a/src/scripting/scriptmanager/ScriptManager.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2004-2010 Mark Kretschmann * - * Copyright (c) 2005-2007 Seb Ruiz * - * Copyright (c) 2006 Alexandre Pereira de Oliveira * - * Copyright (c) 2006 Martin Ellis * - * Copyright (c) 2007 Leo Franchi * - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2009 Jakob Kummerow * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptManager" - -#include "ScriptManager.h" - -#include "core/support/Amarok.h" -#include "core/support/Debug.h" -#include "core/support/Components.h" -#include "core/interfaces/Logger.h" -#include "MainWindow.h" -#include "amarokconfig.h" -#include // for the compile flags -#include "services/scriptable/ScriptableServiceManager.h" -#include "ScriptItem.h" -#include "ScriptUpdater.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include - - -ScriptManager* ScriptManager::s_instance = 0; - -ScriptManager::ScriptManager( QObject* parent ) - : QObject( parent ) -{ - DEBUG_BLOCK - setObjectName( "ScriptManager" ); - - s_instance = this; - - if( AmarokConfig::enableScripts() == false ) - { - AmarokConfig::setEnableScripts( true ); - } - - // Delay this call via eventloop, because it's a bit slow and would block - QTimer::singleShot( 0, this, &ScriptManager::updateAllScripts ); -} - -ScriptManager::~ScriptManager() -{} - -void -ScriptManager::destroy() { - if (s_instance) { - delete s_instance; - s_instance = 0; - } -} - -ScriptManager* -ScriptManager::instance() -{ - return s_instance ? s_instance : new ScriptManager( The::mainWindow() ); -} - -//////////////////////////////////////////////////////////////////////////////// -// public -//////////////////////////////////////////////////////////////////////////////// - -bool -ScriptManager::runScript( const QString& name, bool silent ) -{ - if( !m_scripts.contains( name ) ) - return false; - - return slotRunScript( name, silent ); -} - -bool -ScriptManager::stopScript( const QString& name ) -{ - if( name.isEmpty() ) - return false; - if( !m_scripts.contains( name ) ) - return false; - m_scripts[name]->stop(); - return true; -} - -QStringList -ScriptManager::listRunningScripts() const -{ - QStringList runningScripts; - foreach( const ScriptItem *item, m_scripts ) - { - if( item->running() ) - runningScripts << item->info().pluginName(); - } - return runningScripts; -} - -QString -ScriptManager::specForScript( const QString& name ) const -{ - if( !m_scripts.contains( name ) ) - return QString(); - return m_scripts[name]->specPath(); -} - -bool -ScriptManager::lyricsScriptRunning() const -{ - return !m_lyricsScript.isEmpty(); -} - -void -ScriptManager::notifyFetchLyrics( const QString& artist, const QString& title, const QString& url, Meta::TrackPtr track ) -{ - DEBUG_BLOCK - emit fetchLyrics( artist, title, url, track ); -} - -//////////////////////////////////////////////////////////////////////////////// -// private slots (script updater stuff) -//////////////////////////////////////////////////////////////////////////////// - -void -ScriptManager::updateAllScripts() // SLOT -{ - DEBUG_BLOCK - // find all scripts (both in $KDEHOME and /usr) - QStringList foundScripts; - QStringList locations = QStandardPaths::standardLocations( QStandardPaths::GenericDataLocation ); - for( const auto &location : locations ) - { - QDir dir( location + "/amarok/scripts" ); - - if( !dir.exists() ) - continue; - - for( const auto &scriptLocation : dir.entryList( QDir::NoDotAndDotDot | QDir::Dirs ) ) - { - QDir scriptDir( dir.absoluteFilePath( scriptLocation ) ); - if( scriptDir.exists( QStringLiteral( "main.js" ) ) ) - foundScripts << scriptDir.absoluteFilePath( QStringLiteral( "main.js" ) ); - } - } - - // remove deleted scripts - foreach( ScriptItem *item, m_scripts ) - { - const QString specPath = QString( "%1/script.spec" ).arg( QFileInfo( item->url().path() ).path() ); - if( !QFile::exists( specPath ) ) - { - debug() << "Removing script " << item->info().pluginName(); - item->uninstall(); - m_scripts.remove( item->info().pluginName() ); - } - } - - m_nScripts = foundScripts.count(); - - // get timestamp of the last update check - KConfigGroup config = Amarok::config( "ScriptManager" ); - const uint lastCheck = config.readEntry( "LastUpdateCheck", QVariant( 0 ) ).toUInt(); - const uint now = QDateTime::currentDateTime().toTime_t(); - bool autoUpdateScripts = AmarokConfig::autoUpdateScripts(); - // note: we can't update scripts without the QtCryptoArchitecture, so don't even try - #ifndef QCA2_FOUND - autoUpdateScripts = false; - #endif - - // last update was at least 7 days ago -> check now if auto update is enabled - if( autoUpdateScripts && (now - lastCheck > 7*24*60*60) ) - { - debug() << "ScriptUpdater: Performing script update check now!"; - for( int i = 0; i < m_nScripts; ++i ) - { - ScriptUpdater *updater = new ScriptUpdater( this ); - // all the ScriptUpdaters are now started in parallel. - // tell them which script to work on - updater->setScriptPath( foundScripts.at( i ) ); - // tell them whom to signal when they're finished - connect( updater, &ScriptUpdater::finished, this, &ScriptManager::updaterFinished ); - // and finally tell them to get to work - QTimer::singleShot( 0, updater, &ScriptUpdater::updateScript ); - } - // store current timestamp - config.writeEntry( "LastUpdateCheck", QVariant( now ) ); - config.sync(); - } - // last update was pretty recent, don't check again - else - { - debug() << "ScriptUpdater: Skipping update check"; - for ( int i = 0; i < m_nScripts; i++ ) - { - loadScript( foundScripts.at( i ) ); - } - configChanged( true ); - } -} - -void -ScriptManager::updaterFinished( const QString &scriptPath ) // SLOT -{ - DEBUG_BLOCK - // count this event - m_updateSemaphore.release(); - loadScript( scriptPath ); - if ( m_updateSemaphore.tryAcquire(m_nScripts) ) - { - configChanged( true ); - } - sender()->deleteLater(); -} - -//////////////////////////////////////////////////////////////////////////////// -// private slots -//////////////////////////////////////////////////////////////////////////////// - -bool -ScriptManager::slotRunScript( const QString &name, bool silent ) -{ - ScriptItem *item = m_scripts.value( name ); - connect( item, &ScriptItem::signalHandlerException, - this, &ScriptManager::handleException ); - if( item->info().category() == "Lyrics" ) - { - m_lyricsScript = name; - debug() << "lyrics script started:" << name; - emit lyricsScriptStarted(); - } - return item->start( silent ); -} - -void -ScriptManager::handleException(const QScriptValue& value) -{ - DEBUG_BLOCK - - QScriptEngine *engine = value.engine(); - if (!engine) - return; - - Amarok::Components::logger()->longMessage( i18n( "Script error reported by: %1\n%2", scriptNameForEngine( engine ), value.toString() ), Amarok::Logger::Error ); -} - -void -ScriptManager::ServiceScriptPopulate( const QString &name, int level, int parent_id, - const QString &path, const QString &filter ) -{ - if( m_scripts.value( name )->service() ) - m_scripts.value( name )->service()->slotPopulate( name, level, parent_id, path, filter ); -} - -void -ScriptManager::ServiceScriptCustomize( const QString &name ) -{ - if( m_scripts.value( name )->service() ) - m_scripts.value( name )->service()->slotCustomize( name ); -} - -void -ScriptManager::ServiceScriptRequestInfo( const QString &name, int level, const QString &callbackString ) -{ - if( m_scripts.value( name )->service() ) - m_scripts.value( name )->service()->slotRequestInfo( name, level, callbackString ); -} - -void -ScriptManager::configChanged( bool changed ) -{ - emit scriptsChanged(); - if( !changed ) - return; - //evil scripts may prevent the config dialog from dismissing, delay execution - QTimer::singleShot( 0, this, &ScriptManager::slotConfigChanged ); -} - -//////////////////////////////////////////////////////////////////////////////// -// private -//////////////////////////////////////////////////////////////////////////////// - -void -ScriptManager::slotConfigChanged() -{ - foreach( ScriptItem *item, m_scripts ) - { - const QString name = item->info().pluginName(); - bool enabledByDefault = item->info().isPluginEnabledByDefault(); - bool enabled = Amarok::config( "Plugins" ).readEntry( name + "Enabled", enabledByDefault ); - - if( !item->running() && enabled ) - { - slotRunScript( name ); - } - else if( item->running() && !enabled ) - { - item->stop(); - } - } -} - -bool -ScriptManager::loadScript( const QString& path ) -{ - if( path.isEmpty() ) - return false; - - QStringList SupportAPIVersion; - SupportAPIVersion << QLatin1String("API V1.0.0") << QLatin1String("API V1.0.1"); - QString ScriptVersion; - QFileInfo info( path ); - const QString jsonPath = QString( "%1/script.json" ).arg( info.path() ); - if( !QFile::exists( jsonPath ) ) - { - error() << "script.json for "<< path << " is missing!"; - return false; - } - - KPluginMetaData pluginMetadata( jsonPath ); - if( !pluginMetadata.isValid() ) - { - error() << "PluginMetaData invalid for" << jsonPath; - return false; - } - - const QString pluginName = pluginMetadata.pluginId(); - const QString category = pluginMetadata.category(); - const QString version = pluginMetadata.version(); - - if( pluginName.isEmpty() || category.isEmpty() || version.isEmpty() ) - { - error() << "PluginMetaData has empty values for" << jsonPath; - return false; - } - - KPluginInfo pluginInfo( pluginMetadata ); - - ScriptItem *item; - if( !m_scripts.contains( pluginName ) ) - { - item = new ScriptItem( this, pluginName, path, pluginInfo ); - m_scripts[ pluginName ] = item; - } - else if( m_scripts[pluginName]->info().version() < pluginInfo.version() ) - { - m_scripts[ pluginName ]->deleteLater(); - item = new ScriptItem( this, pluginName, path, pluginInfo ); - m_scripts[ pluginName ] = item; - } - else - item = m_scripts.value( pluginName ); - - //assume it is API V1.0.0 if there is no "API V" prefix found - if( !item->info().dependencies().at(0).startsWith("API V") ) - ScriptVersion = QLatin1String("API V1.0.0"); - else - ScriptVersion = item->info().dependencies().at(0); - - if( !SupportAPIVersion.contains( ScriptVersion ) ) - { - warning() << "script API version not compatible with Amarok."; - return false; - } - - debug() << "found script:" << category << pluginName << version << item->info().dependencies(); - return true; -} - -KPluginInfo::List -ScriptManager::scripts( const QString &category ) const -{ - KPluginInfo::List scripts; - foreach( const ScriptItem *script, m_scripts ) - { - if( script->info().category() == category ) - scripts << script->info(); - } - return scripts; -} - -QString -ScriptManager::scriptNameForEngine( const QScriptEngine *engine ) const -{ - foreach( const QString &name, m_scripts.keys() ) - { - ScriptItem *script = m_scripts[name]; - if( script->engine() == engine ) - return name; - } - - return QString(); -} diff --git a/src/scripting/scriptmanager/ScriptUpdater.h b/src/scripting/scriptmanager/ScriptUpdater.h deleted file mode 100644 --- a/src/scripting/scriptmanager/ScriptUpdater.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2009 Jakob Kummerow * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPTUPDATER_H -#define AMAROK_SCRIPTUPDATER_H - -#include "ScriptUpdaterStatic.h" - -#include - -class KJob; - -class ScriptUpdater : public QObject -{ - - Q_OBJECT - - public: - explicit ScriptUpdater( QObject *parent ); - virtual ~ScriptUpdater(); - void setScriptPath( const QString& scriptPath ); - - public Q_SLOTS: - void updateScript(); - - Q_SIGNALS: - void finished( const QString &scriptPath ); - - private Q_SLOTS: - void phase2( KJob * job ); - void phase3( KJob * job ); - void phase4( KJob * job ); - - private: - - bool isNewer(const QString & update, const QString & installed); - - QString m_scriptPath; - - // dynamically collected information about the script - QString m_scriptname, m_scriptversion, m_fileName; - QTemporaryFile m_archiveFile, m_sigFile, m_versionFile; - -}; - -#endif // AMAROK_SCRIPTUPDATER_H diff --git a/src/scripting/scriptmanager/ScriptUpdater.cpp b/src/scripting/scriptmanager/ScriptUpdater.cpp deleted file mode 100644 --- a/src/scripting/scriptmanager/ScriptUpdater.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2009 Jakob Kummerow * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptUpdater" - -#include "ScriptUpdater.h" - -#include "core/support/Debug.h" - -#include -#include -#include -#include - - -#include -#include - -#ifdef QCA2_FOUND -#include -#endif - -ScriptUpdater::ScriptUpdater( QObject *parent ) : QObject( parent ) -{ -} - -ScriptUpdater::~ScriptUpdater() -{ -} - -void -ScriptUpdater::setScriptPath( const QString& scriptPath ) -{ - m_scriptPath = scriptPath; -} - -void -ScriptUpdater::updateScript() -{ - DEBUG_BLOCK - - // 1a. detect currently installed version - QFileInfo info( m_scriptPath ); - const QString specPath = info.path() + '/' + "script.spec"; - if( !QFile::exists( specPath ) ) - { - // no .spec file found, can't continue - emit finished( m_scriptPath ); - return; - } - KPluginInfo pInfo( specPath ); - if ( !pInfo.isValid() || pInfo.name().isEmpty() || pInfo.version().isEmpty() ) - { - // invalid or unusable .spec file, can't continue - emit finished( m_scriptPath ); - return; - } - m_scriptversion = pInfo.version(); - - // 1b. detect script name - QFile file( m_scriptPath ); - m_fileName = file.fileName(); - QRegExp rxname( "amarok/scripts/(.+)/main.js" ); - rxname.indexIn( m_fileName ); - m_scriptname = rxname.cap( 1 ); - - // 2. check if there are updates: get 'version' file from server - QUrl versionUrl( updateBaseUrl ); - versionUrl = versionUrl.adjusted(QUrl::StripTrailingSlash); - versionUrl.setPath(versionUrl.path() + '/' + ( m_scriptname )); - versionUrl = versionUrl.adjusted(QUrl::StripTrailingSlash); - versionUrl.setPath(versionUrl.path() + '/' + ( '/' + versionFilename )); - m_versionFile.open(); - debug() << m_scriptname << ": Accessing " << versionUrl.toDisplayString() << " ..."; - QUrl versionDest( m_versionFile.fileName() ); - KIO::FileCopyJob *versionJob = KIO::file_copy( versionUrl, versionDest, -1, KIO::Overwrite | KIO::HideProgressInfo ); - connect ( versionJob, &KIO::FileCopyJob::result, this, &ScriptUpdater::phase2 ); -} - -void -ScriptUpdater::phase2( KJob * job ) -{ - DEBUG_BLOCK - if ( job->error() ) - { - // if no 'version' file was found, cancel the update - emit finished( m_scriptPath ); - return; - } - QFile file( m_versionFile.fileName() ); - if ( !file.open( QIODevice::ReadOnly ) ) { - debug() << m_scriptname << ": Failed to open version file for reading!"; - emit finished( m_scriptPath ); - return; - } - QString response( file.readAll() ); - file.close(); - debug() << m_scriptname << ": online version: " << response; - if ( !isNewer( response, m_scriptversion ) ) - { - // if no newer version is available, cancel update - emit finished( m_scriptPath ); - return; - } - debug() << m_scriptname << ": newer version found, starting update :-)"; - - // 3. get the update archive, download it to a temporary file - QUrl archiveSrc( updateBaseUrl ); - archiveSrc = archiveSrc.adjusted(QUrl::StripTrailingSlash); - archiveSrc.setPath(archiveSrc.path() + '/' + ( m_scriptname )); - archiveSrc = archiveSrc.adjusted(QUrl::StripTrailingSlash); - archiveSrc.setPath(archiveSrc.path() + '/' + ( '/' + archiveFilename )); - m_archiveFile.open(); // temporary files only have a fileName() after they've been opened - QUrl archiveDest( m_archiveFile.fileName() ); - KIO::FileCopyJob *archiveJob = KIO::file_copy( archiveSrc, archiveDest, -1, KIO::Overwrite | KIO::HideProgressInfo ); - connect ( archiveJob, &KIO::FileCopyJob::result, this, &ScriptUpdater::phase3 ); -} - -void ScriptUpdater::phase3( KJob * job ) -{ - if ( job->error() ) - { - // if the file wasn't found, cancel the update - emit finished( m_scriptPath ); - return; - } - - // 4. get the archive's signature, download it to a temporary file as well - QUrl sigSrc( updateBaseUrl ); - sigSrc = sigSrc.adjusted(QUrl::StripTrailingSlash); - sigSrc.setPath(sigSrc.path() + '/' + ( m_scriptname )); - sigSrc = sigSrc.adjusted(QUrl::StripTrailingSlash); - sigSrc.setPath(sigSrc.path() + '/' + ( '/' + signatureFilename )); - m_sigFile.open(); - QUrl sigDest( m_sigFile.fileName() ); - KIO::FileCopyJob *sigJob = KIO::file_copy( sigSrc, sigDest, -1, KIO::Overwrite | KIO::HideProgressInfo ); - connect ( sigJob, &KIO::FileCopyJob::result, this, &ScriptUpdater::phase4 ); -} - -void -ScriptUpdater::phase4( KJob * job ) -{ - if ( job->error() ) - { - // if the signature couldn't be downloaded, cancel the update - emit finished( m_scriptPath ); - return; - } - - // 5. compare the signature to the archive's hash -#ifdef QCA2_FOUND - QCA::Initializer init; - QCA::ConvertResult conversionResult; - QCA::PublicKey pubkey = QCA::PublicKey::fromPEM( publicKey, &conversionResult ); - if ( !( QCA::ConvertGood == conversionResult ) ) - { - debug() << m_scriptname << ": Failed to read public key!"; - emit finished( m_scriptPath ); - return; - } - QFile file( m_archiveFile.fileName() ); - if ( !file.open( QIODevice::ReadOnly ) ) - { - debug() << m_scriptname << ": Failed to open archive file for reading!"; - emit finished( m_scriptPath ); - return; - } - QCA::Hash hash( "sha1" ); - hash.update( &file ); - file.close(); - QFile versionFile( m_versionFile.fileName() ); - if ( !versionFile.open( QIODevice::ReadOnly ) ) - { - debug() << m_scriptname << ": Failed to open version file for reading!"; - emit finished( m_scriptPath ); - return; - } - QCA::Hash versionHash( "sha1" ); - versionHash.update( &versionFile ); - versionFile.close(); - QFile sigFile( m_sigFile.fileName() ); - if ( !sigFile.open( QIODevice::ReadOnly ) ) - { - debug() << m_scriptname << ": Failed to open signature file for reading!"; - emit finished( m_scriptPath ); - return; - } - QByteArray signature = QByteArray::fromBase64( sigFile.readAll() ); - sigFile.close(); - pubkey.startVerify( QCA::EMSA3_SHA1 ); - pubkey.update( hash.final() ); - pubkey.update( versionHash.final() ); - if ( !pubkey.validSignature( signature ) ) - { - debug() << m_scriptname << ": Invalid signature, no update performed."; - emit finished( m_scriptPath ); - return; - } - debug() << m_scriptname << ": Signature matches. Performing update now."; - -#else - debug() << m_scriptname << ": Amarok build without QtCrypto. Cannot verify signature"; - return; -#endif - - // 6. everything OK, perform the update by extracting the archive - KTar archive( m_archiveFile.fileName() ); - if( !archive.open( QIODevice::ReadOnly ) ) - { - // in case of errors: bad luck, cancel the update - debug() << m_scriptname << ": Error opening the update package."; - emit finished( m_scriptPath ); - return; - } - const QStringList locations = QStandardPaths::standardLocations( QStandardPaths::GenericDataLocation ); - QString relativePath; - for( const auto &location : locations ) - if( m_fileName.startsWith( location ) ) - relativePath = m_fileName.remove( location ); - if( relativePath.startsWith( '/' ) ) - relativePath.remove( 0, 1 ); - const QFileInfo fileinfo( relativePath ); - const QString destination = QStandardPaths::writableLocation( QStandardPaths::GenericDataLocation ) + '/' + fileinfo.path(); - const QDir dir; - if( !dir.exists( destination ) ) - { - dir.mkpath( destination ); - } - const KArchiveDirectory* const archiveDir = archive.directory(); - archiveDir->copyTo( destination ); - // update m_scriptPath so that the updated version of the script will be loaded - m_scriptPath = destination + "/main.js"; - debug() << m_scriptname << ": Updating finished successfully :-)"; - - // all done, temporary files are deleted automatically by Qt - emit finished( m_scriptPath ); -} - -// decide whether a version string 'update' is newer than 'installed' -bool -ScriptUpdater::isNewer( const QString & update, const QString & installed ) -{ - // only dots are supported as separators, and only integers are supported - // between the dots (so no fancy stuff like 2.1-1 or 2.1.beta2) - QStringList uList = update.split( '.' ); - QStringList iList = installed.split( '.' ); - int i = 0; - // stop working if the end of both lists is reached - while ( i < uList.length() || i < iList.length() ) { - // read current number, or use 0 if it isn't present (so that "2" == "2.0" == "2.0.0.0.0.0" == "2...0") - int up = ( ( uList.length() > i && ( !uList[i].isEmpty() ) ) ? uList[i].toInt() : 0 ); - int in = ( ( iList.length() > i && ( !iList[i].isEmpty() ) ) ? iList[i].toInt() : 0 ); - if ( up > in ) - { - return true; - } - else if ( up < in ) - { - return false; - } - else - { - // both strings are equal up to this point -> look at the next pair of numbers - i++; - } - } - // if we reach this point, both versions are considered equal - return false; -} diff --git a/src/scripting/scripts/CMakeLists.txt b/src/scripting/scripts/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -#add_subdirectory( radio_station_service ) -#add_subdirectory( librivox_service ) -add_subdirectory( lyrics_lyricwiki ) - -#add_subdirectory( qtscript_debug ) -#add_subdirectory( script_console ) -#add_subdirectory( templates ) -#add_subdirectory( webcontrol) diff --git a/src/scripting/scripts/ScriptWriting-HOWTO b/src/scripting/scripts/ScriptWriting-HOWTO deleted file mode 100644 --- a/src/scripting/scripts/ScriptWriting-HOWTO +++ /dev/null @@ -1,7 +0,0 @@ -SCRIPT-WRITING HOWTO -==================== - -This document has been moved to the Amarok Wiki. Please refer to: - - http://community.kde.org/Amarok/Development/Scripting_HowTo_2.0 - diff --git a/src/scripting/scripts/librivox_service/CMakeLists.txt b/src/scripting/scripts/librivox_service/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/librivox_service/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ - -install( FILES - COPYING - README - main.js - LibrivoxService.html - LibrivoxLogo.png - LibrivoxIcon.png - LibrivoxEmblem.png - LibrivoxScalableEmblem.svgz - audio_book128.png - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/librivox_service -) - -kcoreaddons_desktop_to_json("" script.desktop) - -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/script.json - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/librivox_service -) diff --git a/src/scripting/scripts/librivox_service/COPYING b/src/scripting/scripts/librivox_service/COPYING deleted file mode 100644 --- a/src/scripting/scripts/librivox_service/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/src/scripting/scripts/librivox_service/LibrivoxEmblem.png b/src/scripting/scripts/librivox_service/LibrivoxEmblem.png deleted file mode 100644 index 969042151fda77baa88451438607a344c16f075b..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@PkrKO-%30$eNIpKQ*OzMo!7Bw6fXhJ}0+w zZbsGIysCK_jf?Y}mJ~EE&1+kc+rBclYwfDOb;T1lC!_L%MMp8KT@&cXyvM7m8*|euRB?_?o{=rvo)K~)@?plv*U98t}FGsuQndI(Qxoq z)1ljq$M3hCdf0mUQR}%UZRel1U3lJh`9=GcR~^@0cU*tdxnjkUQ=mXE3GxeOaCmkj z4a7=06?wWi zhDcmaPHbBks;QBm6w6F%dupm<%EDQy^mWtE7CSHJ8o34j&PXBeuC}O(MA>z z29@LUGS8lq%VrmOkl4<#Ld+?|aDy{z!xTrYu7>%=>tsR>NN_A^Fo|H(5a4Bsdh;f* iEPyej;ib5l2_r-FGi|kv-z*eCsl(IN&t;ucLK6VC!s9Fe diff --git a/src/scripting/scripts/librivox_service/LibrivoxIcon.png b/src/scripting/scripts/librivox_service/LibrivoxIcon.png deleted file mode 100644 index 319c54ef6c7314c62e97f46391ed6613a778ea92..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@nwNl}ofb+(7fVJMOGOw= zM;S~;8cj$WPDvb3M;%W}9ZyRgP)8n6OCC{39#KjkQA{CIP9juEB2-EvR8S*UN+eZK zCRb7?S5qfgOD9-UDOpS^T2(7rRV!OoEnHVHUrsPzSTSKvGGR|PW??#LQafoAtcAIB+n`d{MZFih)d7Wr_oo;%bXn~_|f~0VRrEZ3(ZHK9C zimj@Su5*yEZ;`QZlCp7>v~iiZbDFtxpuTmb!g!{`c&Eg8sKt4z#(As9d#=fPuF89| z&3v=XezVSexYK{S)PK9xfxy^+!PWJ3s zh}Z0i-5`3Z00008bW%=J01FRqo1EP6QLGCr0003kNkl;)TkY@ql59~T)ga88nq?`ppJo>`6%R@ur-vk7O?G^a>fWDUkF z5{gAaQIwdvAg5_{`ENC(u6Ju-hxhVshK$K$B(%$$Dqlr0P@Z|9bhb9t``qwk7za=S zHu+Wut#N+Tlz@(wKzojp5}a@!dJt*w0>CMcwS8ljgE|nZmhYncss#YdGmSjh<}LD7 zW;h1`xMo6vw!oSWV2kGf(8Fv{172WN54wK7!vHpTq|E{)02f>Y+%Ft90<*jWM)?FI z;D2W?4!L9qu*VhuXD)0E2KX?=GZcZx30X4$q)?O0slp&jkvLsJ^%m!07*qoM6N<$g2>xW!2kdN diff --git a/src/scripting/scripts/librivox_service/LibrivoxLogo.png b/src/scripting/scripts/librivox_service/LibrivoxLogo.png deleted file mode 100644 index f6ff080910f5bf6efe9d8290f0fb20896d4a7a69..0000000000000000000000000000000000000000 GIT binary patch literal 0 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èz$KC6yO2rI4({Ax!74q+LlErlYn=g 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 Z{9jejg@24UsKNjM002ovPDHLkV1gv_aE|~0 diff --git a/src/scripting/scripts/librivox_service/LibrivoxScalableEmblem.svgz b/src/scripting/scripts/librivox_service/LibrivoxScalableEmblem.svgz deleted file mode 100644 index eb0d6856a38ca74ac1d53c12d8801e847056f7e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@&PN0 z)2z5#yPtmh*^6AKZbXraye#C}ElT&No2%8|J-(lT zEEkL8@#tqQ(J!mJ#T&=-U}gPycjY(^s4ePcnylTH|L{=dnlDWjGM9TF-M}AP#njL05351fWxbwi$*+oR zMAnOruGfzotO&;}ZSL1D!FqHrv%CAIA3kRC_^y0fyMYrp2uJFlp2*U*yAjW_`iwfW zmRjA~Jyf!m)uT~YH_tiHN>IDY%j5DftFvw1&b7N+_BI86tG6@Ro}zrbDlHSW$+atz z23S00tEV()uxT&PwpI36K6zp;V zmZ`#U1ky1p((>qa$0Cjc_uPDYh!BrX<_};-eJ_A#?c$eHB^(*BTDjLOynDz}*_64g zM4>i{`iTluoS~Q7-(}LAo7t9CDyv=t8j+JSFRQititCS_Q1*1>o&NMEeJkqr$ljMn zWy#vziM*xt8&Z?@e$TLcEz3Os;m0_PI33R=5N3q=QN(aaPNu+qj(p5RPRLmYs1Q9n z0V_##BJH87Ag6k{ir*oO)nQ5HuI@Iio>9Qy!0xiVk(D`%dhdEn7{zK*{vsagIupga z{GsX&?4Yd7b8rwuX?_&Xwc9b&P5NFwW}<165##-oRxy$as;D{4Mm0Pr>u#>Du2z*u zGm-zI{=lY`3p}LKl(A3nz+1G@oTBplgeQb25`iUc7dL5KjpXrv!_wNW>+<94f*I!IQC< zu!JY{((Op6F0ptr0Mjje#f7T?AvPs=(r1)WHvWOcIT@)}tGiCe9p;f))j)SttLAd;>c?C(@^x_S#r%zyqd#V$#R{!x zl|8+t*8zO#wTHv-+9MHu(+BY#jR=J!Is<-~6HfzRJU^`G}uwHgfAyfvM{5<247uZ9NYjq1u@bO@$LV7P5LRFmKl)Q)tA zpt2Qd?=@rCSPEDfwUZYzSMPMku`9$Nuv(#)m974qbH8(%#ir!rIr&n5F3N{!3&XA! zol->qf{plLgrMw=qd7%jVW zOnlBP5;XLdXg$LAa%P!%tH;A$T45*KRw_?On;8VZS|O!i2fucK)OvL$$c^{z28U^P zg>a7rkYw19Pr!B_`y6^dWK)5L^*9dV2(fM)LGlkmZMdO8mhwY_f#bHPz%~d8h$UCi zIK>gQEEs4CO$eYEN8F;`YHFkg78M0(tfVJ&c5FJ*VC-#A>i09q9`-y~G0-+=G5gvl zVdEGy>NJg8A|X;C&bj5(C2>FzMao{HZve0ts1#~<%q?oDdVi=Eu%d-vI!87Qzy~fK z8A4`u05N;sLpq{jGKst+A6k2@7KLN!w8i^cC3s?2k;Kj(`2f*xcJ~FSK@b5Wpd6 z>v>h|2YTDIH%18tW9Um`5T}B&bH+?o4Fn1o#@eC*$0Q0vdd(qRcz}pL7KjEBLU!E{ zjem!m(|vQMn=$Dt~irU3t}Gg_&c4be z3Jy#Djs$`SgcRUJ;_VwZtuGfFG5T~I`qWGI3 zMqrbLZ6XfK?L*Vd<8Aeh%CMc-XZiE;of7VK@2@;#^Fb!rE=%;=D$U`1%HiJfHp*^; zQ}-TK=~6)I|2Cm^1o^!ILeX9$y+cl2(mF-4f>+2%NcZ?-`d#>M%RD{n0CfsHk!N?s zvTj7xy!6Pi${N^>w=Yw<%qy?iwu_479ul}&HRm=P-j8tE&%>)YoOfWZd$ak^YM}vv ZoTXIi-zjwZQZLPK{s3Xk5DT*+008_6^Tz-H diff --git a/src/scripting/scripts/librivox_service/LibrivoxService.html b/src/scripting/scripts/librivox_service/LibrivoxService.html deleted file mode 100644 --- a/src/scripting/scripts/librivox_service/LibrivoxService.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - Librivox.org - - - -

-
-

- Welcome to the LibriVox.org service. Here you can search for, - listen to, and download (to your local collection) public domain - audio books. -

-

- From the LibirVox.org site:
- "LibriVox volunteers record chapters of books in the public domain and release - the audio files back onto the net. Our goal is to make all public domain books - available as free audio books." -

-
- - - diff --git a/src/scripting/scripts/librivox_service/README b/src/scripting/scripts/librivox_service/README deleted file mode 100644 --- a/src/scripting/scripts/librivox_service/README +++ /dev/null @@ -1,25 +0,0 @@ -
LibriVox.org
- -

-About:
-A script that lets you seach for, and stream free audiobooks from LibriVox.org -

- -

-Usage:
-Just run the script, and a new service will be created in the internet browser -

- -

-Dependencies:
-

    -
  • Amarok 2.0
  • -
  • Ruby 1.8
  • -
-

- -

-Author:
-Nikolaj Hald Nielsen (nhnFreespirit@gmail.com) -

- diff --git a/src/scripting/scripts/librivox_service/audio_book.svgz b/src/scripting/scripts/librivox_service/audio_book.svgz deleted file mode 100644 index d2b3e1fb94a5550a645446605f4aaff09a5cace6..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@U-Je^%QDzJIRH7n{BA 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 diff --git a/src/scripting/scripts/librivox_service/audio_book16.png b/src/scripting/scripts/librivox_service/audio_book16.png deleted file mode 100644 index 6b6585dd2bb30a2692c3aabe650d0ca3a58cd2e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@?2J%{Ww7+K|~M{5)oqCya;pw;Q;`!l~Pk9BO?W(J^Uyo`1q@f_iADc8p?QOXy1yS_Qp255j* zM>h<^!1FvBySsAh$~aHn%;SgutS_vT$@dSiFUhIajUDs=U`=a{@B4(!X3}MvTpljc z?C3>b+QI2L0ftUnj&tHDU?qwok|ZH+G{rJ4vT5fadk}_f)oKJ`h-F&Z%AKA(3Rv9O z*pO^Civ)pMSSe#$7M&06=hi0g7e7;Pc$mHE+W@M4Kq)ooIL=qcak@B}k^S?7D%I0N z!}s}L?A6`Z)wl0vIvvzK&uhkUOyIf-I93c`*!Hke>QD*3i1<+y;n(ZO3OfKeC0Ac4f1N7%4I3F09l5g>7dlh}^2r{~er-PP4~S=H^$|Z!~4Z z(jS>*c6oXEW>FMJJDmG%6cYE)(nnK5K}PG$_o7)(C= zW(?VIoLj5v&F0n7j7N=ItyZhuY&Pp@n!>P226~7Hr{pO%7&cow{P_D_oE!WL z!s_xUc+@!VcDs?*nj}fEy%>`ZEHh)cdhrr3oO+JGqc)v5=2&Bz_g=reXRgBP(%=9c zHa6DUZKV`*b8}>!4q^-ly!Gm9JlI(0yPtm==DNFr1umXD$IaWf!1w2eqVAw^0c?Ao zM;M00y_kNdi}pO?B;n@mTl;d&jN#7eJ?h~E7oK0jDW-t(*v$jBthIQaN0KCDy)Ng^ zoIwF5&-X!1p5rNxKx-C{9mk4P!iD*hhrq*Q^e~E|K`zEnlkB@G-aYvK}47gLo#FbBt&GyToGsuVfp;HC;;xa z+imNdBg-;KGrqs`D@9RIt5k8$;hbaie(5C%TTw(WNeII5?C!}pX#Awt>&4EwDPs&p zlBgf<{>EbSIL79TtIxju25arWvQ&AN!DUq(1h<`Y{h}zQCMPG!dwmLP`Q+;_$3lU< zcmPyMH-HKdAB-XadPPy7wI=I!{}VW_l-5Dz#KICB&Nv6!Ns{24BkT7uTigGGtnjPV z%Wyd30@#V;crZ(zQ}GVYJ-({tGM*Ds?M;sZ3$T%88J_21t;H{w2!eo_$vR3Lg|R44 zQ4RuXPUkRKKk(SA+U&`lv)kLkkhA6(`Yo9J-O(rlXY))y1~jz z7iiAT5*x!-6tTAcShk~9_GD)#zO#Bi`g8TcdT;fwFJR7+*PlFETYD6@+Z$VJkM3pN?k`xo0knWFgBK(hk+I-1@IHf${R7w> jHpUD#*A5o<^hfv~u*+09=P(t+00000NkvXXu0mjfH<}V^ diff --git a/src/scripting/scripts/librivox_service/audio_book32.png b/src/scripting/scripts/librivox_service/audio_book32.png deleted file mode 100644 index 9ceb03a6c0cd8268f2dd9901d3c918a0db53e82d..0000000000000000000000000000000000000000 GIT binary patch literal 0 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 # -# (C) 2008 Peter ZHOU # -# # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation; either version 2 of the License, or # -# (at your option) any later version. # -# # -# This program 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 General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the # -# Free Software Foundation, Inc., # -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -#########################################################################*/ - -Importer.loadQtBinding( "qt.core" ); -Importer.loadQtBinding( "qt.xml" ); -Importer.loadQtBinding( "qt.network" ); -Importer.loadQtBinding( "qt.gui" ); //for QPixmap - -QByteArray.prototype.toString = function() -{ - ts = new QTextStream( this, QIODevice.ReadOnly ); - return ts.readAll(); -} - -function Librivox() -{ - var currentDir = Amarok.Info.scriptPath() + "/"; - - var file = new QFile( currentDir + "LibrivoxService.html" ); - file.open( QIODevice.OpenMode( QIODevice.ReadOnly, QIODevice.Text ) ); - - while ( !file.atEnd() ) - { - html += file.readLine().toString(); - } - - html = html.replace( "_IMAGE_DIR_", currentDir ); - - Amarok.debug ("creating service..."); - //Amarok.debug ("html: " + html ); - ScriptableServiceScript.call( this, "Librivox.org", 3, "Search for free audio books from Librivox", html, true ); - - Amarok.debug ("done creating service!"); -} - -function onCustomize() -{ - Amarok.debug ("customizing Librivox service"); - var currentDir = Amarok.Info.scriptPath() + "/"; - Amarok.debug ( "loading icon: " + currentDir + "LibrivoxIcon.png" ); - var iconPixmap = new QPixmap( currentDir + "LibrivoxIcon.png" ); - script.setIcon( iconPixmap ); - - var emblemPixmap = new QPixmap( currentDir + "LibrivoxEmblem.png" ); - script.setEmblem( emblemPixmap ); - script.setScalableEmblem( currentDir + "LibrivoxScalableEmblem.svgz" ); -} - -function bookFetchResult( reply ) -{ - try - { - var cover = Amarok.Info.scriptPath() + "/audio_book128.png"; - - doc.setContent( reply ); - - bookElements = doc.elementsByTagName( "book" ); - - Amarok.debug ("got " + bookElements.length() + " books!"); - - var titles = new Array( bookElements.length() ); - var links = new Array( bookElements.length() ); - - var i = 0; - for ( ; i < bookElements.length(); i++ ) - { - elt = bookElements.at( i ); - elt2 = elt.firstChildElement( "title" ); - - var title = elt2.text(); - - var rx = new RegExp( ".*\\(in\\s\\\"(.*)\\\"\\).*" ); - var list = title.match( rx ); - - if ( list != null ) - { - Amarok.debug( "got a match: " + list[0] ); - title = list[1]; - } - - titles[i] = title; - - elt2 = elt.firstChildElement( "url_rss" ); - links[i] = elt2.text(); - } - - for( i = 0; i < bookElements.length(); i++ ) - { - title = titles[i]; - link = links[i]; - - item = Amarok.StreamItem; - item.level = 1; - item.callbackData = link; - item.itemName = title; - item.playableUrl = ""; - item.infoHtml = ""; - - item.coverUrl = cover; - - script.insertItem( item ); - } - } - catch( err ) - { - Amarok.debug( err ); - } - - script.donePopulating(); -} - -function episodeFetchResult( result ) -{ - try - { - var cover = Amarok.Info.scriptPath() + "/audio_book128.png"; - doc.setContent( result ); - - //get book and author title as these might not match the filter that was used... - - elt = doc.firstChildElement("rss"); - elt = elt.firstChildElement("channel"); - - elt2 = elt.firstChildElement( "title" ); - var bookTitle = elt2.text(); - - //give propper book titles for chpters in a compilation - Amarok.debug( "Book title: " + bookTitle ); - var rx = new RegExp( ".*\\(in\\s\\\"(.*)\\\"\\).*" ); - var list = bookTitle.match( rx ); - - if ( list != null ) - { - Amarok.debug( "got a match: " + list[0] ); - bookTitle = list[1]; - } - - var author = "Librivox.com"; - - //process chapters - chapterElements = doc.elementsByTagName( "item" ); - - Amarok.debug( "got " + chapterElements.length() + " items..." ); - - for ( var i = 0; i < chapterElements.length(); i++ ) - { - elt = chapterElements.at( i ); - - elt2 = elt.firstChildElement( "link" ); - var url = elt2.text(); - - elt2 = elt.firstChildElement( "title" ); - var title = elt2.text(); - - elt2 = elt.firstChildElement( "itunes:duration" ); - var duration = elt2.text(); - - url = url.replace( "_64kb.mp3", ".ogg" ); - - //lets see if we have a propper title, if not, create soething that does not look like crap - var rx = new RegExp( "(\\d*)_" ); - var list = title.match( rx ); - - if ( list != null ) - title = "Chapter " + list[1]; - - item = Amarok.StreamItem; - item.level = 0; - item.callbackData = ""; - item.itemName = title; - item.playableUrl = url; - item.album = bookTitle; - item.artist = author; - item.coverUrl = cover; - item.infoHtml = title; - - script.insertItem( item ); - - } - } - catch( err ) - { - Amarok.debug( err ); - } - - script.donePopulating(); -} - -function onPopulate( level, callback, filter ) -{ - offset = 0; - - filter = filter.replace(/^%20+|\%20+$/g,''); - filter.trim(); - - if ( filter != "" ) - { - name = filter.replace( /%20/g, " " ); - } - else - { - name = "Enter Query...(use \"Author-\" to search by author)"; - } - - if ( level == 2 ) - { - - if ( offset > 0 ) - name = name + " ( " + offset + " - " + (offset + 100) + " )"; - - item = Amarok.StreamItem; - item.level = 2; - item.callbackData = "dummy"; - item.itemName = name; - item.playableUrl = ""; - item.infoHtml = ""; - script.insertItem( item ); - - script.donePopulating(); - } - else if ( level == 1 ) - { - Amarok.debug( " Populating book level..." ); - - try - { - var list = filter.match( /^[\s]*author[\s]*-[\s]*(.*)/i ); - var path; - if( list !=null ) - { - Amarok.debug( "Searching by author: " + list[1] ); - path = "http://librivox.org/api/feed/audiobooks/?offset=0&limit=1000&format=xml&author=%5E" + list[1]; - } - else - { - Amarok.debug("Searching by title: " + filter ); - path = "http://librivox.org/api/feed/audiobooks/?offset=0&limit=1000&format=xml&title=%5E" + filter; - } - qurl = new QUrl( path ); - a = new Downloader( qurl, bookFetchResult ); - } - catch( err ) - { - Amarok.debug( err ); - } - - } - else if ( level == 0 ) - { - Amarok.debug( " Populating episode level..." ); - Amarok.debug( " url: " + callback ); - - try - { - path = callback; - qurl = new QUrl( path ); - b = new Downloader( qurl, episodeFetchResult ); - } - catch( err ) - { - Amarok.debug( err ); - } - } -} - -function onFetchInfo( level, callback ) -{ - if ( level == 1 ) - { - qurl = new QUrl( callback ); - b = new Downloader( qurl, parseInfo ); - } -} - -function parseInfo( result ) -{ - Amarok.debug( result ); - - rx = new RegExp( "(.*)<\\/description>" ); - list = result.match( rx ); - info = list[1]; - - info = info.replace( "", "" ); - - script.setCurrentInfo( info ); -} - - -http = new QHttp; -data = new QBuffer; -doc = new QDomDocument("doc"); -elt = new QDomElement; -elt2 = new QDomElement; -bookElements = new QDomNodeList; -html = ""; - -script = new Librivox(); -script.populate.connect( onPopulate ); -script.customize.connect( onCustomize ); -script.fetchInfo.connect( onFetchInfo ); diff --git a/src/scripting/scripts/librivox_service/script.desktop b/src/scripting/scripts/librivox_service/script.desktop deleted file mode 100644 --- a/src/scripting/scripts/librivox_service/script.desktop +++ /dev/null @@ -1,78 +0,0 @@ -[Desktop Entry] -Icon=view-services-librivox-amarok -Type=script -ServiceTypes=KPluginInfo - -Name=Librivox.org -Name[bs]=Librivox.org -Name[ca]=Librivox.org -Name[ca@valencia]=Librivox.org -Name[cs]=Librivox.org -Name[da]=Librivox.org -Name[de]=Librivox.org -Name[el]=Librivox.org -Name[en_GB]=Librivox.org -Name[es]=Librivox.org -Name[fi]=Librivox.org -Name[fr]=Librivox.org -Name[gl]=Librivox.org -Name[hu]=Librivox.org -Name[id]=Librivox.org -Name[it]=Librivox.org -Name[nl]=Librivox.org -Name[pl]=Librivox.org -Name[pt]=Librivox.org -Name[pt_BR]=Librivox.org -Name[ro]=Librivox.org -Name[sk]=Librivox.org -Name[sl]=Librivox.org -Name[sr]=Либривокс -Name[sr@ijekavian]=Либривокс -Name[sr@ijekavianlatin]=LibriVox -Name[sr@latin]=LibriVox -Name[sv]=Librivox.org -Name[tr]=Librivox.org -Name[uk]=Librivox.org -Name[x-test]=xxLibrivox.orgxx -Name[zh_TW]=Librivox.org -Comment=A scripted service that lets you search, stream and download free, public domain, audio books from Librivox.org -Comment[bs]=Skriptovana usluga koja vam dopušta pretragu, slušanje i besplatno preuzimanje, javne domene, audio knjiga sa Librivox.org -Comment[ca]=Un servei amb scripts que us permet cercar, escoltar i baixar àudio llibres lliures de domini públic des de Librivox.org -Comment[ca@valencia]=Un servei amb scripts que vos permet cercar, escoltar i baixar àudio llibres lliures de domini públic des de Librivox.org -Comment[cs]=Skriptovaná služba, jenž vám umožní hledat, přehrávat a stahovat svobodné a public domain audio knihy z Librivox.org -Comment[da]=En scriptet tjeneste som giver dig mulighed for at søge, streame og downloade gratis lydbøger, som er public domain, fra Librivox.org -Comment[de]=Ein Skriptdienst, mit dem Sie freie und gemeinfreie Hörbücher auf Librivox.org suchen, streamen und herunterladen können -Comment[el]=Μια υπηρεσία σεναρίων που σας επιτρέπει να κάνετε αναζήτηση, ροή και λήψη ελεύθερων, κοινού κτήματος, ηχητικών βιβλίων από το Librivox.org -Comment[en_GB]=A scripted service that lets you search, stream and download free, public domain, audio books from Librivox.org -Comment[es]=Un servicio mediante guiones que le permite buscar, transmitir o descargar audio-libros libres, de dominio público desde Librivox.org -Comment[fi]=Skriptattu palvelu, joka mahdollistaa ilmaisten sekä public domainin alaisten äänikirjojen etsimisen, suoratoistamisen ja lataamisen Librivox.orgista -Comment[fr]=Un service sous forme de script qui vous permet de rechercher, de lire et de télécharger des livres audio libres, du domaine public. -Comment[gl]=Un servizo compatíbel con scripts que permite buscar, emitir e descargar libros de son libres, no dominio público, desde Librivox.org. -Comment[hu]=Egy szkriptelt szolgáltatás, amely lehetővé teszi a keresést, streamelést és a szabad, közkincs hangoskönyvek letöltését a Librivox.org oldalról -Comment[id]=Sebuah layanan skrip yang langsung bisa anda cari, stream dan bebas unduh, domain publik, pustaka audio dari Librivox.org -Comment[it]=Un servizio basato su script che ti consente di cercare, trasmettere e scaricare libri audio gratuiti e di dominio pubblico da Librivox.org -Comment[nl]=Een "scripted" service die u vrije, zich in het publieke domein bevindende, gesproken boeken laat zoeken en streamen uit Librivox.org -Comment[pl]=Usługa skryptowa, która umożliwia znajdywanie, strumieniowanie i pobieranie darmowych, z domeny publicznej słuchowisk z Librivox.org -Comment[pt]=Um serviço programado que lhe permite pesquisar, transmitir e transferir livros de áudio gratuitos e do domínio público a partir do Librivox.org -Comment[pt_BR]=Um serviço de pesquisa, stream e download grátis de livros em áudio de domínio público a partir do Librivox.org -Comment[sk]=Skriptová služba, ktorá vám umožní hľadať, streamovať a sťahovať slobodné, public domain, audio knihy z Librivox.org -Comment[sl]=Skriptna storitev, ki vam dovoljuje iskanje po, pretakanje in prejemanje brezplačnih zvočnih knjig iz Librivox.org -Comment[sr]=Скриптовани сервис који омогућава тражење, струјање и преузимање бесплатних (јавно власништво) аудио књига са Либривокса -Comment[sr@ijekavian]=Скриптовани сервис који омогућава тражење, струјање и преузимање бесплатних (јавно власништво) аудио књига са Либривокса -Comment[sr@ijekavianlatin]=Skriptovani servis koji omogućava traženje, strujanje i preuzimanje besplatnih (javno vlasništvo) audio knjiga sa LibriVoxa -Comment[sr@latin]=Skriptovani servis koji omogućava traženje, strujanje i preuzimanje besplatnih (javno vlasništvo) audio knjiga sa LibriVoxa -Comment[sv]=En skriptbaserad tjänst som låter dig söka efter, strömma och ladda ner fria, allmänt tillgängliga, ljudböcker från Librivox.org -Comment[tr]=Librivox.org sitesinden ücretsiz, kamuya açık alan adından, ses kitapları aramanızı, göndermenizi veya indirmenizi sağlayan bir betik hizmeti. -Comment[uk]=Керована скриптами служба, за допомогою якої ви можете шукати, слухати і отримувати вільні, доступні усім звукові книги з Librivox.org -Comment[x-test]=xxA scripted service that lets you search, stream and download free, public domain, audio books from Librivox.orgxx -Comment[zh_TW]=一個文稿服務,讓您從 Librivox.org 搜尋、接收並下載自由、公共版權的有聲書 - -X-KDE-PluginInfo-Author=Nikolaj Hald Nielsen -X-KDE-PluginInfo-Email=nhnFreespirit@gmail.com -X-KDE-PluginInfo-Name=Librivox.org -X-KDE-PluginInfo-Version=2.0 -X-KDE-PluginInfo-Category=Scriptable Service -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=LGPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=true diff --git a/src/scripting/scripts/lyrics_lyricwiki/CMakeLists.txt b/src/scripting/scripts/lyrics_lyricwiki/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/lyrics_lyricwiki/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -install( FILES - main.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/lyrics_lyricwiki -) - -kcoreaddons_desktop_to_json("" script.desktop) - -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/script.json - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/lyrics_lyricwiki -) diff --git a/src/scripting/scripts/lyrics_lyricwiki/main.js b/src/scripting/scripts/lyrics_lyricwiki/main.js deleted file mode 100644 --- a/src/scripting/scripts/lyrics_lyricwiki/main.js +++ /dev/null @@ -1,284 +0,0 @@ -/************************************************************************** -* Amarok 2 lyrics script to fetch lyrics from lyrics.wikia.com * -* (formerly lyricwiki.org) * -* * -* Copyright * -* (C) 2008 Aaron Reichman * -* (C) 2008 Leo Franchi * -* (C) 2008 Mark Kretschmann * -* (C) 2008 Peter ZHOU * -* (C) 2009 Jakob Kummerow * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program 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 General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * -**************************************************************************/ - -/* GLOBAL VARIABLES */ -// template for the xml object that will be populated and passed to Amarok.Lyrics.showLyrics() -XML = "{lyrics}"; -// if we change variable xml it will not reinitialized on next lyrics request, so we will get lyrics from previous song -// because of that we need temp variable -NEWXML = ""; -// maximum numbers that we can follow by #REDIRECT [[Band:Song]] -MAXREDIRECTS = 3; -// url to get lyrics using mediawiki API -APIURL = "http://lyrics.wikia.com/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles="; -// urlified artist and title will be here after initialization -ARTIST = ""; -TITLE = ""; -// the error message that is displayed if no lyrics were found or there was an error while trying to fetch them -ERRORMSG = "Lyrics not found. Sorry."; - -var embedLyrics = Amarok.Script.readConfig("embedLyrics", false); - -function readEmbeddedLyrics() -{ - var track = Amarok.Engine.currentTrack(); - var embeddedLyrics = track.tags["lyrics"]; - if( embeddedLyrics != undefined && embeddedLyrics !== "" ) - { - Amarok.debug( "Using embedded lyrics for track \"" + track.title + "\"" ); - Amarok.Lyrics.showLyricsHtml( embeddedLyrics ); - return true; - } - return false; -} - -function embed( lyricsXML ) -{ - if( !embedLyrics ) - return; - - Amarok.Xml.setReaderData( lyricsXML ); - var lyrics = Amarok.Xml.readFirstElementWithName( "lyric" ); - if( lyrics !== "" ) - { - Amarok.Engine.currentTrack().changeTags( { "lyrics":lyrics }, false ); - Amarok.debug( "Writing lyrics to track." ); - Amarok.debug( lyrics ); - return; - } -} - -/* receives a Wiki page (in XML format) that contains url to lyric of the requested song - this API function can correct our tags - for example we trying to receive lyrics for Nightwish:Nightwish_-_Sleepwalker (incorrect tags) - this API functions will redirect us to Nightwish:Sleepwalker (correct tags) -*/ -function onHelpReceived( response ) -{ - try - { - if( response.length == 0 ) - Amarok.Lyrics.showLyricsError( ERRORMSG ); - else - { - Amarok.Xml.setDomObjectData(response); - var urlstr = Amarok.Xml.textOfFirstDomElementWithName( "url" ); - var capture; - if(capture = /.+\/([^?=:]+:[^?=:]+)$/.exec(urlstr)) - { - // matched url is like this one: http://lyrics.wikia.com/Nightwish:Sleepwalker - // but not like this: http://lyrics.wikia.com/index.php?title=Nightwish:Sleepwalker&action=edit - var url = APIURL + capture[1]; - // this zero will not allow to execute this function again - new Downloader( url, new Function("response", "onLyricsReceived(response, 0)") ); - } - else - { - Amarok.Lyrics.showLyricsNotFound( ERRORMSG ); - } - } - } - catch( err ) - { - Amarok.Lyrics.showLyricsError( ERRORMSG ); - Amarok.debug( "script error in function onHelpReceived: " + err ); - } -} - -/* receives a Wiki page (in XML format) using wikimedia API and extracts lyrics from it */ -function onLyricsReceived( response, redirects ) -{ - try - { - if( response.length == 0 ) - Amarok.Lyrics.showLyricsError( "Unable to contact server - no website returned" ); // TODO: this should be i18n able - else - { - Amarok.Xml.setDomObjectData(response); - - var capture; - response = Amarok.Xml.textOfFirstDomElementWithName( "rev" ); - - if(capture = /<(lyrics?>)/i.exec(response)) - { // ok, lyrics found - // lyrycs can be between or tags - // such variant can be in one response: national lyrics english lyrics - // example: http://lyrics.wikia.com/api.php?action=query&prop=revisions&titles=Flёur:Колыбельная_для_Солнца&rvprop=content&format=xml - // we can not use lazy regexp because qt script don't understand it - // so let's extract lyrics with string functions - - var lindex = response.indexOf("<" + capture[1]) + capture[1].length + 1; - var rindex = response.indexOf(" upper && words[i].charAt(upper).toUpperCase() == "I" ) { - upper++; - } - } - // if the word starts with an apostrophe or parenthesis, the next character has to be uppercase - if ( words[i].charAt(0) == "'" || words[i].charAt(0) == "(" ) { - upper++; - } - // finally, perform the capitalization - if ( upper < words[i].length ) { - words[i] = words[i].substring( 0, upper ).toUpperCase() + words[i].substring( upper ); - } else { - words[i] = words[i].toUpperCase(); - } - // now take care of more special cases - // names like "McSomething" - if ( words[i].substring( 0, 2 ) == "Mc" ) { - words[i] = "Mc" + words[i][2].toUpperCase() + words[i].substring( 3 ); - } - // URI-encode the word - words[i] = encodeURIComponent( words[i] ); - } - // join the words back together and return the result - var result = words.join( "_" ); - return result; - } catch ( err ) { - Amarok.debug ( "script error in function URLify: " + err ); - } -} - -// convert all HTML entities to their applicable characters -function entityDecode(string) -{ - try - { - var convertxml = "" + string + ""; - if(Amarok.Xml.setDomObjectData(convertxml)) - { // xml is valid - return Amarok.Xml.textOfFirstDomElementWithName( "entity" ); - } - - return string; - } - catch( err ) - { - Amarok.debug( "script error in function entityDecode: " + err ); - } -} - -// entry point -function getLyrics( artist, title, url, track ) -{ - if( readEmbeddedLyrics() ) - return; - try - { - // save artist and title for later display now - NEWXML = XML.replace( "{artist}", Amarok.Lyrics.escape( artist ) ); - NEWXML = NEWXML.replace( "{title}", Amarok.Lyrics.escape( title ) ); - - // strip "featuring " from the artist - var strip = artist.toLowerCase().indexOf( " ft. "); - if ( strip != -1 ) { - artist = artist.substring( 0, strip ); - } - strip = artist.toLowerCase().indexOf( " feat. " ); - if ( strip != -1 ) { - artist = artist.substring( 0, strip ); - } - strip = artist.toLowerCase().indexOf( " featuring " ); - if ( strip != -1 ) { - artist = artist.substring( 0, strip ); - } - - // URLify artist and title - ARTIST = artist = URLify( entityDecode(artist) ); - TITLE = title = URLify( entityDecode(title) ); - - // assemble the (encoded!) URL, build a QUrl out of it and dispatch the download request - var url = APIURL + artist + ":" + title; - Amarok.debug( "request URL: " + url.toString() ); - // there was no redirections yet - new Downloader( url, new Function("response", "onLyricsReceived(response, -1)") ); - } - catch( err ) - { - Amarok.debug( "error: " + err ); - } -} - - -Amarok.Window.addSettingsSeparator(); -Amarok.Window.addSettingsMenu( "LyricWiki" ); -Amarok.Window.addCustomAction( "LyricWiki", "EmbedLyrics", "Embed Lyrics" ); -Amarok.Window.LyricWiki.EmbedLyrics.checkable = true; -Amarok.Window.LyricWiki.EmbedLyrics.checked = embedLyrics; -Amarok.Window.LyricWiki.EmbedLyrics.toggled.connect( function( checked ) { - embedLyrics = checked; - Amarok.Script.writeConfig( "embedLyrics", embedLyrics ); - } ); - -Amarok.Lyrics.fetchLyrics.connect( getLyrics ); diff --git a/src/scripting/scripts/lyrics_lyricwiki/script.desktop b/src/scripting/scripts/lyrics_lyricwiki/script.desktop deleted file mode 100644 --- a/src/scripting/scripts/lyrics_lyricwiki/script.desktop +++ /dev/null @@ -1,79 +0,0 @@ -[Desktop Entry] -Icon=view-pim-journal -Type=script -ServiceTypes=KPluginInfo - -Name=Lyricwiki -Name[bs]=Lyricwiki -Name[ca]=Lyricwiki -Name[ca@valencia]=Lyricwiki -Name[cs]=Lyricwiki -Name[da]=Lyricwiki -Name[de]=Lyricwiki -Name[el]=Lyricwiki -Name[en_GB]=Lyricwiki -Name[es]=Lyricwiki -Name[fi]=Lyricwiki -Name[fr]=LyricWiki -Name[gl]=Lyricwiki -Name[hu]=Lyricwiki -Name[id]=Lyricwiki -Name[it]=Lyricwiki -Name[nl]=Lyricwiki -Name[pl]=Lyricwiki -Name[pt]=Lyricwiki -Name[pt_BR]=Lyricwiki -Name[ro]=Lyricwiki -Name[sk]=Lyricwiki -Name[sl]=Lyricwiki -Name[sr]=Лириквики -Name[sr@ijekavian]=Лириквики -Name[sr@ijekavianlatin]=LyricWiki -Name[sr@latin]=LyricWiki -Name[sv]=Lyricwiki -Name[tr]=Lyricwiki -Name[uk]=Lyricwiki -Name[x-test]=xxLyricwikixx -Name[zh_TW]=Lyricwiki -Comment=A script to fetch lyrics from lyricwiki.org -Comment[bs]=Skripta za dobavljanje tekstova pjesama sa lyricwiki.org -Comment[ca]=Un script per recuperar lletres des de lyricwiki.org -Comment[ca@valencia]=Un script per recuperar lletres des de lyricwiki.org -Comment[cs]=Skript pro stažení textů písní z lyricwiki.org -Comment[da]=Et script til at hente sangtekster fra lyricwiki.org -Comment[de]=Ein Skript, um Liedtexte von lyricwiki.org zu holen -Comment[el]=Σενάριο για μεταφορά στίχων από το lyricwiki.org -Comment[en_GB]=A script to fetch lyrics from lyricwiki.org -Comment[es]=Un guion para recuperar letras desde lyricwiki.org -Comment[fi]=Skripti, joka hakee laulun sanat lyricwiki.orgista -Comment[fr]=Un script pour télécharger des paroles depuis lyricwiki.org -Comment[gl]=Un script para obter letras de lyricwiki.org. -Comment[hu]=Egy parancsfájl dalszövegek letöltéséhez a lyricwiki.org oldalról -Comment[id]=Script untuk menarik lirik dari lyricwiki.org -Comment[it]=Uno script per scaricare i testi da lyricwiki.org -Comment[nl]=Een script om liedteksten op te halen uit lyricwiki.org -Comment[pl]=Skrypt do pobieranie słów z lyricwiki.org -Comment[pt]=Um programa para obter letras musicais a partir do lyricwiki.org -Comment[pt_BR]=Um script para baixar letras de músicas a partir do lyricwiki.org -Comment[ro]=Script ce obține versuri de la lyricwiki.org -Comment[sk]=Skript na stiahnutie textu z lyricwiki.org -Comment[sl]=Skript za pridobivanje besedil iz lyricwiki.org -Comment[sr]=Скрипта за добављање стихова са Лириквикија -Comment[sr@ijekavian]=Скрипта за добављање стихова са Лириквикија -Comment[sr@ijekavianlatin]=Skripta za dobavljanje stihova sa LyricWikija -Comment[sr@latin]=Skripta za dobavljanje stihova sa LyricWikija -Comment[sv]=Ett skript för att hämta sångtexter från lyricwiki.org -Comment[tr]=Lyricwiki.org şarkı sözleri getirmek için bir betik -Comment[uk]=Скрипт для отримання слів пісень з lyricwiki.org -Comment[x-test]=xxA script to fetch lyrics from lyricwiki.orgxx -Comment[zh_TW]=從 lyricwiki.org 抓取歌詞的文稿 - -X-KDE-PluginInfo-Author=Aaron Reichman -X-KDE-PluginInfo-Email=reldruh@gmail.com -X-KDE-PluginInfo-Name=LyricWiki -X-KDE-PluginInfo-Version=.3 -X-KDE-PluginInfo-Category=Lyrics -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=LGPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=true diff --git a/src/scripting/scripts/qtscript_debug/CMakeLists.txt b/src/scripting/scripts/qtscript_debug/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/qtscript_debug/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -install( FILES - script.spec - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/qtscript_debug -) - -install( PROGRAMS - main.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/qtscript_debug -) - -install( PROGRAMS - debug/debug.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/qtscript_debug/debug -) diff --git a/src/scripting/scripts/qtscript_debug/debug/debug.js b/src/scripting/scripts/qtscript_debug/debug/debug.js deleted file mode 100644 --- a/src/scripting/scripts/qtscript_debug/debug/debug.js +++ /dev/null @@ -1,50 +0,0 @@ -/************************************************* -* Debug functions * -* * -* (c) 2008 Peter ZHOU * -**************************************************/ - -Debug.initialize = function ( key ) -{ - this.debug_prefix = ""; - this.app_name = ""; -} - -Debug.app_name = function ( str ) -{ - this.app_name = str; -} - -Debug.debug = function ( str ) -{ - if ( this.debug_prefix != "" ) this.prefix = this.debug_prefix; - else this.prefix = ""; - this.indent = " "; - Amarok.debug( this.app_name + ":" + this.indent + this.prefix + str ); -} - -Debug.warning = function ( str ) -{ - if ( this.debug_prefix != "" ) this.prefix = this.debug_prefix; - else this.prefix = ""; - this.indent = " "; - Amarok.debug( this.app_name + ":" + this.indent + " WARNING:" + this.prefix + str ); -} - -Debug.error = function ( str ) -{ - if ( this.debug_prefix != "" ) this.prefix = this.debug_prefix; - else this.prefix = ""; - this.indent = " "; - Amarok.debug( this.app_name + ":" + this.indent + " ERROR:" + this.prefix + str ); -} - -Debug.fatal = function ( str ) -{ - if ( this.debug_prefix != "" ) this.prefix = this.debug_prefix; - else this.prefix = ""; - this.indent = " "; - Amarok.debug( this.app_name + ":" + this.indent + " FATAL:" + this.prefix + str ); -} - - diff --git a/src/scripting/scripts/qtscript_debug/main.js b/src/scripting/scripts/qtscript_debug/main.js deleted file mode 100644 --- a/src/scripting/scripts/qtscript_debug/main.js +++ /dev/null @@ -1,100 +0,0 @@ -Importer.loadQtBinding( "qt.core" ); -//Importer.include( "debug/debug.js" ); - -//test engine: - -var version = Amarok.Info.version(); -Amarok.debug( "Amarok Version: " + version ); - -/* -var Engine; -Engine = Amarok.Engine; -Engine.Stop( true ); -Engine.Play(); -Engine.Seek ( 60*1000 ); -*/ - -//test WindowAction - -function Menu1Clicked() -{ - Amarok.debug("hey, menu1!"); -} - -function Menu2Clicked() -{ - Amarok.debug("hey, menu2!"); -} - -Amarok.Window.addToolsSeparator(); - -if ( Amarok.Window.addToolsMenu( "id1", "test Menu1" ) ) - Amarok.Window.ToolsMenu.id1.triggered.connect(Menu1Clicked); -else - Amarok.debug( "Menu1 already exists!" ); - -if ( Amarok.Window.addToolsMenu( "id2", "test Menu2" ) ) - Amarok.Window.ToolsMenu.id2.triggered.connect(Menu2Clicked); -else - Amarok.debug( "Menu2 already exists!" ); - - -var TrackInfo = Amarok.Engine.currentTrack(); -var OSD = Amarok.Window.OSD; -var StatusBar = Amarok.Window.Statusbar; - -if ( TrackInfo.isValid ) -{ - OSD.setText( "Hey, this is " + TrackInfo.artist ); - OSD.show(); - - StatusBar.longMessage( "You are listening to album: " + TrackInfo.album ); -} -else -{ - Amarok.debug(" Track is not valid! "); -} - -function onConfigure() -{ - Amarok.alert( "This script does not require any configuration." ); -} - -function TrackChanged() -{ - Amarok.debug( "Track Changed!" ); -} - -function TrackSeeked() -{ - Amarok.debug( "Track Seeked!" ); -} - -function TrackFinished() -{ - Amarok.debug( "Track Finished!" ); -} - -function PlaylistCountChanged( count ) -{ - Amarok.debug( "Playlist Count Changed!" ); -} - -function VolumeChanged( volume ) -{ - Amarok.debug( "Volume changed to: " + volume ); -} - -Amarok.configured.connect( onConfigure ); -Amarok.Engine.trackChanged.connect( TrackChanged ); -Amarok.Engine.trackSeeked.connect( TrackSeeked ); -Amarok.Engine.trackFinished.connect( TrackFinished ); -Amarok.Playlist.CountChanged.connect( PlaylistCountChanged ); -Amarok.Engine.volumeChanged.connect( VolumeChanged ); - -location = Amarok.Collection.collectionLocation(); -for ( var x in location ) -{ - Amarok.debug ( location[x] ); -} -Amarok.debug( Amarok.Collection.isDirInCollection( "/home/eagle/Music" ) ); \ No newline at end of file diff --git a/src/scripting/scripts/qtscript_debug/script.spec b/src/scripting/scripts/qtscript_debug/script.spec deleted file mode 100644 --- a/src/scripting/scripts/qtscript_debug/script.spec +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Icon=amarok -Type=script -ServiceTypes=KPluginInfo - -Name=QtScript Test -Comment=A simple QtScript Demo Script - -X-KDE-PluginInfo-Author=Peter ZHOU -X-KDE-PluginInfo-Email=peterzhoulei@gmail.com -X-KDE-PluginInfo-Name=QtScript Test -X-KDE-PluginInfo-Version=1.0 -X-KDE-PluginInfo-Category=Generic -X-KDE-PluginInfo-Website=http://amarok.kde.org/ -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=LGPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=false diff --git a/src/scripting/scripts/radio_station_service/CMakeLists.txt b/src/scripting/scripts/radio_station_service/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/radio_station_service/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ - -install( FILES - main.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/radio_station_service -) - -kcoreaddons_desktop_to_json("" script.desktop) - -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/script.json - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/radio_station_service -) diff --git a/src/scripting/scripts/radio_station_service/main.js b/src/scripting/scripts/radio_station_service/main.js deleted file mode 100644 --- a/src/scripting/scripts/radio_station_service/main.js +++ /dev/null @@ -1,87 +0,0 @@ -/*######################################################################### -# # -# Simple script for testing the scriptable service browser # -# by creating a simple static browser with some cool radio # -# streams. URLs shamelessly stolen from Cool-Streams.xml. # -# # -# Copyright # -# (C) 2007, 2008 Nikolaj Hald Nielsen # -# (C) 2008 Peter ZHOU # -# (C) 2008 Mark Kretschmann # -# # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation; either version 2 of the License, or # -# (at your option) any later version. # -# # -# This program 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 General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the # -# Free Software Foundation, Inc., # -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -##########################################################################*/ - -function Station( name, url ) -{ - this.name = name; - this.url = url; -} - -var stationArray = new Array ( - new Station( "Afterhours.FM [Trance/Livesets]", "http://www.ah.fm/192k.m3u" ), - new Station( "Bassdrive [Drum \'n Bass]", "http://www.bassdrive.com/v2/streams/BassDrive.pls" ), - new Station( "Bluemars [Ambient/Space-Music]", "http://207.200.96.225:8020/listen.pls" ), - new Station( "Digitally Imported - Chillout [Chill-Out]", "http://di.fm/mp3/classictechno.pls" ), - new Station( "Digitally Imported - Classic Techno [Techno]", "http://di.fm/mp3/classictechno.pls" ), - new Station( "Digitally Imported - Trance [Trance]", "http://di.fm/mp3/trance.pls" ), - new Station( "Frequence 3 [Pop]", "http://streams.frequence3.net/hd-mp3.m3u" ), - new Station( "Radio GFM - Electro [Electro]", "http://streams.radio-gfm.net/electro.ogg.m3u" ), - new Station( "Radio GFM - Metal [Metal]", "http://streams.radio-gfm.net/metal.ogg.m3u" ), - new Station( "Radio GFM - RockPop [Rock/Pop]", "http://streams.radio-gfm.net/rockpop.ogg.m3u" ), - new Station( "Kohina [Computer-Music]", "http://www.kohina.com/kohinasolanum.m3u" ), - new Station( "Mostly Classical [Classical]", "http://www.sky.fm/mp3/classical.pls" ), - new Station( "MTH.Electro [Minimal Techno]", "http://www.shouted.fm/tunein/electro-dsl.m3u" ), - new Station( "MTH.House [House]", "http://stream.mth-house.de:8500/listen.pls" ), - new Station( "Nectarine Demoscene Radio [Computer-Music]", "http://de.scenemusic.net/necta192.mp3.m3u" ), - new Station( "Proton Radio [House/Dance]", "http://protonradio.com/proton.m3u" ), - new Station( "Psyradio [Progressive Psytrance]", "http://streamer.psyradio.org:8010/" ), - new Station( "Radio Paradise [Rock/Pop/Alternative]", "http://www.radioparadise.com/musiclinks/rp_128.m3u" ), - new Station( "Raggakings [Reggae]", "http://www.raggakings.net/listen.m3u" ), - new Station( "SLAY Radio [C64 Remixes]", "http://www.slayradio.org/tune_in.php/128kbps/listen.m3u" ), - new Station( "NPR All Songs Considered 24/7", "http://npr.ic.llnwd.net/stream/npr_music2.pls" ), - new Station( "SomaFM - Drone Zone [Ambient]", "http://somafm.com/dronezone.pls" ), - new Station( "SomaFM - Groove Salad [Chill-Out]", "http://somafm.com/groovesalad.pls" ), - new Station( "SomaFM - Indie Pop Rocks [Indie]", "http://somafm.com/indiepop.pls" ), - new Station( "SomaFM - Secret Agent [Downtempo/Lounge]", "http://somafm.com/secretagent.pls" ), - new Station( "SomaFM - Tags Trance Trip [Trance]", "http://somafm.com/tagstrance.pls" ), - new Station( "Absolute Radio [Rock/Pop]", "http://network.absoluteradio.co.uk/core/audio/ogg/live.pls?service=vrbb" ) -); - -function CoolStream() -{ - ScriptableServiceScript.call( this, "Cool Streams", 1, "List of some high quality radio streams", "Some really cool radio streams, hand picked for your listening pleasure by your friendly Amarok developers", false ); -} - -function onPopulating( level, callbackData, filter ) -{ - Amarok.debug( " Populating station level..." ); - //add the station streams as leaf nodes - for ( i = 0; i < stationArray.length; i++ ) - { - item = Amarok.StreamItem; - item.level = 0; - item.callbackData = ""; - item.itemName = stationArray[i].name; - item.playableUrl = stationArray[i].url; - item.infoHtml = "A cool stream called " + item.itemName; - script.insertItem( item ); - } - script.donePopulating(); -} - -script = new CoolStream(); -script.populate.connect( onPopulating ); diff --git a/src/scripting/scripts/radio_station_service/script.desktop b/src/scripting/scripts/radio_station_service/script.desktop deleted file mode 100644 --- a/src/scripting/scripts/radio_station_service/script.desktop +++ /dev/null @@ -1,79 +0,0 @@ -[Desktop Entry] -Icon=get-hot-new-stuff-amarok -Type=script -ServiceTypes=KPluginInfo - -Name=Cool Streams -Name[bs]=Odlični tokovi -Name[ca]=Cool Streams -Name[ca@valencia]=Cool Streams -Name[cs]=Skvělé proudy -Name[da]=Cool Streams -Name[de]=Coole Streams -Name[el]=Χαλαρές ροές -Name[en_GB]=Cool Streams -Name[es]=Cool Streams -Name[fi]=Siistit suoratoistot -Name[fr]=Flux sympathiques -Name[gl]=Emisións xeniais -Name[hu]=Szuper adatfolyamok -Name[id]=Cool Streams -Name[it]=Cool Stream -Name[nl]=Cool Streams -Name[pl]=Strumienie Cool -Name[pt]=Transmissões Fixes -Name[pt_BR]=Cool Streams -Name[ro]=Cool Streams -Name[sk]=Cool Streamy -Name[sl]=Všečni pretoki -Name[sr]=Добри токови -Name[sr@ijekavian]=Добри токови -Name[sr@ijekavianlatin]=Dobri tokovi -Name[sr@latin]=Dobri tokovi -Name[sv]=Cool Streams -Name[tr]=Güzel Akışlar -Name[uk]=Cool Streams -Name[x-test]=xxCool Streamsxx -Name[zh_TW]=Cool Streams -Comment=A script that sets up a service with a few cool internet radio stations -Comment[bs]=Skripta koja postavlja uslugu sa nekoliko odličnih radio stanica. -Comment[ca]=Un script que configura un servei amb diverses estacions de ràdio per Internet interessants -Comment[ca@valencia]=Un script que configura un servei amb diverses estacions de ràdio per Internet interessants -Comment[cs]=Skvělé proudy -Comment[da]=Et script som sætter en tjeneste op med nogle få fede internet-radioer -Comment[de]=Ein Skript, das einen Dienst mit einigen coolen Internet-Radiostationen einrichtet -Comment[el]=Σενάριο που ρυθμίζει μια υπηρεσία με κάποιους ευχάριστους ραδιοφωνικούς σταθμούς στο διαδίκτυο -Comment[en_GB]=A script that sets up a service with a few cool internet radio stations -Comment[es]=Un guion que configura un servicio con unas pocas emisoras de radio de Internet interesantes -Comment[fi]=Skripti, joka tarjoaa muutamia siistejä internet-radioasemia -Comment[fr]=Un script qui paramètre un service doté de quelques stations de radio sympathiques -Comment[gl]=Un script que configura un servizo con algunhas estacións de radio de internet xeniais. -Comment[hu]=Egy parancsfájl, amely egy szolgáltatást állít be néhány szuper internetes rádióállomással -Comment[id]=Sebuah skrip yang di siapkan untuk melayani beberapa stasiun radio internet keren -Comment[it]=Uno script che configura un servizio con alcune fantastiche stazioni radio in rete -Comment[nl]=Een script dat een service met een paar coole internet-radio-stations instelt -Comment[pl]=Skrypt, który ustawia usługę dla kilku internetowych rozgłośni radiowych cool -Comment[pt]=Um programa que configura um serviço com algumas estações de rádio fixes na Internet -Comment[pt_BR]=Um script que configura um serviço com algumas estações de rádio legais -Comment[sk]=Skript, ktorý nastaví službu s niekoľkými super internetovými rádiostanicami -Comment[sl]=Skript, ki nastavi storitev z nekaj všečnimi internetnimi radijskimi postajami -Comment[sr]=Скрипта која поставља сервис са неколико добрих интернет радио-станица -Comment[sr@ijekavian]=Скрипта која поставља сервис са неколико добрих интернет радио-станица -Comment[sr@ijekavianlatin]=Skripta koja postavlja servis sa nekoliko dobrih internet radio-stanica -Comment[sr@latin]=Skripta koja postavlja servis sa nekoliko dobrih internet radio-stanica -Comment[sv]=Ett skript som ställer in en tjänst med ett antal häftiga Internet-radiostationer -Comment[tr]=Birkaç güzel internet radyo istasyonu ile hizmet kuran bir betik -Comment[uk]=Скрипт для налаштовування служби прослуховування декількох чудових інтернет-радіостанцій -Comment[x-test]=xxA script that sets up a service with a few cool internet radio stationsxx -Comment[zh_TW]=設定一些很酷的網路電台服務的文稿 - -X-KDE-PluginInfo-Author=Nikolaj Hald Nielsen -X-KDE-PluginInfo-Email=nhnFreespirit@gmail.com -X-KDE-PluginInfo-Name=Cool Streams -X-KDE-PluginInfo-Version=1.0 -X-KDE-PluginInfo-Category=Scriptable Service -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=LGPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=true - diff --git a/src/scripting/scripts/script_console/CMakeLists.txt b/src/scripting/scripts/script_console/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/script_console/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -install( FILES - main.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/script_console -) - -kcoreaddons_desktop_to_json("" script.desktop) - -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/script.json - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/script_console -) diff --git a/src/scripting/scripts/script_console/main.js b/src/scripting/scripts/script_console/main.js deleted file mode 100644 --- a/src/scripting/scripts/script_console/main.js +++ /dev/null @@ -1,108 +0,0 @@ -Importer.loadQtBinding( "qt.core" ); -Importer.loadQtBinding( "qt.gui" ); -Importer.loadQtBinding( "qt.uitools" ); - -function globalScopeEval( inputCode ) -{ - try - { - result = eval( inputCode ) + " "; - } - catch( error ) - { - result = error + " "; - } - return result; -} - -function ScriptConsoleMainWindow() -{ - QMainWindow.call( this, null ); - - var mainWidget = new QWidget( this ); - this.historyList = new QListWidget( mainWidget ); - this.historyList.sizeHint = new QSize(900, 600); - this.historyList.size = new QSize(900, 600); - this.historyList.verticalScrollMode = QAbstractItemView.ScrollPerPixel; - this.inputLine = new QTextEdit( mainWidget ); - this.executeButton = new QPushButton( mainWidget ); - this.commandArray = []; - this.commandPos = -1; - this.executeButton.clicked.connect( this, this.executeLine ); - this.executeButton.text = "Execute Code"; - this.windowTitle = "Amarok Script Console"; - //the following line doesn't work for some reason: - //executeButton.shortcut = new QKeySequence( "CTRL+Return" ); - - var executeShortcut = new QShortcut( this ); - executeShortcut.key = new QKeySequence( "CTRL+Return" ); - executeShortcut.activated.connect( this, this.executeLine ); - - var backHistoryShortcut = new QShortcut( this ); - backHistoryShortcut.key = new QKeySequence( QKeySequence.StandardKey( QKeySequence.MoveToPreviousPage ) ); - backHistoryShortcut.activated.connect( this, this.backHistory ); - - var forwardHistoryShortcut = new QShortcut( this ); - forwardHistoryShortcut.key = new QKeySequence( QKeySequence.StandardKey( QKeySequence.MoveToNextPage ) ); - forwardHistoryShortcut.activated.connect( this, this.forwardHistory ); - - var explanationItem = new QListWidgetItem("The Amarok Script Console allows you to easily execute JavaScript with access to all functions\nand methods you would have in an Amarok script.\nInformation on scripting for Amarok is available at:\nhttp://community.kde.org/Amarok/Development#Scripting\nExecute code: CTRL-Enter\nBack in code history: Page Up\nForward in code history: Page Down"); - //explanationItem.setForeground( new QBrush( new QColor(Qt.darkGray) ) ); - explanationItem.setFlags( !Qt.ItemIsSelectable ); - this.historyList.addItem( explanationItem ); - - var layout = new QGridLayout( mainWidget ); - layout.addWidget( this.historyList, 0, 0, 1, 2 ); - layout.addWidget( this.inputLine, 1, 0, 3, 2 ); - layout.addWidget( this.executeButton, 4, 1 ); - mainWidget.setLayout( layout ); - this.setCentralWidget( mainWidget ); - this.resize(750, 400); - this.show(); -} - -ScriptConsoleMainWindow.prototype = new QMainWindow(); - -ScriptConsoleMainWindow.prototype.executeLine = function() -{ - command = new QListWidgetItem( this.inputLine.plainText ); - this.commandArray.unshift( this.inputLine.plainText ); - boldFont = new QFont(); - boldFont.setBold( true ); - command.setFont( boldFont ); - result = globalScopeEval.call( null, this.inputLine.plainText ); - resultsRow = new QListWidgetItem( result ); - this.historyList.addItem( command ); - this.historyList.addItem( resultsRow ); - this.historyList.setCurrentItem( resultsRow ); - this.inputLine.plainText = ""; - this.commandPos = -1; -} - -ScriptConsoleMainWindow.prototype.backHistory = function() -{ - if( this.commandArray.length > ( this.commandPos + 1 ) ) - { - this.commandPos++; - } - if( this.commandArray.length > 0 ) - { - this.inputLine.plainText = this.commandArray[ this.commandPos ]; - } - Amarok.debug( "back, " + this.commandArray[ this.commandPos ] ); -} - -ScriptConsoleMainWindow.prototype.forwardHistory = function() -{ - if( this.commandArray.length > 0 ) - { - if( this.commandPos > 0 ) - { - this.commandPos--; - } - this.inputLine.plainText = this.commandArray[ this.commandPos ]; - } - Amarok.debug( "forward, " + this.commandPos + ": " + this.commandArray[ this.commandPos ] ); -} - -scriptConsoleMainWindow = new ScriptConsoleMainWindow(); diff --git a/src/scripting/scripts/script_console/script.desktop b/src/scripting/scripts/script_console/script.desktop deleted file mode 100644 --- a/src/scripting/scripts/script_console/script.desktop +++ /dev/null @@ -1,78 +0,0 @@ -[Desktop Entry] -Icon=preferences-other-amarok -Type=script -ServiceTypes=KPluginInfo - -Name=Amarok Script Console -Name[bs]=Amarok skript konzola -Name[ca]=Consola de scripts de l'Amarok -Name[ca@valencia]=Consola de scripts de l'Amarok -Name[cs]=Konzole skriptu pro Amarok -Name[da]=Amarok script-konsol -Name[de]=Amarok-Skript-Konsole -Name[el]=Κονσόλα σεναρίων του Amarok -Name[en_GB]=Amarok Script Console -Name[es]=Consola de guiones de Amarok -Name[fi]=Amarok-skriptikonsoli -Name[fr]=Console de script d'Amarok -Name[gl]=Consola de scripting de Amarok -Name[hu]=Amarok parancsfájl konzol -Name[id]=Konsol Skrip Amarok -Name[it]=Console degli script di Amarok -Name[nl]=Script-console van Amarok -Name[pl]=Konsola skryptów Amaroka -Name[pt]=Consola de Programas do Amarok -Name[pt_BR]=Console de scripts do Amarok -Name[ro]=Consolă de scripturi Amarok -Name[sk]=Skriptová konzola Amarok -Name[sl]=Konzola skriptov za Amarok -Name[sr]=Амарокова скриптна конзола -Name[sr@ijekavian]=Амарокова скриптна конзола -Name[sr@ijekavianlatin]=Amarokova skriptna konzola -Name[sr@latin]=Amarokova skriptna konzola -Name[sv]=Amarok skriptterminal -Name[tr]=Amarok Betik Konsolu -Name[uk]=Скриптова консоль Amarok -Name[x-test]=xxAmarok Script Consolexx -Name[zh_TW]=Amarok 文稿主控台 -Comment=Amarok Script Console -Comment[bs]=Amarok skript konzola -Comment[ca]=Consola de scripts de l'Amarok -Comment[ca@valencia]=Consola de scripts de l'Amarok -Comment[cs]=Konzole skriptu pro Amarok -Comment[da]=Amarok script-konsol -Comment[de]=Amarok-Skript-Konsole -Comment[el]=Κονσόλα σεναρίων του Amarok -Comment[en_GB]=Amarok Script Console -Comment[es]=Consola de guiones de Amarok -Comment[fi]=Amarok-skriptikonsoli -Comment[fr]=Console de script d'Amarok -Comment[gl]=Consola de scripting de Amarok -Comment[hu]=Amarok parancsfájl konzol -Comment[id]=Konsol Skrip Amarok -Comment[it]=Console degli script di Amarok -Comment[nl]=Script-console van Amarok -Comment[pl]=Konsola skryptów Amaroka -Comment[pt]=Consola de Programas do Amarok -Comment[pt_BR]=Console de scripts do Amarok -Comment[ro]=Consolă de scripturi Amarok -Comment[sk]=Skriptová konzola Amarok -Comment[sl]=Konzola skriptov za Amarok -Comment[sr]=Амарокова скриптна конзола -Comment[sr@ijekavian]=Амарокова скриптна конзола -Comment[sr@ijekavianlatin]=Amarokova skriptna konzola -Comment[sr@latin]=Amarokova skriptna konzola -Comment[sv]=Amarok skriptterminal -Comment[tr]=Amarok Betik Konsolu -Comment[uk]=Скриптова консоль Amarok -Comment[x-test]=xxAmarok Script Consolexx -Comment[zh_TW]=Amarok 文稿主控台 - -X-KDE-PluginInfo-Name=Amarok Script Console -X-KDE-PluginInfo-Version=1.0 -X-KDE-PluginInfo-Category=Generic -X-KDE-PluginInfo-Website=http://amarok.kde.org/ -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=GPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=false diff --git a/src/scripting/scripts/templates/CMakeLists.txt b/src/scripting/scripts/templates/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/templates/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -install( FILES - script.spec - template.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/templates -) diff --git a/src/scripting/scripts/templates/script.spec b/src/scripting/scripts/templates/script.spec deleted file mode 100644 --- a/src/scripting/scripts/templates/script.spec +++ /dev/null @@ -1,17 +0,0 @@ -[Desktop Entry] -Icon=get-hot-new-stuff-amarok -Type=script -ServiceTypes=KPluginInfo - -Name=Script Template -Comment=Script Template - -X-KDE-PluginInfo-Author=Script Template -X-KDE-PluginInfo-Email= -X-KDE-PluginInfo-Name=Script Template -X-KDE-PluginInfo-Version=1.0 -X-KDE-PluginInfo-Category=Scriptable Service -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=LGPL -X-KDE-PluginInfo-BugAddress=Change to your own email address. For internal scripts use "submit@bugs.kde.org" -X-KDE-PluginInfo-EnabledByDefault=false diff --git a/src/scripting/scripts/templates/template.js b/src/scripting/scripts/templates/template.js deleted file mode 100644 --- a/src/scripting/scripts/templates/template.js +++ /dev/null @@ -1,26 +0,0 @@ -function Service() -{ - ScriptableServiceScript.call( this, "Template Name", 1, "Title", "Introduction", false ); -} - -function onPopulating( level, callbackData, filter ) -{ - Amarok.debug( "populating level " + level ); - - var numberOfItems = 10; - - for ( i = 0; i < numberOfItems; i++ ) - { - item = Amarok.StreamItem; - item.level = ; - item.callbackData = ; - item.itemName = ; - item.playableUrl = ; - item.infoHtml = ; - script.insertItem( item ); - } - script.donePopulating(); -} - -script = new Service(); -script.populate.connect( onPopulating ); \ No newline at end of file diff --git a/src/scripting/scripts/webcontrol/CMakeLists.txt b/src/scripting/scripts/webcontrol/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/webcontrol/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -install( FILES - main.js - script.spec - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/webcontrol -) diff --git a/src/scripting/scripts/webcontrol/main.js b/src/scripting/scripts/webcontrol/main.js deleted file mode 100644 --- a/src/scripting/scripts/webcontrol/main.js +++ /dev/null @@ -1,222 +0,0 @@ -/*************************************************************************** - * copyright : (C) 2008 Ian Monroe - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License or (at your option) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - **************************************************************************/ - -//Importer.load( "HttpServer.js" ); - - -Importer.loadQtBinding( "qt.core" ); -Importer.loadQtBinding( "qt.network" ); - -QByteArray.prototype.toString = function() -{ - ts = new QTextStream( this, QIODevice.ReadOnly ); - return ts.readAll(); -} - -function HttpServer() -{ - QTcpServer.call( this, null ); - var portNumber = 8080; - do { - var connected = this.listen(new QHostAddress( QHostAddress.Any ), portNumber); - portNumber++; - } while( !connected && ((this.serverError() & QAbstractSocket.AddressInUseError) == 0 ) && portNumber < 9000 ) - if( !this.isListening() ) - { - Amarok.debug( "Unable to open a port for the web server" ); - return; - } - Amarok.debug("Web server started at port " + this.serverPort() ); - this.newConnection.connect( this, this.newIncomingConnection ); - this.registry = new Object(); -} - -HttpServer.prototype = new QTcpServer(); - -HttpServer.prototype.newIncomingConnection = function() -{ - var socket = this.nextPendingConnection(); - var request = new QByteArray(); - var thisHttp = this; - socket.readyRead.connect( function() { - request.append( socket.readAll() ); - var endOfRequest = request.indexOf("\r\n\r\n"); - if( endOfRequest > 0 ) - { - try{ - request = thisHttp.parseHeader( request, socket, endOfRequest + 4 ); - } - catch( error ) { - Amarok.debug( error) - } - } - }); -} - -HttpServer.prototype.parseHeader = function( request, socket, endOfRequest ) -{ - var header = new QHttpRequestHeader( request.left( endOfRequest ).toString() ); - if( header.method() == "GET" ) - { - this.sendResponse( socket, header.path() ); - socket.close(); - } - return request.mid( endOfRequest ); -} - -HttpServer.prototype.sendResponse = function( socket, path ) -{ - var userResponse = null; - for( var registeredPath in this.registry ) - { - Amarok.debug( path.indexOf( registeredPath ) + " for " + registeredPath + " in " + path ); - if( path.indexOf( registeredPath ) == 0 ) - { - userResponse = this.registry[registeredPath]( path.substring( registeredPath.length ) ); - break; - } - } - - Amarok.debug( "respondTo says::" + userResponse + "::"); - if( userResponse == null ) - { - //var response404 = new QHttpResponseHeader( 404, "Not found", 1, 1 ); -// responseHeader.setStatusLine( 404 ); - //responseHeader.setContentType( "text/html" ) - content = "HTTP/1.1 404 Not found\n" - content += "Content-Type: text/html\n"; - content += "Server: AmarokServer\n\r\n"; - content += "File not found\n"; - content += "

404 Error

\n" - content += path + " not found.\n\r\n"; - //responseHeader.setContentLength( content.length() ); - var writeMe = new QByteArray(); - //writeMe.append( response404.toString() ) - writeMe.append( content ) - socket.write( writeMe ); - Amarok.debug("response:\n" + writeMe.toString() + " sent."); - } - else - { - try{ - content = "HTTP/1.1 200\n" - content += "Content-Type: " + userResponse.mimeType + "\n"; - content += "Server: AmarokServer\n\r\n"; - var writeMe = new QByteArray(); - writeMe.append( content ); - writeMe.append( userResponse.content ); - socket.write( writeMe ); - Amarok.debug("response:\n" + writeMe.toString() + " sent."); - } - catch( e ) - { - Amarok.debug( e ) - } - } -} - -HttpServer.prototype.register = function( path, responseFn ) -{ - this.registry[path] = responseFn; - if( path.charAt(0) === "/" ) - { - path = path.slice(1); - } -} - - -function fileResponse( path ) -{ - Amarok.debug( "requesting " + path ); - var prefix = "/home/ian/.kde4/share/apps/amarok/scripts/script_console2/webrok/"; - if( path === "/" || path === "" ) - { - path = "index.js.html"; - } - //we need to make sure it doesn't ../ out of the root - url = new QUrl( path ); - var fi = new QFileInfo( prefix + url.path() ); - if( fi.absoluteFilePath().indexOf( prefix ) == 0 ) - { - Amarok.debug( "sending " + fi.absoluteFilePath() ); - var file = new QFile( fi.absoluteFilePath() ); - if( file.open( QIODevice.ReadOnly ) ) - { - var ret = new Object(); - if( fi.completeSuffix() == "xml" ) - { - ret.mimeType = "application/xml"; - } - else - { - ret.mimeType = "text/html"; - } - ret.content = file.readAll() - return ret; - } - else - { - Amarok.debug("file not found") - return null; - } - } - else - { - Amarok.debug( fi.absoluteFilePath() + " fails security check." ); - return null; //send 404 error - } -} - -function testResponse() -{ - return "

test

"; -} - -function ajaxResponse( pathStr ) -{ - url = new QUrl( pathStr ); - command = url.path(); - Amarok.debug( "the command is " + command ); - switch( command ) - { - case "/play": - row = Number( url.queryItemValue( "row" ) ); - Amarok.Playlist.playByIndex( row ); - Amarok.debug("playing file"); - var ret = new Object(); - ret.mimeType = "text/plain"; - ret.content = "Playing row " + row; - return ret; - break; - case "/savePlaylist": - Amarok.Playlist.savePlaylist("/home/ian/.kde4/share/apps/amarok/scripts/script_console2/webrok/current.xspf"); - var ret = new Object(); - ret.mimeType = "text/plain"; - ret.content = "saving playlist" - return ret; - breakZZz; - } - return null; //404 -} - -http = new HttpServer(); -http.register( "/ajax", ajaxResponse ); -http.register( "/test", testResponse ); -http.register( "/", fileResponse ); diff --git a/src/scripting/scripts/webcontrol/script.spec b/src/scripting/scripts/webcontrol/script.spec deleted file mode 100644 --- a/src/scripting/scripts/webcontrol/script.spec +++ /dev/null @@ -1,15 +0,0 @@ -[Desktop Entry] -Icon=services -Type=script -ServiceTypes=KPluginInfo - -Name=Test Web Server -Comment=Beginnings of a web control script - -X-KDE-PluginInfo-Name=Test Web Server -X-KDE-PluginInfo-Version=1.0 -X-KDE-PluginInfo-Category=Generic -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=GPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=false diff --git a/src/services/scriptable/ScriptableService.h b/src/services/scriptable/ScriptableService.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableService.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROKSCRIPTABLESERVICE_H -#define AMAROKSCRIPTABLESERVICE_H - - -#include "core/support/Amarok.h" -#include "../ServiceBase.h" -#include "ScriptableServiceMeta.h" -#include "ScriptableServiceCollection.h" - - -/* internally, we use the following level mapping: - 0 = track - 1 = album - 2 = artist - 3 = genre - -but we do our best to make this invisible to the scripts -*/ - -typedef QMap ScriptableServiceTrackIdMap; -typedef QMap ScriptableServiceArtistIdMap; -typedef QMap ScriptableServiceAlbumIdMap; -typedef QMap ScriptableServiceGenreIdMap; - - -class ScriptableService : public ServiceBase -{ - Q_OBJECT - -public: - - /** - * Constructor - */ - explicit ScriptableService( const QString &name ); - - /** - * Destructor - */ - ~ScriptableService(); - - void init( int levels, const QString &rootHtml, bool showSearchBar ); - - void polish(); - - Collections::ServiceCollection * collection(); - - int insertItem( int level, int parentId, const QString &name, const QString &infoHtml, const QString &callbackData, const QString &playableUrl, - const QString & albumOverride, const QString & artistOverride, const QString & genreOverride, - const QString & composerOverride, int yearOverride, const QString &coverUrl ); - - - - void donePopulating( int parentId ); - - void setCustomEmblem( const QPixmap &emblem ); - QPixmap customEmblem(); - - - void setCustomScalableEmblem( const QString &emblemPath ); - QString customScalableEmblem(); - - void setCurrentInfo( const QString & info ); - - int contentLevels() { return m_levels; } - bool hasSearchBar() { return m_hasSearchBar; } - -private Q_SLOTS: - - - //void treeItemSelected( const QModelIndex & index ); - //void infoChanged ( QString infoHtml ); - - -private: - - bool m_polished; - - QString m_name; - QString m_rootHtml; - - int m_levels; - bool m_hasSearchBar; - - int addTrack( Meta::ScriptableServiceTrack * track ); - int addAlbum( Meta::ScriptableServiceAlbum * album ); - int addArtist( Meta::ScriptableServiceArtist * artist ); - int addGenre( Meta::ScriptableServiceGenre * genre ); - - Collections::ScriptableServiceCollection * m_collection; - int m_trackIdCounter; - int m_albumIdCounter; - int m_artistIdCounter; - int m_genreIdCounter; - - ScriptableServiceTrackIdMap m_ssTrackIdMap; - ScriptableServiceAlbumIdMap m_ssAlbumIdMap; - ScriptableServiceArtistIdMap m_ssArtistIdMap; - ScriptableServiceGenreIdMap m_ssGenreIdMap; - - QPixmap m_customEmblem; - QString m_customScalableEmblem; - -}; - - -#endif diff --git a/src/services/scriptable/ScriptableService.cpp b/src/services/scriptable/ScriptableService.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableService.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptableService.h" - -#include "scripting/scriptmanager/ScriptManager.h" -#include "browsers/CollectionTreeItem.h" -#include "browsers/SingleCollectionTreeItemModel.h" -#include "browsers/servicebrowser/ServiceBrowser.h" -#include "core/support/Amarok.h" -#include "core/support/Debug.h" -#include "services/scriptable/ScriptableServiceCollectionTreeModel.h" -#include "services/scriptable/ScriptableServiceInfoParser.h" -#include "widgets/SearchWidget.h" - -#include - -using namespace Meta; - -ScriptableService::ScriptableService( const QString & name ) - : ServiceBase( name, 0 ) - , m_polished( false ) - , m_name( name ) - , m_trackIdCounter( 0 ) - , m_albumIdCounter( 0 ) - , m_artistIdCounter( 0 ) - , m_genreIdCounter( 0 ) -{ - DEBUG_BLOCK - debug() << "creating ScriptableService " << name; - m_collection = 0; - m_bottomPanel->hide(); -} - -ScriptableService::~ScriptableService() -{ - m_collection->deleteLater(); -} - -void ScriptableService::init( int levels, const QString & rootHtml, bool showSearchBar ) -{ - DEBUG_BLOCK - m_levels = levels; - m_rootHtml = rootHtml; - m_hasSearchBar = showSearchBar; - m_searchWidget->showAdvancedButton( false ); - setInfoParser( new ScriptableServiceInfoParser( m_name ) ); - m_collection = new Collections::ScriptableServiceCollection( m_name ); - m_collection->setLevels( levels ); - - if ( !showSearchBar ) - m_searchWidget->hide(); -} - -Collections::ServiceCollection * ScriptableService::collection() -{ - return m_collection; -} - - -int ScriptableService::insertItem( int level, int parentId, const QString & name, const QString & infoHtml, const QString & callbackData, const QString & playableUrl, - const QString & albumOverride, const QString & artistOverride, const QString & genreOverride, - const QString & composerOverride, int yearOverride, const QString &coverUrl ) -{ - - /* - please don't remove this block as I regularly need it for debugging - nhn - DEBUG_BLOCK - debug() << "level: " << level; - debug() << "parentId: " << parentId; - debug() << "name: " << name; - debug() << "infoHtml: " << infoHtml; - debug() << "callbackData: " << callbackData; - debug() << "playableUrl: " << playableUrl; - - debug() << "albumOverride: " << albumOverride; - debug() << "artistOverride: " << artistOverride; - debug() << "coverUrl: " << coverUrl;*/ - - if ( ( level +1 > m_levels ) || level < 0 ) - return -1; - - switch ( level ) { - - case 0: - { - if( !callbackData.isEmpty() || playableUrl.isEmpty() ) - return -1; - - AmarokSharedPointer track( new ScriptableServiceTrack( name ) ); - track->setAlbumId( parentId ); - track->setUidUrl( playableUrl ); - track->setServiceName( m_name ); - track->setDescription( infoHtml ); - - if ( !m_customEmblem.isNull() ) - track->setServiceEmblem( m_customEmblem ); - else - track->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted.png" ) ) ); - - if ( !m_customScalableEmblem.isEmpty() ) - track->setServiceScalableEmblem( m_customScalableEmblem ); - else - track->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted-scalable.svgz" ) ); - - if ( !albumOverride.isEmpty() ) - track->setAlbumName( albumOverride ); - if ( !artistOverride.isEmpty() ) - track->setArtistName( artistOverride ); - if ( !genreOverride.isEmpty() ) - track->setGenreName( genreOverride ); - if ( !composerOverride.isEmpty() ) - track->setComposerName( composerOverride ); - if ( yearOverride != 0 ) - track->setYearNumber( yearOverride ); - if ( !coverUrl.isEmpty() ) - track->setCustomAlbumCoverUrl( coverUrl ); - - return addTrack( track.data() ); - break; - - } case 1: - { - if ( callbackData.isEmpty() || !playableUrl.isEmpty() ) - return -1; - - ScriptableServiceAlbum * album = new ScriptableServiceAlbum( name ); - album->setCallbackString( callbackData ); - album->setArtistId( parentId ); - album->setDescription( infoHtml ); - album->setServiceName( m_name ); - //debug() << "setting coverUrl: " << coverUrl; - album->setCoverUrl( coverUrl ); - - album->setServiceName( m_name ); - album->setDescription( infoHtml ); - - if ( !m_customEmblem.isNull() ) - album->setServiceEmblem( m_customEmblem ); - else - album->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted.png" ) ) ); - - if ( !m_customScalableEmblem.isEmpty() ) - album->setServiceScalableEmblem( m_customScalableEmblem ); - else - album->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted-scalable.svgz" ) ); - - return addAlbum( album ); - - } case 2: - { - if ( callbackData.isEmpty() || !playableUrl.isEmpty() ) - return -1; - - ScriptableServiceArtist * artist = new ScriptableServiceArtist( name ); - artist->setCallbackString( callbackData ); - artist->setGenreId( parentId ); - artist->setDescription( infoHtml ); - artist->setServiceName( m_name ); - - artist->setServiceName( m_name ); - artist->setDescription( infoHtml ); - - if ( !m_customEmblem.isNull() ) - artist->setServiceEmblem( m_customEmblem ); - else - artist->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted.png" ) ) ); - - if ( !m_customScalableEmblem.isEmpty() ) - artist->setServiceScalableEmblem( m_customScalableEmblem ); - else - artist->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted-scalable.svgz" ) ); - - - return addArtist( artist ); - - } case 3: - { - - if ( callbackData.isEmpty() || !playableUrl.isEmpty() || parentId != -1 ) - return -1; - - ScriptableServiceGenre * genre = new ScriptableServiceGenre( name ); - genre->setCallbackString( callbackData ); - genre->setDescription( infoHtml ); - genre->setServiceName( m_name ); - - genre->setServiceName( m_name ); - genre->setDescription( infoHtml ); - - if ( !m_customEmblem.isNull() ) - genre->setServiceEmblem( m_customEmblem ); - else - genre->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted.png" ) ) ); - - if ( !m_customScalableEmblem.isEmpty() ) - genre->setServiceScalableEmblem( m_customScalableEmblem ); - else - genre->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/emblem-scripted-scalable.svgz" ) ); - - - return addGenre( genre ); - - } - } - return -1; -} - - -int ScriptableService::addTrack( ScriptableServiceTrack * track ) -{ - int artistId = -1; - int genreId = -1; - - TrackPtr trackPtr = TrackPtr( track ); - m_collection->acquireWriteLock(); - m_collection->addTrack( trackPtr ); - m_collection->releaseLock(); - - m_trackIdCounter++; - track->setId( m_trackIdCounter ); - - - int albumId = track->albumId(); - - //handle albums - if ( m_levels > 1 ) { - - if ( !m_ssAlbumIdMap.contains( albumId ) ){ - return -1; - } - - ScriptableServiceAlbum * album = m_ssAlbumIdMap.value( albumId ); - - track->setAlbum( album->prettyName() ); - track->setAlbumPtr( AlbumPtr( album ) ); - album->addTrack( trackPtr ); - - artistId = album->artistId(); - - } - - if ( m_levels > 2 ) { - - if ( !m_ssArtistIdMap.contains( artistId ) ) { - return -1; - } - - ScriptableServiceArtist * artist = m_ssArtistIdMap.value( artistId ); - track->setArtist( artist->prettyName() ); - track->setArtist( ArtistPtr( artist ) ); - artist->addTrack( trackPtr ); - - genreId = artist->genreId(); - } - - if ( m_levels == 4) { - - if ( !m_ssGenreIdMap.contains( genreId ) ) { - return -1; - } - - ScriptableServiceGenre * genre = m_ssGenreIdMap.value( genreId ); - track->setGenre( genre->prettyName() ); - track->setGenre( GenrePtr( genre ) ); - genre->addTrack( trackPtr ); - - } - - m_ssTrackIdMap.insert( m_trackIdCounter, track ); - m_collection->acquireWriteLock(); - m_collection->addTrack( trackPtr ); - m_collection->releaseLock(); - - //m_collection->emitUpdated(); - - return m_trackIdCounter; -} - -int ScriptableService::addAlbum( ScriptableServiceAlbum * album ) -{ - int artistId = album->artistId(); - if ( m_levels > 2 && !m_ssArtistIdMap.contains( artistId ) ) { - delete album; - return -1; - } - - album->setAlbumArtist( ArtistPtr( m_ssArtistIdMap.value( artistId ) ) ); - - AlbumPtr albumPtr = AlbumPtr( album ); - m_albumIdCounter++; - album->setId( m_albumIdCounter ); - m_ssAlbumIdMap.insert( m_albumIdCounter, album ); - m_collection->acquireWriteLock(); - m_collection->addAlbum( albumPtr ); - m_collection->releaseLock(); - //m_collection->emitUpdated(); - return m_albumIdCounter; -} - -int ScriptableService::addArtist( Meta::ScriptableServiceArtist * artist ) -{ - int genreId = artist->genreId(); - if ( m_levels > 3 && !m_ssGenreIdMap.contains( genreId ) ) { - delete artist; - return -1; - } - - ArtistPtr artistPtr = ArtistPtr( artist ); - m_artistIdCounter++; - artist->setId( m_artistIdCounter ); - m_ssArtistIdMap.insert( m_artistIdCounter, artist ); - m_collection->acquireWriteLock(); - m_collection->addArtist( artistPtr ); - m_collection->releaseLock(); - - return m_artistIdCounter; - -} - -int ScriptableService::addGenre( Meta::ScriptableServiceGenre * genre ) -{ - GenrePtr genrePtr = GenrePtr( genre ); - m_genreIdCounter++; - - //debug() << "adding genre: " << genre->name() << ", with id: " << m_genreIdCounter; - - genre->setId( m_genreIdCounter ); - m_ssGenreIdMap.insert( m_genreIdCounter, genre ); - m_collection->acquireWriteLock(); - m_collection->addGenre( genrePtr ); - m_collection->releaseLock(); - - return m_genreIdCounter; -} - -void ScriptableService::donePopulating( int parentId ) -{ - m_collection->donePopulating( parentId ); -} - -void ScriptableService::polish() -{ - - if ( !m_polished ) { - QList viewLevels; - - switch ( m_levels ) { - case 1: - break; - case 2: - viewLevels << CategoryId::Album; - break; - case 3: - viewLevels << CategoryId::Artist << CategoryId::Album; - break; - case 4: - viewLevels << CategoryId::Genre << CategoryId::Artist << CategoryId::Album; - break; - default: - return; - } - - m_contentView->setModel( new ScriptableServiceCollectionTreeModel( m_collection, viewLevels ) ); - m_polished = true; - - } - - infoChanged( m_rootHtml ); -} - -void ScriptableService::setCustomEmblem( const QPixmap &emblem ) -{ - m_customEmblem = emblem; -} - -QPixmap ScriptableService::customEmblem() -{ - return m_customEmblem; -} - - -QString ScriptableService::customScalableEmblem() -{ - return m_customScalableEmblem; -} - - -void ScriptableService::setCustomScalableEmblem ( const QString& emblemPath ) -{ - m_customScalableEmblem = emblemPath; -} - - - -void ScriptableService::setCurrentInfo( const QString & info ) -{ - infoChanged( info ); -} - - - - - diff --git a/src/services/scriptable/ScriptableServiceCollection.h b/src/services/scriptable/ScriptableServiceCollection.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceCollection.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef DYNAMICSCRIPTABLESERVICECOLLECTION_H -#define DYNAMICSCRIPTABLESERVICECOLLECTION_H - -#include "../ServiceCollection.h" -#include "AmarokProcess.h" - -namespace Collections { - -/** -A collection that can call back a script to populate items as needed. - - @author -*/ -class ScriptableServiceCollection : public ServiceCollection -{ - Q_OBJECT -public: - explicit ScriptableServiceCollection( const QString &name ); - - ~ScriptableServiceCollection(); - - virtual Collections::QueryMaker* queryMaker(); - - void donePopulating( int parentId ); - - void setLevels( int theValue ) { - m_levels = theValue; - } - - int levels() const { - return m_levels; - } - - void setLastFilter( const QString & filter ) { m_lastFilter = filter; } - QString lastFilter() { return m_lastFilter; } - - void clear(); - - Q_SIGNALS: - void updateComplete(); - -private: - - QString m_name; - int m_levels; - QString m_lastFilter; - -}; - -} //namespace Collections - -#endif diff --git a/src/services/scriptable/ScriptableServiceCollection.cpp b/src/services/scriptable/ScriptableServiceCollection.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceCollection.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptableServiceCollection.h" - -#include "core/support/Debug.h" -#include "ScriptableServiceQueryMaker.h" - -using namespace Collections; - -ScriptableServiceCollection::ScriptableServiceCollection( const QString &name ) - : ServiceCollection( 0, name, name ) -{ - DEBUG_BLOCK - m_name = name; -} - - -ScriptableServiceCollection::~ScriptableServiceCollection() -{ -} - -Collections::QueryMaker * ScriptableServiceCollection::queryMaker() -{ - return new ScriptableServiceQueryMaker( this, m_name ); -} - -void ScriptableServiceCollection::donePopulating( int parentId ) -{ - DEBUG_BLOCK - Q_UNUSED( parentId ); - emit updateComplete(); -} - -void ScriptableServiceCollection::clear() -{ - acquireWriteLock(); - genreMap().clear(); - setGenreMap( GenreMap() ); - artistMap().clear(); - setArtistMap( ArtistMap() ); - albumMap().clear(); - setAlbumMap( AlbumMap() ); - trackMap().clear(); - setTrackMap( TrackMap() ); - releaseLock(); -} - diff --git a/src/services/scriptable/ScriptableServiceCollectionTreeModel.h b/src/services/scriptable/ScriptableServiceCollectionTreeModel.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceCollectionTreeModel.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Matěj Laitl * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPTABLESERVICECOLLECTIONTREEMODEL_H -#define SCRIPTABLESERVICECOLLECTIONTREEMODEL_H - -#include "browsers/SingleCollectionTreeItemModel.h" - -/** - * Tiny wrapper around SingleCollectionTreeItemModel that implements - * converting service tracks that are in fact playlist to MultiTracks (for mime data, - * with help of ScriptableServiceQueryMaker - */ -class ScriptableServiceCollectionTreeModel : public SingleCollectionTreeItemModel -{ - public: - ScriptableServiceCollectionTreeModel( Collections::Collection *collection, - const QList &levelType ); - - using SingleCollectionTreeItemModel::mimeData; // prevent warning - /** - * Overridden to masquerade playlist tracks as MultiTracks - */ - virtual QMimeData* mimeData( const QList &items ) const; -}; - -#endif // SCRIPTABLESERVICECOLLECTIONTREEMODEL_H diff --git a/src/services/scriptable/ScriptableServiceCollectionTreeModel.cpp b/src/services/scriptable/ScriptableServiceCollectionTreeModel.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceCollectionTreeModel.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2013 Matěj Laitl * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptableServiceCollectionTreeModel" - -#include "ScriptableServiceCollectionTreeModel.h" - -#include "AmarokMimeData.h" -#include "core/support/Debug.h" -#include "core-impl/collections/support/TextualQueryFilter.h" -#include "services/scriptable/ScriptableServiceMeta.h" -#include "services/scriptable/ScriptableServiceQueryMaker.h" - -ScriptableServiceCollectionTreeModel::ScriptableServiceCollectionTreeModel( - Collections::Collection *collection, - const QList &levelType ) - : SingleCollectionTreeItemModel( collection, levelType ) -{ -} - -QMimeData * -ScriptableServiceCollectionTreeModel::mimeData( const QList &items ) const -{ - // this is basically a copy of superclass method with a couple of changes: - // 1. we don't reuse tracks already in the model - // 2. we tell the querymaker to masquerade special tracks - - using namespace Collections; - Meta::TrackList tracks; - QList queries; - foreach( CollectionTreeItem *item, items ) - { - if( item->isTrackItem() ) - { - using namespace Meta; - const ScriptableServiceTrack *serviceTrack = - dynamic_cast( item->data().data() ); - if( !serviceTrack ) - { - error() << "failed to convert generic track" << item->data() << "to ScriptableServiceTrack"; - continue; - } - tracks << serviceTrack->playableTrack(); - continue; - } - - ScriptableServiceQueryMaker *qm = qobject_cast( item->queryMaker() ); - if( !qm ) - { - error() << "failed to convert generic QueryMaker to ScriptableService one"; - continue; - } - qm->setConvertToMultiTracks( true ); - for( CollectionTreeItem *tmp = item; tmp; tmp = tmp->parent() ) - tmp->addMatch( qm, levelCategory( tmp->level() - 1 ) ); - Collections::addTextualFilter( qm, m_currentFilter ); - queries.append( qm ); - } - - if( queries.isEmpty() && tracks.isEmpty() ) - return 0; - - AmarokMimeData *mimeData = new AmarokMimeData(); - mimeData->setTracks( tracks ); - mimeData->setQueryMakers( queries ); - mimeData->startQueries(); - return mimeData; -} diff --git a/src/services/scriptable/ScriptableServiceInfoParser.h b/src/services/scriptable/ScriptableServiceInfoParser.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceInfoParser.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPTABLESERVICEINFOPARSER_H -#define SCRIPTABLESERVICEINFOPARSER_H - -#include "../InfoParserBase.h" -#include "ScriptableServiceMeta.h" -#include - -/** -Info parser for the scriptable services - - @author -*/ -class ScriptableServiceInfoParser : public InfoParserBase -{ -Q_OBJECT -public: - explicit ScriptableServiceInfoParser( const QString &serviceName ); - - ~ScriptableServiceInfoParser(); - - - virtual void getInfo( Meta::GenrePtr genre ); - virtual void getInfo( Meta::ArtistPtr artist ); - virtual void getInfo( Meta::AlbumPtr album ) ; - virtual void getInfo( Meta::TrackPtr track ); - -private: - QString m_serviceName; - -}; - -#endif diff --git a/src/services/scriptable/ScriptableServiceInfoParser.cpp b/src/services/scriptable/ScriptableServiceInfoParser.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceInfoParser.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptableServiceInfoParser.h" - -#include "scripting/scriptmanager/ScriptManager.h" -#include "services/ServiceMetaBase.h" - -using namespace Meta; - -ScriptableServiceInfoParser::ScriptableServiceInfoParser( const QString &serviceName ) - : InfoParserBase() - , m_serviceName( serviceName ) -{ -} - - -ScriptableServiceInfoParser::~ScriptableServiceInfoParser() -{ -} - -void ScriptableServiceInfoParser::getInfo( ArtistPtr artist ) -{ - ScriptableServiceArtist * serviceArtist = dynamic_cast< ScriptableServiceArtist * >( artist.data() ); - if (serviceArtist == 0) return; - - emit( info( serviceArtist->description() ) ); - - if ( serviceArtist->description().isEmpty() ) - { - showLoading( i18n( "Loading info..." ) ); - ScriptManager::instance()->ServiceScriptRequestInfo( m_serviceName, serviceArtist->level(), serviceArtist->callbackString() ); - } -} - -void ScriptableServiceInfoParser::getInfo(AlbumPtr album) -{ - DEBUG_BLOCK - ScriptableServiceAlbum * serviceAlbum = dynamic_cast< ScriptableServiceAlbum * >( album.data() ); - if (serviceAlbum == 0) return; - - emit( info( serviceAlbum->description() ) ); - - if ( serviceAlbum->description().isEmpty() ) - { - showLoading( i18n( "Loading info..." ) ); - ScriptManager::instance()->ServiceScriptRequestInfo( m_serviceName, serviceAlbum->level(), serviceAlbum->callbackString() ); - } -} - -void ScriptableServiceInfoParser::getInfo(TrackPtr track) -{ - DEBUG_BLOCK - ScriptableServiceTrack * serviceTrack = dynamic_cast< ScriptableServiceTrack * >( track.data() ); - if (serviceTrack == 0) return; - - emit( info( serviceTrack->description() ) ); - - if ( serviceTrack->description().isEmpty() ) - { - showLoading( i18n( "Loading info..." ) ); - ScriptManager::instance()->ServiceScriptRequestInfo( m_serviceName, serviceTrack->level(), serviceTrack->callbackString() ); - } -} - -void ScriptableServiceInfoParser::getInfo( Meta::GenrePtr genre ) -{ - ScriptableServiceGenre * serviceGenre = dynamic_cast< ScriptableServiceGenre * >( genre.data() ); - if (serviceGenre == 0) return; - - emit( info( serviceGenre->description() ) ); - - if ( serviceGenre->description().isEmpty() ) - { - showLoading( i18n( "Loading info..." ) ); - ScriptManager::instance()->ServiceScriptRequestInfo( m_serviceName, serviceGenre->level(), serviceGenre->callbackString() ); - } -} diff --git a/src/services/scriptable/ScriptableServiceManager.h b/src/services/scriptable/ScriptableServiceManager.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceManager.h +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROKSCRIPTABLESERVICEMANAGER_H -#define AMAROKSCRIPTABLESERVICEMANAGER_H - -#include "AmarokProcess.h" -#include "../ServiceBase.h" -#include "ScriptableService.h" - -#include -#include -#include - -class ScriptableServiceManager; - -namespace The { - AMAROK_EXPORT ScriptableServiceManager* scriptableServiceManager(); -} - -class ScriptableServiceManager : public QObject -{ - Q_OBJECT - - friend ScriptableServiceManager* The::scriptableServiceManager(); - - public: - void removeRunningScript( const QString &name ); - ScriptableService * service( const QString &name ); - - - Q_SIGNALS: - /** - * Signal emitted whenever a new service is ready to be added - * @param service The service to add - */ - void addService( ServiceBase * service ); - - void serviceUpdated( ServiceBase * service ); - - public Q_SLOTS: - - /** - * Initialzises a new service. This method is exported to DBUS - * @param name the name of the service to create. Mujst be the same as the name of the script - * @param levels How many levels of items should be added ( 1 - 4 ) - * @param rootHtml The html to display when the service is selected - * @return returns true if successful and false otherwise - */ - bool initService( const QString &name, int levels, const QString &shortDescription, const QString &rootHtml, bool showSearchBar ); - - /** - * Add a new item to a service - * @param serviceName The name of the service to add an item to - * @param level The level of this item - * @param parentId The id of the parent item that this item should be a child of ( -1 if no parent ) - * @param name The name of this item - * @param infoHtml The html info to display when this item is selected - * @param callbackData The callback data needed to let the script know how to populate this items children ( Empty string if leaf item ) - * @param playableUrl The url to play if added to the playlist ( Empty string if not leaf node ) - * @return the id of the created item ( or -1 on failure ) - */ - int insertItem( const QString &serviceName, int level, int parentId, const QString &name, const QString &infoHtml, const QString &callbackData, const QString &playableUrl, - const QString & albumOverride, const QString & artistOverride, const QString & genreOverride, - const QString & composerOverride, int yearOverride, const QString &coverUrl ); - - - /** - * Let the service know that the script has added all child nodes - * @param serviceName The service we have been adding items to - * @param parentId The id of the parent node - */ - void donePopulating( const QString &serviceName, int parentId ); - - void setIcon( const QString &serviceName, const QPixmap &icon ); - - void setEmblem( const QString &serviceName, const QPixmap &emblem ); - - void setScalableEmblem( const QString &serviceName, const QString &emblemPath ); - - void setCurrentInfo( const QString &serviceName, const QString &info ); - - - private: - - /** - * Constructor - */ - ScriptableServiceManager(); - - /** - * Destructor - */ - ~ScriptableServiceManager(); - - static ScriptableServiceManager * s_instance; - - QMap m_serviceMap; - QString m_rootHtml; -}; - -#endif - diff --git a/src/services/scriptable/ScriptableServiceManager.cpp b/src/services/scriptable/ScriptableServiceManager.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceManager.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptableServiceManager.h" - - -#include "core-impl/collections/support/MemoryCollection.h" -#include "core/support/Debug.h" -#include "ScriptableServiceCollection.h" -#include "ScriptableServiceMeta.h" -#include "scripting/scriptmanager/ScriptManager.h" -#include "../ServiceMetaBase.h" -#include "browsers/servicebrowser/ServiceBrowser.h" - - -using namespace Meta; - -ScriptableServiceManager * ScriptableServiceManager::s_instance = 0; - - -ScriptableServiceManager::ScriptableServiceManager() -{} - - -ScriptableServiceManager::~ScriptableServiceManager() -{ - DEBUG_BLOCK -} - - -bool ScriptableServiceManager::initService( const QString &name, int levels, const QString &shortDescription, const QString &rootHtml, bool showSearchBar ) { - - DEBUG_BLOCK - - debug() << "initializing scripted service: " << name; - - ScriptableService * service = new ScriptableService ( name ); - m_serviceMap[name] = service; - - service->setIcon( QIcon::fromTheme( "view-services-scripted-amarok" ) ); - service->setShortDescription( shortDescription ); - service->init( levels, rootHtml, showSearchBar ); - m_rootHtml = rootHtml; - - debug() << "emitting scripted service " << name; - emit addService( service ); - - return true; -} - - -int ScriptableServiceManager::insertItem( const QString &serviceName, int level, int parentId, const QString &name, const QString &infoHtml, const QString &callbackData, const QString &playableUrl, - const QString & albumOverride, const QString & artistOverride, const QString & genreOverride, - const QString & composerOverride, int yearOverride, const QString &coverUrl) -{ - if ( !m_serviceMap.contains( serviceName ) ) { - //invalid service name - return -1; - } - - return m_serviceMap[serviceName]->insertItem( level, parentId, name, infoHtml, callbackData, playableUrl, albumOverride, artistOverride, genreOverride, composerOverride, yearOverride, coverUrl ); - - //return -1; // FIXME: what should this return? -} - -void ScriptableServiceManager::setCurrentInfo( const QString &serviceName, const QString & info ) -{ - DEBUG_BLOCK - if ( !m_serviceMap.contains( serviceName ) ) { - //invalid service name - return; - } - - m_serviceMap[serviceName]->setCurrentInfo( info ); -} - - -void ScriptableServiceManager::donePopulating(const QString & serviceName, int parentId) -{ - DEBUG_BLOCK - debug() << "Service name: " << serviceName << ", parent id: " << parentId; - if ( !m_serviceMap.contains( serviceName ) ) { - //invalid service name - return; - } - - m_serviceMap[serviceName]->donePopulating( parentId ); -} - -void ScriptableServiceManager::removeRunningScript(const QString & name) -{ - if ( !m_serviceMap.contains( name ) ) { - debug() << "no such service to remove"; - return; - } - - //service gets deleted by serviceBrowser - ServiceBrowser::instance()->removeCategory( m_serviceMap.take( name ) ); -} - -void ScriptableServiceManager::setIcon( const QString & serviceName, const QPixmap & icon ) -{ - DEBUG_BLOCK - debug() << "service: " << serviceName; - if ( !m_serviceMap.contains( serviceName ) ) { - //invalid service name - debug() << "does not exist.... "; - return; - } - - - m_serviceMap[serviceName]->setIcon( QIcon( icon ) ); - emit( serviceUpdated( m_serviceMap[serviceName] ) ); -} - -void ScriptableServiceManager::setEmblem( const QString & serviceName, const QPixmap & emblem ) -{ - if ( !m_serviceMap.contains( serviceName ) ) { - //invalid service name - return; - } - - m_serviceMap[serviceName]->setCustomEmblem( emblem ); - emit( serviceUpdated( m_serviceMap[serviceName] ) ); -} - - -void ScriptableServiceManager::setScalableEmblem ( const QString& serviceName, const QString& emblemPath ) -{ - if ( !m_serviceMap.contains( serviceName ) ) { - //invalid service name - return; - } - - m_serviceMap[serviceName]->setCustomScalableEmblem( emblemPath ); - emit( serviceUpdated( m_serviceMap[serviceName] ) ); -} - - -ScriptableService * ScriptableServiceManager::service(const QString &name) -{ - - if ( !m_serviceMap.contains( name ) ) { - return 0; - } - - return m_serviceMap[name]; -} - - -namespace The { - ScriptableServiceManager* - scriptableServiceManager() - { - if ( ScriptableServiceManager::s_instance == 0 ) - ScriptableServiceManager::s_instance = new ScriptableServiceManager(); - - return ScriptableServiceManager::s_instance; - } -} - - - - - - - - - - - - diff --git a/src/services/scriptable/ScriptableServiceMeta.h b/src/services/scriptable/ScriptableServiceMeta.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceMeta.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007-2009 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef DYNAMICSCRIPTABLESERVICEMETA_H -#define DYNAMICSCRIPTABLESERVICEMETA_H - -#include "../ServiceMetaBase.h" -#include "../ServiceAlbumCoverDownloader.h" - -/** - Meta types for use in the dynamic scriptable service. Nearly identical to - the ServiceMetaBse types, except for a field for storing data to - pass to the script to fetch child items for Genres, Artists and Albums - and a level specifier - - @author Nikolaj Hald Nielsen -*/ - - -namespace Meta -{ - -class ScriptableServiceMetaItem -{ - public: - explicit ScriptableServiceMetaItem( int level ); - - void setCallbackString( const QString &callbackString ); - QString callbackString() const; - int level() const; - - void setServiceName( const QString &name ); - void setServiceDescription( const QString &description ); - void setServiceEmblem( const QPixmap &emblem ); - void setServiceScalableEmblem( const QString &emblemPath ); - - protected: - /* - * This is arbitrary string data to pass back to the script. This can be whatever - * information the script needs to fetch the children of this item... - */ - QString m_callbackString; - int m_level; - QString m_serviceName; - QString m_serviceDescription; - QPixmap m_serviceEmblem; - QString m_serviceScalableEmblem; - -}; - -class ScriptableServiceTrack : public Meta::ServiceTrack, public ScriptableServiceMetaItem -{ - public: - explicit ScriptableServiceTrack( const QString &name ); - explicit ScriptableServiceTrack( const QStringList &resultRow ); - - virtual QString sourceName(); - virtual QString sourceDescription(); - virtual QPixmap emblem(); - virtual QString scalableEmblem(); - - void setAlbumName( const QString &newAlbum ); - void setArtistName( const QString &newArtist ); - void setGenreName( const QString &newGenre ); - void setComposerName( const QString &newComposer ); - void setYearNumber( int newYear ); - - void setCustomAlbumCoverUrl( const QString &coverurl ); - - virtual QString collectionName() const { return m_serviceName; } - virtual void setUidUrl( const QString &url ); - - /** - * If this track is in fact a remote playlist, return Meta::MultiTrack that wraps - * it here, else return pointer to self. - */ - Meta::TrackPtr playableTrack() const; - - private: - Meta::TrackPtr m_playableTrack; -}; - -class ScriptableServiceAlbum : public Meta::ServiceAlbumWithCover, public ScriptableServiceMetaItem -{ - public: - explicit ScriptableServiceAlbum( const QString &name ); - explicit ScriptableServiceAlbum( const QStringList &resultRow ); - - virtual QString downloadPrefix() const { return "script"; } - virtual void setCoverUrl( const QString &coverUrl ) { m_coverUrl = coverUrl; } - virtual QString coverUrl() const { return m_coverUrl; } - - virtual QUrl imageLocation( int size = 1 ) { Q_UNUSED( size ); return QUrl( coverUrl() ); } - - virtual QString sourceName(); - virtual QString sourceDescription(); - virtual QPixmap emblem(); - virtual QString scalableEmblem(); - - virtual bool isBookmarkable() const; - virtual QString collectionName() const { return m_serviceName; } - virtual bool simpleFiltering() const { return true; } - - private: - QString m_coverUrl; - -}; - -class ScriptableServiceArtist : public Meta::ServiceArtist, public ScriptableServiceMetaItem -{ - public: - explicit ScriptableServiceArtist( const QString &name ); - explicit ScriptableServiceArtist( const QStringList &resultRow ); - - void setGenreId( int artistId ); - int genreId() const; - - virtual QString sourceName(); - virtual QString sourceDescription(); - virtual QPixmap emblem(); - virtual QString scalableEmblem(); - - virtual bool isBookmarkable() const; - virtual QString collectionName() const { return m_serviceName; } - virtual bool simpleFiltering() const { return true; } - - private: - int m_genreId; -}; - - -class ScriptableServiceGenre : public Meta::ServiceGenre, public ScriptableServiceMetaItem -{ - public: - explicit ScriptableServiceGenre( const QString &name ); - explicit ScriptableServiceGenre( const QStringList &resultRow ); - - void setDescription( const QString &description ); - QString description(); - - virtual QString sourceName(); - virtual QString sourceDescription(); - virtual QPixmap emblem(); - virtual QString scalableEmblem(); - - private: - QString m_description; -}; - -} - -#endif diff --git a/src/services/scriptable/ScriptableServiceMeta.cpp b/src/services/scriptable/ScriptableServiceMeta.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceMeta.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007-2009 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#include "ScriptableServiceMeta.h" -#include "ScriptableServiceMeta_p.h" - -#include "core/meta/support/PrivateMetaRegistry.h" -#include "core-impl/meta/multi/MultiTrack.h" -#include "core-impl/playlists/types/file/PlaylistFileSupport.h" -#include "services/scriptable/ScriptableService.h" -#include "services/scriptable/ScriptableServiceManager.h" - -using namespace Meta; - -ScriptableServiceMetaItem::ScriptableServiceMetaItem( int level ) - : m_callbackString( QString() ) - , m_level( level ) - , m_serviceName( QString() ) - , m_serviceDescription( QString() ) - , m_serviceEmblem( QPixmap() ) -{} - -void Meta::ScriptableServiceMetaItem::setCallbackString( const QString &callbackString ) -{ - m_callbackString = callbackString; -} - -QString Meta::ScriptableServiceMetaItem::callbackString() const -{ - return m_callbackString; -} - -int Meta::ScriptableServiceMetaItem::level() const -{ - return m_level; -} - -void Meta::ScriptableServiceMetaItem::setServiceName( const QString & name ) -{ - m_serviceName = name; -} - -void Meta::ScriptableServiceMetaItem::setServiceDescription( const QString & description ) -{ - m_serviceDescription = description; -} - -void Meta::ScriptableServiceMetaItem::setServiceEmblem( const QPixmap & emblem ) -{ - m_serviceEmblem = emblem; -} - -void Meta::ScriptableServiceMetaItem::setServiceScalableEmblem ( const QString& emblemPath ) -{ - m_serviceScalableEmblem = emblemPath; -} - - -/* ScriptableServiceTrack */ -ScriptableServiceTrack::ScriptableServiceTrack( const QString & name ) - : ServiceTrack( name ) - , ScriptableServiceMetaItem( 0 ) -{} - -ScriptableServiceTrack::ScriptableServiceTrack( const QStringList & resultRow ) - : ServiceTrack( resultRow ) - , ScriptableServiceMetaItem( 0 ) -{} - - -void Meta::ScriptableServiceTrack::setAlbumName( const QString &newAlbum ) -{ - Meta::AlbumPtr albumPtr = Meta::PrivateMetaRegistry::instance()->album( m_serviceName, newAlbum ); - if ( !albumPtr ) { - ScriptableServiceInternalAlbum * intAlbum = new ScriptableServiceInternalAlbum( newAlbum ); - intAlbum->setServiceName( m_serviceName ); - intAlbum->setServiceDescription( m_serviceDescription ); - intAlbum->setServiceEmblem( m_serviceEmblem ); - intAlbum->setServiceScalableEmblem( m_serviceScalableEmblem ); - albumPtr = Meta::AlbumPtr( intAlbum ); - Meta::PrivateMetaRegistry::instance()->insertAlbum( m_serviceName, newAlbum, albumPtr ); - } - - setAlbumPtr( albumPtr ); -} - -void Meta::ScriptableServiceTrack::setArtistName( const QString &newArtist ) -{ - Meta::ArtistPtr artistPtr = Meta::PrivateMetaRegistry::instance()->artist( m_serviceName, newArtist ); - if ( !artistPtr ) { - ScriptableServiceInternalArtist * intArtist = new ScriptableServiceInternalArtist( newArtist ); - intArtist->setServiceName( m_serviceName ); - intArtist->setServiceDescription( m_serviceDescription ); - intArtist->setServiceEmblem( m_serviceEmblem ); - intArtist->setServiceScalableEmblem( m_serviceScalableEmblem ); - artistPtr = Meta::ArtistPtr( intArtist ); - Meta::PrivateMetaRegistry::instance()->insertArtist( m_serviceName, newArtist, artistPtr ); - } - - setArtist( artistPtr ); -} - -void Meta::ScriptableServiceTrack::setGenreName( const QString &newGenre ) -{ - Meta::GenrePtr genrePtr = Meta::PrivateMetaRegistry::instance()->genre( m_serviceName, newGenre ); - if ( !genrePtr ) { - ScriptableServiceInternalGenre * intGenre = new ScriptableServiceInternalGenre( newGenre ); - intGenre->setServiceName( m_serviceName ); - intGenre->setServiceDescription( m_serviceDescription ); - intGenre->setServiceEmblem( m_serviceEmblem ); - intGenre->setServiceScalableEmblem( m_serviceScalableEmblem ); - genrePtr = Meta::GenrePtr( intGenre ); - Meta::PrivateMetaRegistry::instance()->insertGenre( m_serviceName, newGenre, genrePtr ); - } - - setGenre( genrePtr ); -} - -void Meta::ScriptableServiceTrack::setComposerName( const QString &newComposer ) -{ - Meta::ComposerPtr composerPtr = Meta::PrivateMetaRegistry::instance()->composer( m_serviceName, newComposer ); - if ( !composerPtr ) { - ScriptableServiceInternalComposer * intComposer = new ScriptableServiceInternalComposer( newComposer); - intComposer->setServiceName( m_serviceName ); - intComposer->setServiceDescription( m_serviceDescription ); - intComposer->setServiceEmblem( m_serviceEmblem ); - intComposer->setServiceScalableEmblem( m_serviceScalableEmblem ); - composerPtr = Meta::ComposerPtr( intComposer ); - Meta::PrivateMetaRegistry::instance()->insertComposer( m_serviceName, newComposer, composerPtr ); - } - - setComposer( composerPtr ); -} - -void Meta::ScriptableServiceTrack::setYearNumber( int newYear ) -{ - const QString yearString = QString::number( newYear ); - - Meta::YearPtr yearPtr = Meta::PrivateMetaRegistry::instance()->year( m_serviceName, yearString ); - if ( !yearPtr ) { - ScriptableServiceInternalYear * intYear = new ScriptableServiceInternalYear( yearString ); - intYear->setServiceName( m_serviceName ); - intYear->setServiceDescription( m_serviceDescription ); - intYear->setServiceEmblem( m_serviceEmblem ); - intYear->setServiceScalableEmblem( m_serviceScalableEmblem ); - yearPtr = Meta::YearPtr( intYear ); - Meta::PrivateMetaRegistry::instance()->insertYear( m_serviceName, yearString, yearPtr ); - } - - setYear( yearPtr ); -} - -void Meta::ScriptableServiceTrack::setCustomAlbumCoverUrl( const QString & coverurl ) -{ - DEBUG_BLOCK - if ( album() ) { - debug() << "one"; - ServiceAlbumWithCoverPtr albumWithCover = ServiceAlbumWithCoverPtr::dynamicCast( album() ); - if ( albumWithCover ) { - debug() << "two"; - albumWithCover->setCoverUrl( coverurl ); - } - } -} - - -QString Meta::ScriptableServiceTrack::sourceName() -{ - return m_serviceName; -} - -QString Meta::ScriptableServiceTrack::sourceDescription() -{ - return m_serviceDescription; -} - -QPixmap Meta::ScriptableServiceTrack::emblem() -{ - return m_serviceEmblem; -} - -QString Meta::ScriptableServiceTrack::scalableEmblem() -{ - return m_serviceScalableEmblem; -} - -void ScriptableServiceTrack::setUidUrl( const QString &url ) -{ - Meta::ServiceTrack::setUidUrl( url ); - - using namespace Playlists; - Meta::TrackPtr track( this ); - PlaylistPtr playlist = canExpand( track ) ? expand( track ) : PlaylistPtr(); - if( playlist ) - // since this is a playlist masqueurading as a single track, make a MultiTrack out of it: - m_playableTrack = Meta::TrackPtr( new Meta::MultiTrack( playlist ) ); - else - m_playableTrack = TrackPtr(); -} - -TrackPtr ScriptableServiceTrack::playableTrack() const -{ - return m_playableTrack ? m_playableTrack : TrackPtr( const_cast( this ) ); -} - - -/* DynamicScriptableAlbum */ -ScriptableServiceAlbum::ScriptableServiceAlbum( const QString & name ) - : ServiceAlbumWithCover( name ) - , ScriptableServiceMetaItem( 1 ) -{} - -ScriptableServiceAlbum::ScriptableServiceAlbum( const QStringList & resultRow ) - : ServiceAlbumWithCover( resultRow ) - , ScriptableServiceMetaItem( 1 ) -{} - -QString Meta::ScriptableServiceAlbum::sourceName() -{ - return m_serviceName; -} - -QString Meta::ScriptableServiceAlbum::sourceDescription() -{ - return m_serviceDescription; -} - -QPixmap Meta::ScriptableServiceAlbum::emblem() -{ - return m_serviceEmblem; -} - -QString Meta::ScriptableServiceAlbum::scalableEmblem() -{ - return m_serviceScalableEmblem; -} - -bool Meta::ScriptableServiceAlbum::isBookmarkable() const -{ - ScriptableService * service = The::scriptableServiceManager()->service( m_serviceName ); - if ( service ) - return service->hasSearchBar(); - else - return false; -} - - - -/* ScriptableServiceArtist */ -ScriptableServiceArtist::ScriptableServiceArtist( const QString & name ) - : ServiceArtist( name ) - , ScriptableServiceMetaItem( 2 ) - , m_genreId( 0 ) -{} - -ScriptableServiceArtist::ScriptableServiceArtist( const QStringList & resultRow ) - : ServiceArtist( resultRow ) - , ScriptableServiceMetaItem( 2 ) - , m_genreId( 0 ) -{} - - -void Meta::ScriptableServiceArtist::setGenreId(int genreId) -{ - m_genreId = genreId; -} - - -int Meta::ScriptableServiceArtist::genreId() const -{ - return m_genreId; -} - -QString Meta::ScriptableServiceArtist::sourceName() -{ - return m_serviceName; -} - -QString Meta::ScriptableServiceArtist::sourceDescription() -{ - return m_serviceDescription; -} - -QPixmap Meta::ScriptableServiceArtist::emblem() -{ - return m_serviceEmblem; -} - -QString Meta::ScriptableServiceArtist::scalableEmblem() -{ - return m_serviceScalableEmblem; -} - -bool Meta::ScriptableServiceArtist::isBookmarkable() const -{ - ScriptableService * service = The::scriptableServiceManager()->service( m_serviceName ); - if ( service ) - return service->hasSearchBar(); - else - return false; -} - - -/* ScriptableServiceGenre */ -ScriptableServiceGenre::ScriptableServiceGenre( const QString & name ) - : ServiceGenre( name ) - , ScriptableServiceMetaItem( 3 ) -{} - -ScriptableServiceGenre::ScriptableServiceGenre( const QStringList & resultRow ) - : ServiceGenre( resultRow ) - , ScriptableServiceMetaItem( 3 ) -{} - - -void Meta::ScriptableServiceGenre::setDescription(const QString & description) -{ - m_description = description; -} - -QString Meta::ScriptableServiceGenre::description() -{ - return m_description; -} - -QString Meta::ScriptableServiceGenre::sourceName() -{ - return m_serviceName; -} - -QString Meta::ScriptableServiceGenre::sourceDescription() -{ - return m_serviceDescription; -} - -QPixmap Meta::ScriptableServiceGenre::emblem() -{ - return m_serviceEmblem; -} - -QString Meta::ScriptableServiceGenre::scalableEmblem() -{ - return m_serviceScalableEmblem; -} - - - - - - - diff --git a/src/services/scriptable/ScriptableServiceMeta_p.h b/src/services/scriptable/ScriptableServiceMeta_p.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceMeta_p.h +++ /dev/null @@ -1,320 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Maximilian Kossick * - * Copyright (c) 2008 Peter ZHOU * - * Copyright (c) 2008-2009 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef AMAROK_SCRIPTABLE_SERVICE_META_P_H -#define AMAROK_SCRIPTABLE_SERVICE_META_P_H - - -#include "core/support/Debug.h" -#include "core/meta/Meta.h" -#include "core/capabilities/SourceInfoCapability.h" - -#include -#include -#include -#include - -#include - - - -// internal helper classes - - -/** - * Base class for the private meta types. This is used to give these private items source info capability which is neede in some cases,for instance when bookmarking. - */ -class ScriptableServiceInternalMetaItem -{ - public: - - QString serviceName() { return m_serviceName; } - QString serviceDescription() { return m_serviceDescription; } - QPixmap serviceEmblem() { return m_serviceEmblem; } - QString serviceScalableEmblem() { return m_serviceScalableEmblem; } - - void setServiceName( const QString &name ) { m_serviceName = name; } - void setServiceDescription( const QString &description ) { m_serviceDescription = description; } - void setServiceEmblem( const QPixmap &emblem ) { m_serviceEmblem = emblem; } - void setServiceScalableEmblem( const QString &emblemPath ) { m_serviceScalableEmblem = emblemPath; } - - protected: - QString m_serviceName; - QString m_serviceDescription; - QPixmap m_serviceEmblem; - QString m_serviceScalableEmblem; -}; - - -class AMAROK_EXPORT ScriptableServiceInternalSourceInfoCapability : public Capabilities::SourceInfoCapability -{ - public: - explicit ScriptableServiceInternalSourceInfoCapability( ScriptableServiceInternalMetaItem * sourceInfoProvider ) - { - m_sourceInfoProvider = sourceInfoProvider; - } - ~ScriptableServiceInternalSourceInfoCapability() {}; - - QString sourceName() { return m_sourceInfoProvider->serviceName(); } - QString sourceDescription() { return m_sourceInfoProvider->serviceDescription(); } - QPixmap emblem() { return m_sourceInfoProvider->serviceEmblem(); } - QString scalableEmblem() { return m_sourceInfoProvider->serviceScalableEmblem(); } - - - private: - ScriptableServiceInternalMetaItem * m_sourceInfoProvider; - -}; - - -class ScriptableServiceInternalArtist : public Meta::Artist, public ScriptableServiceInternalMetaItem -{ - public: - explicit ScriptableServiceInternalArtist( const QString &name = QString() ) - : Meta::Artist() - , m_name( name ) - {} - - Meta::TrackList tracks() - { - return Meta::TrackList(); - } - - QString name() const - { - if( !m_name.isEmpty() ) - return m_name; - else - return i18nc( "The value is not known", "Unknown" ); - } - - QString prettyName() const - { - return name(); - } - - virtual bool hasCapabilityInterface( Capabilities::Capability::Type type ) const - { - return ( type == Capabilities::Capability::SourceInfo ); - } - - virtual Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) - { - if ( type == Capabilities::Capability::SourceInfo ) - return new ScriptableServiceInternalSourceInfoCapability( this ); - return 0; - } - -private: - QString m_name; - -}; - -class ScriptableServiceInternalAlbum : public Meta::ServiceAlbumWithCover, public ScriptableServiceInternalMetaItem -{ - public: - explicit ScriptableServiceInternalAlbum( const QString &name = QString() ) - : Meta::ServiceAlbumWithCover( QString() ) - , m_name( name ) - {} - - bool isCompilation() const - { - return false; - } - - bool hasAlbumArtist() const - { - return false; - } - - Meta::ArtistPtr albumArtist() const - { - return Meta::ArtistPtr(); - } - - Meta::TrackList tracks() - { - return Meta::TrackList(); - } - - QString name() const - { - if( !m_name.isEmpty() ) - return m_name; - else - return i18nc( "The value is not known", "Unknown" ); - } - - QString prettyName() const - { - return name(); - } - - virtual QString downloadPrefix() const { return "script"; } - virtual void setCoverUrl( const QString &coverUrl ) { m_coverUrl = coverUrl; } - virtual QString coverUrl() const { return m_coverUrl; } - - virtual QUrl imageLocation( int size = 1 ) { Q_UNUSED( size ); return QUrl( coverUrl() ); } - - virtual bool hasCapabilityInterface( Capabilities::Capability::Type type ) const - { - return ( type == Capabilities::Capability::SourceInfo ); - } - - virtual Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) - { - if ( type == Capabilities::Capability::SourceInfo ) - return new ScriptableServiceInternalSourceInfoCapability( this ); - return 0; - } - - private: - QString m_name; - QString m_coverUrl; -}; - -class ScriptableServiceInternalGenre : public Meta::Genre, public ScriptableServiceInternalMetaItem -{ - public: - explicit ScriptableServiceInternalGenre( const QString &name = QString() ) - : Meta::Genre() - , m_name( name ) - {} - - Meta::TrackList tracks() - { - return Meta::TrackList(); - } - - QString name() const - { - if( !m_name.isEmpty() ) - return m_name; - else - return i18nc( "The value is not known", "Unknown" ); - } - - QString prettyName() const - { - return name(); - } - - virtual bool hasCapabilityInterface( Capabilities::Capability::Type type ) const - { - return ( type == Capabilities::Capability::SourceInfo ); - } - - virtual Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) - { - if ( type == Capabilities::Capability::SourceInfo ) - return new ScriptableServiceInternalSourceInfoCapability( this ); - return 0; - } - - private: - QString m_name; -}; - -class ScriptableServiceInternalComposer : public Meta::Composer, public ScriptableServiceInternalMetaItem -{ - public: - explicit ScriptableServiceInternalComposer( const QString &name = QString() ) - : Meta::Composer() - , m_name( name ) - {} - - Meta::TrackList tracks() - { - return Meta::TrackList(); - } - - QString name() const - { - - if( !m_name.isEmpty() ) - return m_name; - else - return i18nc( "The value is not known", "Unknown" ); - } - - QString prettyName() const - { - return name(); - } - - virtual bool hasCapabilityInterface( Capabilities::Capability::Type type ) const - { - return ( type == Capabilities::Capability::SourceInfo ); - } - - virtual Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) - { - if ( type == Capabilities::Capability::SourceInfo ) - return new ScriptableServiceInternalSourceInfoCapability( this ); - return 0; - } - - private: - QString m_name; -}; - -class ScriptableServiceInternalYear : public Meta::Year, public ScriptableServiceInternalMetaItem -{ - public: - explicit ScriptableServiceInternalYear( const QString &name = QString() ) - : Meta::Year() - , m_name( name ) - {} - - Meta::TrackList tracks() - { - return Meta::TrackList(); - } - - QString name() const - { - if( !m_name.isEmpty() ) - return m_name; - else - return i18nc( "The value is not known", "Unknown" ); - } - - QString prettyName() const - { - return name(); - } - - virtual bool hasCapabilityInterface( Capabilities::Capability::Type type ) const - { - return ( type == Capabilities::Capability::SourceInfo ); - } - - virtual Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) - { - if ( type == Capabilities::Capability::SourceInfo ) - return new ScriptableServiceInternalSourceInfoCapability( this ); - return 0; - } - - private: - QString m_name; -}; - - -#endif diff --git a/src/services/scriptable/ScriptableServiceQueryMaker.h b/src/services/scriptable/ScriptableServiceQueryMaker.h deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceQueryMaker.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#ifndef SCRIPTABLESERVICEQUERYMAKER_H -#define SCRIPTABLESERVICEQUERYMAKER_H - -#include "../DynamicServiceQueryMaker.h" - -#include "core/meta/forward_declarations.h" - -#include "ScriptableServiceCollection.h" - -namespace Collections { - -/** - * A query maker for fetching external data from scripred services. - */ -class ScriptableServiceQueryMaker : public DynamicServiceQueryMaker -{ - Q_OBJECT - -public: - ScriptableServiceQueryMaker( ScriptableServiceCollection * collection, QString name ); - ~ScriptableServiceQueryMaker(); - - virtual void run(); - virtual void abortQuery(); - - virtual QueryMaker* setQueryType( QueryType type ); - - virtual QueryMaker* addFilter( qint64 value, const QString &filter, bool matchBegin = false, bool matchEnd = false ); - - using QueryMaker::addMatch; - virtual QueryMaker* addMatch( const Meta::GenrePtr &genre ); - virtual QueryMaker* addMatch( const Meta::ArtistPtr &artist, ArtistMatchBehaviour behaviour = TrackArtists ); - virtual QueryMaker* addMatch( const Meta::AlbumPtr &album ); - - virtual QueryMaker* setAlbumQueryMode( AlbumQueryMode mode ); - - // ScriptableServiceQueryMaker-specific methods - - /** - * Set to true if ScriptableServiceQueryMaker should convert tracks which are in - * fact playlists to Meta::MultiTrack instances to be playable. Defaults to false. - */ - void setConvertToMultiTracks( bool convert ); - -protected Q_SLOTS: - void slotScriptComplete( ); - -private Q_SLOTS: - void fetchGenre(); - void fetchArtists(); - void fetchAlbums(); - void fetchTracks(); - -protected: - void handleResult( const Meta::GenreList &genres ); - void handleResult( const Meta::ArtistList &artists ); - void handleResult( const Meta::AlbumList &albums ); - void handleResult( const Meta::TrackList &tracks ); - - ScriptableServiceCollection * m_collection; - AmarokProcIO * m_script; - - struct Private; - Private * const d; - - QString m_sessionId; - int m_parentAlbumId; - int m_parentArtistId; - -private: - QString m_name; - bool m_convertToMultiTracks; -}; - -} //namespace Collections - -#endif diff --git a/src/services/scriptable/ScriptableServiceQueryMaker.cpp b/src/services/scriptable/ScriptableServiceQueryMaker.cpp deleted file mode 100644 --- a/src/services/scriptable/ScriptableServiceQueryMaker.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Nikolaj Hald Nielsen * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 2 of the License, or (at your option) any later * - * version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "ScriptableServiceQueryMaker" - -#include "ScriptableServiceQueryMaker.h" - -#include "core/meta/support/MetaConstants.h" -#include "core/support/Debug.h" -#include "core-impl/collections/support/MemoryMatcher.h" -#include "scripting/scriptmanager/ScriptManager.h" -#include "services/scriptable/ScriptableServiceMeta.h" - -#include - -using namespace Collections; - -struct ScriptableServiceQueryMaker::Private { - //don't change the order of items in this enum - enum QueryType { TRACK=1, ALBUM=2, ARTIST=3, GENRE=4, NONE=5 }; - QueryType type; - QueryType closestParent; - int maxsize; - QString callbackString; - int parentId; - AlbumQueryMode albumMode; - QString filter; - QString lastFilter; -}; - -ScriptableServiceQueryMaker::ScriptableServiceQueryMaker( ScriptableServiceCollection * collection, QString name ) - : DynamicServiceQueryMaker() - , d( new Private ) - , m_convertToMultiTracks( false ) -{ - setParent( collection ); - m_collection = collection; - m_name = name; - - connect( collection, &Collections::ScriptableServiceCollection::updateComplete, - this, &ScriptableServiceQueryMaker::slotScriptComplete ); - - d->type = Private::NONE; - d->closestParent = Private::NONE; - d->maxsize = -1; - d->parentId = -1; - d->albumMode = AllAlbums; -} - -ScriptableServiceQueryMaker::~ScriptableServiceQueryMaker() -{ - delete d; -} - - -void ScriptableServiceQueryMaker::run() -{ - if ( d->albumMode == OnlyCompilations ) - return; - - if ( d->type == Private::NONE ) - //TODO error handling - return; - - if ( d->callbackString.isEmpty() ) - d->callbackString = "none"; - - - if ( d->type == Private::GENRE ) { - if ( ( m_collection->levels() == 4 ) && ( m_collection->lastFilter() != d->filter ) ) - { - m_collection->clear(); - } - QTimer::singleShot( 0, this, &ScriptableServiceQueryMaker::fetchGenre ); - } - else if ( d->type == Private::ARTIST ) - { - if ( ( m_collection->levels() == 3 ) && ( m_collection->lastFilter() != d->filter ) ) - { - m_collection->clear(); - } - QTimer::singleShot( 0, this, &ScriptableServiceQueryMaker::fetchArtists ); - } - else if ( d->type == Private::ALBUM ) - { - if ( ( m_collection->levels() == 2 ) && ( m_collection->lastFilter() != d->filter ) ) - { - m_collection->clear(); - } - QTimer::singleShot( 0, this, &ScriptableServiceQueryMaker::fetchAlbums ); - } - else if ( d->type == Private::TRACK ) - { - if ( ( m_collection->levels() == 1 ) && ( m_collection->lastFilter() != d->filter ) ) - { - m_collection->clear(); - } - QTimer::singleShot( 0, this, &ScriptableServiceQueryMaker::fetchTracks ); - } - -} - -void ScriptableServiceQueryMaker::abortQuery() -{ -} - -QueryMaker * ScriptableServiceQueryMaker::setQueryType( QueryType type ) -{ - switch( type ) { - case QueryMaker::Artist: - case QueryMaker::AlbumArtist: - d->type = Private::ARTIST; - return this; - - case QueryMaker::Album: - d->type = Private::ALBUM; - return this; - - case QueryMaker::Track: - d->type = Private::TRACK; - return this; - - case QueryMaker::Genre: - d->type = Private::GENRE; - return this; - - case QueryMaker::Composer: - case QueryMaker::Year: - case QueryMaker::Custom: - case QueryMaker::Label: - case QueryMaker::None: - //TODO: Implement. - return this; - } - - return this; -} - -QueryMaker * ScriptableServiceQueryMaker::addMatch( const Meta::GenrePtr &genre ) -{ - if ( d->closestParent > Private::GENRE ) - { - d->closestParent = Private::GENRE; - const Meta::ScriptableServiceGenre * scriptableGenre = static_cast< const Meta::ScriptableServiceGenre * >( genre.data() ); - d->callbackString = scriptableGenre->callbackString(); - d->parentId = scriptableGenre->id(); - } - return this; -} - -QueryMaker * ScriptableServiceQueryMaker::addMatch( const Meta::ArtistPtr & artist, QueryMaker::ArtistMatchBehaviour behaviour ) -{ - Q_UNUSED( behaviour ); - const Meta::ScriptableServiceArtist *scriptableArtist = dynamic_cast( artist.data() ); - if ( scriptableArtist && d->closestParent > Private::ARTIST ) - { - d->closestParent = Private::ARTIST; - d->callbackString = scriptableArtist->callbackString(); - d->parentId = scriptableArtist->id(); - } - return this; -} - -QueryMaker * ScriptableServiceQueryMaker::addMatch( const Meta::AlbumPtr & album ) -{ - if ( d->closestParent > Private::ALBUM ) - { - d->closestParent = Private::ALBUM; - debug() << "Here!"; - const Meta::ScriptableServiceAlbum * scriptableAlbum = static_cast< const Meta::ScriptableServiceAlbum * >( album.data() ); - d->callbackString = scriptableAlbum->callbackString(); - d->parentId = scriptableAlbum->id(); - } - return this; -} - -void -ScriptableServiceQueryMaker::setConvertToMultiTracks( bool convert ) -{ - m_convertToMultiTracks = convert; -} - -void ScriptableServiceQueryMaker::handleResult( const Meta::GenreList & genres ) -{ - if ( d->maxsize >= 0 && genres.count() > d->maxsize ) - emit newGenresReady( genres.mid( 0, d->maxsize ) ); - else - emit newGenresReady( genres ); -} - -void ScriptableServiceQueryMaker::handleResult( const Meta::AlbumList & albums ) -{ - if ( d->maxsize >= 0 && albums.count() > d->maxsize ) - emit newAlbumsReady( albums.mid( 0, d->maxsize ) ); - else - emit newAlbumsReady( albums ); -} - -void ScriptableServiceQueryMaker::handleResult( const Meta::ArtistList & artists ) -{ - if ( d->maxsize >= 0 && artists.count() > d->maxsize ) - emit newArtistsReady( artists.mid( 0, d->maxsize ) ); - else - emit newArtistsReady( artists ); -} - -void ScriptableServiceQueryMaker::handleResult( const Meta::TrackList &tracks ) -{ - Meta::TrackList ret; - if( m_convertToMultiTracks ) - { - foreach( const Meta::TrackPtr &track, tracks ) - { - using namespace Meta; - const ScriptableServiceTrack *serviceTrack = - dynamic_cast( track.data() ); - if( !serviceTrack ) - { - error() << "failed to convert generic track" << track.data() << "to ScriptableServiceTrack"; - continue; - } - ret << serviceTrack->playableTrack(); - } - } - else - ret = tracks; - - if ( d->maxsize >= 0 && ret.count() > d->maxsize ) - emit newTracksReady( ret.mid( 0, d->maxsize ) ); - else - emit newTracksReady( ret ); -} - -void ScriptableServiceQueryMaker::fetchGenre() -{ - DEBUG_BLOCK - Meta::GenreList genre = m_collection->genreMap().values(); - - if ( genre.count() > 0 ) - { - handleResult( genre ); - emit( queryDone() ); - } - else - //this is where we call the script to get it to add more stuff! - ScriptManager::instance()->ServiceScriptPopulate( m_name, 3, d->parentId, d->callbackString, d->filter ); -} - -void ScriptableServiceQueryMaker::fetchArtists() -{ - DEBUG_BLOCK - Meta::ArtistList artists; - - if ( d->parentId != -1 ) - { - Meta::GenrePtr genrePtr = m_collection->genreById( d->parentId ); - Meta::ScriptableServiceGenre * scGenre = dynamic_cast ( genrePtr.data() ); - if ( scGenre ) - { - Meta::ArtistList allArtists = m_collection->artistMap().values(); - - foreach ( Meta::ArtistPtr artistPtr, allArtists ) - { - Meta::ScriptableServiceArtist *scArtist = dynamic_cast ( artistPtr.data() ); - if ( scArtist && scArtist->genreId() == d->parentId ) - artists.append( artistPtr ); - } - } - } - - if ( artists.count() > 0 ) - { - handleResult( artists ); - emit( queryDone() ); - } - else - //this is where we call the script to get it to add more stuff! - ScriptManager::instance()->ServiceScriptPopulate( m_name, 2, d->parentId, d->callbackString, d->filter ); -} - -void ScriptableServiceQueryMaker::fetchAlbums() -{ - DEBUG_BLOCK - debug() << "parent id: " << d->parentId; - - if ( d->albumMode == OnlyCompilations) - return; - - Meta::AlbumList albums; - - if ( d->parentId != -1 ) - { - albums = matchAlbums( m_collection, m_collection->artistById( d->parentId ) ); - } - else - albums = m_collection->albumMap().values(); - if ( albums.count() > 0 ) - { - handleResult( albums ); - emit( queryDone() ); - } - else - //this is where we call the script to get it to add more stuff! - ScriptManager::instance()->ServiceScriptPopulate( m_name, 1, d->parentId, d->callbackString, d->filter ); -} - -void ScriptableServiceQueryMaker::fetchTracks() -{ - DEBUG_BLOCK - - Meta::TrackList tracks; - - debug() << "parent id: " << d->parentId; - - Meta::AlbumPtr album; - if ( d->parentId != -1 && ( album = m_collection->albumById( d->parentId ) ) ) - { - AlbumMatcher albumMatcher( album ); - tracks = albumMatcher.match( m_collection->trackMap().values() ); - } - else - tracks = m_collection->trackMap().values(); - - if ( tracks.count() > 0 ) { - handleResult( tracks ); - emit( queryDone() ); - } - else - //this is where we call the script to get it to add more stuff! - { - debug() << "i am sending signals!"; - ScriptManager::instance()->ServiceScriptPopulate( m_name, 0, d->parentId, d->callbackString, d->filter ); - } -} - -void ScriptableServiceQueryMaker::slotScriptComplete() -{ - DEBUG_BLOCK - - if ( d->type == Private::GENRE ) - { - Meta::GenreList genre = m_collection->genreMap().values(); - handleResult( genre ); - } - else if ( d->type == Private::ARTIST ) - { - Meta::ArtistList artists; - if ( d->parentId != -1 ) - { - Meta::GenrePtr genrePtr = m_collection->genreById( d->parentId ); - Meta::ScriptableServiceGenre * scGenre = dynamic_cast ( genrePtr.data() ); - if ( scGenre ) - { - Meta::ArtistList allArtists = m_collection->artistMap().values(); - - foreach ( Meta::ArtistPtr artistPtr, allArtists ) - { - Meta::ScriptableServiceArtist *scArtist = dynamic_cast ( artistPtr.data() ); - - if ( scArtist && scArtist->genreId() == d->parentId ) - artists.append( artistPtr ); - } - } - } - else - artists = m_collection->artistMap().values(); - debug() << "there are " << artists.count() << " artists"; - handleResult( artists ); - } - else if ( d->type == Private::ALBUM ) - { - Meta::AlbumList albums; - if ( d->parentId != -1 ) - { - albums = matchAlbums( m_collection, m_collection->artistById( d->parentId ) ); - } - else - albums = m_collection->albumMap().values(); - - debug() << "there are " << albums.count() << " albums"; - handleResult( albums ); - } - else if ( d->type == Private::TRACK ) - { - Meta::TrackList tracks; - if ( d->parentId != -1 ) - { - Meta::AlbumPtr album = m_collection->albumById( d->parentId ); - if( album ) - { - AlbumMatcher albumMatcher( album ); - tracks = albumMatcher.match( m_collection->trackMap().values() ); - } - } - else - tracks = m_collection->trackMap().values(); - debug() << "there are " << tracks.count() << " tracks"; - handleResult( tracks ); - } - emit( queryDone() ); -} - -QueryMaker * ScriptableServiceQueryMaker::setAlbumQueryMode( AlbumQueryMode mode ) -{ - d->albumMode = mode; - return this; -} - -QueryMaker * ScriptableServiceQueryMaker::addFilter( qint64 value, const QString & filter, bool matchBegin, bool matchEnd ) -{ - Q_UNUSED( matchBegin ) - Q_UNUSED( matchEnd ) - - DEBUG_BLOCK - - if ( value == Meta::valTitle ) - { - //I am sure there is a really good reason to add this space, as nothing works if it is removed, but WHY?!? - d->filter += filter + ' '; - d->filter = d->filter.replace( ' ', "%20" ); - } - - int level = 0; - - if ( d->type == Private::GENRE ) - level = 4; - if ( d->type == Private::ARTIST ) - level = 3; - else if ( d->type == Private::ALBUM ) - level = 2; - else if ( d->type == Private::TRACK ) - level = 1; - - // should only clear all if we are querying for a top level item - if ( m_collection->levels() == level ) - { - //we need to clear everything as we have no idea what the scripts wants to do... - //TODO: with KSharedPointers in use, does this leak!? - - debug() << "clear all!!!!!!!!!!!!!!"; - m_collection->clear(); - } - - d->lastFilter = d->filter; - m_collection->setLastFilter( d->filter ); - return this; - -} - diff --git a/src/services/scriptable/shoutcast_service.rb b/src/services/scriptable/shoutcast_service.rb deleted file mode 100644 --- a/src/services/scriptable/shoutcast_service.rb +++ /dev/null @@ -1,75 +0,0 @@ - -# Simple script for testing the scriptable service browser -# by creating a simple dynamic shoutcast directory browser. -# when called with no arguments it creates the service, and -# when called with a parent node id and a genre, it populates that -# parent node with all stations in that genre -# -# (c) 2007 Nikolaj Hald Nielsen -# -# License: GNU General Public License V2 - - -require 'net/http' -require 'uri' - - - - -def parse_genre(nodeId, genre) - - puts "genre: " + genre - stations_xml = Net::HTTP.get(URI.parse('http://www.shoutcast.com/sbin/newxml.phtml?genre=' + genre) ) - station_elements = stations_xml.split("\n") - station_elements.each do |station| - station =~ /(<\/genre>)/# - - system("qdbus", "org.kde.amarok", "/ScriptableServiceManager", "insertDynamicElement", $2, script_command, $2, "A collection of streams in the " + genre + " genre", 0.to_s, "Shoutcast Streams") - - end - - `qdbus org.kde.amarok /ScriptableServiceManager updateComplete "Shoutcast Streams"` - -end - -if ARGV.size == 0 then - setup_service() -else - parse_genre(ARGV[0], ARGV[1]) -end - - - - - - - - - -