Skip to content

Commit a56b552

Browse files
committed
Refactor
* Add Switch to HistoryWidget * Add "active" setting key * Change icon when inactive * Connect to owner-changed signal * Show different widget when Privacy is on and inactivate switch
1 parent a94dc74 commit a56b552

File tree

2 files changed

+66
-93
lines changed

2 files changed

+66
-93
lines changed

src/HistoryWidget.vala

Lines changed: 55 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,34 @@ public class Clipboard.HistoryWidget : Gtk.Box {
88
private Gtk.ListBox clipboard_item_list;
99
private string last_text = "";
1010
private uint wait_timeout = 0;
11+
private Granite.SwitchModelButton active_switch;
12+
private Gtk.Box privacy_widget;
13+
private Gtk.ScrolledWindow scroll_box;
14+
private Gtk.Stack stack;
15+
private unowned Gtk.Clipboard clipboard;
1116

1217
public signal void close_request ();
1318

1419
construct {
1520
orientation = VERTICAL;
1621
spacing = 6;
1722

18-
var active_switch = new Granite.SwitchModelButton (_("Clipboard Manager")) {
23+
active_switch = new Granite.SwitchModelButton (_("Clipboard Manager")) {
1924
description = _("Monitoring the clipboard contents")
2025
};
2126

27+
var inactive_header_label = new Granite.HeaderLabel (_("The ClipboardManager is disabled"));
28+
var inactive_subheader_label = new Gtk.Label ("") {
29+
label = Granite.TOOLTIP_SECONDARY_TEXT_MARKUP.printf (_("History is off in the Privacy and Security settings")),
30+
use_markup = true
31+
};
32+
privacy_widget = new Gtk.Box (VERTICAL, 0) {
33+
margin_start = 6,
34+
margin_end = 6
35+
};
36+
privacy_widget.add (inactive_header_label);
37+
privacy_widget.add (inactive_subheader_label);
38+
2239
Clipboard.Indicator.settings.bind ("active", active_switch, "active", DEFAULT);
2340

2441
clipboard_text_set = new Gee.HashSet<string> ();
@@ -27,14 +44,20 @@ public class Clipboard.HistoryWidget : Gtk.Box {
2744
selection_mode = SINGLE
2845
};
2946
clipboard_item_list.set_placeholder (new Gtk.Label (_("Clipboard Empty")));
30-
var scroll_box = new Gtk.ScrolledWindow (null, null);
47+
48+
scroll_box = new Gtk.ScrolledWindow (null, null);
3149
scroll_box.max_content_height = 512;
3250
scroll_box.propagate_natural_height = true;
3351
scroll_box.hscrollbar_policy = Gtk.PolicyType.NEVER;
3452
scroll_box.add (clipboard_item_list);
3553

54+
stack = new Gtk.Stack ();
55+
stack.add_named (scroll_box, "clipboard");
56+
stack.add_named (privacy_widget, "privacy");
57+
3658
add (active_switch);
37-
add (scroll_box);
59+
add (stack);
60+
3861
show_all ();
3962

4063
clipboard_item_list.row_activated.connect ((row) => {
@@ -43,6 +66,8 @@ public class Clipboard.HistoryWidget : Gtk.Box {
4366
clipboard.set_text (text, -1);
4467
close_request ();
4568
});
69+
70+
clipboard = Gtk.Clipboard.get_default (Gdk.Display.get_default ());
4671
}
4772

4873
~HistoryWidget () {
@@ -51,38 +76,45 @@ public class Clipboard.HistoryWidget : Gtk.Box {
5176

5277
// No notifications from clipboard? So poll it periodically for new text
5378
public void wait_for_text () {
54-
var clipboard = Gtk.Clipboard.get_default (Gdk.Display.get_default ());
55-
wait_timeout = Timeout.add_full (Priority.LOW, 1000, () => {
56-
if (clipboard.wait_is_text_available ()) {
57-
clipboard.request_text ((cb, text) => {
58-
if (text != last_text && !clipboard_text_set.contains (text)) {
59-
last_text = text;
60-
clipboard_text_set.add (text);
61-
var new_item = new ItemRow (text);
62-
clipboard_item_list.prepend (new_item);
63-
clipboard_item_list.select_row (new_item);
64-
clipboard_item_list.show_all ();
65-
}
66-
});
67-
}
68-
69-
return Source.CONTINUE;
70-
});
79+
clipboard.owner_change.connect (on_clipboard_owner_change);
7180
}
7281

73-
public void stop_waiting_for_text () {
74-
if (wait_timeout > 0) {
75-
Source.remove (wait_timeout);
82+
private void on_clipboard_owner_change () requires (clipboard != null) {
83+
if (clipboard.wait_is_text_available ()) {
84+
clipboard.request_text ((cb, text) => {
85+
if (!clipboard_text_set.contains (text)) {
86+
clipboard_text_set.add (text);
87+
var new_item = new ItemRow (text);
88+
clipboard_item_list.prepend (new_item);
89+
clipboard_item_list.select_row (new_item);
90+
clipboard_item_list.show_all ();
91+
}
92+
});
7693
}
7794
}
7895

96+
public void stop_waiting_for_text () requires (clipboard != null) {
97+
clipboard.owner_change.disconnect (on_clipboard_owner_change);
98+
}
99+
79100
public void clear_history () {
80101
clipboard_text_set.clear ();
81102
clipboard_item_list.@foreach ((child) => {
82103
child.destroy ();
83104
});
84105
}
85106

107+
public void set_privacy_mode (bool privacy_on) {
108+
active_switch.sensitive = !privacy_on;
109+
stack.visible_child_name = privacy_on ? "privacy" : "clipboard";
110+
if (privacy_on) {
111+
stop_waiting_for_text ();
112+
clear_history ();
113+
} else {
114+
wait_for_text ();
115+
}
116+
}
117+
86118
private class ItemRow : Gtk.ListBoxRow {
87119
public string text { get; construct; }
88120
public string prettier_text { get; construct; }
@@ -115,52 +147,4 @@ public class Clipboard.HistoryWidget : Gtk.Box {
115147
add (label);
116148
}
117149
}
118-
119-
// Taken from the Code project (https://github.com/elementary/code)
120-
private class SettingSwitch : Gtk.Grid {
121-
public string label { get; construct; }
122-
public string settings_key { get; construct; }
123-
public string description { get; construct; }
124-
125-
public SettingSwitch (string label, string settings_key, string description = "") {
126-
Object (
127-
description: description,
128-
label: label,
129-
settings_key: settings_key
130-
);
131-
}
132-
133-
construct {
134-
var switch_widget = new Gtk.Switch () {
135-
valign = CENTER
136-
};
137-
138-
var label_widget = new Gtk.Label (label) {
139-
halign = START,
140-
hexpand = true,
141-
mnemonic_widget = switch_widget
142-
};
143-
144-
column_spacing = 12;
145-
attach (label_widget, 0, 0);
146-
attach (switch_widget, 1, 0, 1, 2);
147-
148-
if (description != "") {
149-
var description_label = new Gtk.Label (description) {
150-
halign = START,
151-
wrap = true,
152-
xalign = 0
153-
};
154-
description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
155-
description_label.get_style_context ().add_class (Granite.STYLE_CLASS_SMALL_LABEL);
156-
157-
attach (description_label, 0, 1);
158-
159-
switch_widget.get_accessible ().accessible_description = description;
160-
}
161-
162-
Clipboard.Indicator.settings.bind (settings_key, switch_widget, "active", DEFAULT);
163-
}
164-
}
165-
166150
}

src/Indicator.vala

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ public class Clipboard.Indicator : Wingpanel.Indicator {
1010
private const string STOPPED_ICON_NAME = "task-past-due-symbolic";
1111
private Gtk.Image panel_icon;
1212
private HistoryWidget history_widget;
13-
private Gtk.Box privacy_widget;
13+
1414
public bool always_hide { get; set; }
15+
public bool active { get; set; }
1516
public bool privacy_on { get; set; }
1617

1718
public Wingpanel.IndicatorManager.ServerType server_type { get; construct set; }
@@ -31,21 +32,13 @@ public class Clipboard.Indicator : Wingpanel.Indicator {
3132

3233
settings = new GLib.Settings ("io.github.ellie_commons.indicator-clipboard");
3334
settings.bind ("always-hide", this, "always-hide", DEFAULT);
35+
settings.bind ("active", this, "active", DEFAULT);
36+
3437

35-
var inactive_header_label = new Granite.HeaderLabel (_("The ClipboardManager is disabled"));
36-
var inactive_subheader_label = new Gtk.Label ("") {
37-
label = Granite.TOOLTIP_SECONDARY_TEXT_MARKUP.printf (_("History is off in the Privacy and Security settings")),
38-
use_markup = true
39-
};
40-
privacy_widget = new Gtk.Box (VERTICAL, 0) {
41-
margin_start = 6,
42-
margin_end = 6
43-
};
44-
privacy_widget.add (inactive_header_label);
45-
privacy_widget.add (inactive_subheader_label);
4638
// Ensure correct appearance before showing
4739
get_display_widget ();
4840
get_widget ();
41+
update_appearance ();
4942
}
5043

5144

@@ -57,7 +50,7 @@ public class Clipboard.Indicator : Wingpanel.Indicator {
5750
this.visible = false;
5851
} else {
5952
gnome_privacy_settings = new Settings ("org.gnome.desktop.privacy");
60-
gnome_privacy_settings.bind ("remember-recent-files", this, "privacy-on", GET | INVERT_BOOLEAN);
53+
gnome_privacy_settings.bind ("remember-recent-files", this, "privacy-on", DEFAULT | INVERT_BOOLEAN);
6154
}
6255
}
6356

@@ -74,14 +67,12 @@ public class Clipboard.Indicator : Wingpanel.Indicator {
7467
});
7568

7669
this.notify["privacy-on"].connect (update_appearance);
77-
// this.notify["privacy-on"].connect (get_widget);
7870
this.notify["always-hide"].connect (update_appearance);
71+
this.notify["active"].connect (update_appearance);
7972
update_appearance ();
8073
}
8174

82-
// There doesn't seem to be a way of stopping Wingpanel showing the (blank) popover in the inactive state
83-
// So show informative label.
84-
return !privacy_on ? history_widget : privacy_widget;
75+
return history_widget;
8576
}
8677

8778
public override void opened () {
@@ -92,16 +83,14 @@ public class Clipboard.Indicator : Wingpanel.Indicator {
9283
}
9384

9485
private void update_appearance () {
95-
if (privacy_on || always_hide) {
96-
history_widget.clear_history ();
97-
history_widget.stop_waiting_for_text ();
86+
if (!active || privacy_on || always_hide) {
9887
panel_icon.icon_name = STOPPED_ICON_NAME;
99-
} else if (!privacy_on && !always_hide) {
100-
history_widget.wait_for_text ();
88+
} else if (active && !privacy_on && !always_hide) {
10189
panel_icon.icon_name = NORMAL_ICON_NAME;
10290
}
10391

10492
visible = !always_hide;
93+
history_widget.set_privacy_mode (privacy_on);
10594
}
10695
}
10796

0 commit comments

Comments
 (0)