themactep-fliewr 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/LICENSE +27 -0
- data/README +52 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/bin/fliewr +27 -0
- data/data/api.url +1 -0
- data/data/fliewr.desktop +9 -0
- data/data/fliewr.svg +4 -0
- data/data/themes/default/error.html +1 -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/fliewr.gemspec +60 -0
- data/lib/fliewr/core.rb +71 -0
- data/lib/fliewr/ui.rb +370 -0
- data/lib/ppds/class_factory.rb +17 -0
- data/lib/ppds/config.rb +47 -0
- data/lib/ppds/flickr.rb +51 -0
- metadata +82 -0
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
|
data/data/fliewr.desktop
ADDED
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,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
|
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,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
|
data/lib/ppds/config.rb
ADDED
@@ -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
|
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,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
|
+
|