fliewr 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +27 -0
- data/README +46 -0
- data/Rakefile +50 -0
- data/bin/fliewr +23 -0
- data/data/fliewr.desktop +9 -0
- data/data/pixmaps/fliewr.svg +4 -0
- data/data/themes/default/error.html +4 -0
- data/data/themes/default/item.html +10 -0
- data/data/themes/default/style.css +72 -0
- data/data/themes/default/theme.html +16 -0
- data/lib/fliewr/core.rb +71 -0
- data/lib/fliewr/ui.rb +372 -0
- data/lib/ppds/flickr.rb +51 -0
- metadata +97 -0
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,46 @@
|
|
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
|
+
* LibXml Ruby
|
27
|
+
http://libxml.rubyforge.org/
|
28
|
+
|
29
|
+
* REST Client
|
30
|
+
http://github.com/adamwiggins/rest-client/
|
31
|
+
|
32
|
+
|
33
|
+
=== Installation ===
|
34
|
+
|
35
|
+
$ sudo gem source -a http://gems.github.com/
|
36
|
+
$ sudo gem install themactep-fliewr
|
37
|
+
|
38
|
+
|
39
|
+
=== Homepage ===
|
40
|
+
|
41
|
+
http://themactep.com/fliewr
|
42
|
+
|
43
|
+
|
44
|
+
=== Authors ===
|
45
|
+
|
46
|
+
Paul Philippov <themactep@gmail.com>
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rake/testtask'
|
7
|
+
require 'spec/rake/spectask'
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'fliewr'
|
11
|
+
s.version = '2.0.0'
|
12
|
+
s.has_rdoc = false
|
13
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
14
|
+
s.summary = 'Flickr Viewr for GNOME'
|
15
|
+
s.description = 'fliewr a GNOME application to monitor updates from Flickr contacts'
|
16
|
+
s.author = 'Paul Philippov'
|
17
|
+
s.email = 'themactep@gmail.com'
|
18
|
+
s.homepage = 'http://themactep.com/fliewr'
|
19
|
+
s.rubyforge_project = 'fliewr'
|
20
|
+
s.executables = ['fliewr']
|
21
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,data,lib,spec}/**/*")
|
22
|
+
s.require_path = "lib"
|
23
|
+
s.bindir = "bin"
|
24
|
+
s.add_dependency "ppds-libs"
|
25
|
+
s.add_dependency "libxml-ruby"
|
26
|
+
s.add_dependency "rest-client"
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::GemPackageTask.new(spec) do |p|
|
30
|
+
p.gem_spec = spec
|
31
|
+
p.need_tar = true
|
32
|
+
p.need_zip = true
|
33
|
+
end
|
34
|
+
|
35
|
+
Rake::RDocTask.new do |rdoc|
|
36
|
+
files =['README', 'LICENSE', 'lib/**/*.rb']
|
37
|
+
rdoc.rdoc_files.add(files)
|
38
|
+
rdoc.main = "README" # page to start on
|
39
|
+
rdoc.title = "fliewr Docs"
|
40
|
+
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
|
41
|
+
rdoc.options << '--line-numbers'
|
42
|
+
end
|
43
|
+
|
44
|
+
Rake::TestTask.new do |t|
|
45
|
+
t.test_files = FileList['test/**/*.rb']
|
46
|
+
end
|
47
|
+
|
48
|
+
Spec::Rake::SpecTask.new do |t|
|
49
|
+
t.spec_files = FileList['spec/**/*.rb']
|
50
|
+
end
|
data/bin/fliewr
ADDED
@@ -0,0 +1,23 @@
|
|
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
|
+
begin
|
14
|
+
require 'rubygems'
|
15
|
+
rescue LoadError
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'fliewr/core'
|
20
|
+
|
21
|
+
Fliewr::Core.new
|
22
|
+
Thread.new { Fliewr::StatusIcon.new }
|
23
|
+
$app.main
|
data/data/fliewr.desktop
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,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/lib/fliewr/core.rb
ADDED
@@ -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,372 @@
|
|
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
|
+
|
10
|
+
DATA_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data'))
|
11
|
+
|
12
|
+
class UI < Gtk::Window
|
13
|
+
|
14
|
+
attr_accessor :logo, :statusbar, :theme_base, :theme_item, :theme_error, :theme_style
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super Gtk::Window::TOPLEVEL
|
18
|
+
|
19
|
+
filename = File.join(Fliewr::DATA_ROOT, 'pixmaps', 'fliewr.svg')
|
20
|
+
self.logo = Gdk::Pixbuf.new filename, 128, 128
|
21
|
+
|
22
|
+
self.set_title 'Fliewr'
|
23
|
+
self.set_icon self.logo
|
24
|
+
self.set_width_request 278
|
25
|
+
self.set_height_request 400
|
26
|
+
self.set_allow_shrink false
|
27
|
+
self.set_default_width $cfg.get(:window_width).to_i
|
28
|
+
self.set_default_height $cfg.get(:window_height).to_i
|
29
|
+
self.move $cfg.get(:window_x_pos).to_i, $cfg.get(:window_y_pos).to_i
|
30
|
+
|
31
|
+
theme = $cfg.get(:theme) || 'default'
|
32
|
+
theme_root = File.join(DATA_ROOT,'themes',theme)
|
33
|
+
self.theme_base = File.open(File.join(theme_root,'theme.html'), "r") { |f| f.read }
|
34
|
+
self.theme_item = File.open(File.join(theme_root,'item.html'), "r") { |f| f.read }
|
35
|
+
self.theme_error = File.open(File.join(theme_root,'error.html'), "r") { |f| f.read }
|
36
|
+
self.theme_style = File.open(File.join(theme_root,'style.css'), "r") { |f| f.read }
|
37
|
+
|
38
|
+
self.signal_connect(:destroy) { quit }
|
39
|
+
self.signal_connect(:delete_event) { minimize }
|
40
|
+
self.signal_connect(:check_resize) { remember_size_position }
|
41
|
+
self.signal_connect(:window_state_event) do |widget, event|
|
42
|
+
case event.event_type
|
43
|
+
when Gdk::Event::WINDOW_STATE
|
44
|
+
minimize if event.changed_mask.iconified? and event.new_window_state.iconified?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
self.statusbar = Gtk::Statusbar.new
|
49
|
+
self.statusbar.set_has_resize_grip false
|
50
|
+
|
51
|
+
toolbar = Gtk::Toolbar.new
|
52
|
+
toolbar.icon_size = Gtk::IconSize::MENU
|
53
|
+
|
54
|
+
icon = Gtk::Image.new Gtk::Stock::HOME, Gtk::IconSize::MENU
|
55
|
+
button = Gtk::ToolButton.new icon, 'Flickr'
|
56
|
+
button.set_important true
|
57
|
+
button.signal_connect(:clicked) do |widget|
|
58
|
+
visit_user_profile
|
59
|
+
end
|
60
|
+
toolbar.insert 0, button
|
61
|
+
|
62
|
+
icon = Gtk::Image.new Gtk::Stock::REFRESH, Gtk::IconSize::MENU
|
63
|
+
button = Gtk::ToolButton.new icon, 'Refresh'
|
64
|
+
button.set_important true
|
65
|
+
button.set_can_default true
|
66
|
+
button.set_can_focus true
|
67
|
+
button.signal_connect(:clicked) do |widget|
|
68
|
+
$app.ask_update
|
69
|
+
end
|
70
|
+
toolbar.insert 1, button
|
71
|
+
self.set_default button
|
72
|
+
self.set_focus button
|
73
|
+
|
74
|
+
icon = Gtk::Image.new Gtk::Stock::PREFERENCES, Gtk::IconSize::MENU
|
75
|
+
button = Gtk::ToolButton.new icon, 'Settings'
|
76
|
+
button.signal_connect(:clicked) do |widget|
|
77
|
+
Fliewr::SettingsDialog.new
|
78
|
+
end
|
79
|
+
toolbar.insert 2, button
|
80
|
+
|
81
|
+
separator = Gtk::SeparatorToolItem.new
|
82
|
+
separator.set_draw false
|
83
|
+
separator.set_expand true
|
84
|
+
toolbar.insert 3, separator
|
85
|
+
|
86
|
+
icon = Gtk::Image.new Gtk::Stock::QUIT, Gtk::IconSize::MENU
|
87
|
+
button = Gtk::ToolButton.new icon, 'Quit'
|
88
|
+
button.signal_connect(:clicked) do |widget|
|
89
|
+
$app.quit
|
90
|
+
end
|
91
|
+
toolbar.insert 4, button
|
92
|
+
|
93
|
+
@browser = Gtk::MozEmbed.new
|
94
|
+
@browser.signal_connect(:open_uri) do |widget, uri|
|
95
|
+
open_in_external_browser(uri)
|
96
|
+
end
|
97
|
+
|
98
|
+
vbox = Gtk::VBox.new false, 4
|
99
|
+
vbox.pack_start toolbar, false
|
100
|
+
vbox.pack_start @browser
|
101
|
+
vbox.pack_start self.statusbar, false
|
102
|
+
self.add vbox
|
103
|
+
end
|
104
|
+
|
105
|
+
def remember_size_position
|
106
|
+
x, y = self.position
|
107
|
+
w, h = self.size
|
108
|
+
$cfg.set :window_x_pos, x
|
109
|
+
$cfg.set :window_y_pos, y
|
110
|
+
$cfg.set :window_width, w
|
111
|
+
$cfg.set :window_height, h
|
112
|
+
end
|
113
|
+
|
114
|
+
def minimize
|
115
|
+
remember_size_position
|
116
|
+
hide
|
117
|
+
end
|
118
|
+
|
119
|
+
def maximize
|
120
|
+
self.show
|
121
|
+
self.present
|
122
|
+
end
|
123
|
+
|
124
|
+
def open_in_gecko(html)
|
125
|
+
@browser.open_stream "file:///", "text/html"
|
126
|
+
@browser.append_data self.theme_base % [ self.theme_style, html ]
|
127
|
+
@browser.close_stream
|
128
|
+
end
|
129
|
+
|
130
|
+
def refresh_with(data)
|
131
|
+
html = data.map { |d| templatize(d) }.join
|
132
|
+
open_in_gecko html
|
133
|
+
end
|
134
|
+
|
135
|
+
def templatize(data)
|
136
|
+
self.theme_item % [
|
137
|
+
photolink(data.owner, data.id),
|
138
|
+
photopreview(data.farm, data.server, data.id, data.secret),
|
139
|
+
user_profile_link(data.owner),
|
140
|
+
data.username,
|
141
|
+
userpic(data.iconfarm, data.iconserver, data.owner),
|
142
|
+
data.title,
|
143
|
+
dateupload(data.dateupload)
|
144
|
+
]
|
145
|
+
end
|
146
|
+
|
147
|
+
def photopreview(*args)
|
148
|
+
'http://farm%s.static.flickr.com/%s/%s_%s_m.jpg' % args
|
149
|
+
end
|
150
|
+
|
151
|
+
def photolink(*args)
|
152
|
+
'http://www.flickr.com/photos/%s/%s' % args
|
153
|
+
end
|
154
|
+
|
155
|
+
def user_profile_link(id = @nsid)
|
156
|
+
'http://www.flickr.com/people/%s' % id
|
157
|
+
end
|
158
|
+
|
159
|
+
def userpic(farm, server, owner)
|
160
|
+
return 'http://www.flickr.com/images/buddyicon.jpg' if farm.to_i == 0
|
161
|
+
'http://farm%s.static.flickr.com/%s/buddyicons/%s.jpg' % [ farm, server, owner ]
|
162
|
+
end
|
163
|
+
|
164
|
+
def dateupload(date_and_time)
|
165
|
+
Time.at(date_and_time.to_i)
|
166
|
+
end
|
167
|
+
|
168
|
+
def visit_user_profile
|
169
|
+
open_in_external_browser user_profile_link
|
170
|
+
end
|
171
|
+
|
172
|
+
def open_in_external_browser(uri)
|
173
|
+
Thread.new { system('xdg-open "%s"' % uri) }
|
174
|
+
end
|
175
|
+
|
176
|
+
def quit
|
177
|
+
$app.quit
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
class StatusIcon < Gtk::StatusIcon
|
183
|
+
def initialize
|
184
|
+
super
|
185
|
+
self.file = File.join(Fliewr::DATA_ROOT, 'pixmaps', 'fliewr.svg')
|
186
|
+
self.set_tooltip 'Flickr Viewr'
|
187
|
+
self.signal_connect(:activate) do
|
188
|
+
if $gui.visible?
|
189
|
+
$gui.minimize
|
190
|
+
else
|
191
|
+
$gui.move $cfg.get(:window_x_pos), $cfg.get(:window_y_pos)
|
192
|
+
$gui.show.present
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
menu = Gtk::Menu.new
|
197
|
+
|
198
|
+
self.signal_connect(:popup_menu) do |icon, button, time|
|
199
|
+
menu.popup nil, nil, button, time
|
200
|
+
end
|
201
|
+
|
202
|
+
separator = Gtk::SeparatorMenuItem.new
|
203
|
+
|
204
|
+
item = Gtk::ImageMenuItem.new Gtk::Stock::HOME
|
205
|
+
item.signal_connect(:activate) do
|
206
|
+
$app.visit_user_profile
|
207
|
+
end
|
208
|
+
menu.append item
|
209
|
+
|
210
|
+
item = Gtk::ImageMenuItem.new Gtk::Stock::REFRESH
|
211
|
+
item.signal_connect(:activate) do
|
212
|
+
$app.update
|
213
|
+
end
|
214
|
+
menu.append item
|
215
|
+
|
216
|
+
item = Gtk::CheckMenuItem.new 'Always on top'
|
217
|
+
item.signal_connect(:toggled) do |widget|
|
218
|
+
$gui.keep_above = widget.active?
|
219
|
+
end
|
220
|
+
menu.append item
|
221
|
+
|
222
|
+
item = Gtk::ImageMenuItem.new Gtk::Stock::PREFERENCES
|
223
|
+
item.signal_connect(:activate) do
|
224
|
+
Fliewr::SettingsDialog.new
|
225
|
+
end
|
226
|
+
menu.append item
|
227
|
+
|
228
|
+
item = Gtk::ImageMenuItem.new Gtk::Stock::ABOUT
|
229
|
+
item.signal_connect(:activate) do
|
230
|
+
AboutDialog.new
|
231
|
+
end
|
232
|
+
menu.append item
|
233
|
+
menu.append separator
|
234
|
+
|
235
|
+
item = Gtk::ImageMenuItem.new Gtk::Stock::QUIT
|
236
|
+
item.signal_connect(:activate) do
|
237
|
+
$app.quit
|
238
|
+
end
|
239
|
+
menu.append item
|
240
|
+
menu.show_all
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class AboutDialog < Gtk::AboutDialog
|
245
|
+
def initialize
|
246
|
+
Gtk::AboutDialog.set_email_hook do |widget, email|
|
247
|
+
system("xdg-email #{email}")
|
248
|
+
end
|
249
|
+
Gtk::AboutDialog.set_url_hook do |widget, link|
|
250
|
+
system("xdg-open #{link}")
|
251
|
+
end
|
252
|
+
super
|
253
|
+
self.name = 'Flickr Viewr'
|
254
|
+
self.program_name = 'Flickr Viewr'
|
255
|
+
self.comments = "Flickr photostream viewer"
|
256
|
+
self.version = '2.0'
|
257
|
+
self.copyright = "Copyright (c)2008 Paul Philippov"
|
258
|
+
self.license = "This software is released under the BSD License.\nhttp://creativecommons.org/licenses/BSD/"
|
259
|
+
self.authors = ['Paul Philippov <paul@ppds.ws>']
|
260
|
+
self.documenters = ['Paul Philippov <paul@ppds.ws>']
|
261
|
+
self.website = "http://fliewr.googlecode.com/"
|
262
|
+
self.logo = $gui.logo
|
263
|
+
self.run
|
264
|
+
self.destroy
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
class SettingsDialog < Gtk::Dialog
|
269
|
+
def initialize
|
270
|
+
super "Settings", nil, Gtk::Dialog::MODAL,
|
271
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT],
|
272
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
|
273
|
+
|
274
|
+
self.set_default_response Gtk::Dialog::RESPONSE_ACCEPT
|
275
|
+
self.signal_connect :response do |dialog, response|
|
276
|
+
case response
|
277
|
+
when Gtk::Dialog::RESPONSE_ACCEPT
|
278
|
+
if /\d\d\d\d\d\d\d\d@N\d\d/ =~ @nsid_entry.text
|
279
|
+
$cfg.set :nsid, @nsid_entry.text
|
280
|
+
$cfg.set :update_interval, @update_interval_spin.value
|
281
|
+
$cfg.set :max_photos, @max_photos_spin.value
|
282
|
+
$cfg.set :one_per_contact, @one_per_contact_toggle.active?
|
283
|
+
$cfg.set :only_from_friends, @only_from_friends_toggle.active?
|
284
|
+
$cfg.set :include_self, @include_self_toggle.active?
|
285
|
+
$app.update
|
286
|
+
else
|
287
|
+
Alert.new "User ID has incorrect format"
|
288
|
+
end
|
289
|
+
when Gtk::Dialog::RESPONSE_CANCEL
|
290
|
+
true
|
291
|
+
end
|
292
|
+
end
|
293
|
+
hbox = Gtk::HBox.new false, 8
|
294
|
+
hbox.set_border_width 8
|
295
|
+
self.vbox.pack_start hbox, false, false, 0
|
296
|
+
|
297
|
+
stock = Gtk::Image.new Gtk::Stock::PREFERENCES, Gtk::IconSize::DIALOG
|
298
|
+
hbox.pack_start stock, false, false, 0
|
299
|
+
|
300
|
+
table = Gtk::Table.new 3, 6
|
301
|
+
table.set_row_spacings 4
|
302
|
+
table.set_column_spacings 8
|
303
|
+
hbox.pack_start table, true, true, 0
|
304
|
+
|
305
|
+
@nsid_entry = Gtk::Entry.new
|
306
|
+
@nsid_entry.width_chars = 13
|
307
|
+
@nsid_entry.max_length = 12
|
308
|
+
@nsid_entry.text = $cfg.get(:nsid)
|
309
|
+
table.attach_defaults label('Your Flickr user ID'), 0, 1, 0, 1
|
310
|
+
table.attach_defaults @nsid_entry, 1, 2, 0, 1
|
311
|
+
table.attach_defaults button_with_click(:find, :find_nsid), 2, 3, 0, 1
|
312
|
+
|
313
|
+
@update_interval_spin = Gtk::SpinButton.new(1, 100, 1)
|
314
|
+
@update_interval_spin.value = $cfg.get(:update_interval).to_i
|
315
|
+
table.attach_defaults label('Check new photos every'), 0, 1, 1, 2
|
316
|
+
table.attach_defaults @update_interval_spin, 1, 2, 1, 2
|
317
|
+
table.attach_defaults label('minutes'), 2, 3, 1, 2
|
318
|
+
|
319
|
+
@max_photos_spin = Gtk::SpinButton.new(1, 50, 1)
|
320
|
+
@max_photos_spin.value = $cfg.get(:max_photos).to_i
|
321
|
+
table.attach_defaults label('Maximum photos to display'), 0, 1, 2, 3
|
322
|
+
table.attach_defaults @max_photos_spin, 1, 2, 2, 3
|
323
|
+
|
324
|
+
@one_per_contact_toggle = Gtk::CheckButton.new
|
325
|
+
@one_per_contact_toggle.active = $cfg.get(:one_per_contact)
|
326
|
+
table.attach_defaults label('Only one photo per contact'), 0, 1, 3, 4
|
327
|
+
table.attach_defaults @one_per_contact_toggle, 1, 2, 3, 4
|
328
|
+
|
329
|
+
@only_from_friends_toggle = Gtk::CheckButton.new
|
330
|
+
@only_from_friends_toggle.active = $cfg.get(:only_from_friend)
|
331
|
+
table.attach_defaults label('Only from friends and family'), 0, 1, 4, 5
|
332
|
+
table.attach_defaults @only_from_friends_toggle, 1, 2, 4, 5
|
333
|
+
|
334
|
+
@include_self_toggle = Gtk::CheckButton.new
|
335
|
+
@include_self_toggle.active = $cfg.get(:include_self)
|
336
|
+
table.attach_defaults label('Include your own photos'), 0, 1, 5, 6
|
337
|
+
table.attach_defaults @include_self_toggle, 1, 2, 5, 6
|
338
|
+
|
339
|
+
self.show_all
|
340
|
+
self.run
|
341
|
+
self.destroy
|
342
|
+
end
|
343
|
+
|
344
|
+
def button_with_click(stock_id, method_name)
|
345
|
+
button = Gtk::Button.new icon(stock_id)
|
346
|
+
button.signal_connect(:clicked) do |widget|
|
347
|
+
self.method(method_name).call
|
348
|
+
end
|
349
|
+
button.show_all
|
350
|
+
end
|
351
|
+
|
352
|
+
def find_nsid
|
353
|
+
$gui.open_in_external_browser 'http://www.flickr.com/services/api/explore/?method=flickr.people.getInfo'
|
354
|
+
end
|
355
|
+
|
356
|
+
def icon(stock_id)
|
357
|
+
Gtk::Stock.const_get stock_id.to_s.upcase
|
358
|
+
end
|
359
|
+
|
360
|
+
def label(text)
|
361
|
+
Gtk::Label.new(text).set_alignment(0, 0.5)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
class Alert
|
366
|
+
def initialize(*args)
|
367
|
+
html = $gui.theme_error % [args].flatten.map { |e| "<li>#{e}</li>" }.join
|
368
|
+
$gui.open_in_gecko(html)
|
369
|
+
false
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
data/lib/ppds/flickr.rb
ADDED
@@ -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,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 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-24 00:00:00 +07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ppds-libs
|
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
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: libxml-ruby
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rest-client
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: fliewr a GNOME application to monitor updates from Flickr contacts
|
46
|
+
email: themactep@gmail.com
|
47
|
+
executables:
|
48
|
+
- fliewr
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README
|
53
|
+
- LICENSE
|
54
|
+
files:
|
55
|
+
- LICENSE
|
56
|
+
- README
|
57
|
+
- Rakefile
|
58
|
+
- bin/fliewr
|
59
|
+
- data/themes/default/item.html
|
60
|
+
- data/themes/default/error.html
|
61
|
+
- data/themes/default/style.css
|
62
|
+
- data/themes/default/theme.html
|
63
|
+
- data/fliewr.desktop
|
64
|
+
- data/pixmaps/fliewr.svg
|
65
|
+
- lib/ppds/flickr.rb
|
66
|
+
- lib/fliewr/core.rb
|
67
|
+
- lib/fliewr/ui.rb
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://themactep.com/fliewr
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
version:
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project: fliewr
|
92
|
+
rubygems_version: 1.3.5
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: Flickr Viewr for GNOME
|
96
|
+
test_files: []
|
97
|
+
|