lyrics-ebook 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +340 -0
- data/README +46 -0
- data/bin/lyrics-ebook +47 -0
- data/lib/eeepub/LICENSE +20 -0
- data/lib/eeepub/README.md +77 -0
- data/lib/eeepub/Rakefile +49 -0
- data/lib/eeepub/VERSION +1 -0
- data/lib/eeepub/examples/files/bar.html +42 -0
- data/lib/eeepub/examples/files/foo.html +42 -0
- data/lib/eeepub/examples/simple_epub.rb +25 -0
- data/lib/eeepub/lib/eeepub.rb +17 -0
- data/lib/eeepub/lib/eeepub/container_item.rb +108 -0
- data/lib/eeepub/lib/eeepub/easy.rb +100 -0
- data/lib/eeepub/lib/eeepub/maker.rb +127 -0
- data/lib/eeepub/lib/eeepub/ncx.rb +68 -0
- data/lib/eeepub/lib/eeepub/ocf.rb +112 -0
- data/lib/eeepub/lib/eeepub/opf.rb +148 -0
- data/lib/eeepub/spec/eeepub/easy_spec.rb +66 -0
- data/lib/eeepub/spec/eeepub/maker_spec.rb +124 -0
- data/lib/eeepub/spec/eeepub/ncx_spec.rb +80 -0
- data/lib/eeepub/spec/eeepub/ocf_spec.rb +43 -0
- data/lib/eeepub/spec/eeepub/opf_spec.rb +262 -0
- data/lib/eeepub/spec/eeepub_spec.rb +4 -0
- data/lib/eeepub/spec/spec_helper.rb +12 -0
- data/lib/lyrics_ebook.rb +71 -0
- data/lib/lyrics_ebook/cache2html.rb +33 -0
- data/lib/lyrics_ebook/cache_manager.rb +77 -0
- data/lib/lyrics_ebook/lyric.rb +32 -0
- data/lib/lyrics_ebook/lyric_download.rb +50 -0
- data/lib/lyrics_ebook/lyrics2html.rb +106 -0
- data/lib/lyrics_ebook/mini_lyrics_parser.rb +26 -0
- data/lib/lyrics_ebook/mp3_parser.rb +37 -0
- data/lib/wiki_lyrics/amarok/COPYING +340 -0
- data/lib/wiki_lyrics/amarok/README +51 -0
- data/lib/wiki_lyrics/amarok/amarok.rb +355 -0
- data/lib/wiki_lyrics/amarok/pluginadapter.rb +113 -0
- data/lib/wiki_lyrics/amarok/plugins.rb +95 -0
- data/lib/wiki_lyrics/amarok/wikilyrics.rb +578 -0
- data/lib/wiki_lyrics/amarok/wikilyrics.spec +4 -0
- data/lib/wiki_lyrics/amarok/wikipluginadapter.rb +392 -0
- data/lib/wiki_lyrics/cli/optionsparser.rb +228 -0
- data/lib/wiki_lyrics/cli/pluginadapter.rb +56 -0
- data/lib/wiki_lyrics/cli/plugins.rb +79 -0
- data/lib/wiki_lyrics/cli/wikilyrics.rb +178 -0
- data/lib/wiki_lyrics/cli/wikipluginadapter.rb +140 -0
- data/lib/wiki_lyrics/docs/COPYING +340 -0
- data/lib/wiki_lyrics/docs/ChangeLog +293 -0
- data/lib/wiki_lyrics/docs/HOWTO.pdf +0 -0
- data/lib/wiki_lyrics/docs/HOWTO.tex +151 -0
- data/lib/wiki_lyrics/docs/HOWTO.txt +139 -0
- data/lib/wiki_lyrics/docs/README +45 -0
- data/lib/wiki_lyrics/docs/TODO +12 -0
- data/lib/wiki_lyrics/gui/gui-gtk.rb +945 -0
- data/lib/wiki_lyrics/gui/gui-qt3.rb +785 -0
- data/lib/wiki_lyrics/gui/gui-qt4.rb +845 -0
- data/lib/wiki_lyrics/gui/gui-tk.rb +1104 -0
- data/lib/wiki_lyrics/gui/gui.rb +268 -0
- data/lib/wiki_lyrics/gui/test.rb +74 -0
- data/lib/wiki_lyrics/i18n/README +1 -0
- data/lib/wiki_lyrics/i18n/en.rb +181 -0
- data/lib/wiki_lyrics/i18n/es.rb +181 -0
- data/lib/wiki_lyrics/i18n/i18n.rb +126 -0
- data/lib/wiki_lyrics/i18n/sk.rb +174 -0
- data/lib/wiki_lyrics/itrans/COPYRIGHT +31 -0
- data/lib/wiki_lyrics/itrans/itrans +0 -0
- data/lib/wiki_lyrics/itrans/itrans.txt +8 -0
- data/lib/wiki_lyrics/itrans/lyric.txt +23 -0
- data/lib/wiki_lyrics/itrans/udvng.ifm +206 -0
- data/lib/wiki_lyrics/lyrics.rb +567 -0
- data/lib/wiki_lyrics/lyrics_AZLyrics.rb +113 -0
- data/lib/wiki_lyrics/lyrics_DarkLyrics.rb +124 -0
- data/lib/wiki_lyrics/lyrics_Giitaayan.rb +124 -0
- data/lib/wiki_lyrics/lyrics_Jamendo.rb +166 -0
- data/lib/wiki_lyrics/lyrics_LeosLyrics.rb +142 -0
- data/lib/wiki_lyrics/lyrics_LoudSongs.rb +135 -0
- data/lib/wiki_lyrics/lyrics_LyricWiki.rb +329 -0
- data/lib/wiki_lyrics/lyrics_LyricsDownload.rb +118 -0
- data/lib/wiki_lyrics/lyrics_LyricsMania.rb +141 -0
- data/lib/wiki_lyrics/lyrics_Lyriki.rb +287 -0
- data/lib/wiki_lyrics/lyrics_SeekLyrics.rb +108 -0
- data/lib/wiki_lyrics/lyrics_Sing365.rb +103 -0
- data/lib/wiki_lyrics/lyrics_TerraLetras.rb +126 -0
- data/lib/wiki_lyrics/mediawikilyrics.rb +1464 -0
- data/lib/wiki_lyrics/tests/plugin_tests.rb +161 -0
- data/lib/wiki_lyrics/tests/tests.rb +74 -0
- data/lib/wiki_lyrics/utils/formdata.rb +56 -0
- data/lib/wiki_lyrics/utils/htmlentities.rb +291 -0
- data/lib/wiki_lyrics/utils/http.rb +198 -0
- data/lib/wiki_lyrics/utils/itrans.rb +160 -0
- data/lib/wiki_lyrics/utils/kde.rb +88 -0
- data/lib/wiki_lyrics/utils/logger.rb +123 -0
- data/lib/wiki_lyrics/utils/strings.rb +378 -0
- data/lib/wiki_lyrics/utils/xmlhash.rb +111 -0
- data/lib/wiki_lyrics/wikilyrics.kdevelop +152 -0
- data/lib/wiki_lyrics/wikilyrics.kdevses +18 -0
- data/lib/wiki_lyrics/win/gtk_fix.bat +3 -0
- data/lib/wiki_lyrics/win/tk_fix.bat +3 -0
- data/lib/wiki_lyrics/win/wikilyrics.bat +4 -0
- data/lib/wiki_lyrics/win/win_fix.rb +52 -0
- data/templates/art_.erb.xhtml +29 -0
- data/templates/artists.erb.xhtml +19 -0
- data/templates/cover.erb.xhtml +22 -0
- data/test/cache_manager_test.rb +73 -0
- data/test/data/artist name/title name.lyric +6 -0
- data/test/lyric_test.rb +41 -0
- metadata +194 -0
Binary file
|
@@ -0,0 +1,151 @@
|
|
1
|
+
\documentclass[english,11pt,notitlepage]{article}
|
2
|
+
\usepackage[T1]{fontenc}
|
3
|
+
\usepackage[latin1]{inputenc}
|
4
|
+
\usepackage{amsmath}
|
5
|
+
\usepackage{babel}
|
6
|
+
|
7
|
+
\usepackage[a4paper,headheight=16pt,scale={0.8,0.8},hoffset=0cm]{geometry}
|
8
|
+
|
9
|
+
\newcommand{\noun}[1]{\textsc{#1}}
|
10
|
+
|
11
|
+
\newenvironment{codecomment}
|
12
|
+
% {\begin{list}{}{\leftmargin0.5cm\rightmargin0.5cm}\item{}\begin{footnotesize}}
|
13
|
+
{\begin{list}{}{\leftmargin0cm\rightmargin0cm}\item{}\begin{small}}
|
14
|
+
{\end{small}\end{list}}
|
15
|
+
|
16
|
+
\title{Wiki-Lyrics HOW-TO}
|
17
|
+
|
18
|
+
\begin{document}
|
19
|
+
|
20
|
+
\maketitle
|
21
|
+
|
22
|
+
\section{Introduction}
|
23
|
+
|
24
|
+
\subsection{What is Wiki-Lyrics?}
|
25
|
+
|
26
|
+
\noindent It's an Amarok lyrics script. However, it has some features that makes it ``special'':
|
27
|
+
|
28
|
+
\begin{itemize}
|
29
|
+
\item It can get lyrics (and suggestions) from \emph{a lot of sites}.
|
30
|
+
\item It can be easily extended to support other sites.
|
31
|
+
\item It automatically searches suggestions for the requested lyrics.
|
32
|
+
\item It can upload lyrics, cover art and album data to Lyriki and/or LyricWiki (wiki's for lyrics).
|
33
|
+
\end{itemize}
|
34
|
+
|
35
|
+
\subsection{How does it works}
|
36
|
+
|
37
|
+
\noindent Wiki-Lyrics itself has a sort of plugin system: in the main script's directory there are some Ruby files named \texttt{lyrics\_*.rb}, each one defining a plugin (a special Ruby class) that can get the lyrics from \emph{one site}. The main script calls them when it needs to fetch lyrics and/or suggestions.
|
38
|
+
|
39
|
+
\section{The plugins}
|
40
|
+
|
41
|
+
\subsection{Writing a plugin}
|
42
|
+
|
43
|
+
\noindent First few lines are ``standard'':
|
44
|
+
|
45
|
+
\begin{verbatim}
|
46
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
47
|
+
require 'utils/strings'
|
48
|
+
require 'lyrics'
|
49
|
+
\end{verbatim}
|
50
|
+
|
51
|
+
\noindent This is to import some classes and modules we'll have to use.
|
52
|
+
|
53
|
+
\noindent Now we can create our class, let's call it FooLyrics:
|
54
|
+
|
55
|
+
\begin{verbatim}
|
56
|
+
class FooLyrics < Lyrics
|
57
|
+
\end{verbatim}
|
58
|
+
|
59
|
+
\noindent First two methods provide basic information about the site and are self explanatory:
|
60
|
+
|
61
|
+
\begin{verbatim}
|
62
|
+
def FooLyrics.site_host()
|
63
|
+
return 'www.lyrics.foo.bar'
|
64
|
+
end
|
65
|
+
|
66
|
+
def FooLyrics.site_name()
|
67
|
+
return 'Foo'
|
68
|
+
end
|
69
|
+
\end{verbatim}
|
70
|
+
|
71
|
+
\noindent OK, that was easy. We just created 2 class-methods that return the URL and the name of the site we are getting the lyrics from. Now, let's write some real code. Though the \texttt{Lyrics} class can be extended in several ways, in the most common scenario (and the one we'll explain here), there are 4 additional methods our class should implement:
|
72
|
+
|
73
|
+
\begin{verbatim}
|
74
|
+
def build_lyrics_fetch_data( artist, title, album=nil, year=nil )
|
75
|
+
a = CGI.escape( artist )
|
76
|
+
t = CGI.escape( title )
|
77
|
+
return { 'url'=>"http://#{site_host()}/index.php?a=#{a}&t=#{t}.html" }
|
78
|
+
end
|
79
|
+
\end{verbatim}
|
80
|
+
\begin{codecomment}
|
81
|
+
The method receives song information and must return a hash with at least one key, \texttt{'url'}, and optionally another one, \texttt{'post'}. As the method name suggests, the data returned by this method will be used to fetch the lyrics page for the song in question, with the \texttt{'url'} key being the URL of the page to retrieve. Normally the page will be retrieved through a \texttt{GET} request but if some parameters need to be posted to the site in order to get the lyrics, you can provide them with the optional key \texttt{'post'}, which expects a hash. When \texttt{'post'} is specified, the page will be retrieved through a \texttt{POST} request and the data provided will be sent to the site (note that \texttt{GET} parameters are specified as part of the URL).
|
82
|
+
\end{codecomment}
|
83
|
+
|
84
|
+
\hskip
|
85
|
+
|
86
|
+
\begin{verbatim}
|
87
|
+
def parse_lyrics( url, body, artist, title, album=nil, year=nil )
|
88
|
+
lyrics_data = {}
|
89
|
+
# isolate the lyrics in the received page body
|
90
|
+
...
|
91
|
+
lyrics_data['lyrics'] = body
|
92
|
+
return lyrics_data
|
93
|
+
end
|
94
|
+
\end{verbatim}
|
95
|
+
\begin{codecomment}
|
96
|
+
The method receives the fetched page and it's URL and the information received by \texttt{build\_lyrics\_fetch\_data}. It also has to return a hash with at least one key, \texttt{'lyrics'}, and other optional keys: \texttt{'artist'}, \texttt{'title'}, \texttt{'album'}, \texttt{'year'} and \texttt{'custom\_data'}. If the page contains the lyrics to the requested song, they must be returned in the \texttt{'lyrics'} key as plain text (not html, though you can leave formatting tags such as \texttt{<b>}, \texttt{<i>} or \texttt{<u>}); otherwise the \texttt{'lyrics'} key should be set to \texttt{nil}.
|
97
|
+
You might wonder why return any of the optional keys that are already provided as arguments. The reason is that Wiki-Lyrics does not only retrieves lyrics but can also submit song information to Lyriki and LyricWiki. Instead of only providing the lyrics to the song, Wiki-Lyrics tries to provide those sites with as much (relevant) information as possible. To account for the fact that some information can be missing from the files metadata (or just be inaccurate), all plugins should try to obtain as much information as possible from the lyrics page. The keys that are expected along the lyrics for every plugin (\texttt{'artist'}, \texttt{'title'}, \texttt{'album'} and \texttt{'year'}) will be automatically filled with the values provided to the method if not filled by the plugin (so don't bother filling them unless the data is obtained from the page itself). Any other information available can be returned in the \texttt{'custom\_data'} key, which must contain yet another hash. For example both, Lyriki and LyricWiki plugins return song credits and lyricist this way (as \texttt{'credits'} and \texttt{'lyricist'} keys respectively).
|
98
|
+
\end{codecomment}
|
99
|
+
|
100
|
+
\hskip
|
101
|
+
|
102
|
+
\begin{verbatim}
|
103
|
+
def build_suggestions_fetch_data( artist, title, album=nil, year=nil )
|
104
|
+
a = CGI.escape( artist )
|
105
|
+
return { 'url'=>"http://#{site_host()}/index.php?search=#{a}.html" }
|
106
|
+
end
|
107
|
+
\end{verbatim}
|
108
|
+
\begin{codecomment}
|
109
|
+
This method is similar to \texttt{build\_lyrics\_fetch\_data} but, instead of the URL of the lyrics page, it must return the URL where suggestions for the given song can be found (same things noted before for the \texttt{'post'} key apply here).
|
110
|
+
\end{codecomment}
|
111
|
+
|
112
|
+
\hskip
|
113
|
+
|
114
|
+
\begin{verbatim}
|
115
|
+
def parse_suggestions( url, body, artist, title, album=nil, year=nil )
|
116
|
+
suggestions = []
|
117
|
+
# isolate the suggestions in the received page body
|
118
|
+
body.split( /separator regexp/ ) # split the suggestions in the body
|
119
|
+
# analyze the suggestion and extract it's url, artist and title
|
120
|
+
suggestions << { 'url'=> s_url, 'artist'=>s_artist, 'title'=>s_title }
|
121
|
+
end
|
122
|
+
return suggestions
|
123
|
+
end
|
124
|
+
\end{verbatim}
|
125
|
+
\begin{codecomment}
|
126
|
+
As the name suggests, this method must parse the suggestions found in the received page body and return them as an array of hashes (one hash per suggestion), each hash containing \texttt{'url'}, \texttt{'artist'} and \texttt{'title'} keys.
|
127
|
+
\end{codecomment}
|
128
|
+
|
129
|
+
\subsubsection{Useful functions}
|
130
|
+
|
131
|
+
\noindent Wiki-Lyrics includes some functions to help you in some ``standard'' operations. Some of those are listed below\footnote{For other commonly used functions take a look at the Ruby modules in the \texttt{utils} directory.}:
|
132
|
+
|
133
|
+
\begin{itemize}
|
134
|
+
\item \texttt{Strings.latin12utf8(text)} convert text from latin1 to utf-8
|
135
|
+
\item \texttt{Strings.utf82latin1(text)} convert text from utf-8 to latin1
|
136
|
+
\item \texttt{build\_google\_feeling\_lucky\_url(artist, title)} returns the URL of the ``feeling lucky'' google search
|
137
|
+
\end{itemize}
|
138
|
+
|
139
|
+
\subsection{Save and install the plugin}
|
140
|
+
To have Wiki-Lyrics automatically detect plugins, these have to be saved under the script's main directory following the \texttt{lyrics\_PLUGINCLASSNAME.rb} filename convention (\emph{mandatory}, otherwise the plugin won't be loaded).
|
141
|
+
|
142
|
+
\noindent Countinuing our example, we would have to save our plugin as \texttt{lyrics\_FooLyrics.rb} under Wiki-Lyrics main directory, usually \texttt{\$HOME/.kde/share/apps/amarok/scripts/wiki\_lyrics}.
|
143
|
+
|
144
|
+
\section{Enjoy}
|
145
|
+
|
146
|
+
\noindent Now open Amarok, start Wiki-Lyrics script and configure it to use your new plugin.
|
147
|
+
|
148
|
+
\noindent And, of course, sing along ;-)
|
149
|
+
|
150
|
+
|
151
|
+
\end{document}
|
@@ -0,0 +1,139 @@
|
|
1
|
+
Wiki-Lyrics HOW-TO
|
2
|
+
March 28, 2007
|
3
|
+
|
4
|
+
1 Introduction
|
5
|
+
|
6
|
+
1.1 What is Wiki-Lyrics?
|
7
|
+
|
8
|
+
It's an Amarok lyrics script. However, it has some features that makes it "special":
|
9
|
+
|
10
|
+
• It can get lyrics (and suggestions) from a lot of sites.
|
11
|
+
• It can be easily extended to support other sites.
|
12
|
+
• It automatically searches suggestions for the requested lyrics.
|
13
|
+
• It can upload lyrics, cover art and album data to Lyriki and/or LyricWiki (wiki's for lyrics).
|
14
|
+
|
15
|
+
|
16
|
+
1.2 How does it works
|
17
|
+
|
18
|
+
Wiki-Lyrics himself has a sort of plugin system: in the main script's directory there are some Ruby
|
19
|
+
files named lyrics_*.rb, each one defining a plugin (a special Ruby class) that can get the lyrics
|
20
|
+
from one site. The main script calls them when it needs to fetch lyrics and/or suggestions.
|
21
|
+
|
22
|
+
|
23
|
+
2 The plugins
|
24
|
+
|
25
|
+
2.1 Writing a plugin
|
26
|
+
|
27
|
+
First few lines are "standard":
|
28
|
+
|
29
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
30
|
+
require 'utils/strings'
|
31
|
+
require 'lyrics'
|
32
|
+
This is to import some classes and modules we'll have to use.
|
33
|
+
Now we can create our class, let's call it FooLyrics:
|
34
|
+
|
35
|
+
class FooLyrics < Lyrics
|
36
|
+
|
37
|
+
First two methods provide basic information about the site and are self explanatory:
|
38
|
+
|
39
|
+
def FooLyrics.site_host()
|
40
|
+
return 'www.lyrics.foo.bar'
|
41
|
+
end
|
42
|
+
|
43
|
+
def FooLyrics.site_name()
|
44
|
+
return 'Foo'
|
45
|
+
end
|
46
|
+
|
47
|
+
OK, that was easy. We just created 2 class-methods that return the URL and the name of the site
|
48
|
+
we are getting the lyrics from. Now, let's write some real code. Though the Lyrics class can be
|
49
|
+
extended in several ways, in the most common scenario (and the one we'll explain here), there are
|
50
|
+
4 additional methods our class should implement:
|
51
|
+
|
52
|
+
def build_lyrics_fetch_data( artist, title, album=nil, year=nil )
|
53
|
+
a = CGI.escape( artist )
|
54
|
+
t = CGI.escape( title )
|
55
|
+
return { 'url'=>"http://#{site_host()}/index.php?a=#{a}&t=#{t}.html" }
|
56
|
+
end
|
57
|
+
|
58
|
+
The method receives song information and must return a hash with at least one key, 'url', and optionally
|
59
|
+
another one, 'post'. As the method name suggests, the data returned by this method will be used to fetch
|
60
|
+
the lyrics page for the song in question, with the 'url' key being the URL of the page to retrieve. Normally
|
61
|
+
the page will be retrieved through a GET request but if some parameters need to be posted to the site in order
|
62
|
+
to get the lyrics, you can provide them with the optional key 'post', which expects a hash. When 'post'
|
63
|
+
is specified, the page will be retrieved through a POST request and the data provided will be sent to the site
|
64
|
+
(note that GET parameters are specied as part of the URL).
|
65
|
+
|
66
|
+
|
67
|
+
def parse_lyrics( url, body, artist, title, album=nil, year=nil )
|
68
|
+
lyrics_data = {}
|
69
|
+
# isolate the lyrics in the received page body
|
70
|
+
...
|
71
|
+
lyrics_data['lyrics'] = body
|
72
|
+
return lyrics_data
|
73
|
+
end
|
74
|
+
|
75
|
+
The method receives the fetched page and it's URL and the information received by build_lyrics_fetch_data.
|
76
|
+
It also has to return a hash with at least one key, 'lyrics', and other optional keys: 'artist', 'title',
|
77
|
+
'album', 'year' and 'custom_data'. If the page contains the lyrics to the requested song, they must be
|
78
|
+
returned in the 'lyrics' key as plain text (not html, though you can leave formatting tags such as <b>, <i>
|
79
|
+
or <u>); otherwise the 'lyrics' key should be set to nil. You might wonder why return any of the optional
|
80
|
+
keys that are already provided as arguments. The reason is that Wiki-Lyrics does not only retrieves lyrics but
|
81
|
+
can also submit song information to Lyriki and LyricWiki. Instead of only providing the lyrics to the song,
|
82
|
+
Wiki-Lyrics tries to provide those sites with as much (relevant) information as possible. To account for the
|
83
|
+
fact that some information can be missing from the les metadata (or just be inaccurate), all plugins should
|
84
|
+
try to obtain as much information as possible from the lyrics page. The keys that are expected along the
|
85
|
+
lyrics for every plugin ('artist', 'title', 'album' and 'year') will be automatically lled with the values
|
86
|
+
provided to the method if not lled by the plugin (so don't bother lling them unless the data is obtained
|
87
|
+
from the page itself). Any other information available can be returned in the 'custom_data' key, which must
|
88
|
+
contain yet another hash. For example both, Lyriki and LyricWiki plugins return song credits and lyricist this
|
89
|
+
way (as 'credits' and 'lyricist' keys respectively).
|
90
|
+
|
91
|
+
|
92
|
+
def build_suggestions_fetch_data( artist, title, album=nil, year=nil )
|
93
|
+
a = CGI.escape( artist )
|
94
|
+
return { 'url'=>"http://#{site_host()}/index.php?search=#{a}.html" }
|
95
|
+
end
|
96
|
+
|
97
|
+
This method is similar to build_lyrics_fetch_data but, instead of the URL of the lyrics page, it must
|
98
|
+
return the URL where suggestions for the given song can be found (same things noted before for the 'post'
|
99
|
+
key apply here).
|
100
|
+
|
101
|
+
|
102
|
+
def parse_suggestions( url, body, artist, title, album=nil, year=nil )
|
103
|
+
suggestions = []
|
104
|
+
# isolate the suggestions in the received page body
|
105
|
+
body.split( /separator regexp/ ) # split the suggestions in the body
|
106
|
+
# analyze the suggestion and extract it's url, artist and title
|
107
|
+
suggestions << { 'url'=> s_url, 'artist'=>s_artist, 'title'=>s_title }
|
108
|
+
end
|
109
|
+
return suggestions
|
110
|
+
end
|
111
|
+
|
112
|
+
As the name suggests, this method must parse the suggestions found in the received page body and return
|
113
|
+
them as an array of hashes (one hash per suggestion), each hash containing 'url', 'artist' and 'title'
|
114
|
+
keys.
|
115
|
+
|
116
|
+
|
117
|
+
2.1.1 Useful functions
|
118
|
+
|
119
|
+
Wiki-Lyrics includes some functions to help you in some "standard" operations. Some of those are
|
120
|
+
listed below :
|
121
|
+
|
122
|
+
• Strings.latin12utf8(text) convert text from latin1 to utf-8
|
123
|
+
• Strings.utf82latin1(text) convert text from utf-8 to latin1
|
124
|
+
• build_google_feeling_lucky_url(artist, title) returns the URL of the "feeling lucky" google search
|
125
|
+
|
126
|
+
|
127
|
+
2.2 Save and install the plugin
|
128
|
+
|
129
|
+
To have Wiki-Lyrics automatically detect plugins, these have to be saved under the script's main
|
130
|
+
directory following the lyrics_PLUGINCLASSNAME.rb filename convention (mandatory, otherwise the
|
131
|
+
plugin won't be loaded).
|
132
|
+
|
133
|
+
Countinuing our example, we would have to save our plugin as lyrics_FooLyrics.rb under Wiki-Lyrics main
|
134
|
+
directory, usually $HOME/.kde/share/apps/amarok/scripts/wiki_lyrics.
|
135
|
+
|
136
|
+
|
137
|
+
3 Enjoy
|
138
|
+
Now open Amarok, start Wiki-Lyrics script and congure it to use your new plugin.
|
139
|
+
And, of course, sing along ;-)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
Wiki-Lyrics v0.13.4
|
2
|
+
===================
|
3
|
+
|
4
|
+
About:
|
5
|
+
======
|
6
|
+
Wiki-Lyrics is a set of Ruby classes and scripts to interface with various
|
7
|
+
lyrics sites and submit content to Lyriki and LyricWiki, wikis for lyrics.
|
8
|
+
Currently there's only 2 interfaces: an Amarok script and a standalone
|
9
|
+
interface. However, the standalone interface can be used from Winamp and
|
10
|
+
other Windows players with the help of the AMIP plugin, and directly from
|
11
|
+
other Linux players such as Audacious.
|
12
|
+
Visit http://www.lyriki.com/Help:Wiki-Lyrics_Script for more information.
|
13
|
+
|
14
|
+
Supported sites:
|
15
|
+
================
|
16
|
+
- Lyriki (www.lyriki.com)
|
17
|
+
- LyricWiki (www.lyricwiki.org)
|
18
|
+
- AZ Lyrics (www.azlyrics.com)
|
19
|
+
- DarkLyrics (www.darklyrics.com)
|
20
|
+
- Giitaayan (www.giitaayan.com)
|
21
|
+
- Jamendo (www.jamendo.com)
|
22
|
+
- Leos Lyrics (www.leoslyrics.com)
|
23
|
+
- Lyrics Download (www.lyricsdownload.com)
|
24
|
+
- Lyrics Mania (www.lyricsmania.com)
|
25
|
+
- LoudSon.gs (www.loudson.gs)
|
26
|
+
- Seek Lyrics (www.seeklyrics.com)
|
27
|
+
- Sing365 (www.sing365.com)
|
28
|
+
- Terra Letras (letras.terra.com.br)
|
29
|
+
|
30
|
+
Dependencies:
|
31
|
+
=============
|
32
|
+
- Ruby 1.8
|
33
|
+
- Amarok 1.4 (required only to use the Amarok script)
|
34
|
+
- QtRuby, Ruby/GTK or Ruby/Tk (required to see dialogs and submit content)
|
35
|
+
|
36
|
+
Authors:
|
37
|
+
========
|
38
|
+
- Sergio Pistone (sergio_pistone@yahoo.com.ar)
|
39
|
+
- Eduardo Robles Elvira (edulix@gmail.com) (Jamendo)
|
40
|
+
- Swapan Sarkar (swapan@yahoo.com) (Giitaayan)
|
41
|
+
- Davide Lo Re (boyska@gmail.com) (Lyrics Mania)
|
42
|
+
|
43
|
+
Translators:
|
44
|
+
============
|
45
|
+
- Jozef Riha (Slovak)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
* add method to indicate site's encoding and convert to utf8 before processing if needed
|
2
|
+
* add method to preprocess fetched content (siplify spaces, escape entities, etc.)
|
3
|
+
* try to guess the text language (to apply metadata capitalization accordingly)
|
4
|
+
|
5
|
+
* other possible sites:
|
6
|
+
http://www.getlyrics.com/
|
7
|
+
http://www.lyrics4all.net/
|
8
|
+
http://www.songs-lyrics.net/
|
9
|
+
http://www.lyricskeeper.com/
|
10
|
+
http://lyrics.astraweb.com
|
11
|
+
http://www.planetadeletras.com/
|
12
|
+
http://www.songs-lyrics.net/
|
@@ -0,0 +1,945 @@
|
|
1
|
+
# Copyright (C) 2006-2008 by Sergio Pistone
|
2
|
+
# sergio_pistone@yahoo.com.ar
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the
|
16
|
+
# Free Software Foundation, Inc.,
|
17
|
+
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
18
|
+
|
19
|
+
require "gtk2"
|
20
|
+
require "date"
|
21
|
+
require File.expand_path( File.dirname( __FILE__ ) + "/../i18n/i18n" )
|
22
|
+
|
23
|
+
Gtk.init()
|
24
|
+
|
25
|
+
module GTK
|
26
|
+
|
27
|
+
def GTK.empty_string?( text )
|
28
|
+
return text ? (text.empty? ? true : text.strip().empty? ) : true
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
require "gtksourceview1"
|
33
|
+
class TextView < Gtk::SourceView
|
34
|
+
# def initialize( *args )
|
35
|
+
# super( *args )
|
36
|
+
# show_line_markers = false
|
37
|
+
# show_line_numbers = false
|
38
|
+
# end
|
39
|
+
end
|
40
|
+
class TextBuffer < Gtk::SourceBuffer
|
41
|
+
end
|
42
|
+
rescue LoadError => e
|
43
|
+
class TextView < Gtk::TextView
|
44
|
+
end
|
45
|
+
class TextBuffer < Gtk::TextBuffer
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class BaseDialog < Gtk::Window
|
50
|
+
|
51
|
+
attr_reader :accepted
|
52
|
+
attr_reader :values
|
53
|
+
|
54
|
+
def initialize( values, close_on_escape=true )
|
55
|
+
super()
|
56
|
+
@values = values
|
57
|
+
set_window_position( Gtk::Window::POS_CENTER )
|
58
|
+
signal_connect( "destroy" ) { Gtk.main_quit() }
|
59
|
+
if close_on_escape
|
60
|
+
self.signal_connect( "key_press_event" ) do |widget, event|
|
61
|
+
destroy() if event.keyval == Gdk::Keyval::GDK_Escape
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_action_buttons( mode="right", accept_text=nil, cancel_text=nil )
|
67
|
+
accept_text = GTK.empty_string?( accept_text ) ? I18n.get( "gui.common.accept" ) : accept_text
|
68
|
+
cancel_text = GTK.empty_string?( cancel_text ) ? I18n.get( "gui.common.cancel" ) : cancel_text
|
69
|
+
@accept_button = Gtk::Button.new( accept_text )
|
70
|
+
@cancel_button = Gtk::Button.new( cancel_text )
|
71
|
+
@accept_button.signal_connect( "clicked" ) { accept() }
|
72
|
+
@cancel_button.signal_connect( "clicked" ) { destroy() }
|
73
|
+
if mode == "left"
|
74
|
+
hbox = Gtk::HButtonBox.new();
|
75
|
+
hbox.layout_style = Gtk::ButtonBox::START
|
76
|
+
hbox.add( @accept_button )
|
77
|
+
hbox.add( @cancel_button )
|
78
|
+
elsif mode == "split"
|
79
|
+
hbox = Gtk::HBox.new();
|
80
|
+
hbox.pack_start( @accept_button )
|
81
|
+
hbox.pack_start( @cancel_button )
|
82
|
+
else
|
83
|
+
hbox = Gtk::HButtonBox.new();
|
84
|
+
hbox.layout_style = Gtk::ButtonBox::END
|
85
|
+
hbox.add( @accept_button )
|
86
|
+
hbox.add( @cancel_button )
|
87
|
+
end
|
88
|
+
return hbox
|
89
|
+
end
|
90
|
+
protected :create_action_buttons
|
91
|
+
|
92
|
+
def exec()
|
93
|
+
@accepted = false
|
94
|
+
set_modal( true )
|
95
|
+
show_all()
|
96
|
+
end
|
97
|
+
|
98
|
+
def accept()
|
99
|
+
@accepted = true
|
100
|
+
destroy()
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
class PluginsManagerDialog < BaseDialog
|
107
|
+
|
108
|
+
def initialize( values )
|
109
|
+
super( values )
|
110
|
+
|
111
|
+
set_border_width( 5 )
|
112
|
+
set_resizable( true )
|
113
|
+
set_default_size( 400, 280 )
|
114
|
+
|
115
|
+
set_title( I18n.get( "gui.pluginsmanager.title", @values["script_name"] ) )
|
116
|
+
|
117
|
+
sites_group = Gtk::Frame.new( I18n.get( "gui.pluginsmanager.sites" ) )
|
118
|
+
|
119
|
+
@move_up_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.moveup" ) )
|
120
|
+
@move_down_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.movedown" ) )
|
121
|
+
|
122
|
+
@used_plugins_store = Gtk::ListStore.new( String )
|
123
|
+
@used_plugins_view = Gtk::TreeView.new( @used_plugins_store )
|
124
|
+
column = Gtk::TreeViewColumn.new( I18n.get( "gui.pluginsmanager.sites.inuse" ), Gtk::CellRendererText.new(), :text => 0 )
|
125
|
+
@used_plugins_view.append_column( column )
|
126
|
+
used_plugins_viewport = Gtk::Viewport.new(
|
127
|
+
@used_plugins_view.focus_hadjustment(),
|
128
|
+
@used_plugins_view.focus_vadjustment()
|
129
|
+
)
|
130
|
+
used_plugins_viewport.set_shadow_type( Gtk::SHADOW_IN )
|
131
|
+
used_plugins_viewport.add( @used_plugins_view )
|
132
|
+
used_plugins_scrolledwindow = Gtk::ScrolledWindow.new()
|
133
|
+
used_plugins_scrolledwindow.add( used_plugins_viewport )
|
134
|
+
@values["used_plugins"].each() do |plugin|
|
135
|
+
iter = @used_plugins_store.append()
|
136
|
+
@used_plugins_store.set_value( iter, 0, plugin )
|
137
|
+
end
|
138
|
+
|
139
|
+
@add_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.add" ) )
|
140
|
+
@remove_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.remove" ) )
|
141
|
+
|
142
|
+
@unused_plugins_store = Gtk::ListStore.new( String )
|
143
|
+
@unused_plugins_view = Gtk::TreeView.new( @unused_plugins_store )
|
144
|
+
column = Gtk::TreeViewColumn.new( I18n.get( "gui.pluginsmanager.sites.available" ), Gtk::CellRendererText.new(), :text=>0 )
|
145
|
+
@unused_plugins_view.append_column( column )
|
146
|
+
unused_plugins_viewport = Gtk::Viewport.new(
|
147
|
+
@unused_plugins_view.focus_hadjustment(),
|
148
|
+
@unused_plugins_view.focus_vadjustment()
|
149
|
+
)
|
150
|
+
unused_plugins_viewport.set_shadow_type( Gtk::SHADOW_IN )
|
151
|
+
unused_plugins_viewport.add( @unused_plugins_view )
|
152
|
+
unused_plugins_scrolledwindow = Gtk::ScrolledWindow.new()
|
153
|
+
unused_plugins_scrolledwindow.add( unused_plugins_viewport )
|
154
|
+
@values["unused_plugins"].each() do |plugin|
|
155
|
+
iter = @unused_plugins_store.append()
|
156
|
+
@unused_plugins_store.set_value( iter, 0, plugin )
|
157
|
+
end
|
158
|
+
|
159
|
+
misc_group = Gtk::Frame.new( I18n.get( "gui.pluginsmanager.misc" ) )
|
160
|
+
|
161
|
+
@cleanup_lyrics_checkbox = Gtk::CheckButton.new( I18n.get( "gui.pluginsmanager.misc.cleanup" ) )
|
162
|
+
@cleanup_lyrics_checkbox.set_active( values["cleanup_lyrics"].to_s() == "true" )
|
163
|
+
|
164
|
+
@single_threaded_checkbox = Gtk::CheckButton.new( I18n.get( "gui.pluginsmanager.misc.singlethreaded" ) )
|
165
|
+
@single_threaded_checkbox.set_active( values["single_threaded"].to_s() == "true" )
|
166
|
+
|
167
|
+
@write_log_checkbox = Gtk::CheckButton.new( I18n.get( "gui.pluginsmanager.misc.writelog", "$HOME/.wikilyrics.log" ) )
|
168
|
+
@write_log_checkbox.set_active( values["write_log"].to_s() == "true" )
|
169
|
+
|
170
|
+
buttons = create_action_buttons()
|
171
|
+
|
172
|
+
group_grid = Gtk::Table.new( 4, 4, false )
|
173
|
+
group_grid.set_row_spacings( 5 )
|
174
|
+
group_grid.set_column_spacings( 5 )
|
175
|
+
group_grid.attach( @move_up_button, 0, 1, 1, 2, Gtk::FILL, 0 )
|
176
|
+
group_grid.attach( @move_down_button, 0, 1, 2, 3, Gtk::FILL, 0 )
|
177
|
+
group_grid.attach( used_plugins_scrolledwindow, 1, 2, 0, 4, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND )
|
178
|
+
group_grid.attach( @add_button, 2, 3, 1, 2, Gtk::FILL, 0 )
|
179
|
+
group_grid.attach( @remove_button, 2, 3, 2, 3, Gtk::FILL, 0 )
|
180
|
+
group_grid.attach( unused_plugins_scrolledwindow, 3, 4, 0, 4, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND )
|
181
|
+
sites_group.add( group_grid )
|
182
|
+
|
183
|
+
misc_group_vbox = Gtk::VBox.new( false, 0 );
|
184
|
+
misc_group_vbox.add( @cleanup_lyrics_checkbox )
|
185
|
+
misc_group_vbox.add( @single_threaded_checkbox )
|
186
|
+
misc_group_vbox.add( @write_log_checkbox )
|
187
|
+
misc_group.add( misc_group_vbox )
|
188
|
+
|
189
|
+
vbox = Gtk::VBox.new( false, 3 );
|
190
|
+
vbox.pack_start( sites_group, true )
|
191
|
+
vbox.pack_start( misc_group, false )
|
192
|
+
vbox.pack_start( buttons, false )
|
193
|
+
|
194
|
+
add( vbox )
|
195
|
+
|
196
|
+
@move_up_button.signal_connect( "clicked" ) { move_up() }
|
197
|
+
@move_down_button.signal_connect( "clicked" ) { move_down() }
|
198
|
+
@add_button.signal_connect( "clicked" ) { add_plugin() }
|
199
|
+
@remove_button.signal_connect( "clicked" ) { remove_plugin() }
|
200
|
+
|
201
|
+
update_accept_button()
|
202
|
+
end
|
203
|
+
|
204
|
+
def move_up()
|
205
|
+
sel_iter = @used_plugins_view.selection().selected()
|
206
|
+
return if sel_iter == nil || sel_iter == @used_plugins_store.iter_first()
|
207
|
+
sel_path = sel_iter.path()
|
208
|
+
plugin = sel_iter.get_value( 0 )
|
209
|
+
@used_plugins_store.remove( sel_iter )
|
210
|
+
sel_path.prev!()
|
211
|
+
prev_iter = @used_plugins_store.get_iter( sel_path )
|
212
|
+
iter = @used_plugins_store.insert_before( prev_iter )
|
213
|
+
@used_plugins_store.set_value( iter, 0, plugin )
|
214
|
+
@used_plugins_view.selection().select_iter( iter )
|
215
|
+
end
|
216
|
+
|
217
|
+
def move_down()
|
218
|
+
sel_iter = @used_plugins_view.selection().selected()
|
219
|
+
return if sel_iter == nil
|
220
|
+
plugin = sel_iter.get_value( 0 )
|
221
|
+
sel_path = sel_iter.path()
|
222
|
+
return if ! sel_iter.next!()
|
223
|
+
next_iter = sel_iter
|
224
|
+
iter = @used_plugins_store.insert_after( next_iter )
|
225
|
+
@used_plugins_store.set_value( iter, 0, plugin )
|
226
|
+
@used_plugins_store.remove( @used_plugins_store.get_iter( sel_path ) )
|
227
|
+
@used_plugins_view.selection().select_iter( iter )
|
228
|
+
end
|
229
|
+
|
230
|
+
def add_plugin()
|
231
|
+
unused_sel_iter = @unused_plugins_view.selection().selected()
|
232
|
+
return if unused_sel_iter == nil
|
233
|
+
plugin = unused_sel_iter.get_value( 0 )
|
234
|
+
@unused_plugins_store.remove( unused_sel_iter )
|
235
|
+
iter = @used_plugins_store.append()
|
236
|
+
@used_plugins_store.set_value( iter, 0, plugin )
|
237
|
+
@used_plugins_view.selection().select_iter( iter )
|
238
|
+
update_accept_button()
|
239
|
+
end
|
240
|
+
|
241
|
+
def remove_plugin()
|
242
|
+
used_sel_iter = @used_plugins_view.selection().selected()
|
243
|
+
return if used_sel_iter == nil
|
244
|
+
plugin = used_sel_iter.get_value( 0 )
|
245
|
+
@used_plugins_store.remove( used_sel_iter )
|
246
|
+
iter = @unused_plugins_store.append()
|
247
|
+
@unused_plugins_store.set_value( iter, 0, plugin )
|
248
|
+
@unused_plugins_view.selection().select_iter( iter )
|
249
|
+
update_accept_button()
|
250
|
+
end
|
251
|
+
|
252
|
+
def update_accept_button()
|
253
|
+
@accept_button.set_sensitive( @used_plugins_store.iter_first() )
|
254
|
+
end
|
255
|
+
|
256
|
+
def accept()
|
257
|
+
@values = {
|
258
|
+
"cleanup_lyrics" => @cleanup_lyrics_checkbox.active?(),
|
259
|
+
"single_threaded" => @single_threaded_checkbox.active?(),
|
260
|
+
"write_log" => @write_log_checkbox.active?(),
|
261
|
+
"used_plugins" => [],
|
262
|
+
"script_name" => @values["script_name"],
|
263
|
+
"unused_plugins" => []
|
264
|
+
}
|
265
|
+
iter = @used_plugins_store.iter_first()
|
266
|
+
while ( iter )
|
267
|
+
@values["used_plugins"].insert( -1, iter.get_value( 0 ) )
|
268
|
+
break if ! iter.next!()
|
269
|
+
end
|
270
|
+
iter = @unused_plugins_store.iter_first()
|
271
|
+
while ( iter )
|
272
|
+
@values["unused_plugins"].insert( -1, iter.get_value( 0 ) )
|
273
|
+
break if ! iter.next!()
|
274
|
+
end
|
275
|
+
super()
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
class WikiPluginDialog < BaseDialog
|
282
|
+
|
283
|
+
def initialize( values )
|
284
|
+
super( values )
|
285
|
+
|
286
|
+
set_border_width( 5 )
|
287
|
+
set_resizable( true )
|
288
|
+
set_default_size( 300, 50 )
|
289
|
+
|
290
|
+
set_title( I18n.get( "gui.wikiplugin.title", values["site_name"] ) )
|
291
|
+
|
292
|
+
general_group = Gtk::Frame.new( I18n.get( "gui.wikiplugin.general" ) )
|
293
|
+
|
294
|
+
@submit_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.submit", values["site_name"] ) )
|
295
|
+
@submit_checkbox.set_active( values["submit"].to_s() == "true" )
|
296
|
+
|
297
|
+
@review_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.review" ) )
|
298
|
+
@review_checkbox.set_sensitive( @submit_checkbox.active?() )
|
299
|
+
@review_checkbox.set_active( @review_checkbox.sensitive?() && values["review"].to_s() == "true" )
|
300
|
+
|
301
|
+
@prompt_autogen_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.autogen" ) )
|
302
|
+
@prompt_autogen_checkbox.set_sensitive( @review_checkbox.active?() )
|
303
|
+
@prompt_autogen_checkbox.set_active( @prompt_autogen_checkbox.sensitive?() && values["prompt_autogen"].to_s() == "true" )
|
304
|
+
|
305
|
+
@prompt_no_lyrics_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.nolyrics" ) )
|
306
|
+
@prompt_no_lyrics_checkbox.set_sensitive( @review_checkbox.active?() )
|
307
|
+
@prompt_no_lyrics_checkbox.set_active( @prompt_no_lyrics_checkbox.sensitive?() && values["prompt_no_lyrics"].to_s() == "true" )
|
308
|
+
|
309
|
+
login_group = Gtk::Frame.new( I18n.get( "gui.wikiplugin.login" ) )
|
310
|
+
|
311
|
+
username_label = Gtk::Label.new( I18n.get( "gui.wikiplugin.login.username" ) );
|
312
|
+
username_label.set_xalign( 0 )
|
313
|
+
@username_lineedit = Gtk::Entry.new()
|
314
|
+
@username_lineedit.set_text( values["username"] )
|
315
|
+
|
316
|
+
password_label = Gtk::Label.new( I18n.get( "gui.wikiplugin.login.password" ) );
|
317
|
+
password_label.set_xalign( 0 )
|
318
|
+
@password_lineedit = Gtk::Entry.new()
|
319
|
+
@password_lineedit.set_text( values["password"] )
|
320
|
+
@password_lineedit.visibility = false
|
321
|
+
|
322
|
+
@username_lineedit.signal_connect( "changed" ) { update_accept_button_state() }
|
323
|
+
@submit_checkbox.signal_connect( "toggled" ) { toggle_submit_checked() }
|
324
|
+
@review_checkbox.signal_connect( "toggled" ) { toggle_review_checked() }
|
325
|
+
|
326
|
+
buttons = create_action_buttons()
|
327
|
+
update_accept_button_state()
|
328
|
+
|
329
|
+
general_grid = Gtk::Table.new( 4, 4, false )
|
330
|
+
general_grid.set_row_spacings( 3 )
|
331
|
+
general_grid.set_column_spacings( 3 )
|
332
|
+
general_grid.attach( @submit_checkbox, 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
333
|
+
general_grid.attach( @review_checkbox, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0, 0 )
|
334
|
+
general_grid.attach( @prompt_autogen_checkbox, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
335
|
+
general_grid.attach( @prompt_no_lyrics_checkbox, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
|
336
|
+
general_group.add( general_grid )
|
337
|
+
|
338
|
+
login_grid = Gtk::Table.new( 4, 4, false )
|
339
|
+
login_grid.set_row_spacings( 3 )
|
340
|
+
login_grid.set_column_spacings( 3 )
|
341
|
+
login_grid.attach( username_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
342
|
+
login_grid.attach( @username_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
343
|
+
login_grid.attach( password_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
344
|
+
login_grid.attach( @password_lineedit, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
|
345
|
+
login_group.add( login_grid )
|
346
|
+
|
347
|
+
vbox = Gtk::VBox.new( false, 3 );
|
348
|
+
vbox.add( general_group )
|
349
|
+
vbox.add( login_group )
|
350
|
+
vbox.pack_start( buttons, false )
|
351
|
+
|
352
|
+
add( vbox )
|
353
|
+
end
|
354
|
+
|
355
|
+
def toggle_submit_checked()
|
356
|
+
checked = @submit_checkbox.active?()
|
357
|
+
@review_checkbox.set_sensitive( checked )
|
358
|
+
if ! checked
|
359
|
+
@review_checkbox.set_active( false )
|
360
|
+
@prompt_autogen_checkbox.set_active( false )
|
361
|
+
@prompt_no_lyrics_checkbox.set_active( false )
|
362
|
+
end
|
363
|
+
update_accept_button_state()
|
364
|
+
end
|
365
|
+
|
366
|
+
def toggle_review_checked()
|
367
|
+
checked = @review_checkbox.active?()
|
368
|
+
@prompt_autogen_checkbox.set_sensitive( checked )
|
369
|
+
@prompt_no_lyrics_checkbox.set_sensitive( checked )
|
370
|
+
if ! checked
|
371
|
+
@prompt_autogen_checkbox.set_active( false )
|
372
|
+
@prompt_no_lyrics_checkbox.set_active( false )
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def update_accept_button_state()
|
377
|
+
@accept_button.set_sensitive( ! @submit_checkbox.active?() || ! @username_lineedit.text().empty? )
|
378
|
+
end
|
379
|
+
|
380
|
+
def accept()
|
381
|
+
@values = {
|
382
|
+
"submit" => @submit_checkbox.active?(),
|
383
|
+
"review" => @review_checkbox.active?(),
|
384
|
+
"prompt_autogen" => @prompt_autogen_checkbox.active?(),
|
385
|
+
"prompt_no_lyrics" => @prompt_no_lyrics_checkbox.active?(),
|
386
|
+
"username" => @username_lineedit.text(),
|
387
|
+
"password" => @password_lineedit.text(),
|
388
|
+
}
|
389
|
+
super()
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
class SubmitSongDialog < BaseDialog
|
394
|
+
|
395
|
+
def initialize( values )
|
396
|
+
super( values )
|
397
|
+
|
398
|
+
set_border_width( 5 )
|
399
|
+
set_resizable( true )
|
400
|
+
set_default_size( 600, 400 )
|
401
|
+
resize( 600, 400 )
|
402
|
+
|
403
|
+
edit_mode = @values["edit_mode"].to_s() == "true"
|
404
|
+
|
405
|
+
set_title( I18n.get( "gui.submitsong.title." + (edit_mode ? "edit" : "submit"), values["site_name"] ) )
|
406
|
+
|
407
|
+
artist_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.artist" )}</b>" );
|
408
|
+
artist_label.set_xalign( 0.9 )
|
409
|
+
artist_label.set_use_markup( true )
|
410
|
+
@artist_lineedit = Gtk::Entry.new()
|
411
|
+
@artist_lineedit.set_text( values["artist"] )
|
412
|
+
|
413
|
+
title_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.song" )}</b>" );
|
414
|
+
title_label.set_xalign( 0.9 )
|
415
|
+
title_label.set_use_markup( true )
|
416
|
+
@title_lineedit = Gtk::Entry.new()
|
417
|
+
@title_lineedit.set_text( values["title"] )
|
418
|
+
|
419
|
+
credits_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.credits" )}</b>" );
|
420
|
+
credits_label.set_xalign( 0.9 )
|
421
|
+
credits_label.set_use_markup( true )
|
422
|
+
@credits_lineedit = Gtk::Entry.new()
|
423
|
+
@credits_lineedit.set_text( values["credits"] )
|
424
|
+
|
425
|
+
lyricist_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.lyricist" )}</b>" );
|
426
|
+
lyricist_label.set_xalign( 0.9 )
|
427
|
+
lyricist_label.set_use_markup( true )
|
428
|
+
@lyricist_lineedit = Gtk::Entry.new()
|
429
|
+
@lyricist_lineedit.set_text( values["lyricist"] )
|
430
|
+
|
431
|
+
year_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.year" )}</b>" );
|
432
|
+
year_label.set_xalign( 0.9 )
|
433
|
+
year_label.set_use_markup( true )
|
434
|
+
@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"], 1900, Date.today().year, 1, 10, 0 ) )
|
435
|
+
@year_spinbox.set_numeric( true )
|
436
|
+
|
437
|
+
album_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.album" )}</b>" );
|
438
|
+
album_label.set_xalign( 0.9 )
|
439
|
+
album_label.set_use_markup( true )
|
440
|
+
@album_lineedit = Gtk::Entry.new()
|
441
|
+
@album_lineedit.set_text( values["album"] )
|
442
|
+
|
443
|
+
@instrumental_checkbox = Gtk::CheckButton.new( I18n.get( "gui.submitsong.instrumental" ) )
|
444
|
+
@instrumental_checkbox.set_active( values["instrumental"].to_s == "true" )
|
445
|
+
@instrumental_checkbox.signal_connect( "toggled" ) { toggle_instrumental_checked() }
|
446
|
+
|
447
|
+
lyrics_scrolled_window = Gtk::ScrolledWindow.new()
|
448
|
+
lyrics_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
|
449
|
+
@lyrics_text_buffer = GTK::TextBuffer.new()
|
450
|
+
@lyrics_text_buffer.set_text( values["lyrics"] )
|
451
|
+
@lyrics_text = GTK::TextView.new()
|
452
|
+
@lyrics_text.set_indent( 2 )
|
453
|
+
@lyrics_text.set_buffer( @lyrics_text_buffer )
|
454
|
+
lyrics_scrolled_window.add( @lyrics_text )
|
455
|
+
@lyrics_text.set_sensitive( ! @instrumental_checkbox.active?() )
|
456
|
+
|
457
|
+
@reviewed_checkbox = Gtk::CheckButton.new( I18n.get( "gui.common.reviewed" ) )
|
458
|
+
@reviewed_checkbox.set_active( false )
|
459
|
+
|
460
|
+
buttons = create_action_buttons( "split", I18n.get( "gui.common.submit" ) )
|
461
|
+
|
462
|
+
lyrics_frame = Gtk::Frame.new()
|
463
|
+
lyrics_frame.add( lyrics_scrolled_window )
|
464
|
+
lyrics_frame.set_shadow_type( Gtk::SHADOW_IN )
|
465
|
+
|
466
|
+
grid = Gtk::Table.new( 9, 4, false )
|
467
|
+
grid.set_row_spacings( 3 )
|
468
|
+
grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
469
|
+
grid.attach( @artist_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
470
|
+
grid.attach( title_label, 2, 3, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
471
|
+
grid.attach( @title_lineedit, 3, 4, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
472
|
+
grid.attach( credits_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
473
|
+
grid.attach( @credits_lineedit, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
|
474
|
+
grid.attach( lyricist_label, 2, 3, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
475
|
+
grid.attach( @lyricist_lineedit, 3, 4, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
|
476
|
+
grid.attach( year_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
477
|
+
grid.attach( @year_spinbox, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
478
|
+
grid.attach( album_label, 2, 3, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
479
|
+
grid.attach( @album_lineedit, 3, 4, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
480
|
+
grid.attach( @instrumental_checkbox, 0, 4, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
|
481
|
+
grid.attach( lyrics_frame, 0, 4, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL )
|
482
|
+
grid.attach( @reviewed_checkbox, 0, 4, 5, 6, Gtk::EXPAND|Gtk::FILL, 0 )
|
483
|
+
grid.attach( buttons, 0, 4, 6, 7, Gtk::EXPAND|Gtk::FILL, 0 )
|
484
|
+
|
485
|
+
add( grid )
|
486
|
+
|
487
|
+
end
|
488
|
+
|
489
|
+
def toggle_instrumental_checked()
|
490
|
+
@lyrics_text.set_sensitive( ! @instrumental_checkbox.active?() )
|
491
|
+
end
|
492
|
+
|
493
|
+
def accept()
|
494
|
+
@values = {
|
495
|
+
"artist" => @artist_lineedit.text(),
|
496
|
+
"year" => @year_spinbox.value().to_i(),
|
497
|
+
"album" => @album_lineedit.text(),
|
498
|
+
"title" => @title_lineedit.text(),
|
499
|
+
"lyrics" => @lyrics_text_buffer.text(),
|
500
|
+
"instrumental" => @instrumental_checkbox.active?(),
|
501
|
+
"lyricist" => @lyricist_lineedit.text(),
|
502
|
+
"credits" => @credits_lineedit.text(),
|
503
|
+
"reviewed" => @reviewed_checkbox.active?()
|
504
|
+
}
|
505
|
+
super()
|
506
|
+
end
|
507
|
+
|
508
|
+
end
|
509
|
+
|
510
|
+
|
511
|
+
class SubmitAlbumDialog < BaseDialog
|
512
|
+
|
513
|
+
def initialize( values )
|
514
|
+
super( values )
|
515
|
+
|
516
|
+
set_border_width( 5 )
|
517
|
+
set_resizable( true )
|
518
|
+
set_default_size( 600, 400 )
|
519
|
+
resize( 600, 400 )
|
520
|
+
|
521
|
+
set_title( I18n.get( "gui.submitalbum.title", values["site_name"] ) )
|
522
|
+
|
523
|
+
artist_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.artist" )}</b>" );
|
524
|
+
artist_label.set_xalign( 0.9 )
|
525
|
+
artist_label.set_use_markup( true )
|
526
|
+
@artist_lineedit = Gtk::Entry.new()
|
527
|
+
@artist_lineedit.set_text( values["artist"] )
|
528
|
+
|
529
|
+
album_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.album" )}</b>" );
|
530
|
+
album_label.set_xalign( 0.9 )
|
531
|
+
album_label.set_use_markup( true )
|
532
|
+
@album_lineedit = Gtk::Entry.new()
|
533
|
+
@album_lineedit.set_text( values["album"] )
|
534
|
+
|
535
|
+
year_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.year" )}</b>" );
|
536
|
+
year_label.set_xalign( 0.9 )
|
537
|
+
year_label.set_use_markup( true )
|
538
|
+
@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"].to_i(), 1900, Date.today().year, 1, 10, 0 ) )
|
539
|
+
@year_spinbox.set_numeric( true )
|
540
|
+
|
541
|
+
month_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.month" )}</b>" );
|
542
|
+
month_label.set_xalign( 0.9 )
|
543
|
+
month_label.set_use_markup( true )
|
544
|
+
@month_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["month"].to_i(), 0, 12, 1, 1, 0 ) )
|
545
|
+
@month_spinbox.set_numeric( true )
|
546
|
+
|
547
|
+
day_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.day" )}</b>" );
|
548
|
+
day_label.set_xalign( 0.9 )
|
549
|
+
day_label.set_use_markup( true )
|
550
|
+
@day_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["day"].to_i(), 0, 31, 1, 1, 0 ) )
|
551
|
+
@day_spinbox.set_numeric( true )
|
552
|
+
|
553
|
+
image_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.image" )}</b>" );
|
554
|
+
image_label.set_xalign( 0.9 )
|
555
|
+
image_label.set_use_markup( true )
|
556
|
+
@image_path_lineedit = Gtk::Entry.new()
|
557
|
+
if values.include?( "image_path" )
|
558
|
+
@image_path_lineedit.set_text( values["image_path"] )
|
559
|
+
@image_button = Gtk::Button.new( "..." )
|
560
|
+
@image_button.signal_connect( "clicked" ) { browse_image() }
|
561
|
+
else
|
562
|
+
@image_path_lineedit.set_text( I18n.get( "gui.submitalbum.coverfound" ) )
|
563
|
+
@image_path_lineedit.set_sensitive( false )
|
564
|
+
end
|
565
|
+
|
566
|
+
tracks_scrolled_window = Gtk::ScrolledWindow.new()
|
567
|
+
tracks_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
|
568
|
+
@tracks_text_buffer = GTK::TextBuffer.new()
|
569
|
+
@tracks_text_buffer.set_text( values["tracks"] )
|
570
|
+
@tracks_text = GTK::TextView.new()
|
571
|
+
@tracks_text.set_indent( 2 )
|
572
|
+
@tracks_text.set_buffer( @tracks_text_buffer )
|
573
|
+
tracks_scrolled_window.add( @tracks_text )
|
574
|
+
|
575
|
+
@reviewed_checkbox = Gtk::CheckButton.new( I18n.get( "gui.common.reviewed" ) )
|
576
|
+
@reviewed_checkbox.set_active( false )
|
577
|
+
|
578
|
+
buttons = create_action_buttons( "split", I18n.get( "gui.common.submit" ) )
|
579
|
+
|
580
|
+
image_hbox = Gtk::HBox.new();
|
581
|
+
image_hbox.pack_start( @image_path_lineedit, true, true )
|
582
|
+
image_hbox.pack_start( @image_button, false, true ) if values.include?( "image_path" )
|
583
|
+
|
584
|
+
tracks_frame = Gtk::Frame.new()
|
585
|
+
tracks_frame.add( tracks_scrolled_window )
|
586
|
+
tracks_frame.set_shadow_type( Gtk::SHADOW_IN )
|
587
|
+
|
588
|
+
grid = Gtk::Table.new( 9, 4, false )
|
589
|
+
grid.set_row_spacings( 3 )
|
590
|
+
grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
591
|
+
grid.attach( @artist_lineedit, 1, 6, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
592
|
+
grid.attach( album_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
593
|
+
grid.attach( @album_lineedit, 1, 6, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
|
594
|
+
grid.attach( year_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
595
|
+
grid.attach( @year_spinbox, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
596
|
+
grid.attach( month_label, 2, 3, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
597
|
+
grid.attach( @month_spinbox, 3, 4, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
598
|
+
grid.attach( day_label, 4, 5, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
599
|
+
grid.attach( @day_spinbox, 5, 6, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
600
|
+
grid.attach( image_label, 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
601
|
+
grid.attach( image_hbox, 1, 6, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
|
602
|
+
grid.attach( tracks_frame, 0, 6, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL )
|
603
|
+
grid.attach( @reviewed_checkbox, 0, 6, 5, 6, Gtk::EXPAND|Gtk::FILL, 0 )
|
604
|
+
grid.attach( buttons, 0, 6, 6, 7, Gtk::EXPAND|Gtk::FILL, 0 )
|
605
|
+
|
606
|
+
add( grid )
|
607
|
+
|
608
|
+
end
|
609
|
+
|
610
|
+
def browse_image()
|
611
|
+
dirname = @image_path_lineedit.text().strip()
|
612
|
+
dirname = GTK.empty_string?( dirname ) ? (ENV["HOME"] ? ENV["HOME"] : ".") : File.dirname( dirname )
|
613
|
+
dialog = Gtk::FileChooserDialog.new(
|
614
|
+
I18n.get( "gui.uploadcover.browseimage.title" ), self, Gtk::FileChooser::ACTION_OPEN, nil,
|
615
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
616
|
+
[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT]
|
617
|
+
)
|
618
|
+
|
619
|
+
filter = Gtk::FileFilter.new()
|
620
|
+
filter.set_name( I18n.get( "gui.uploadcover.browseimage.images" ) )
|
621
|
+
["jpg", "png", "bmp"].each() { |ext| filter.add_pattern( "*.#{ext}" ).add_pattern( "*.#{ext.upcase}" ) }
|
622
|
+
dialog.add_filter( filter )
|
623
|
+
filter = Gtk::FileFilter.new()
|
624
|
+
filter.set_name( I18n.get( "gui.uploadcover.browseimage.allfiles" ) )
|
625
|
+
filter.add_pattern( "*" )
|
626
|
+
dialog.add_filter( filter )
|
627
|
+
|
628
|
+
dialog.set_local_only( true )
|
629
|
+
dialog.set_select_multiple( false )
|
630
|
+
dialog.set_current_folder( File.expand_path( dirname ) )
|
631
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
632
|
+
image_path = GLib.filename_to_utf8( dialog.filename )
|
633
|
+
@image_path_lineedit.set_text( image_path.strip() ) if ! GTK.empty_string?( image_path )
|
634
|
+
end
|
635
|
+
dialog.destroy()
|
636
|
+
end
|
637
|
+
|
638
|
+
def accept()
|
639
|
+
aux = {
|
640
|
+
"artist" => @artist_lineedit.text(),
|
641
|
+
"album" => @album_lineedit.text(),
|
642
|
+
"year" => @year_spinbox.value().to_i(),
|
643
|
+
"month" => @month_spinbox.value().to_i(),
|
644
|
+
"day" => @day_spinbox.value().to_i(),
|
645
|
+
"tracks" => @tracks_text_buffer.text(),
|
646
|
+
"reviewed" => @reviewed_checkbox.active?()
|
647
|
+
}
|
648
|
+
aux["image_path"] = @image_path_lineedit.text() if @values.include?( "image_path" )
|
649
|
+
@values = aux
|
650
|
+
super()
|
651
|
+
end
|
652
|
+
|
653
|
+
end
|
654
|
+
|
655
|
+
|
656
|
+
class UploadCoverDialog < BaseDialog
|
657
|
+
|
658
|
+
def initialize( values )
|
659
|
+
super( values )
|
660
|
+
|
661
|
+
set_border_width( 5 )
|
662
|
+
set_resizable( true )
|
663
|
+
set_default_size( 350, 100 )
|
664
|
+
set_title( I18n.get( "gui.uploadcover.title", values["site_name"] ) )
|
665
|
+
|
666
|
+
album_group = Gtk::Frame.new( I18n.get( "gui.common.album" ) )
|
667
|
+
|
668
|
+
artist_label = Gtk::Label.new( I18n.get( "gui.common.artist" ) )
|
669
|
+
artist_label.set_xalign( 0 )
|
670
|
+
@artist_lineedit = Gtk::Entry.new()
|
671
|
+
@artist_lineedit.set_text( values["artist"] )
|
672
|
+
|
673
|
+
album_label = Gtk::Label.new( I18n.get( "gui.common.album" ) )
|
674
|
+
album_label.set_xalign( 0 )
|
675
|
+
@album_lineedit = Gtk::Entry.new()
|
676
|
+
@album_lineedit.set_text( values["album"] )
|
677
|
+
|
678
|
+
year_label = Gtk::Label.new( I18n.get( "gui.common.year" ) );
|
679
|
+
year_label.set_xalign( 0 )
|
680
|
+
@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"], 1900, Date.today().year, 1, 10, 0 ) )
|
681
|
+
@year_spinbox.set_numeric( true )
|
682
|
+
|
683
|
+
image_group = Gtk::Frame.new( I18n.get( "gui.common.image" ) )
|
684
|
+
|
685
|
+
image_label = Gtk::Label.new( I18n.get( "gui.uploadcover.imagepath" ) )
|
686
|
+
image_label.set_use_markup( true )
|
687
|
+
@image_path_lineedit = Gtk::Entry.new()
|
688
|
+
@image_path_lineedit.set_text( values["image_path"] )
|
689
|
+
@image_button = Gtk::Button.new( "..." )
|
690
|
+
@image_button.signal_connect( "clicked" ) { browse_image() }
|
691
|
+
|
692
|
+
buttons = create_action_buttons()
|
693
|
+
|
694
|
+
album_grid = Gtk::Table.new( 4, 4, false )
|
695
|
+
album_grid.set_row_spacings( 3 )
|
696
|
+
album_grid.set_column_spacings( 3 )
|
697
|
+
album_grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
698
|
+
album_grid.attach( @artist_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
699
|
+
album_grid.attach( album_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
700
|
+
album_grid.attach( @album_lineedit, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
701
|
+
album_grid.attach( year_label, 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
702
|
+
album_grid.attach( @year_spinbox, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
|
703
|
+
album_group.add( album_grid )
|
704
|
+
|
705
|
+
image_grid = Gtk::Table.new( 4, 4, false )
|
706
|
+
image_grid.set_row_spacings( 3 )
|
707
|
+
image_grid.set_column_spacings( 3 )
|
708
|
+
image_grid.attach( image_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
709
|
+
image_grid.attach( @image_path_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
710
|
+
image_grid.attach( @image_button, 2, 3, 0, 1, 0, 0 )
|
711
|
+
image_group.add( image_grid )
|
712
|
+
|
713
|
+
vbox = Gtk::VBox.new( false, 3 );
|
714
|
+
vbox.add( album_group )
|
715
|
+
vbox.add( image_group )
|
716
|
+
vbox.add( buttons )
|
717
|
+
|
718
|
+
add( vbox )
|
719
|
+
|
720
|
+
end
|
721
|
+
|
722
|
+
def browse_image()
|
723
|
+
dirname = @image_path_lineedit.text().strip()
|
724
|
+
dirname = GTK.empty_string?( dirname ) ? (ENV["HOME"] ? ENV["HOME"] : ".") : File.dirname( dirname )
|
725
|
+
dialog = Gtk::FileChooserDialog.new(
|
726
|
+
I18n.get( "gui.uploadcover.browseimage.title" ), self, Gtk::FileChooser::ACTION_OPEN, nil,
|
727
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
728
|
+
[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT]
|
729
|
+
)
|
730
|
+
|
731
|
+
filter = Gtk::FileFilter.new()
|
732
|
+
filter.set_name( I18n.get( "gui.uploadcover.browseimage.images" ) )
|
733
|
+
["jpg", "png", "bmp"].each() { |ext| filter.add_pattern( "*.#{ext}" ).add_pattern( "*.#{ext.upcase}" ) }
|
734
|
+
dialog.add_filter( filter )
|
735
|
+
filter = Gtk::FileFilter.new()
|
736
|
+
filter.set_name( I18n.get( "gui.uploadcover.browseimage.allfiles" ) )
|
737
|
+
filter.add_pattern( "*" )
|
738
|
+
dialog.add_filter( filter )
|
739
|
+
|
740
|
+
dialog.set_local_only( true )
|
741
|
+
dialog.set_select_multiple( false )
|
742
|
+
dialog.set_current_folder( File.expand_path( dirname ) )
|
743
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
744
|
+
image_path = GLib.filename_to_utf8( dialog.filename )
|
745
|
+
@image_path_lineedit.set_text( image_path.strip() ) if ! GTK.empty_string?( image_path )
|
746
|
+
end
|
747
|
+
dialog.destroy()
|
748
|
+
end
|
749
|
+
|
750
|
+
def accept()
|
751
|
+
@values = {
|
752
|
+
"artist" => @artist_lineedit.text(),
|
753
|
+
"album" => @album_lineedit.text(),
|
754
|
+
"year" => @year_spinbox.value().to_i(),
|
755
|
+
"image_path" => @image_path_lineedit.text()
|
756
|
+
}
|
757
|
+
super()
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
|
762
|
+
class FixPagesDialog < BaseDialog
|
763
|
+
|
764
|
+
def initialize( values )
|
765
|
+
super( values )
|
766
|
+
|
767
|
+
@fetch_func = eval( @values["fetch_func"] )
|
768
|
+
@fix_func = eval( @values["fix_func"] )
|
769
|
+
@submit_func = eval( @values["submit_func"] )
|
770
|
+
|
771
|
+
set_border_width( 5 )
|
772
|
+
set_resizable( true )
|
773
|
+
set_default_size( 600, 400 )
|
774
|
+
resize( 600, 400 )
|
775
|
+
|
776
|
+
set_title( "#{values["site_name"]} - #{values["title"]}" )
|
777
|
+
|
778
|
+
label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.url" )}</b>" );
|
779
|
+
label.set_use_markup( true )
|
780
|
+
label.set_xalign( 0.9 )
|
781
|
+
@url_lineedit = Gtk::Entry.new()
|
782
|
+
@url_lineedit.set_text( values["url"] )
|
783
|
+
|
784
|
+
page_scrolled_window = Gtk::ScrolledWindow.new()
|
785
|
+
page_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
|
786
|
+
@page_text_buffer = GTK::TextBuffer.new()
|
787
|
+
@page_text_buffer.set_text( "" )
|
788
|
+
@page_text = GTK::TextView.new()
|
789
|
+
@page_text.set_indent( 2 )
|
790
|
+
@page_text.set_buffer( @page_text_buffer )
|
791
|
+
page_scrolled_window.add( @page_text )
|
792
|
+
page_frame = Gtk::Frame.new()
|
793
|
+
page_frame.add( page_scrolled_window )
|
794
|
+
page_frame.set_shadow_type( Gtk::SHADOW_IN )
|
795
|
+
|
796
|
+
@fetch_button = Gtk::Button.new( I18n.get( "gui.common.load" ) )
|
797
|
+
@fix_button = Gtk::Button.new( I18n.get( "gui.common.fix" ) )
|
798
|
+
@submit_button = Gtk::Button.new( I18n.get( "gui.common.submit" ) )
|
799
|
+
|
800
|
+
hbox = Gtk::HButtonBox.new();
|
801
|
+
hbox.layout_style = Gtk::ButtonBox::END
|
802
|
+
hbox.add( @fetch_button )
|
803
|
+
hbox.add( @fix_button )
|
804
|
+
hbox.add( @submit_button )
|
805
|
+
|
806
|
+
grid = Gtk::Table.new( 3, 2, false )
|
807
|
+
grid.set_row_spacings( 3 )
|
808
|
+
grid.attach( label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
809
|
+
grid.attach( @url_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
810
|
+
grid.attach( page_frame, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL )
|
811
|
+
grid.attach( hbox, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
812
|
+
|
813
|
+
add( grid )
|
814
|
+
|
815
|
+
@fetch_button.signal_connect( "clicked" ) { fetch_page() }
|
816
|
+
@fix_button.signal_connect( "clicked" ) { fix_page() }
|
817
|
+
@submit_button.signal_connect( "clicked" ) { submit_page() }
|
818
|
+
end
|
819
|
+
|
820
|
+
def fetch_page()
|
821
|
+
if (page_content = @fetch_func.call( @url_lineedit.text() ))
|
822
|
+
@original_content = page_content
|
823
|
+
@original_url = @url_lineedit.text()
|
824
|
+
@page_text_buffer.set_text( page_content )
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
def fix_page()
|
829
|
+
@page_text_buffer.set_text( @fix_func.call( @page_text_buffer.text() ) ) if @original_content
|
830
|
+
end
|
831
|
+
|
832
|
+
def submit_page()
|
833
|
+
if @original_content && @original_content != (page_content = @page_text_buffer.text())
|
834
|
+
if @submit_func.call( @original_url, page_content )
|
835
|
+
@original_content = page_content
|
836
|
+
puts I18n.get( "gui.fixpages.success", @original_url )
|
837
|
+
else
|
838
|
+
puts I18n.get( "gui.fixpages.error", @original_url )
|
839
|
+
end
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
843
|
+
end
|
844
|
+
|
845
|
+
|
846
|
+
class SearchLyricsDialog < BaseDialog
|
847
|
+
|
848
|
+
def initialize( values )
|
849
|
+
super( values )
|
850
|
+
|
851
|
+
set_border_width( 5 )
|
852
|
+
set_resizable( true )
|
853
|
+
set_default_size( 300, 50 )
|
854
|
+
set_title( I18n.get( "gui.searchlyrics.title" ) )
|
855
|
+
|
856
|
+
group = Gtk::Frame.new( I18n.get( "gui.searchlyrics.search" ) )
|
857
|
+
|
858
|
+
artist_label = Gtk::Label.new( I18n.get( "gui.common.artist" ) )
|
859
|
+
artist_label.set_xalign( 0 )
|
860
|
+
@artist_lineedit = Gtk::Entry.new()
|
861
|
+
@artist_lineedit.set_text( values["artist"] )
|
862
|
+
|
863
|
+
title_label = Gtk::Label.new( I18n.get( "gui.common.song" ) )
|
864
|
+
title_label.set_xalign( 0 )
|
865
|
+
@title_lineedit = Gtk::Entry.new()
|
866
|
+
@title_lineedit.set_text( values["title"] )
|
867
|
+
|
868
|
+
album_label = Gtk::Label.new( I18n.get( "gui.common.album" ) );
|
869
|
+
album_label.set_xalign( 0 )
|
870
|
+
@album_lineedit = Gtk::Entry.new()
|
871
|
+
@album_lineedit.set_text( values["album"] )
|
872
|
+
|
873
|
+
year_label = Gtk::Label.new( I18n.get( "gui.common.year" ) );
|
874
|
+
year_label.set_xalign( 0 )
|
875
|
+
@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"], 1900, Date.today().year, 1, 10, 0 ) )
|
876
|
+
@year_spinbox.set_numeric( true )
|
877
|
+
|
878
|
+
buttons = create_action_buttons()
|
879
|
+
|
880
|
+
grid = Gtk::Table.new( 4, 4, false )
|
881
|
+
grid.set_row_spacings( 3 )
|
882
|
+
grid.set_column_spacings( 3 )
|
883
|
+
grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
884
|
+
grid.attach( @artist_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
|
885
|
+
grid.attach( title_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
886
|
+
grid.attach( @title_lineedit, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
|
887
|
+
grid.attach( album_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
888
|
+
grid.attach( @album_lineedit, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
|
889
|
+
grid.attach( year_label, 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, 0, 5 )
|
890
|
+
grid.attach( @year_spinbox, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
|
891
|
+
group.add( grid )
|
892
|
+
|
893
|
+
vbox = Gtk::VBox.new( false, 3 );
|
894
|
+
vbox.add( group )
|
895
|
+
vbox.add( buttons )
|
896
|
+
|
897
|
+
add( vbox )
|
898
|
+
|
899
|
+
end
|
900
|
+
|
901
|
+
def accept()
|
902
|
+
@values = {
|
903
|
+
"artist" => @artist_lineedit.text(),
|
904
|
+
"title" => @title_lineedit.text(),
|
905
|
+
"album" => @album_lineedit.text(),
|
906
|
+
"year" => @year_spinbox.value().to_i(),
|
907
|
+
}
|
908
|
+
super()
|
909
|
+
end
|
910
|
+
end
|
911
|
+
|
912
|
+
|
913
|
+
class ShowLyricsDialog < BaseDialog
|
914
|
+
|
915
|
+
def initialize( values )
|
916
|
+
super( values )
|
917
|
+
|
918
|
+
set_border_width( 5 )
|
919
|
+
set_resizable( true )
|
920
|
+
set_default_size( 400, 400 )
|
921
|
+
resize( 350, 400 )
|
922
|
+
|
923
|
+
title = I18n.get( "gui.lyrics.title", @values["title"], @values["artist"] )
|
924
|
+
title += " [#{@values["site_name"]}]" if @values["site_name"]
|
925
|
+
set_title( title )
|
926
|
+
|
927
|
+
lyrics_scrolled_window = Gtk::ScrolledWindow.new()
|
928
|
+
lyrics_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
|
929
|
+
@lyrics_text_buffer = GTK::TextBuffer.new()
|
930
|
+
@lyrics_text_buffer.set_text( values["lyrics"] )
|
931
|
+
@lyrics_text = GTK::TextView.new()
|
932
|
+
@lyrics_text.set_indent( 2 )
|
933
|
+
@lyrics_text.set_buffer( @lyrics_text_buffer )
|
934
|
+
lyrics_scrolled_window.add( @lyrics_text )
|
935
|
+
|
936
|
+
lyrics_frame = Gtk::Frame.new()
|
937
|
+
lyrics_frame.add( lyrics_scrolled_window )
|
938
|
+
lyrics_frame.set_shadow_type( Gtk::SHADOW_IN )
|
939
|
+
|
940
|
+
add( lyrics_frame )
|
941
|
+
end
|
942
|
+
|
943
|
+
end
|
944
|
+
|
945
|
+
end
|