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 +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
|
+
|