themactep-fliewr 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ nbproject
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ == Fliewr
2
+
3
+ Copyright (c) 2008, Paul Philippov
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification,
7
+ are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+ * Neither the name of the PPDS.WS nor the names of its contributors may be used
15
+ to endorse or promote products derived from this software without specific
16
+ prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,52 @@
1
+ == Fliewr (Flickr Viewr) ==
2
+
3
+ Flickr friends photostream viewer.
4
+
5
+
6
+ === Licence ===
7
+
8
+ New BSD License
9
+
10
+
11
+ === Requirements: ===
12
+
13
+ * Ruby
14
+ http://www.ruby-lang.org/
15
+
16
+ * GTK+
17
+ http://www.mozilla.org/
18
+
19
+ * Gecko engine from Mozilla
20
+ http://www.mozilla.org/
21
+
22
+ * Ruby Gtk2 bindings and Ruby/GTK bindings for Mozilla
23
+ from Ruby-GNOME2 Project
24
+ http://ruby-gnome2.sourceforge.jp/
25
+
26
+ * Ruby XML library
27
+ http://libxml.rubyforge.org/
28
+
29
+ Say Gentoo Linux users could run following command:
30
+
31
+ $ sudo emerge -uva \
32
+ dev-lang/ruby \
33
+ dev-ruby/ruby-gconf2 \
34
+ dev-ruby/ruby-gtk2 \
35
+ dev-ruby/ruby-gtkmozembed \
36
+ dev-ruby/libxml
37
+
38
+
39
+ === Installation ===
40
+
41
+ $ sudo gem source -a http://gems.github.com/
42
+ $ sudo gem install themactep-fliewr
43
+
44
+
45
+ === Homepage ===
46
+
47
+ http://github.com/themactep/fliewr
48
+
49
+
50
+ === Authors ===
51
+
52
+ Paul Philippov <themactep@gmail.com>
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gemspec|
8
+ gemspec.name = "fliewr"
9
+ gemspec.summary = "Flickr Viewr for GNOME"
10
+ gemspec.description = "fliewr is a GNOME application to watch updates from Flickr contacts."
11
+ gemspec.email = "themactep@gmail.com"
12
+ gemspec.homepage = "http://github.com/themactep/fliewr"
13
+ gemspec.description = "TODO"
14
+ gemspec.authors = ["Paul Philippov"]
15
+ gemspec.add_dependency "libxml"
16
+ gemspec.add_dependency "rest-client"
17
+ end
18
+ rescue LoadError
19
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
20
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/bin/fliewr ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # $Id: fliewr.rb 2009/02/08 21:48:53 EET paul Exp $
3
+ #
4
+ =begin
5
+ Flickr Viewr - Flicker Friends Photostream Viewer.
6
+
7
+ Copyright (c) 2008, Paul Philippov <paul@ppds.ws>
8
+
9
+ This software is released under the BSD License.
10
+ http://creativecommons.org/licenses/BSD/
11
+ =end
12
+
13
+ app_file = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
14
+ APP_ROOT = File.expand_path(File.dirname(app_file))
15
+ Dir.glob(APP_ROOT + '/../**/').reverse.each { |d| $:.unshift d }
16
+
17
+ begin
18
+ require 'rubygems'
19
+ rescue LoadError
20
+ nil
21
+ end
22
+
23
+ require 'fliewr/core'
24
+
25
+ Fliewr::Core.new
26
+ Thread.new { Fliewr::StatusIcon.new }
27
+ $app.main
data/data/api.url ADDED
@@ -0,0 +1 @@
1
+ http://api.flickr.com/services/rest?method=flickr.photos.getContactsPublicPhotos&api_key=0282f93eb6da0425310bd5791f4c2fc0&extras=date_upload,icon_server,license&user_id=%s&count=%d&single_photo=%d&just_friends=%d&include_self=%d
@@ -0,0 +1,9 @@
1
+ [Desktop Entry]
2
+ Name=Fliewr
3
+ Comment=Flickr Viewr
4
+ Exec=fliewr
5
+ Icon=fliewr
6
+ StartupNotify=true
7
+ Terminal=false
8
+ Type=Application
9
+ Categories=Network;
data/data/fliewr.svg ADDED
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128">
2
+ <path fill="#0063dc" stroke="none" d="M 64.504461,16.817487 C 38.168536,17.488304 16.999778,39.17825 16.999778,65.787131 C 16.999778,84.014679 26.943418,99.898404 41.666404,108.32951 C 37.617837,101.19225 35.285462,92.947102 35.285462,84.150747 C 35.285462,57.119498 57.130753,35.181103 84.047286,35.181103 C 92.813625,35.181103 101.03145,37.517116 108.14248,41.589241 C 99.748559,26.798284 83.915678,16.817487 65.761602,16.817487 C 65.341032,16.817487 64.922491,16.806836 64.504461,16.817487 z" />
3
+ <path fill="#ff0084" stroke="none" d="M 94.809723,47.321192 C 97.715396,52.419557 99.386031,58.317585 99.386031,64.60187 C 99.386031,83.90596 83.71894,99.573047 64.414849,99.573047 C 58.127778,99.573047 52.234085,97.891152 47.134167,94.98308 C 53.153275,105.54919 64.506779,112.68725 77.529041,112.68725 C 96.833137,112.68725 112.50022,97.020162 112.50022,77.716061 C 112.50022,64.699042 105.36882,53.342179 94.809723,47.321192 z" />
4
+ </svg>
@@ -0,0 +1 @@
1
+ <div class="error"> <h1>Error</h1> %s</div>
@@ -0,0 +1,10 @@
1
+ <div class="message">
2
+ <a class="image" href="%s" style="background-image:url(%s);"></a>
3
+ <div class="popup">
4
+ <div class="userpic">
5
+ <a href="%s" title="%s"><img src="%s" alt="" /></a>
6
+ </div>
7
+ <h1>%s</h1>
8
+ <p class="time">%s</p>
9
+ </div>
10
+ </div>
@@ -0,0 +1,72 @@
1
+ body {
2
+ padding : 0;
3
+ color : #999;
4
+ color : #fff;
5
+ background : #333;
6
+ line-height : 1.250;
7
+ font : 12px "NokiaSansCn", "LucidaGrande", sans-serif;
8
+ }
9
+ body, img {
10
+ margin : 0;
11
+ }
12
+ img {
13
+ border : none;
14
+ }
15
+ div, h1, p, a {
16
+ margin-bottom : 0;
17
+ }
18
+ a {
19
+ color : #fff;
20
+ text-decoration : none;
21
+ }
22
+ div.error {
23
+ padding : 10px;
24
+ }
25
+ div.message {
26
+ clear : both;
27
+ position : relative;
28
+ padding : 7px;
29
+ margin : 5px;
30
+ color : #bbb;
31
+ background-color : #444;
32
+ -moz-border-radius : 7px;
33
+ }
34
+ a.image {
35
+ display : block;
36
+ height : 130px;
37
+ background-position : center;
38
+ }
39
+ div.userpic {
40
+ width : 55px;
41
+ height : 100%;
42
+ float : left;
43
+ }
44
+ div.imgbox {
45
+ width : 48px;
46
+ height : 48px;
47
+ margin-bottom : 5px;
48
+ background-repeat : no-repeat;
49
+ }
50
+ div.popup {
51
+ position : absolute;
52
+ left : 7px;
53
+ right : 7px;
54
+ bottom : 7px;
55
+ background-color : #000;
56
+ padding : 5px;
57
+ display : none;
58
+ }
59
+ div.message:hover div.popup {
60
+ display : inherit;
61
+ }
62
+ h1 {
63
+ font : bold 11px "NokiaSans", "LucidaGrande", sans-serif;
64
+ margin-top : 0;
65
+ height : 2.500em;
66
+ overflow : hidden;
67
+ color : #ff0;
68
+ }
69
+ p.time {
70
+ font-size : 10px;
71
+ text-align : right;
72
+ }
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en">
4
+ <head>
5
+ <title>Flickr Viewr</title>
6
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7
+ <style type="text/css">
8
+ /*<![CDATA[*/
9
+ %s
10
+ /*]]>*/
11
+ </style>
12
+ </head>
13
+ <body>
14
+ %s
15
+ </body>
16
+ </html>
data/fliewr.gemspec ADDED
@@ -0,0 +1,60 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{fliewr}
8
+ s.version = "2.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Paul Philippov"]
12
+ s.date = %q{2009-08-22}
13
+ s.default_executable = %q{fliewr}
14
+ s.description = %q{TODO}
15
+ s.email = %q{themactep@gmail.com}
16
+ s.executables = ["fliewr"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/fliewr",
28
+ "data/api.url",
29
+ "data/fliewr.desktop",
30
+ "data/fliewr.svg",
31
+ "data/themes/default/error.html",
32
+ "data/themes/default/item.html",
33
+ "data/themes/default/style.css",
34
+ "data/themes/default/theme.html",
35
+ "fliewr.gemspec",
36
+ "lib/fliewr/core.rb",
37
+ "lib/fliewr/ui.rb",
38
+ "lib/ppds/class_factory.rb",
39
+ "lib/ppds/config.rb",
40
+ "lib/ppds/flickr.rb"
41
+ ]
42
+ s.homepage = %q{http://github.com/themactep/fliewr}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.5}
46
+ s.summary = %q{Flickr Viewr for GNOME}
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<libxml>, [">= 0"])
54
+ else
55
+ s.add_dependency(%q<libxml>, [">= 0"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<libxml>, [">= 0"])
59
+ end
60
+ end
@@ -0,0 +1,71 @@
1
+ require 'ppds/config'
2
+ require 'ppds/flickr'
3
+ require 'fliewr/ui'
4
+ require 'gtk2'
5
+
6
+ module Fliewr
7
+ class Core
8
+
9
+ def initialize
10
+ $app = self
11
+ $cfg = Ppds::Config.new 'fliewr'
12
+
13
+ $gui = Fliewr::UI.new
14
+ $gui.show_all
15
+
16
+ $api = Ppds::Flickr.new
17
+
18
+ start_timer
19
+ end
20
+
21
+ def update
22
+ Gtk.timeout_remove(@@timeout) if @@timeout
23
+ $gui.statusbar.push 0, "updating..."
24
+
25
+ Thread.new do
26
+ ask_update $cfg.get(:update_interval) * 60
27
+ photos = $api.update $cfg.get(:max_photos)
28
+ $gui.refresh_with photos
29
+ @last_updated_at = timestamp
30
+ end
31
+ start_timer
32
+ rescue Exception => e
33
+ Alert.new @nsid, e.message, e.backtrace
34
+ end
35
+
36
+ def timestamp
37
+ Time.now.to_i
38
+ end
39
+
40
+ def ask_update(time_ahead = 0)
41
+ @requires_update_at = timestamp + time_ahead
42
+ end
43
+
44
+ def start_timer
45
+ @@timeout = Gtk::timeout_add(1000) do
46
+ sec_to_next_update = @requires_update_at.to_i - timestamp
47
+ if sec_to_next_update < 0
48
+ update
49
+ else
50
+ $gui.statusbar.push 0, "%s to update" % human_time(sec_to_next_update)
51
+ end
52
+ end
53
+ end
54
+
55
+ def human_time(time)
56
+ seconds = time.modulo(SECONDS_PER_MINUTE)
57
+ minutes = (time - seconds) / SECONDS_PER_MINUTE
58
+ "%d:%02d" % [minutes, seconds]
59
+ end
60
+
61
+ def main
62
+ Gtk::main
63
+ end
64
+
65
+ def quit
66
+ Gtk::main_quit
67
+ ensure
68
+ $cfg.save
69
+ end
70
+ end
71
+ end
data/lib/fliewr/ui.rb ADDED
@@ -0,0 +1,370 @@
1
+ require 'gtk2'
2
+ require 'gtkmozembed'
3
+
4
+ Gtk::MozEmbed.set_profile_path ENV['HOME'] + '/.mozilla', 'fliewr'
5
+
6
+ module Fliewr
7
+
8
+ SECONDS_PER_MINUTE = 60
9
+ IMAGE_ROOT = File.expand_path(File.join(APP_ROOT, '..', 'data'))
10
+
11
+ class UI < Gtk::Window
12
+
13
+ attr_accessor :logo, :statusbar, :theme_base, :theme_item, :theme_error, :theme_style
14
+
15
+ def initialize
16
+ super Gtk::Window::TOPLEVEL
17
+
18
+ filename = File.join(Fliewr::IMAGE_ROOT, 'fliewr.svg')
19
+ self.logo = Gdk::Pixbuf.new filename, 128, 128
20
+
21
+ self.set_title 'Fliewr'
22
+ self.set_icon self.logo
23
+ self.set_width_request 278
24
+ self.set_height_request 400
25
+ self.set_allow_shrink false
26
+ self.set_default_width $cfg.get(:window_width).to_i
27
+ self.set_default_height $cfg.get(:window_height).to_i
28
+ self.move $cfg.get(:window_x_pos).to_i, $cfg.get(:window_y_pos).to_i
29
+
30
+ theme = $cfg.get(:theme) || 'default'
31
+ self.theme_base = File.open(File.join('../data/themes/',theme,'theme.html'), "r") { |f| f.read }
32
+ self.theme_item = File.open(File.join('../data/themes/',theme,'item.html'), "r") { |f| f.read }
33
+ self.theme_error = File.open(File.join('../data/themes/',theme,'error.html'), "r") { |f| f.read }
34
+ self.theme_style = File.open(File.join('../data/themes/',theme,'style.css'), "r") { |f| f.read }
35
+
36
+ self.signal_connect(:destroy) { quit }
37
+ self.signal_connect(:delete_event) { minimize }
38
+ self.signal_connect(:check_resize) { remember_size_position }
39
+ self.signal_connect(:window_state_event) do |widget, event|
40
+ case event.event_type
41
+ when Gdk::Event::WINDOW_STATE
42
+ minimize if event.changed_mask.iconified? and event.new_window_state.iconified?
43
+ end
44
+ end
45
+
46
+ self.statusbar = Gtk::Statusbar.new
47
+ self.statusbar.set_has_resize_grip false
48
+
49
+ toolbar = Gtk::Toolbar.new
50
+ toolbar.icon_size = Gtk::IconSize::MENU
51
+
52
+ icon = Gtk::Image.new Gtk::Stock::HOME, Gtk::IconSize::MENU
53
+ button = Gtk::ToolButton.new icon, 'Flickr'
54
+ button.set_important true
55
+ button.signal_connect(:clicked) do |widget|
56
+ visit_user_profile
57
+ end
58
+ toolbar.insert 0, button
59
+
60
+ icon = Gtk::Image.new Gtk::Stock::REFRESH, Gtk::IconSize::MENU
61
+ button = Gtk::ToolButton.new icon, 'Refresh'
62
+ button.set_important true
63
+ button.set_can_default true
64
+ button.set_can_focus true
65
+ button.signal_connect(:clicked) do |widget|
66
+ $app.ask_update
67
+ end
68
+ toolbar.insert 1, button
69
+ self.set_default button
70
+ self.set_focus button
71
+
72
+ icon = Gtk::Image.new Gtk::Stock::PREFERENCES, Gtk::IconSize::MENU
73
+ button = Gtk::ToolButton.new icon, 'Settings'
74
+ button.signal_connect(:clicked) do |widget|
75
+ Fliewr::SettingsDialog.new
76
+ end
77
+ toolbar.insert 2, button
78
+
79
+ separator = Gtk::SeparatorToolItem.new
80
+ separator.set_draw false
81
+ separator.set_expand true
82
+ toolbar.insert 3, separator
83
+
84
+ icon = Gtk::Image.new Gtk::Stock::QUIT, Gtk::IconSize::MENU
85
+ button = Gtk::ToolButton.new icon, 'Quit'
86
+ button.signal_connect(:clicked) do |widget|
87
+ $app.quit
88
+ end
89
+ toolbar.insert 4, button
90
+
91
+ @browser = Gtk::MozEmbed.new
92
+ @browser.signal_connect(:open_uri) do |widget, uri|
93
+ open_in_external_browser(uri)
94
+ end
95
+
96
+ vbox = Gtk::VBox.new false, 4
97
+ vbox.pack_start toolbar, false
98
+ vbox.pack_start @browser
99
+ vbox.pack_start self.statusbar, false
100
+ self.add vbox
101
+ end
102
+
103
+ def remember_size_position
104
+ x, y = self.position
105
+ w, h = self.size
106
+ $cfg.set :window_x_pos, x
107
+ $cfg.set :window_y_pos, y
108
+ $cfg.set :window_width, w
109
+ $cfg.set :window_height, h
110
+ end
111
+
112
+ def minimize
113
+ remember_size_position
114
+ hide
115
+ end
116
+
117
+ def maximize
118
+ self.show
119
+ self.present
120
+ end
121
+
122
+ def open_in_gecko(html)
123
+ @browser.open_stream "file:///", "text/html"
124
+ @browser.append_data self.theme_base % [ self.theme_style, html ]
125
+ @browser.close_stream
126
+ end
127
+
128
+ def refresh_with(data)
129
+ html = data.map { |d| templatize(d) }.join
130
+ open_in_gecko html
131
+ end
132
+
133
+ def templatize(data)
134
+ self.theme_item % [
135
+ photolink(data.owner, data.id),
136
+ photopreview(data.farm, data.server, data.id, data.secret),
137
+ user_profile_link(data.owner),
138
+ data.username,
139
+ userpic(data.iconfarm, data.iconserver, data.owner),
140
+ data.title,
141
+ dateupload(data.dateupload)
142
+ ]
143
+ end
144
+
145
+ def photopreview(*args)
146
+ 'http://farm%s.static.flickr.com/%s/%s_%s_m.jpg' % args
147
+ end
148
+
149
+ def photolink(*args)
150
+ 'http://www.flickr.com/photos/%s/%s' % args
151
+ end
152
+
153
+ def user_profile_link(id = @nsid)
154
+ 'http://www.flickr.com/people/%s' % id
155
+ end
156
+
157
+ def userpic(farm, server, owner)
158
+ return 'http://www.flickr.com/images/buddyicon.jpg' if farm.to_i == 0
159
+ 'http://farm%s.static.flickr.com/%s/buddyicons/%s.jpg' % [ farm, server, owner ]
160
+ end
161
+
162
+ def dateupload(date_and_time)
163
+ Time.at(date_and_time.to_i)
164
+ end
165
+
166
+ def visit_user_profile
167
+ open_in_external_browser user_profile_link
168
+ end
169
+
170
+ def open_in_external_browser(uri)
171
+ Thread.new { system('xdg-open "%s"' % uri) }
172
+ end
173
+
174
+ def quit
175
+ $app.quit
176
+ end
177
+ end
178
+
179
+
180
+ class StatusIcon < Gtk::StatusIcon
181
+ def initialize
182
+ super
183
+ self.file = File.join(Fliewr::IMAGE_ROOT, 'fliewr.svg')
184
+ self.set_tooltip 'Flickr Viewr'
185
+ self.signal_connect(:activate) do
186
+ if $gui.visible?
187
+ $gui.minimize
188
+ else
189
+ $gui.move $cfg.get(:window_x_pos), $cfg.get(:window_y_pos)
190
+ $gui.show.present
191
+ end
192
+ end
193
+
194
+ self.signal_connect(:popup_menu) do |icon, button, time|
195
+ menu.popup nil, nil, button, time
196
+ end
197
+
198
+ separator = Gtk::SeparatorMenuItem.new
199
+
200
+ menu = Gtk::Menu.new
201
+
202
+ item = Gtk::ImageMenuItem.new Gtk::Stock::HOME
203
+ item.signal_connect(:activate) do
204
+ $app.visit_user_profile
205
+ end
206
+ menu.append item
207
+
208
+ item = Gtk::ImageMenuItem.new Gtk::Stock::REFRESH
209
+ item.signal_connect(:activate) do
210
+ $app.update
211
+ end
212
+ menu.append item
213
+
214
+ item = Gtk::CheckMenuItem.new 'Always on top'
215
+ item.signal_connect(:toggled) do |widget|
216
+ $gui.keep_above = widget.active?
217
+ end
218
+ menu.append item
219
+
220
+ item = Gtk::ImageMenuItem.new Gtk::Stock::PREFERENCES
221
+ item.signal_connect(:activate) do
222
+ Fliewr::SettingsDialog.new
223
+ end
224
+ menu.append item
225
+
226
+ item = Gtk::ImageMenuItem.new Gtk::Stock::ABOUT
227
+ item.signal_connect(:activate) do
228
+ AboutDialog.new
229
+ end
230
+ menu.append item
231
+ menu.append separator
232
+
233
+ item = Gtk::ImageMenuItem.new Gtk::Stock::QUIT
234
+ item.signal_connect(:activate) do
235
+ $app.quit
236
+ end
237
+ menu.append item
238
+ menu.show_all
239
+ end
240
+ end
241
+
242
+ class AboutDialog < Gtk::AboutDialog
243
+ def initialize
244
+ Gtk::AboutDialog.set_email_hook do |widget, email|
245
+ system("xdg-email #{email}")
246
+ end
247
+ Gtk::AboutDialog.set_url_hook do |widget, link|
248
+ system("xdg-open #{link}")
249
+ end
250
+ super
251
+ self.name = 'Flickr Viewr'
252
+ self.program_name = 'Flickr Viewr'
253
+ self.comments = "Flickr photostream viewer"
254
+ self.version = '2.0'
255
+ self.copyright = "Copyright (c)2008 Paul Philippov"
256
+ self.license = "This software is released under the BSD License.\nhttp://creativecommons.org/licenses/BSD/"
257
+ self.authors = ['Paul Philippov <paul@ppds.ws>']
258
+ self.documenters = ['Paul Philippov <paul@ppds.ws>']
259
+ self.website = "http://fliewr.googlecode.com/"
260
+ self.logo = $gui.logo
261
+ self.run
262
+ self.destroy
263
+ end
264
+ end
265
+
266
+ class SettingsDialog < Gtk::Dialog
267
+ def initialize
268
+ super "Settings", nil, Gtk::Dialog::MODAL,
269
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT],
270
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
271
+
272
+ self.set_default_response Gtk::Dialog::RESPONSE_ACCEPT
273
+ self.signal_connect :response do |dialog, response|
274
+ case response
275
+ when Gtk::Dialog::RESPONSE_ACCEPT
276
+ if /\d\d\d\d\d\d\d\d@N\d\d/ =~ @nsid_entry.text
277
+ $cfg.set :nsid, @nsid_entry.text
278
+ $cfg.set :update_interval, @update_interval_spin.value
279
+ $cfg.set :max_photos, @max_photos_spin.value
280
+ $cfg.set :one_per_contact, @one_per_contact_toggle.active?
281
+ $cfg.set :only_from_friends, @only_from_friends_toggle.active?
282
+ $cfg.set :include_self, @include_self_toggle.active?
283
+ $app.update
284
+ else
285
+ Alert.new "User ID has incorrect format"
286
+ end
287
+ when Gtk::Dialog::RESPONSE_CANCEL
288
+ true
289
+ end
290
+ end
291
+ hbox = Gtk::HBox.new false, 8
292
+ hbox.set_border_width 8
293
+ self.vbox.pack_start hbox, false, false, 0
294
+
295
+ stock = Gtk::Image.new Gtk::Stock::PREFERENCES, Gtk::IconSize::DIALOG
296
+ hbox.pack_start stock, false, false, 0
297
+
298
+ table = Gtk::Table.new 3, 6
299
+ table.set_row_spacings 4
300
+ table.set_column_spacings 8
301
+ hbox.pack_start table, true, true, 0
302
+
303
+ @nsid_entry = Gtk::Entry.new
304
+ @nsid_entry.width_chars = 13
305
+ @nsid_entry.max_length = 12
306
+ @nsid_entry.text = $cfg.get(:nsid)
307
+ table.attach_defaults label('Your Flickr user ID'), 0, 1, 0, 1
308
+ table.attach_defaults @nsid_entry, 1, 2, 0, 1
309
+ table.attach_defaults button_with_click(:find, :find_nsid), 2, 3, 0, 1
310
+
311
+ @update_interval_spin = Gtk::SpinButton.new(1, 100, 1)
312
+ @update_interval_spin.value = $cfg.get(:update_interval).to_i
313
+ table.attach_defaults label('Check new photos every'), 0, 1, 1, 2
314
+ table.attach_defaults @update_interval_spin, 1, 2, 1, 2
315
+ table.attach_defaults label('minutes'), 2, 3, 1, 2
316
+
317
+ @max_photos_spin = Gtk::SpinButton.new(1, 50, 1)
318
+ @max_photos_spin.value = $cfg.get(:max_photos).to_i
319
+ table.attach_defaults label('Maximum photos to display'), 0, 1, 2, 3
320
+ table.attach_defaults @max_photos_spin, 1, 2, 2, 3
321
+
322
+ @one_per_contact_toggle = Gtk::CheckButton.new
323
+ @one_per_contact_toggle.active = $cfg.get(:one_per_contact)
324
+ table.attach_defaults label('Only one photo per contact'), 0, 1, 3, 4
325
+ table.attach_defaults @one_per_contact_toggle, 1, 2, 3, 4
326
+
327
+ @only_from_friends_toggle = Gtk::CheckButton.new
328
+ @only_from_friends_toggle.active = $cfg.get(:only_from_friend)
329
+ table.attach_defaults label('Only from friends and family'), 0, 1, 4, 5
330
+ table.attach_defaults @only_from_friends_toggle, 1, 2, 4, 5
331
+
332
+ @include_self_toggle = Gtk::CheckButton.new
333
+ @include_self_toggle.active = $cfg.get(:include_self)
334
+ table.attach_defaults label('Include your own photos'), 0, 1, 5, 6
335
+ table.attach_defaults @include_self_toggle, 1, 2, 5, 6
336
+
337
+ self.show_all
338
+ self.run
339
+ self.destroy
340
+ end
341
+
342
+ def button_with_click(stock_id, method_name)
343
+ button = Gtk::Button.new icon(stock_id)
344
+ button.signal_connect(:clicked) do |widget|
345
+ self.method(method_name).call
346
+ end
347
+ button.show_all
348
+ end
349
+
350
+ def find_nsid
351
+ $gui.open_in_external_browser 'http://www.flickr.com/services/api/explore/?method=flickr.people.getInfo'
352
+ end
353
+
354
+ def icon(stock_id)
355
+ Gtk::Stock.const_get stock_id.to_s.upcase
356
+ end
357
+
358
+ def label(text)
359
+ Gtk::Label.new(text).set_alignment(0, 0.5)
360
+ end
361
+ end
362
+
363
+ class Alert
364
+ def initialize(*args)
365
+ html = $gui.theme_error % [args].flatten.map { |e| "<li>#{e}</li>" }.join
366
+ $gui.open_in_gecko(html)
367
+ false
368
+ end
369
+ end
370
+ end
@@ -0,0 +1,17 @@
1
+ module Ppds
2
+ class ClassFactory
3
+ def initialize(data=[])
4
+ for att in data
5
+ set(att.name.gsub(/-/,'_'), att.value)
6
+ end
7
+ end
8
+
9
+ def get(name)
10
+ instance_variable_get("@#{name}")
11
+ end
12
+
13
+ def set(name, value)
14
+ instance_variable_set("@#{name}", value)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,47 @@
1
+ require 'gconf2'
2
+
3
+ module Ppds
4
+ class Config
5
+ @@gconf = GConf::Client.default
6
+
7
+ def gconf
8
+ @@gconf
9
+ end
10
+
11
+ def initialize(app)
12
+ @root = '/apps/%s' % app
13
+ gconf.add_dir(@root)
14
+ end
15
+
16
+ def name_from_key(key)
17
+ key.split('/').last
18
+ end
19
+
20
+ def key_from_name(name)
21
+ [ @root, name ].join("/")
22
+ end
23
+
24
+ def all
25
+ gconf.all_entries(@root)
26
+ end
27
+
28
+ def get(name)
29
+ gconf[key_from_name(name)]
30
+ end
31
+
32
+ def set(name, value)
33
+ gconf[key_from_name(name)] = value
34
+ end
35
+
36
+ def save
37
+ gconf.suggest_sync
38
+ end
39
+
40
+ def destroy
41
+ for one in all
42
+ gconf.unset(one.key)
43
+ end
44
+ save
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,51 @@
1
+ require 'ppds/class_factory'
2
+ require 'rest_client'
3
+ require 'xml'
4
+
5
+ module Ppds
6
+ class Photo < ClassFactory
7
+ attr_accessor :id, :secret, :server, :farm, :title, :owner, :username,
8
+ :ispublic, :isfriend, :isfamily, :dateupload, :iconserver,
9
+ :iconfarm, :license
10
+ end
11
+
12
+ class Flickr
13
+ API_URL = 'http://api.flickr.com/services/rest'
14
+ API_KEY = '0282f93eb6da0425310bd5791f4c2fc0'
15
+
16
+ attr_accessor :photos
17
+
18
+ def initialize
19
+ end
20
+
21
+ def query(action, data)
22
+ data.update({
23
+ :api_key => API_KEY,
24
+ :method => action
25
+ })
26
+ RestClient.post(API_URL, data)
27
+ rescue RestClient::RequestFailed
28
+ raise 'Query failed: %s' % $!
29
+ rescue RestClient::RequestTimeout
30
+ raise 'Timeout occured'
31
+ rescue Exception
32
+ raise $!
33
+ end
34
+
35
+ def update(qty)
36
+ data = {
37
+ :extras => 'date_upload,icon_server,license',
38
+ :count => qty,
39
+ :user_id => $cfg.get(:nsid).to_s,
40
+ :single_photo => $cfg.get(:one_per_contact) ? 1 : 0,
41
+ :just_friends => $cfg.get(:only_from_friends) ? 1 : 0,
42
+ :include_self => $cfg.get(:include_self) ? 1 : 0
43
+ }
44
+ xml = query('flickr.photos.getContactsPublicPhotos', data)
45
+ @xml = XML::Parser.string(xml).parse
46
+ self.photos = @xml.find('//photos/photo').map do |node|
47
+ Photo.new(node.attributes)
48
+ end
49
+ end
50
+ end
51
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: themactep-fliewr
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Philippov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-22 00:00:00 -07:00
13
+ default_executable: fliewr
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: libxml
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: TODO
26
+ email: themactep@gmail.com
27
+ executables:
28
+ - fliewr
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README
34
+ files:
35
+ - .gitignore
36
+ - LICENSE
37
+ - README
38
+ - Rakefile
39
+ - VERSION
40
+ - bin/fliewr
41
+ - data/api.url
42
+ - data/fliewr.desktop
43
+ - data/fliewr.svg
44
+ - data/themes/default/error.html
45
+ - data/themes/default/item.html
46
+ - data/themes/default/style.css
47
+ - data/themes/default/theme.html
48
+ - fliewr.gemspec
49
+ - lib/fliewr/core.rb
50
+ - lib/fliewr/ui.rb
51
+ - lib/ppds/class_factory.rb
52
+ - lib/ppds/config.rb
53
+ - lib/ppds/flickr.rb
54
+ has_rdoc: false
55
+ homepage: http://github.com/themactep/fliewr
56
+ licenses:
57
+ post_install_message:
58
+ rdoc_options:
59
+ - --charset=UTF-8
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.5
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Flickr Viewr for GNOME
81
+ test_files: []
82
+