summaryrefslogtreecommitdiffstats
path: root/noatun-plugins/lyrics
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit84da08d7b7fcda12c85caeb5a10b4903770a6f69 (patch)
tree2a6aea76f2dfffb4cc04bb907c4725af94f70e72 /noatun-plugins/lyrics
downloadtdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.tar.gz
tdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaddons@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'noatun-plugins/lyrics')
-rw-r--r--noatun-plugins/lyrics/Makefile.am17
-rw-r--r--noatun-plugins/lyrics/TODO17
-rw-r--r--noatun-plugins/lyrics/cmodule.cpp218
-rw-r--r--noatun-plugins/lyrics/cmodule.h43
-rw-r--r--noatun-plugins/lyrics/historymanager.cpp56
-rw-r--r--noatun-plugins/lyrics/historymanager.h28
-rw-r--r--noatun-plugins/lyrics/lyrics.cpp268
-rw-r--r--noatun-plugins/lyrics/lyrics.h55
-rw-r--r--noatun-plugins/lyrics/lyrics.plugin117
-rw-r--r--noatun-plugins/lyrics/lyricsui.rc24
10 files changed, 843 insertions, 0 deletions
diff --git a/noatun-plugins/lyrics/Makefile.am b/noatun-plugins/lyrics/Makefile.am
new file mode 100644
index 0000000..ac34a17
--- /dev/null
+++ b/noatun-plugins/lyrics/Makefile.am
@@ -0,0 +1,17 @@
+INCLUDES= $(all_includes)
+kde_module_LTLIBRARIES = noatunlyrics.la
+
+noatunlyrics_la_SOURCES = lyrics.cpp historymanager.cpp cmodule.cpp
+
+noatunlyrics_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+noatunlyrics_la_LIBADD = $(LIB_KHTML) $(LIB_KFILE) -lnoatun
+
+noatunlyrics_la_METASOURCES = AUTO
+
+noinst_HEADERS = lyrics.h
+
+noatun_DATA = lyrics.plugin lyricsui.rc
+noatundir = $(kde_datadir)/noatun
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/lyrics.pot
diff --git a/noatun-plugins/lyrics/TODO b/noatun-plugins/lyrics/TODO
new file mode 100644
index 0000000..0b0c503
--- /dev/null
+++ b/noatun-plugins/lyrics/TODO
@@ -0,0 +1,17 @@
+*** TODO for the Lyrics plugin
+ any contribution is welcomed! ***
+
+- Save scroll position (in a per search engine basis, probably)
+ - To account for tables (like in SM)
+- Save Lyrics to file:
+ - As a URL
+ - As a HTML file
+ - As Selected text
+- Automatically searchs at all the places
+ (configurable "no result" regexp)
+- Ideas for the interface:
+ - Save as (URL|HTML|SELECTED TEXT)
+ - Auto save songs (at ~ or global)
+ - Remove (.*) ie, stuff like (live), (cover), etc
+ - Remove non alphabetic stuff
+- Max search size
diff --git a/noatun-plugins/lyrics/cmodule.cpp b/noatun-plugins/lyrics/cmodule.cpp
new file mode 100644
index 0000000..2501ebb
--- /dev/null
+++ b/noatun-plugins/lyrics/cmodule.cpp
@@ -0,0 +1,218 @@
+#include "cmodule.h"
+#include "lyrics.h"
+#include <qlayout.h>
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <kmessagebox.h>
+#include <qvgroupbox.h>
+#include <qgrid.h>
+#include <klistbox.h>
+#include <klineedit.h>
+#include <kbuttonbox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+extern Lyrics *lyrics;
+
+const char *const DEFAULT_NAME =
+ "Google,"
+ "Pure Lyrics,"
+ "Sing365,"
+ "Lyrics Planet,"
+ "Lyrics World,"
+ "Get Lyrics,"
+ "AZLyrics,"
+ "Astraweb,"
+ "SongMeanings,"
+ "Google (Feeling Lucky),"
+ "Everything2,"
+ "Everything2 (author info)";
+
+const char *const DEFAULT_QUERY =
+ "http://www.google.com/search?q=lyrics+$(title)+$(author)+$(album),"
+ "http://www.purelyrics.com/index.php?search_artist=$(author)&search_album=$(album)&search_title=$(title)&search_lyrics=&search_advsubmit2=Search,"
+ "http://search.sing365.com/search.php?searchstr=$(title)&submit=search&category=song,"
+ "http://www.lyricsplanet.com/index.php3?style=searchtitle&fix=1&searchstring=$(title),"
+ "http://www.lyricsworld.com/cgi-bin/search.cgi?q=$(title)+$(author),"
+ "http://www.getlyrics.com/search.php?Song=$(title),"
+ "http://www.azlyrics.com/cgi-bin/s.cgi?q=$(title)+$(author),"
+ "http://search.lyrics.astraweb.com?word=$(title)+$(author)+$(album),"
+ "http://www.songmeanings.net/search.php?type=titles&query=$(title),"
+ "http://www.google.com/search?q=lyrics+%22$(title)%22+%22$(author)%22+%22$(album)%22&btnI=I%27m+Feeling+Lucky,"
+ "http://everything2.com/index.pl?node=$(title),"
+ "http://everything2.com/index.pl?node=$(author),"
+ "http://www.letssingit.com/cgi-exe/am.cgi?a=search&p=1&s=$(title)&l=song";
+
+LyricsCModule::LyricsCModule(QObject *_parent) : CModule(i18n("Lyrics"), i18n("Configure Lyrics Plugin"), "document", _parent) {
+ /* Thanks to the kde-usability guys for the help designing this dialog!
+ * help to simon edwards of KGuardGod, for a big help designing it */
+ QVBoxLayout *vlayout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
+ QHBoxLayout *hlayout = new QHBoxLayout(vlayout, KDialog::spacingHint());
+ vlayout->setStretchFactor( hlayout, 1 );
+
+ // Search box
+ QVBoxLayout *boxlayout = new QVBoxLayout( hlayout, KDialog::spacingHint() );
+ boxlayout->addWidget( new QLabel( i18n("Search providers:" ), this ) );
+ providersBox = new KListBox( this, "providersBox" );
+ boxlayout->addWidget(providersBox);
+
+ boxButtons = new KButtonBox( this, Vertical );
+ boxButtons->addButton( i18n( "New Search Provider" ), this, SLOT( newSearch() ) );
+ boxButtons->addButton( i18n( "Delete Search Provider" ), this, SLOT( delSearch() ) );
+ boxButtons->addButton( i18n( "Move Up" ), this, SLOT( moveUpSearch() ) );
+ boxButtons->addButton( i18n( "Move Down" ), this, SLOT( moveDownSearch() ) );
+ boxButtons->layout();
+ boxlayout->addWidget( boxButtons );
+
+ // Edit box
+ QGroupBox *propBox = new QVGroupBox( i18n("Search Provider Properties" ), this );
+ QGrid *editGrid = new QGrid(2, propBox );
+ editGrid->setSpacing( propBox->insideSpacing() );
+ new QLabel( i18n( "Name:" ), editGrid );
+ nameEdit = new KLineEdit( editGrid );
+ new QLabel( i18n( "Query:" ), editGrid );
+ queryEdit = new KLineEdit( editGrid );
+ /* ATTENTION to translators:
+ * The property names can't be translated. This means that $(author) must be kept as $(author), $(title) as $(title), etc, or it won't work.*/
+ QLabel *textLabel = new QLabel(i18n("For your query, you can use any property of your multimedia item, just enclosing it with a $(property).\n\nSome common properties used are $(title), $(author) and $(album). For example, to search in Google for the author, title and track, just use:\nhttp://www.google.com/search?q=$(author)+$(title)+$(track)"), propBox, "textLabel");
+ textLabel->setAlignment(Qt::WordBreak);
+ hlayout->addWidget( propBox, 1 );
+
+ /* Signal/slots */
+ nameEdit->setEnabled( false );
+ queryEdit->setEnabled( false );
+ connect( providersBox, SIGNAL( highlighted( QListBoxItem * ) ), this, SLOT( selected( QListBoxItem * ) ) );
+ connect( nameEdit, SIGNAL( textChanged( const QString &) ), this, SLOT( nameChanged( const QString & ) ) );
+ connect( queryEdit, SIGNAL( textChanged( const QString & ) ), this, SLOT( queryChanged( const QString & ) ) );
+
+
+
+ vlayout->addStretch();
+ reopen();
+ save();
+}
+
+void LyricsCModule::newSearch(QString name, QString query) {
+ kdDebug(90020) << "New search" << endl;
+ SearchProvider s = { name, query };
+ mProviders.push_back( s );
+ providersBox->insertItem( name );
+ providersBox->setCurrentItem( providersBox->count()-1 );
+ nameEdit->setEnabled( true );
+ queryEdit->setEnabled( true );
+//X if ( providersBox->count() == 1 )
+//X providersBox->setCurrentItem( 0 );
+}
+
+void LyricsCModule::selected( QListBoxItem *i ) {
+ kdDebug(90020) << "selected" << endl;
+ int index = providersBox->index( i );
+ if ( index < 0 )
+ return;
+ if ( nameEdit->text() != mProviders[ index ].name )
+ nameEdit->setText( mProviders[ index ].name );
+ if ( queryEdit->text() != mProviders[ index ].url )
+ queryEdit->setText( mProviders[ index ].url );
+}
+
+
+void LyricsCModule::delSearch() {
+ if ( mProviders.size() == 1 ) {
+ KMessageBox::sorry( this, i18n( "You must have at least one search provider. The current one will not be removed." ) );
+ return;
+ }
+ int index = providersBox->currentItem();
+ QValueVector<SearchProvider>::iterator it;
+ for ( it = mProviders.begin(); ( *it ).name != mProviders[ index ].name || ( *it ).url != mProviders[ index ].url; ++it );
+ mProviders.erase( it );
+ providersBox->removeItem( index );
+ providersBox->setSelected( providersBox->currentItem(), true );
+}
+
+void LyricsCModule::moveUpSearch() {
+ if ( providersBox->currentItem() <= 0 )
+ return;
+ int index = providersBox->currentItem();
+ QString name = mProviders[ index ].name;
+ QString url = mProviders[ index ].url;
+ mProviders[ index ].name = mProviders[ index-1 ].name;
+ mProviders[ index ].url = mProviders[ index-1 ].url;
+ mProviders[ index-1 ].name = name;
+ mProviders[ index-1 ].url = url;
+ providersBox->changeItem( mProviders[ index-1 ].name, index-1 );
+ providersBox->changeItem( mProviders[ index ].name, index );
+ providersBox->setSelected( index-1, true );
+}
+
+void LyricsCModule::moveDownSearch() {
+ if ( static_cast<unsigned int>( providersBox->currentItem() ) >= providersBox->count()-1 )
+ return;
+ int index = providersBox->currentItem();
+ QString name = mProviders[ index ].name;
+ QString url = mProviders[ index ].url;
+ mProviders[ index ].name = mProviders[ index+1 ].name;
+ mProviders[ index ].url = mProviders[ index+1 ].url;
+ mProviders[ index+1 ].name = name;
+ mProviders[ index+1 ].url = url;
+ providersBox->changeItem( mProviders[ index+1 ].name, index+1 );
+ providersBox->changeItem( mProviders[ index ].name, index );
+ providersBox->setSelected( index+1, true );
+}
+
+void LyricsCModule::nameChanged( const QString &name ) {
+ kdDebug(90020) << "name changed" << endl;
+ if ( providersBox->currentItem() < 0 )
+ return;
+ mProviders[ providersBox->currentItem() ].name = name;
+ if ( name != providersBox->text( providersBox->currentItem() ) )
+ providersBox->changeItem( name, providersBox->currentItem() );
+}
+
+void LyricsCModule::queryChanged( const QString &query ) {
+ kdDebug(90020) << "query changed" << endl;
+ if ( providersBox->currentItem() < 0 )
+ return;
+ mProviders[ providersBox->currentItem() ].url = query;
+}
+
+
+void LyricsCModule::save() {
+ KConfig *conf = KGlobal::config();
+ conf->setGroup( "Lyrics" );
+ QStringList queryList, nameList;
+ QValueVector<SearchProvider>::iterator it;
+ for ( it = mProviders.begin(); it != mProviders.end(); ++it ) {
+ kdDebug(90020) << "query:" << ( *it ).url << endl;
+ queryList += ( *it ).url;
+ nameList += ( *it ).name;
+ }
+ conf->writeEntry( "queryList", queryList );
+ conf->writeEntry( "nameList", nameList );
+ /* TODO */
+ // APPLY settings
+ if ( lyrics )
+ lyrics->setProviders( mProviders );
+}
+
+void LyricsCModule::reopen() {
+ QStringList queryList, nameList;
+ KConfig *conf = KGlobal::config();
+ mProviders.clear();
+ providersBox->clear();
+ kdDebug(90020) << "config read" << endl;
+ conf->setGroup( "Lyrics" );
+ queryList = conf->readListEntry( "queryList" );
+ nameList = conf->readListEntry( "nameList" );
+ if ( queryList.count() == 0 && nameList.count() == 0 ) {
+ queryList = QStringList::split( ",", DEFAULT_QUERY );
+ nameList = QStringList::split( ",", DEFAULT_NAME );
+ }
+ QStringList::Iterator queryIt, nameIt;
+ for ( queryIt = queryList.begin(), nameIt = nameList.begin(); queryIt != queryList.end() && nameIt != nameList.end(); ++queryIt, ++nameIt ) {
+ kdDebug(90020) << "Read:" << *queryIt << " and " << *nameIt << endl;
+ newSearch( *nameIt, *queryIt );
+ }
+}
+
+#include "cmodule.moc"
diff --git a/noatun-plugins/lyrics/cmodule.h b/noatun-plugins/lyrics/cmodule.h
new file mode 100644
index 0000000..dbb2da7
--- /dev/null
+++ b/noatun-plugins/lyrics/cmodule.h
@@ -0,0 +1,43 @@
+#ifndef _LYRICSCMODULE_H_
+#define _LYRICSCMODULE_H_
+
+#include <noatun/pref.h>
+#include <qvaluevector.h>
+#include <klocale.h>
+
+class KLineEdit;
+class KListBox;
+class KButtonBox;
+
+struct SearchProvider {
+ QString name;
+ QString url;
+};
+
+class LyricsCModule : public CModule {
+ Q_OBJECT
+ public:
+ LyricsCModule(QObject *_parent);
+ public slots:
+ virtual void save(void);
+ virtual void reopen(void);
+ void newSearch(QString name = i18n( "New Search Provider" ), QString query = "");
+ void delSearch();
+ void moveUpSearch();
+ void moveDownSearch();
+ void selected( QListBoxItem *i );
+ void nameChanged( const QString &name );
+ void queryChanged( const QString &query );
+ protected:
+ KListBox *providersBox;
+ KButtonBox *boxButtons;
+ KLineEdit *nameEdit;
+ KLineEdit *queryEdit;
+ QValueVector<SearchProvider> mProviders;
+};
+
+
+
+
+
+#endif
diff --git a/noatun-plugins/lyrics/historymanager.cpp b/noatun-plugins/lyrics/historymanager.cpp
new file mode 100644
index 0000000..1524d7b
--- /dev/null
+++ b/noatun-plugins/lyrics/historymanager.cpp
@@ -0,0 +1,56 @@
+#include "historymanager.h"
+
+/** HISTORY MANAGER ***
+*** TODO: Add more complex support (like in Konqueror)
+ Maybe use Konqueror's History Manager */
+
+HistoryManager::HistoryManager(QObject *parent) : QObject(parent) {
+}
+
+HistoryManager::~HistoryManager() {
+}
+
+void HistoryManager::addURL(const KURL &url) {
+ /* push current URL to the back */
+ if (!currentURL.isEmpty()) {
+ if (back_stack.count() == 0)
+ emit uiChanged( Back, true );
+ back_stack.push(currentURL);
+ }
+ /* Make a copy of the new URL */
+ currentURL = url;
+ /* Clear the forward stack */
+ if (forward_stack.count() > 0)
+ emit uiChanged( Forward, false );
+ forward_stack.clear();
+}
+
+KURL HistoryManager::back() {
+ if (back_stack.count() <= 0)
+ return KURL();
+ /* The currentURL is now pushed in the forward_stack */
+ if (forward_stack.count() == 0)
+ emit uiChanged( Forward, true );
+ forward_stack.push(currentURL);
+ /* The last URL is the back stack is now popped as the current one */
+ if (back_stack.count() == 1)
+ emit uiChanged( Back, false );
+ currentURL = back_stack.pop();
+ return currentURL;
+}
+
+KURL HistoryManager::forward() {
+ if (forward_stack.count() <= 0)
+ return KURL();
+ /* Push the currentURL into the back_stack */
+ if (back_stack.count() == 0)
+ emit uiChanged( Back, true );
+ back_stack.push(currentURL);
+ /* Pop from the forward_stack into the currentURL */
+ if (forward_stack.count() == 1)
+ emit uiChanged( Forward, false );
+ currentURL = forward_stack.pop();
+ return currentURL;
+}
+
+#include "historymanager.moc"
diff --git a/noatun-plugins/lyrics/historymanager.h b/noatun-plugins/lyrics/historymanager.h
new file mode 100644
index 0000000..d2fdb29
--- /dev/null
+++ b/noatun-plugins/lyrics/historymanager.h
@@ -0,0 +1,28 @@
+#ifndef _HISTORY_MANAGER_H
+#define _HISTORY_MANAGER_H
+
+#include <kurl.h>
+#include <qvaluestack.h>
+#include <qobject.h>
+
+class HistoryManager : public QObject {
+ Q_OBJECT
+ public:
+ HistoryManager(QObject *parent = NULL);
+ ~HistoryManager();
+ KURL back();
+ KURL forward();
+ void addURL(const KURL &);
+ enum Buttons {
+ Back,
+ Forward
+ };
+ signals:
+ void uiChanged(int, bool);
+ protected:
+ QValueStack<KURL> back_stack;
+ QValueStack<KURL> forward_stack;
+ KURL currentURL;
+};
+
+#endif
diff --git a/noatun-plugins/lyrics/lyrics.cpp b/noatun-plugins/lyrics/lyrics.cpp
new file mode 100644
index 0000000..611db9c
--- /dev/null
+++ b/noatun-plugins/lyrics/lyrics.cpp
@@ -0,0 +1,268 @@
+#include <klocale.h>
+#include <klineeditdlg.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <khtmlview.h>
+#include <kstdaction.h>
+#include <kstatusbar.h>
+#include <qregexp.h>
+#include "lyrics.h"
+#include <noatun/player.h>
+#include <kdebug.h>
+#include "historymanager.h"
+
+
+extern "C"
+{
+ Plugin *create_plugin()
+ {
+ KGlobal::locale()->insertCatalogue("lyrics");
+ return new Lyrics();
+ }
+}
+
+Lyrics *lyrics;
+
+Lyrics::Lyrics() : KMainWindow(), Plugin(), active(false)
+{
+ lyrics = this;
+ /* Create default actions */
+ (void)KStdAction::close(this, SLOT(close()), actionCollection());
+ ( void )KStdAction::goTo( this, SLOT( goTo() ), actionCollection(), "go_web_goTo" );
+ //(void)KStdAction::print(this, SLOT(print()), actionCollection());
+ //(void)KStdAction::printPreview(this, SLOT(printPreview()), actionCollection());
+ //(void)KStdAction::mail(this, SLOT(mail()), actionCollection());
+ //(void)KStdAction::find(this, SLOT(find()), actionCollection());
+ follow_act = new KToggleAction(i18n("&Follow Noatun Playlist"), "goto", 0, actionCollection(), "follow");
+ KStdAction::redisplay(this, SLOT(viewLyrics()), actionCollection());
+ attach_act = new KToggleAction(i18n("&Link URL to File"), "attach", KShortcut("CTRL+ALT+A"), actionCollection(), "attach_url");
+ connect(attach_act, SIGNAL(toggled(bool)), this, SLOT(attach(bool)));
+ back_act = KStdAction::back(this, SLOT(back()), actionCollection());
+ back_act->setEnabled(false);
+ forward_act = KStdAction::forward(this, SLOT(forward()), actionCollection());
+ forward_act->setEnabled(false);
+ new KWidgetAction( new QLabel(i18n("Search provider:"), this, "kde toolbar widget"), i18n("Search Provider"), 0, 0, 0, actionCollection(), "search_label");
+ site_act = new KSelectAction(i18n("&Search Provider"), 0, this, SLOT(viewLyrics()), actionCollection(), "search_provider");
+
+ /* Add entry to menu */
+ menuID = napp->pluginMenuAdd(i18n("&View Lyrics"), this, SLOT(viewLyrics()));
+
+ /* Create history manager and htmlpart */
+ history = new HistoryManager(this);
+ htmlpart = new KHTMLPart(this);
+ //htmlpart->view()->setMinimumSize(350, 420);
+
+ /* Connect signals/slots */
+ connect( htmlpart->browserExtension(), SIGNAL(openURLRequestDelayed( const KURL &, const KParts::URLArgs & )), this, SLOT(openURLRequest( const KURL &, const KParts::URLArgs & )));
+ connect( htmlpart, SIGNAL(started(KIO::Job *)), this, SLOT(loadingURL(KIO::Job *)) );
+ connect( htmlpart, SIGNAL(completed()), this, SLOT(loadedURL()) );
+ connect( history, SIGNAL(uiChanged(int, bool)), this, SLOT(changeUI(int, bool)) );
+ connect( napp->player(), SIGNAL(newSong()), this, SLOT(newSong()) );
+
+ /* Status bar */
+ statusBar()->insertItem(i18n("Ready"), 0, 1);
+ statusBar()->setItemAlignment(0, Qt::AlignLeft);
+
+ /* Finalize the GUI */
+ setCentralWidget(htmlpart->view());
+ createGUI("lyricsui.rc");
+ setAutoSaveSettings("Lyrics");
+
+ /* Load configuration */
+ KConfig *config = KGlobal::config();
+ config->setGroup("Lyrics");
+ follow_act->setChecked(config->readBoolEntry("follow", true));
+ /* Create config object */
+ new LyricsCModule(this);
+
+}
+
+void Lyrics::goTo() {
+ bool sel = false;
+ QString url = KLineEditDlg::getText( i18n( "Please enter the URL you want to go to:" ), htmlpart->url().prettyURL(), &sel, this );
+ if ( !url.isEmpty() && sel )
+ go( KURL( url ) );
+}
+
+void Lyrics::setProviders( QValueVector<SearchProvider> &sites ) {
+ mSites = sites;
+ QStringList sitesName;
+ for (unsigned int i = 0; i < mSites.size(); ++i) {
+ sitesName += mSites[i].name;
+ }
+ site_act->setItems(sitesName);
+ site_act->setCurrentItem(0);
+}
+
+void Lyrics::attach(bool a) {
+ if ( !napp->player()->current() )
+ return;
+ if (a) {
+ KMessageBox::information(this, i18n("Choosing this option, the current URL will be attached to the current file. This way, if you try to view the lyrics of this file later, you won't have to search for it again. This information can be stored between sessions, as long as your playlist stores metadata about the multimedia items (almost all the playlists do). If you want to be able to search for other lyrics for this music, you must select this option again to clear the stored URL."), QString::null, "lyrics::attach_info");
+ kdDebug(90020) << "Setting URL for (attach)" << napp->player()->current().title() << endl;
+ napp->player()->current().setProperty("Lyrics::URL", htmlpart->url().url());
+ site_act->setEnabled(false);
+ actionCollection()->action("search_label")->setEnabled(false);
+ }
+ else {
+ kdDebug(90020) << "Clearing URL for " << napp->player()->current().title() << endl;
+ napp->player()->current().clearProperty("Lyrics::URL");
+ site_act->setEnabled(true);
+ actionCollection()->action("search_label")->setEnabled(true);
+ }
+}
+
+void Lyrics::loadingURL(KIO::Job *)
+{
+ statusBar()->changeItem(i18n("Loading..."), 0);
+}
+
+void Lyrics::loadedURL()
+{
+ if ( !napp->player()->current() )
+ return;
+ statusBar()->changeItem(i18n("Loaded"), 0);
+ setCaption(i18n("Lyrics: %1").arg(napp->player()->current().property("title")));
+ if (!htmlpart->url().url().isEmpty() && napp->player()->current() && !napp->player()->current().property("Lyrics::URL").isEmpty()) {
+ kdDebug(90020) << "Setting URL for (loaded)" << napp->player()->current().title() << endl;
+ napp->player()->current().setProperty("Lyrics::URL", htmlpart->url().url());
+ }
+}
+
+void Lyrics::back()
+{
+ KURL url = history->back();
+ if (url.isEmpty())
+ return;
+ kdDebug(90020) << "Going to " << url.url() << endl;
+ htmlpart->openURL(url);
+}
+
+void Lyrics::forward()
+{
+ KURL url = history->forward();
+ if (url.isEmpty())
+ return;
+ kdDebug(90020) << "Going to " << url.url() << endl;
+ htmlpart->openURL(url);
+}
+
+void Lyrics::changeUI(int button, bool enable)
+{
+ if (button == HistoryManager::Back)
+ back_act->setEnabled( enable );
+ else if (button == HistoryManager::Forward)
+ forward_act->setEnabled( enable );
+}
+
+void Lyrics::go(const KURL &url)
+{
+ history->addURL(url);
+ kdDebug(90020) << "Going to " << url.url() << endl;
+ htmlpart->openURL(url);
+}
+
+void Lyrics::newSong() {
+ kdDebug(90020) << "New song!" << endl;
+ // If I'm not following, just forget about it
+ if (!follow_act->isChecked())
+ return;
+ if (active)
+ viewLyrics();
+ // TODO: If not visible, maybe it would be a good idea
+ // to load the lyrics on advance
+}
+
+
+void Lyrics::viewLyrics(int index)
+{
+ if (!napp->player()->current()) {
+ KMessageBox::sorry(this, i18n("You can only view the lyrics of the current song, and currently there is none."));
+ return;
+ }
+//X <small>(if the above information is incorrect, the search may not find the correct music. If that's the case, use a tag editor to fix it. Hint: Use the luckytag plugin from the kdeaddons module to try to guess title, author and album from the song filename)</small><br>
+ QString url, name;
+ if (index < 0)
+ index = site_act->currentItem();
+ if ( index < 0 )
+ return;
+ url = mSites[index].url;
+ name = mSites[index].name;
+ QRegExp props_regexp("\\$\\((\\w+)\\)");
+ int pos = props_regexp.search(url);
+ while (pos >= 0) {
+ QString property = props_regexp.cap(1);
+ url.replace(pos, props_regexp.matchedLength(), napp->player()->current().property(property));
+ pos = props_regexp.search(url);
+ }
+ QString title(napp->player()->current().property("title"));
+ setCaption(i18n("Loading Lyrics for %1").arg(title));
+ // Check if we have a music playing
+ if (napp->player()->current()) {
+ htmlpart->begin();
+ htmlpart->write(i18n("<HTML>"
+ "<BODY>"
+ "<p><strong>Please wait! Searching for...</strong></p>"
+ "<TABLE BORDER=1 WIDTH=\"100%\">"
+ "<TR><TD BGCOLOR=\"#707671\"><strong>Title</strong></TD><TD>%1</TD></TR>"
+ "<TR><TD BGCOLOR=\"#707671\"><strong>Author</strong></TD><TD>%2</TD></TR>"
+ "<TR><TD BGCOLOR=\"#707671\"><strong>Album</strong></TD><TD>%3</TD></TR>"
+ "</TABLE>").arg( napp->player()->current().property( "title" ) ).arg( napp->player()->current().property( "author" ) ).arg( napp->player()->current().property( "album" ) ) );
+ KURL _url;
+ /* Check if we should use the store url or the query one */
+ if (napp->player()->current().property("Lyrics::URL").isEmpty()) {
+ /* Use the query one */
+ _url = url;
+ _url.setQuery(_url.query().replace(QRegExp("%20"), "+"));
+ kdDebug(90020) << "I'm using the query url" << endl;
+ attach_act->setChecked(false);
+ site_act->setEnabled(true);
+ actionCollection()->action("search_label")->setEnabled(true);
+ htmlpart->write( i18n( "<hr><p><strong>Searching at %1</strong><br><small>(<a href=\"%3\">%2</a></small>)</p>" ).arg( name ).arg( _url.prettyURL() ).arg( _url.url() ) );
+ } else {
+ _url = napp->player()->current().property("Lyrics::URL");
+ _url.setQuery(_url.query().replace(QRegExp("%20"), "+"));
+ kdDebug(90020) << "I'm using the stored url" << endl;
+ attach_act->setChecked(true);
+ site_act->setEnabled(false);
+ actionCollection()->action("search_label")->setEnabled(false);
+ htmlpart->write( i18n( "<hr><p><strong>Using the stored URL</strong><br><small>(<a href=\"%2\">%1</a></small>)</p>" ).arg( _url.prettyURL() ).arg( _url.url() ) );
+ }
+ htmlpart->write( "</BODY></HTML>" );
+ htmlpart->end();
+ go(_url);
+ this->show();
+ KMessageBox::information( this, i18n( "In order to find the lyrics for the current song, this plugin uses the properties stored with each song, such as its title, author and album. These properties are usually retrieved by a tag reader, but in some cases they may not be present or be incorrect. In that case, the Lyrics plugin will not be able to find the lyrics until these properties are fixed (you can fix them using the tag editor).\nHint: The lucky tag plugin, present in the kdeaddons module, can try to guess properties such as title and author from the filename of a song. Enabling it may increase the probability of finding lyrics." ), QString::null, "Lyrics::usage_info" );
+ active = true;
+ }
+}
+
+void Lyrics::openURLRequest( const KURL &url, const KParts::URLArgs & )
+{
+ go(url);
+}
+
+Lyrics::~Lyrics()
+{
+ /* Save configurations */
+ KConfig *config = KGlobal::config();
+ config->setGroup("Lyrics");
+ config->writeEntry("follow", follow_act->isChecked());
+ // Force saving, as closeEvent is probably never called
+ saveMainWindowSettings(config, "Lyrics");
+ napp->pluginMenuRemove(menuID);
+}
+
+bool Lyrics::queryClose()
+{
+ if( kapp->sessionSaving())
+ return true;
+ hide();
+ htmlpart->closeURL();
+ htmlpart->begin();
+ htmlpart->end();
+ active = false;
+ return false;
+}
+
+#include "lyrics.moc"
diff --git a/noatun-plugins/lyrics/lyrics.h b/noatun-plugins/lyrics/lyrics.h
new file mode 100644
index 0000000..9454604
--- /dev/null
+++ b/noatun-plugins/lyrics/lyrics.h
@@ -0,0 +1,55 @@
+#ifndef LYRICS_H
+#define LYRICS_H
+
+#include <noatun/plugin.h>
+#include <noatun/player.h>
+#include <noatun/app.h>
+#include <kmainwindow.h>
+#include <qvaluevector.h>
+#include <khtml_part.h>
+#include <kaction.h>
+#include "cmodule.h"
+
+class HistoryManager;
+
+class Lyrics : public KMainWindow, public Plugin {
+Q_OBJECT
+
+public:
+ Lyrics();
+ ~Lyrics();
+ void go(const KURL &);
+ void setProviders( QValueVector<SearchProvider> &sites );
+
+public slots:
+ void viewLyrics(int index = -1);
+ void back();
+ void forward();
+
+protected:
+ bool queryClose();
+
+protected slots:
+ void changeUI(int, bool);
+ void openURLRequest( const KURL &, const KParts::URLArgs & );
+ void loadingURL(KIO::Job *);
+ void loadedURL();
+ void attach(bool);
+ void newSong();
+ void goTo();
+
+private:
+ int menuID;
+ KAction *back_act, *forward_act;
+ KToggleAction *follow_act;
+ KToggleAction *attach_act;
+ KSelectAction *site_act;
+ KHTMLPart *htmlpart;
+ QValueVector<SearchProvider> mSites;
+ HistoryManager *history;
+ bool active;
+
+};
+
+
+#endif
diff --git a/noatun-plugins/lyrics/lyrics.plugin b/noatun-plugins/lyrics/lyrics.plugin
new file mode 100644
index 0000000..cc9b3ad
--- /dev/null
+++ b/noatun-plugins/lyrics/lyrics.plugin
@@ -0,0 +1,117 @@
+Filename=noatunlyrics.la
+Author=Ismael Orenstein
+Site=http://noatun.derkarl.org/
+Email=perdig@linuxbr.com.br
+Type=other
+License=BSD
+Name=Lyrics
+Name[af]=Lirieke
+Name[ar]=الكلمات
+Name[az]=Mahnı Sözləri
+Name[bg]=Текстове
+Name[bs]=Tekstovi
+Name[cs]=Text skladby
+Name[cy]=Geiriau cân
+Name[da]=Sangtekst
+Name[de]=Liedtext
+Name[el]=Στίχοι
+Name[eo]=Kantoteksto
+Name[es]=Letras
+Name[et]=Laulusõnad
+Name[fa]=آهنگ
+Name[fi]=Sanat
+Name[fr]=Paroles
+Name[fy]=Liettekst
+Name[gl]=Letras
+Name[he]=מילים
+Name[hi]=लिरिक्स
+Name[hr]=Tekstovi pjesama
+Name[it]=Testi
+Name[ka]=სიმღერის ტექსტები
+Name[km]=អត្ថបទ​ចម្រៀង
+Name[lt]=Lyrika
+Name[mk]=Стихови
+Name[nb]=Tekst
+Name[nds]=Leedtexten
+Name[ne]=रचना
+Name[nl]=Liedtekst
+Name[nn]=Tekst
+Name[pa]=ਬੋਲ
+Name[pl]=Słowa piosenek
+Name[pt]=Letras
+Name[ro]=Versuri
+Name[ru]=Текст песни
+Name[sk]=Texty
+Name[sl]=Besedila pesmi
+Name[sr]=Текст песме
+Name[sr@Latn]=Tekst pesme
+Name[sv]=Sångtext
+Name[ta]= பாடல்வரிகள்
+Name[tg]=Матни сурудҳо
+Name[tr]=Şarkı Sözleri
+Name[uk]=Текст пісні
+Name[uz]=Qoʻshiqning soʻzlari
+Name[uz@cyrillic]=Қўшиқнинг сўзлари
+Name[vi]=Lời nhạc
+Name[xh]=Amazwi
+Name[zh_CN]=歌词
+Comment=Display the lyrics for the current song
+Comment[af]=Vertoon die lirieke vir die huidige liedjie
+Comment[ar]=يعرض كلمات الأغنية الحالية
+Comment[az]=Hazırkı mahnının sözlərini göstər
+Comment[bg]=Показване текста на текущата песента (лириката)
+Comment[bs]=Prikazuje tekst trenutne pjesme
+Comment[ca]=Mostra la lletra de la cançó actual
+Comment[cs]=Zobrazuje slova k současné skladbě
+Comment[cy]=Arddangos y geiriau am y gân gyfredol
+Comment[da]=Vis sangteksten for den aktuelle sang
+Comment[de]=Zeigt den Liedtext für das aktuelle Stück
+Comment[el]=Εμφανίζει τους στίχους για το τρέχον τραγούδι
+Comment[eo]=Montras la tekston de la nuna kantaĵo
+Comment[es]=Muestra las letras para la canción actual
+Comment[et]=Näitab aktiivse laulu sõnu
+Comment[eu]=Uneko kantaren letra bistaratzen du
+Comment[fa]=نمایش آهنگ برای ترانۀ جاری
+Comment[fi]=Näyttää kappaleen sanat
+Comment[fr]=Afficheur des paroles de la chanson en cours
+Comment[fy]=Toant de teksten fan it besteande nûmer
+Comment[ga]=Taispeáin liricí an amhráin reatha
+Comment[gl]=Mostra as letras da peza actual
+Comment[he]=הצגת מילות השיר הנוכחי
+Comment[hi]=मौज़ूदा गीत का काव्य दिखाता है
+Comment[hr]=Prikazivanje teksta trenutne pjesme
+Comment[hu]=Megjeleníti az aktuális szám szövegét
+Comment[is]=Sýnir texta lagsins
+Comment[it]=Mostra il testo della canzone corrente
+Comment[ja]=現在の曲の歌詞を表示
+Comment[ka]=მიმდინარე სიმღერის ტექსტს აჩვენებს
+Comment[kk]=Орындалып жатқан әннің сөздерін көрсету
+Comment[km]=បង្ហាញ​អត្ថបទ​ចម្រៀង​សម្រាប់​​បទចម្រៀង​បច្ចុប្បន្ន
+Comment[lt]=Rodo esamos dainos lyriką
+Comment[mk]=Ги прикажува стиховите на тековната песна
+Comment[ms]=Memaparkan lirik lagu semasa
+Comment[nb]=Vis teksten til den gjeldende sangen
+Comment[nds]=Wiest den Text vun dat aktuelle Leed
+Comment[ne]=हालको गीतका लागि रचना प्रदर्शन गर्नुहोस्
+Comment[nl]=Toont de teksten van het huidige nummer
+Comment[nn]=Visar teksten til den gjeldande songen
+Comment[pl]=Wyświetla słowa do aktualnej piosenki
+Comment[pt]=Mostra as letras da música actual
+Comment[pt_BR]=Exibe a letra da música para a canção atual
+Comment[ro]=Afişează versurile pentru cîntecul curent
+Comment[ru]=Показ текста песни произведения при его проигрывании
+Comment[sk]=Zobrazí text aktuálnej skladby
+Comment[sl]=Prikaže besedilo trenutne pesmi
+Comment[sr]=Приказује текст за текућу песму
+Comment[sr@Latn]=Prikazuje tekst za tekuću pesmu
+Comment[sv]=Visar texten för den aktuella sången
+Comment[ta]=இப்போதைய பாடலின் வரிகளை காட்டு
+Comment[tg]=Нишон додани матни суруд дар вақти ба кор андохтани ӯ
+Comment[tr]=Geçerli şarkı için sözleri gösterir
+Comment[uk]=Відображення тексту поточної пісні
+Comment[uz]=Joriy qoʻshiqning soʻzlarini koʻrsatish
+Comment[uz@cyrillic]=Жорий қўшиқнинг сўзларини кўрсатиш
+Comment[vi]=Hiển thị lời bài hát hiện thời
+Comment[xh]=Bonisa amazwi engoma ekhoyo
+Comment[zh_CN]=显示当前歌曲的歌词
+Comment[zh_TW]=顯示目前歌曲的歌詞
diff --git a/noatun-plugins/lyrics/lyricsui.rc b/noatun-plugins/lyrics/lyricsui.rc
new file mode 100644
index 0000000..09b72e3
--- /dev/null
+++ b/noatun-plugins/lyrics/lyricsui.rc
@@ -0,0 +1,24 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="noatunlyrics">
+<MenuBar>
+ <Menu name="go_web">
+ <Action name="go_web_goTo"/>
+ </Menu>
+ <Menu name="settings">
+ <Action name="follow"/>
+ <Action name="attach_url"/>
+ <Action name="search_provider"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar">
+ <Action name="go_back"/>
+ <Action name="go_forward"/>
+ <Action name="view_redisplay"/>
+ <Separator/>
+ <Action name="follow"/>
+ <Separator/>
+ <Action name="attach_url"/>
+ <Action name="search_label"/>
+ <Action name="search_provider"/>
+</ToolBar>
+</kpartgui>