4 public class MultipleItemTag
: Gtk
.CheckButton
6 private weak Stuffkeeper
.DataBackend backend
= null;
7 private weak List
<weak Stuffkeeper
.DataItem
> items
= null;
8 private DataTag tag
= null;
9 private bool updating
= false;
10 private void update_check_state()
13 foreach (DataItem item
in this
.items
) {
14 if(item
.has_tag(tag
)) check
++;
16 this
.set_active(false);
17 this
.set_inconsistent(false);
18 if(check
== this
.items
.length()) this
.set_active(true);
19 else if (check
> 0) this
.set_inconsistent(true);
21 /* The following callbacks where lambda's but because of vala bug, it are actual callbacks now */
22 private void toggled_callback()
24 if(this
.updating
) return;
26 foreach(DataItem item
in this
.items
) {
27 if(item
.has_tag(this
.tag
) == false)
28 item
.add_tag(this
.tag
);
31 foreach(DataItem item
in this
.items
) {
32 if(item
.has_tag(this
.tag
) == true)
33 item
.remove_tag(this
.tag
);
37 private void item_tags_changed_callback(DataItem item
)
39 if(this
.updating
) return;
42 this
.updating
= false;
44 private void database_locked(ParamSpec arg1
)
46 this
.set_sensitive(!this
.backend
.get_locked());
48 public MultipleItemTag (Stuffkeeper
.DataBackend backend
, DataTag tag
, List
<weak Stuffkeeper
.DataItem
> items
)
51 this
.backend
=backend
;
53 this
.update_check_state();
54 foreach (DataItem item
in this
.items
) {
55 item
.item_tags_changed
.connect(item_tags_changed_callback
);
57 this
.backend
.notify
["locked"].connect(database_locked
);
58 this
.set_sensitive(!this
.backend
.get_locked());
59 this
.toggled
.connect(toggled_callback
);
62 public class Stuffkeeper
.MultipleItemView
: Gtk
.VBox
64 private List
<weak Stuffkeeper
.DataItem
> items
= null;
65 private Gtk
.EventBox sw_event
= null;
66 private Gtk
.EventBox header
=null;
67 private weak Stuffkeeper
.DataBackend backend
= null;
68 private Gtk
.VBox sw_vbox
= null;
69 private Gtk
.Table tag_vbox
= null;
70 private Gtk
.VBox items_vbox
= null;
71 public MultipleItemView (Stuffkeeper
.DataBackend skdb
, List
<weak Stuffkeeper
.DataItem
> items
, string? custom_title
)
75 header
= new Gtk
.EventBox();
76 /* Color the header */
77 this
.style_set
.connect((source
, style
) => {
78 var color
= source
.style
.bg
[Gtk
.StateType
.SELECTED
];
79 this
.header
.modify_bg(Gtk
.StateType
.NORMAL
, color
);
80 color
= source
.style
.fg
[Gtk
.StateType
.SELECTED
];
81 this
.header
.get_child().modify_fg(Gtk
.StateType
.NORMAL
, color
);
82 color
= source
.style
.text
[Gtk
.StateType
.SELECTED
];
83 this
.header
.get_child().modify_text(Gtk
.StateType
.NORMAL
, color
);
85 if(custom_title
!= null) {
86 var vbox
= new Gtk
.VBox(false, 6);
87 var header_label
= new Gtk
.Label("");
88 header_label
.set_markup(GLib
.Markup
.printf_escaped("<span size='x-large' weight='bold'>%s</span>",custom_title
));
89 header_label
.set_alignment(0.0f
, 0.5f
);
90 header_label
.set_padding(8,0);
91 vbox
.pack_start(header_label
, true, true, 0);
92 header_label
= new Gtk
.Label("");
93 header_label
.set_markup(GLib
.Markup
.printf_escaped("<span size='small'>%u %s</span>", this
.items
.length(), "Selected items"));
94 header_label
.set_alignment(0.0f
, 0.5f
);
95 header_label
.set_padding(8,0);
96 vbox
.pack_start(header_label
, false, false, 0);
99 var header_label
= new Gtk
.Label("");
100 header_label
.set_markup(GLib
.Markup
.printf_escaped("<span size='x-large' weight='bold'>%u %s</span>", this
.items
.length(), "Selected items"));
101 header_label
.set_alignment(0.0f
, 0.5f
);
102 header_label
.set_padding(8,8);
103 header
.add(header_label
);
105 this
.pack_start(header
, false, false, 0);
107 var sw
= new Gtk
.ScrolledWindow(null, null);
108 sw
.set_policy(Gtk
.PolicyType
.AUTOMATIC
, Gtk
.PolicyType
.AUTOMATIC
);
109 /* Color background */
110 sw_event
= new Gtk
.EventBox();
111 this
.style_set
.connect((source
, style
) => {
112 Gdk
.Color color
=source
.style
.white
;//light[Gtk.StateType.NORMAL];
113 this
.sw_event
.modify_bg(Gtk
.StateType
.NORMAL
, color
);
115 sw_vbox
= new Gtk
.VBox(false, 6);
116 sw_vbox
.border_width
= 8;
117 sw
.add_with_viewport(sw_event
);
118 sw_event
.add(sw_vbox
);
119 this
.pack_start(sw
, true, true, 0);
121 var title_labels
= new Gtk
.Label("");
122 title_labels
.set_markup(GLib
.Markup
.printf_escaped("<b>%s</b>", "Items:"));
123 title_labels
.set_alignment(0.0f
, 0.5f
);
124 title_labels
.modify_fg(Gtk
.StateType
.NORMAL
, this
.style
.black
);
125 sw_vbox
.pack_start(title_labels
, false, false, 0);
126 items_vbox
= new Gtk
.VBox(false, 6);
127 this
.sw_vbox
.pack_start(items_vbox
, false, false, 0);
129 var tag_label
= new Gtk
.Label("");
130 tag_label
.set_markup(GLib
.Markup
.printf_escaped("<b>%s</b>", "Tags:"));
131 tag_label
.set_alignment(0.0f
, 0.5f
);
132 tag_label
.modify_fg(Gtk
.StateType
.NORMAL
, this
.style
.black
);
133 sw_vbox
.pack_start(tag_label
, false, false, 0);
134 tag_vbox
= new Gtk
.Table(0,0,false);
135 sw_vbox
.pack_start(tag_vbox
, false, false, 0);
137 this
.backend
.tag_added
.connect(tag_added
);
138 this
.backend
.tag_removed
.connect(reload_tags
);
141 private void tag_added(DataTag tag
)
145 static int compare_func(DataTag tag1
, DataTag tag2
)
147 return tag1
.get_title().collate(tag2
.get_title());
149 private void reload_tags(uint id
)
153 var list
= tag_vbox
.get_children();
154 foreach(Gtk
.Widget child
in list
) {
157 if(this
.items
.length() == 0) return;
158 var taglist
= this
.backend
.get_tags();
159 taglist
.sort((GLib
.CompareFunc
)compare_func
);
160 foreach ( DataTag tag
in taglist
)
162 var hbox
= new Gtk
.HBox (false, 6);
163 var chk
= new
MultipleItemTag(backend
, tag
, this
.items
);
164 hbox
.pack_start(chk
, false, false, 0);
165 var tlabel
= new Stuffkeeper
.DataLabel
.tag(tag
);
166 tlabel
.modify_fg(Gtk
.StateType
.NORMAL
, this
.style
.black
);
167 tlabel
.set_alignment(0.0f
, 0.5f
);
168 hbox
.pack_start(tlabel
, true, true, 0);
169 this
.tag_vbox
.attach(hbox
, items
%column
, items
%column
+1, items
/column
, items
/column
+1,
170 Gtk
.AttachOptions
.EXPAND
|Gtk
.AttachOptions
.FILL
, Gtk
.AttachOptions
.EXPAND
|Gtk
.AttachOptions
.FILL
,0,0);
175 public void reload_items(List
<weak Stuffkeeper
.DataItem
> items
)
177 foreach(Gtk
.Widget child
in items_vbox
.get_children()) {
181 this
.items
= items
.copy();
182 foreach(DataItem item
in items
) {
183 var hbox
= new Gtk
.HBox(false, 6);
184 var button
= new Gtk
.Button();
185 var arrow
= new Gtk
.Image
.from_pixbuf(item
.get_schema().get_pixbuf());
186 button
.relief
= Gtk
.ReliefStyle
.NONE
;
187 this
.style_set
.connect((source
, style
) => {
188 Gdk
.Color color
=source
.style
.white
;//light[Gtk.StateType.NORMAL];
189 button
.modify_bg(Gtk
.StateType
.NORMAL
, color
);
191 Gdk
.Color color
=this
.style
.white
;//light[Gtk.StateType.NORMAL];
192 button
.modify_bg(Gtk
.StateType
.NORMAL
, color
);
193 /** TODO image needs updating when schema changed it icon! */
194 hbox
.pack_start(arrow
, false, false,0);
195 var title
= new Stuffkeeper
.DataEntry(item
, null);
196 hbox
.pack_start(title
, true, true, 0);
198 items_vbox
.pack_start(button
, false, false, 0);
199 button
.set_data
<weak DataItem
>("item", item
);
200 button
.clicked
.connect((source
) => {
201 DataItem fitem
= button
.get_data
<weak DataItem
>("item");
202 new Stuffkeeper
.ItemWindow(fitem
.get_backend(), fitem
, Stuffkeeper
.config_file
);
205 items_vbox
.show_all();