openall_time_applet 0.0.1

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.
@@ -0,0 +1,185 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <interface>
3
+ <requires lib="gtk+" version="2.24"/>
4
+ <!-- interface-naming-policy project-wide -->
5
+ <object class="GtkWindow" id="window">
6
+ <property name="can_focus">False</property>
7
+ <property name="title" translatable="yes">Timelog</property>
8
+ <property name="window_position">center</property>
9
+ <property name="default_width">640</property>
10
+ <property name="default_height">480</property>
11
+ <child>
12
+ <object class="GtkVBox" id="vbox1">
13
+ <property name="visible">True</property>
14
+ <property name="can_focus">False</property>
15
+ <child>
16
+ <object class="GtkFrame" id="frame1">
17
+ <property name="visible">True</property>
18
+ <property name="can_focus">False</property>
19
+ <property name="label_xalign">0</property>
20
+ <property name="shadow_type">none</property>
21
+ <child>
22
+ <object class="GtkAlignment" id="alignment1">
23
+ <property name="visible">True</property>
24
+ <property name="can_focus">False</property>
25
+ <property name="left_padding">12</property>
26
+ <child>
27
+ <object class="GtkTable" id="table1">
28
+ <property name="visible">True</property>
29
+ <property name="can_focus">False</property>
30
+ <property name="n_rows">3</property>
31
+ <property name="n_columns">2</property>
32
+ <property name="column_spacing">3</property>
33
+ <property name="row_spacing">3</property>
34
+ <child>
35
+ <object class="GtkLabel" id="label3">
36
+ <property name="visible">True</property>
37
+ <property name="can_focus">False</property>
38
+ <property name="xalign">0</property>
39
+ <property name="label" translatable="yes">Description</property>
40
+ </object>
41
+ <packing>
42
+ <property name="x_options">GTK_FILL</property>
43
+ <property name="y_options">GTK_FILL</property>
44
+ </packing>
45
+ </child>
46
+ <child>
47
+ <object class="GtkLabel" id="label4">
48
+ <property name="visible">True</property>
49
+ <property name="can_focus">False</property>
50
+ <property name="xalign">0</property>
51
+ <property name="label" translatable="yes">Time</property>
52
+ </object>
53
+ <packing>
54
+ <property name="top_attach">1</property>
55
+ <property name="bottom_attach">2</property>
56
+ <property name="x_options">GTK_FILL</property>
57
+ <property name="y_options">GTK_FILL</property>
58
+ </packing>
59
+ </child>
60
+ <child>
61
+ <object class="GtkEntry" id="txtDescr">
62
+ <property name="visible">True</property>
63
+ <property name="can_focus">True</property>
64
+ <property name="invisible_char">•</property>
65
+ <property name="primary_icon_activatable">False</property>
66
+ <property name="secondary_icon_activatable">False</property>
67
+ <property name="primary_icon_sensitive">True</property>
68
+ <property name="secondary_icon_sensitive">True</property>
69
+ </object>
70
+ <packing>
71
+ <property name="left_attach">1</property>
72
+ <property name="right_attach">2</property>
73
+ </packing>
74
+ </child>
75
+ <child>
76
+ <object class="GtkEntry" id="txtTime">
77
+ <property name="visible">True</property>
78
+ <property name="can_focus">True</property>
79
+ <property name="invisible_char">•</property>
80
+ <property name="primary_icon_activatable">False</property>
81
+ <property name="secondary_icon_activatable">False</property>
82
+ <property name="primary_icon_sensitive">True</property>
83
+ <property name="secondary_icon_sensitive">True</property>
84
+ </object>
85
+ <packing>
86
+ <property name="left_attach">1</property>
87
+ <property name="right_attach">2</property>
88
+ <property name="top_attach">1</property>
89
+ <property name="bottom_attach">2</property>
90
+ </packing>
91
+ </child>
92
+ <child>
93
+ <object class="GtkLabel" id="label5">
94
+ <property name="visible">True</property>
95
+ <property name="can_focus">False</property>
96
+ <property name="xalign">0</property>
97
+ <property name="label" translatable="yes">Transport</property>
98
+ </object>
99
+ <packing>
100
+ <property name="top_attach">2</property>
101
+ <property name="bottom_attach">3</property>
102
+ <property name="x_options">GTK_FILL</property>
103
+ <property name="y_options">GTK_FILL</property>
104
+ </packing>
105
+ </child>
106
+ <child>
107
+ <object class="GtkEntry" id="txtTimeTransport">
108
+ <property name="visible">True</property>
109
+ <property name="can_focus">True</property>
110
+ <property name="invisible_char">•</property>
111
+ <property name="primary_icon_activatable">False</property>
112
+ <property name="secondary_icon_activatable">False</property>
113
+ <property name="primary_icon_sensitive">True</property>
114
+ <property name="secondary_icon_sensitive">True</property>
115
+ </object>
116
+ <packing>
117
+ <property name="left_attach">1</property>
118
+ <property name="right_attach">2</property>
119
+ <property name="top_attach">2</property>
120
+ <property name="bottom_attach">3</property>
121
+ </packing>
122
+ </child>
123
+ </object>
124
+ </child>
125
+ </object>
126
+ </child>
127
+ <child type="label">
128
+ <object class="GtkLabel" id="label1">
129
+ <property name="visible">True</property>
130
+ <property name="can_focus">False</property>
131
+ <property name="label" translatable="yes">&lt;b&gt;Timelog&lt;/b&gt;</property>
132
+ <property name="use_markup">True</property>
133
+ </object>
134
+ </child>
135
+ </object>
136
+ <packing>
137
+ <property name="expand">False</property>
138
+ <property name="fill">True</property>
139
+ <property name="position">0</property>
140
+ </packing>
141
+ </child>
142
+ <child>
143
+ <object class="GtkHButtonBox" id="hbuttonbox1">
144
+ <property name="visible">True</property>
145
+ <property name="can_focus">False</property>
146
+ <property name="spacing">3</property>
147
+ <property name="layout_style">end</property>
148
+ <child>
149
+ <object class="GtkButton" id="btnSave">
150
+ <property name="label">gtk-save</property>
151
+ <property name="visible">True</property>
152
+ <property name="can_focus">True</property>
153
+ <property name="receives_default">True</property>
154
+ <property name="use_action_appearance">False</property>
155
+ <property name="use_stock">True</property>
156
+ <signal name="clicked" handler="on_btnSave_clicked" swapped="no"/>
157
+ </object>
158
+ <packing>
159
+ <property name="expand">False</property>
160
+ <property name="fill">False</property>
161
+ <property name="position">0</property>
162
+ </packing>
163
+ </child>
164
+ </object>
165
+ <packing>
166
+ <property name="expand">False</property>
167
+ <property name="fill">True</property>
168
+ <property name="position">1</property>
169
+ </packing>
170
+ </child>
171
+ <child>
172
+ <object class="GtkLabel" id="label2">
173
+ <property name="visible">True</property>
174
+ <property name="can_focus">False</property>
175
+ </object>
176
+ <packing>
177
+ <property name="expand">True</property>
178
+ <property name="fill">True</property>
179
+ <property name="position">2</property>
180
+ </packing>
181
+ </child>
182
+ </object>
183
+ </child>
184
+ </object>
185
+ </interface>
data/gui/trayicon.rb ADDED
@@ -0,0 +1,55 @@
1
+ class Openall_time_applet::Gui::Trayicon
2
+ attr_reader :args
3
+
4
+ def initialize(args)
5
+ @args = args
6
+
7
+ @ti = Gtk::StatusIcon.new
8
+ @ti.file = "../gfx/icon_time.png"
9
+ @ti.signal_connect("popup-menu", &self.method(:on_statusicon_rightclick))
10
+
11
+ #Build rightclick-menu for tray-icon.
12
+ timelog_new = Gtk::ImageMenuItem.new(Gtk::Stock::NEW)
13
+ timelog_new.label = _("New timelog")
14
+ timelog_new.signal_connect("activate", &self.method(:on_timelogNew_activate))
15
+
16
+ overview = Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
17
+ overview.label = _("Overview")
18
+ overview.signal_connect("activate", &self.method(:on_overview_activate))
19
+
20
+ pref = Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
21
+ pref.signal_connect("activate", &self.method(:on_preferences_activate))
22
+
23
+ quit = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
24
+ quit.signal_connect("activate", &self.method(:on_quit_activate))
25
+
26
+ @menu = Gtk::Menu.new
27
+ @menu.append(timelog_new)
28
+ @menu.append(overview)
29
+ @menu.append(Gtk::SeparatorMenuItem.new)
30
+ @menu.append(pref)
31
+ @menu.append(Gtk::SeparatorMenuItem.new)
32
+ @menu.append(quit)
33
+ @menu.show_all
34
+ end
35
+
36
+ def on_statusicon_rightclick(tray, button, time)
37
+ @menu.popup(nil, nil, button, time)
38
+ end
39
+
40
+ def on_preferences_activate(*args)
41
+ @args[:oata].show_preferences
42
+ end
43
+
44
+ def on_timelogNew_activate(*args)
45
+ @args[:oata].show_timelog_new
46
+ end
47
+
48
+ def on_overview_activate(*args)
49
+ @args[:oata].show_overview
50
+ end
51
+
52
+ def on_quit_activate(*args)
53
+ Gtk.main_quit
54
+ end
55
+ end
@@ -0,0 +1,38 @@
1
+ class Openall_time_applet::Gui::Win_overview
2
+ attr_reader :args, :gui
3
+
4
+ def initialize(args)
5
+ @args = args
6
+
7
+ @gui = Gtk::Builder.new.add("../glade/win_overview.glade")
8
+ @gui.translate
9
+ @gui.connect_signals{|h| method(h)}
10
+
11
+ @gui["tvTimelogs"].init([_("ID"), _("Description"), _("Time"), _("Transport"), _("Needs sync")])
12
+ @gui["tvTimelogs"].columns[0].visible = false
13
+ self.reload_timelogs
14
+
15
+ @gui["window"].show_all
16
+ end
17
+
18
+ def reload_timelogs
19
+ @args[:oata].ob.list(:Timelog, {"orderby" => "id"}) do |timelog|
20
+ descr = timelog[:descr].to_s.gsub("\n", " ").gsub(/\s{2,}/, " ")
21
+ descr = Knj::Strings.shorten(descr, 20)
22
+
23
+ sync_need = Knj::Strings.yn_str(timelog[:sync_need], _("Yes"), _("No"))
24
+
25
+ @gui["tvTimelogs"].append([timelog.id, descr, timelog[:time], timelog[:time_transport], sync_need])
26
+ end
27
+ end
28
+
29
+ def on_tvTimelogs_row_activated(*args)
30
+ row = @gui["tvTimelogs"].sel
31
+ return nil if !row
32
+
33
+ timelog = @args[:oata].ob.get(:Timelog, row[0])
34
+ win_timelog_edit = @args[:oata].show_timelog_edit(timelog)
35
+ win_timelog_edit.gui["window"].modal = @gui["window"]
36
+ win_timelog_edit.gui["window"].transient_for = @gui["window"]
37
+ end
38
+ end
@@ -0,0 +1,63 @@
1
+ class Openall_time_applet::Gui::Win_preferences
2
+ attr_reader :args, :gui
3
+
4
+ def initialize(args)
5
+ @args = args
6
+
7
+ @gui = Gtk::Builder.new.add("../glade/win_preferences.glade")
8
+ @gui.translate
9
+ @gui.connect_signals{|h| method(h)}
10
+
11
+ self.load_values
12
+
13
+ @gui["window"].show_all
14
+ end
15
+
16
+ def load_values
17
+ @gui["txtHost"].text = Knj::Opts.get("openall_host")
18
+ @gui["txtPort"].text = Knj::Opts.get("openall_port")
19
+ @gui["txtUsername"].text = Knj::Opts.get("openall_username")
20
+ @gui["txtPassword"].text = Base64.strict_decode64(Knj::Opts.get("openall_password"))
21
+
22
+ if Knj::Opts.get("openall_ssl") == "1"
23
+ @gui["cbSSL"].active = true
24
+ else
25
+ @gui["cbSSL"].active = false
26
+ end
27
+ end
28
+
29
+ def on_btnSave_clicked
30
+ Knj::Opts.set("openall_host", @gui["txtHost"].text)
31
+ Knj::Opts.set("openall_port", @gui["txtPort"].text)
32
+ Knj::Opts.set("openall_ssl", Knj::Strings.yn_str(@gui["cbSSL"].active?, 1, 0))
33
+ Knj::Opts.set("openall_username", @gui["txtUsername"].text)
34
+ Knj::Opts.set("openall_password", Base64.strict_encode64(@gui["txtPassword"].text))
35
+ @gui["window"].destroy
36
+ end
37
+
38
+ def on_btnTest_clicked
39
+ ws = Knj::Gtk2::StatusWindow.new("transient_for" => @gui["window"])
40
+ ws.label = _("Connecting and logging in...")
41
+
42
+ Knj::Thread.new do
43
+ begin
44
+ @args[:oata].oa_conn do |conn|
45
+ ws.percent = 0.3
46
+ ws.label = _("Getting task-list.")
47
+ task_list = conn.task_list
48
+
49
+ ws.label = sprintf(_("Got %s tasks."), task_list.length)
50
+ ws.percent = 1
51
+ end
52
+ rescue => e
53
+ raise e
54
+ Knj::Gtk2.msgbox(e.message, "warning", _("Error"))
55
+ ensure
56
+ Knj::Thread.new do
57
+ sleep 1.5
58
+ ws.destroy
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ class Openall_time_applet::Gui::Win_timelog_edit
2
+ attr_reader :args, :gui
3
+
4
+ def initialize(args)
5
+ @args = args
6
+
7
+ @gui = Gtk::Builder.new.add("../glade/win_timelog_edit.glade")
8
+ @gui.translate
9
+ @gui.connect_signals{|h| method(h)}
10
+
11
+ @gui["window"].show_all
12
+ end
13
+
14
+ def on_btnSave_clicked(*args)
15
+ save_hash = {
16
+ :descr => @gui["txtDescr"].text,
17
+ :time => @gui["txtTime"].text,
18
+ :time_transport => @gui["txtTimeTransport"].text
19
+ }
20
+
21
+ if @timelog
22
+ @timelog.update(save_hash)
23
+ else
24
+ @timelog = @args[:oata].ob.add(:Timelog, save_hash)
25
+ end
26
+
27
+ @gui["window"].destroy
28
+ end
29
+ end
@@ -0,0 +1,130 @@
1
+ require "rubygems"
2
+ require "knjrbfw"
3
+ require "gtk2"
4
+ require "sqlite3"
5
+ require "gettext"
6
+ require "base64"
7
+
8
+ require "knj/gtk2"
9
+ require "knj/gtk2_tv"
10
+ require "knj/gtk2_statuswindow"
11
+
12
+ class Openall_time_applet
13
+ def self.exec
14
+ require "#{File.dirname(__FILE__)}/../bin/openall_time_applet"
15
+ end
16
+
17
+ #Subclass controlling autoloading of models.
18
+ class Models
19
+ def self.const_missing(name)
20
+ require "../models/#{name.to_s.downcase}.rb"
21
+ return Openall_time_applet::Models.const_get(name)
22
+ end
23
+ end
24
+
25
+ class Gui
26
+ #Autoloader for subclasses.
27
+ def self.const_missing(name)
28
+ require "../gui/#{name.to_s.downcase}.rb"
29
+ return Openall_time_applet::Gui.const_get(name)
30
+ end
31
+ end
32
+
33
+ #Autoloader for subclasses.
34
+ def self.const_missing(name)
35
+ namel = name.to_s.downcase
36
+ tries = [
37
+ "../classes/#{namel}.rb"
38
+ ]
39
+ tries.each do |try|
40
+ if File.exists?(try)
41
+ require try
42
+ return Openall_time_applet.const_get(name)
43
+ end
44
+ end
45
+
46
+ raise "Could not load constant: '#{name}'."
47
+ end
48
+
49
+ #Various readable variables.
50
+ attr_reader :db, :ob
51
+
52
+ #Config controlling paths and more.
53
+ CONFIG = {
54
+ :settings_path => "#{Knj::Os.homedir}/.openall_time_applet",
55
+ :db_path => "#{Knj::Os.homedir}/.openall_time_applet/openall_time_applet.sqlite3"
56
+ }
57
+
58
+ #Initializes config-dir and database.
59
+ def initialize(args = {})
60
+ Dir.mkdir(CONFIG[:settings_path]) if !File.exists?(CONFIG[:settings_path])
61
+
62
+ #Database-connection.
63
+ @db = Knj::Db.new(
64
+ :type => "sqlite3",
65
+ :path => CONFIG[:db_path],
66
+ :return_keys => "symbols"
67
+ )
68
+
69
+ #Models-handeler.
70
+ @ob = Knj::Objects.new(
71
+ :datarow => true,
72
+ :db => @db,
73
+ :class_path => "../models",
74
+ :class_pre => "",
75
+ :module => Openall_time_applet::Models
76
+ )
77
+
78
+ #Options used to save various information (Openall-username and such).
79
+ Knj::Opts.init("knjdb" => @db, "table" => "Option")
80
+ end
81
+
82
+ #Updates the database according to the db-schema.
83
+ def update_db
84
+ require "../conf/db_schema.rb"
85
+ rev = Knj::Db::Revision.new.init_db("db" => @db, "schema" => Openall_time_applet::DB_SCHEMA)
86
+ end
87
+
88
+ def oa_conn
89
+ begin
90
+ conn = Openall_time_applet::Connection.new(
91
+ :oata => self,
92
+ :host => Knj::Opts.get("openall_host"),
93
+ :port => Knj::Opts.get("openall_port"),
94
+ :username => Knj::Opts.get("openall_username"),
95
+ :password => Base64.strict_decode64(Knj::Opts.get("openall_password"))
96
+ )
97
+ yield(conn)
98
+ ensure
99
+ conn.destroy if conn
100
+ end
101
+ end
102
+
103
+ #Spawns the trayicon in systray.
104
+ def spawn_trayicon
105
+ return nil if @ti
106
+ @ti = Openall_time_applet::Gui::Trayicon.new(:oata => self)
107
+ end
108
+
109
+ #Spawns the preference-window.
110
+ def show_preferences
111
+ Openall_time_applet::Gui::Win_preferences.new(:oata => self)
112
+ end
113
+
114
+ def show_timelog_new
115
+ Openall_time_applet::Gui::Win_timelog_edit.new(:oata => self)
116
+ end
117
+
118
+ def show_timelog_edit(timelog)
119
+ Openall_time_applet::Gui::Win_timelog_edit.new(:oata => self, :timelog => timelog)
120
+ end
121
+
122
+ def show_overview
123
+ Openall_time_applet::Gui::Win_overview.new(:oata => self)
124
+ end
125
+ end
126
+
127
+ #Gettext support.
128
+ def _(*args, &block)
129
+ return GetText._(*args, &block)
130
+ end