aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/fair-viewer84
-rwxr-xr-xbin/gtk-fair-viewer101
-rw-r--r--lib/WWW/FairViewer.pm19
-rw-r--r--lib/WWW/FairViewer/Channels.pm5
-rw-r--r--lib/WWW/FairViewer/GuideCategories.pm2
-rw-r--r--lib/WWW/FairViewer/VideoCategories.pm48
-rw-r--r--lib/WWW/FairViewer/Videos.pm31
-rw-r--r--share/gtk-fair-viewer.glade99
8 files changed, 76 insertions, 313 deletions
diff --git a/bin/fair-viewer b/bin/fair-viewer
index c72db85..a9f412b 100755
--- a/bin/fair-viewer
+++ b/bin/fair-viewer
@@ -197,7 +197,6 @@ my %CONFIG = (
comments_order => 'top', # valid values: top, new
subscriptions_order => 'relevance', # valid values: alphabetical, relevance, unread
- hl => 'en_US',
region => undef,
# URI options
@@ -661,7 +660,6 @@ usage: $execname [options] ([url] | [keywords])
* Categories
-c --categories : display the available YouTube categories
- -hl --catlang=s : language for categories (default: en_US)
* Region
--region=s : set the region code (default: US)
@@ -687,7 +685,8 @@ usage: $execname [options] ([url] | [keywords])
-ua --activities:s : show activity events for a given channel
* Trending
- --trending:s : show trending videos in a given category ID or name
+ --trending:s : show trending videos in a given category
+ valid categories: music gaming news movies
* Channels
-sc --channels : search for YouTube channels
@@ -1110,7 +1109,7 @@ sub apply_configuration {
videoDefinition
videoDimension videoDuration
date order
- channelId region debug hl
+ channelId region debug
http_proxy page comments_order
subscriptions_order user_agent
cookie_file timeout ytdl ytdl_cmd
@@ -1129,20 +1128,6 @@ sub apply_configuration {
}
}
- if (defined $opt->{category_id}) {
-
- my $str = delete $opt->{category_id};
- my $category = extract_category($str);
-
- if (ref($category) eq 'HASH') {
- say ":: Category selected: $category->{snippet}{title}" if $yv_obj->get_debug;
- $yv_obj->set_videoCategoryId($category->{id});
- }
- else {
- warn_invalid('category', $str);
- }
- }
-
if (defined $opt->{hd}) {
$yv_obj->set_videoDefinition(delete($opt->{hd}) ? 'high' : 'any');
}
@@ -1306,19 +1291,7 @@ sub apply_configuration {
}
if (defined $opt->{trending}) {
-
- my $str = delete $opt->{trending};
- my $category = extract_category($str);
- my $cat_id = undef;
-
- if (ref($category) eq 'HASH') {
- say ":: Category selected: $category->{snippet}{title}" if $yv_obj->get_debug;
- $cat_id = $category->{id};
- }
- elsif ($str) {
- warn_invalid('category', $str);
- }
-
+ my $cat_id = delete $opt->{trending};
print_videos($yv_obj->trending_videos_from_category($cat_id));
}
@@ -1519,8 +1492,6 @@ sub parse_arguments {
'user-agent|agent=s' => \$opt{user_agent},
'http-proxy|https-proxy|proxy=s' => \$opt{http_proxy},
- 'catlang|cl|hl=s' => \$opt{hl},
- 'category|cat-id|cat=s' => \$opt{category_id},
'r|region|region-code=s' => \$opt{region},
'order|order-by|sort|sort-by=s' => \$opt{order},
@@ -1715,34 +1686,6 @@ sub get_valid_playlist_id {
return $id;
}
-sub extract_category {
- my ($str) = @_;
-
- $str || return;
-
- state $results = $yv_obj->video_categories;
- return if ref($results) ne 'HASH';
-
- my $categories = $results->{items};
- return if ref($categories) ne 'ARRAY';
-
- foreach my $category (@$categories) {
- if ($category->{id} eq $str) {
- return $category;
- }
- }
-
- my $str_re = qr/\Q$str\E/i;
-
- foreach my $category (@$categories) {
- if ($yv_utils->get_title($category) =~ /$str_re/) {
- return $category;
- }
- }
-
- return;
-}
-
sub extract_channel_id {
my ($str) = @_;
@@ -2448,10 +2391,9 @@ sub valid_num {
sub adjust_width {
my ($str, $len, $prepend) = @_;
- $len > 0 or do {
- warn "[WARN] Insufficient space for the title: increase your terminal width!\n";
+ if ($len <= 0) {
return $str;
- };
+ }
state $pkg = (
eval {
@@ -2749,18 +2691,14 @@ sub print_comments {
sub print_categories {
my ($results) = @_;
- return if ref($results) ne 'HASH';
- my $categories = $results->{items};
+ my $categories = $results;
return if ref($categories) ne 'ARRAY';
my $i = 0;
print "\n" if @{$categories};
- # Filter out nonassignable categories
- @$categories = grep { $_->{snippet}{assignable} } @$categories;
-
foreach my $category (@{$categories}) {
- printf "%s. %-40s (id: %s)\n", colored(sprintf('%2d', ++$i), 'bold'), $yv_utils->get_title($category), $category->{id};
+ printf "%s. %-40s\n", colored(sprintf('%2d', ++$i), 'bold'), $category->{title};
}
my @keywords = get_input_for_categories();
@@ -2796,11 +2734,7 @@ sub print_categories {
elsif (valid_num($key, $categories)) {
my $category = $categories->[$key - 1];
my $cat_id = $category->{id};
- my $videos = $yv_obj->videos_from_category($cat_id);
-
- if (not $yv_utils->has_entries($videos)) {
- $videos = $yv_obj->trending_videos_from_category($cat_id);
- }
+ my $videos = $yv_obj->trending_videos_from_category($cat_id);
print_videos($videos);
}
diff --git a/bin/gtk-fair-viewer b/bin/gtk-fair-viewer
index 3274ce2..bafdc12 100755
--- a/bin/gtk-fair-viewer
+++ b/bin/gtk-fair-viewer
@@ -186,20 +186,19 @@ my %CONFIG = (
# Fair options
dash_support => 1,
dash_mp4_audio => 1,
- dash_segmented => 1, # may load slow
+ dash_segmented => 1, # may load slow
prefer_mp4 => 0,
prefer_av1 => 0,
ignore_av1 => 0,
maxResults => 10,
- hfr => 1, # true to prefer high frame rate (HFR) videos
+ hfr => 1, # true to prefer high frame rate (HFR) videos
resolution => 'best',
videoDimension => undef,
videoLicense => undef,
- hl => 'en_US',
region => undef,
- comments_width => 80, # wrap comments longer than `n` characters
- comments_order => 'top', # valid values: time, relevance
+ comments_width => 80, # wrap comments longer than `n` characters
+ comments_order => 'top', # valid values: time, relevance
# API
api_host => "auto",
@@ -338,7 +337,6 @@ my %objects = (
'treeviewcolumn2' => \my $thumbs_column,
'textview2' => \my $textview_help,
'from_author_entry' => \my $from_author_entry,
- 'category_id_entry' => \my $category_id_entry,
'more_options_expander' => \my $more_options_expander,
'notebook1' => \my $notebook,
'comboboxtext9' => \my $resolution_combobox,
@@ -352,9 +350,7 @@ my %objects = (
'comboboxtext6' => \my $panel_account_type_combobox,
'comboboxtext2' => \my $order_combobox,
'comboboxtext7' => \my $channel_type_combobox,
- 'videos_checkbox' => \my $search_for_videos_checkbox,
- 'playlists_checkbox' => \my $search_for_playlists_checkbox,
- 'channels_checkbox' => \my $search_for_channels_checkbox,
+ 'comboboxtext10' => \my $search_for_combobox,
'spinbutton1' => \my $spin_results,
'spinbutton2' => \my $spin_start_with_page,
'thumbs_checkbutton' => \my $thumbs_checkbutton,
@@ -822,7 +818,6 @@ my $yv_obj = WWW::FairViewer->new(
config_dir => $config_dir,
ytdl => $CONFIG{ytdl},
ytdl_cmd => $CONFIG{ytdl_cmd},
- hl => $CONFIG{hl},
env_proxy => $CONFIG{env_proxy},
cache_dir => $CONFIG{cache_dir},
cookie_file => $CONFIG{cookie_file},
@@ -852,9 +847,6 @@ $order_combobox->set_active(0);
# Spin button start with page
$spin_start_with_page->set_value(1);
-# Set search for videos
-$search_for_videos_checkbox->set_active(1);
-
sub apply_configuration {
# Fullscreen mode
@@ -875,14 +867,11 @@ sub apply_configuration {
foreach my $option_name (
qw(
- api_host
videoSyndicated comments_order
- maxResults videoDimension
- videoLicense
- region videoCategoryId
- debug http_proxy user_agent
+ maxResults videoDimension videoLicense
+ region debug http_proxy user_agent
timeout cookie_file ytdl ytdl_cmd
- prefer_mp4 prefer_av1
+ api_host prefer_mp4 prefer_av1
)
) {
@@ -1703,6 +1692,7 @@ sub combobox_definition_changed {
}
sub combobox_published_within_changed {
+
my $period = $published_within_combobox->get_active_text;
if ($period =~ /^any/) {
@@ -1781,17 +1771,15 @@ sub add_category_header {
sub append_categories {
my ($categories, $type) = @_;
- foreach my $category (@{$categories->{items}}) {
+ foreach my $category (@$categories) {
- # Ignore nonassignable categories
- $category->{snippet}{assignable} || next;
-
- my $label = $yv_utils->get_title($category);
+ my $label = $category->{title};
my $id = $category->{id};
$label =~ s{&}{&amp;}g;
my $iter = $cats_liststore->append;
+
$cats_liststore->set(
$iter,
0 => $label,
@@ -1803,33 +1791,7 @@ sub append_categories {
return 1;
}
-#<<<
-#~ {
- # Standard categories:
- #~ add_category_header("Categories");
-
- #~ my $cats = $yv_obj->video_categories();
- #~ if (ref($cats) eq 'HASH' and ref($cats->{items}) eq 'ARRAY') {
-
- #~ my $help_text = '';
- #~ foreach my $cat (sort { $a->{id} <=> $b->{id} } @{$cats->{items}}) {
- #~ $cat->{snippet}{assignable} || next;
- #~ $help_text .= sprintf("%2d - %s\n", $cat->{id}, $yv_utils->get_title($cat));
- #~ }
-
- #~ # Set tooltip text for "CategoryID" entry
- #~ chomp($help_text);
- #~ $category_id_entry->set_tooltip_text($help_text);
-
- #~ # Append the categories to the "Categories" tab
- #~ append_categories($cats, 'cat');
- #~ }
-
- # EDU categories:
- #add_category_header("EDU Categories");
- #append_categories($yv_obj->get_educategories(), 'edu-cat');
-#~ }
-#>>>
+append_categories($yv_obj->video_categories, 'cat');
my $tops_liststore = $gui->get_object('liststore6');
my $tops_treeview = $gui->get_object('treeview4');
@@ -2285,29 +2247,7 @@ sub search {
$yv_obj->set_channelId();
}
- # Set the category ID
- my $category_id = $category_id_entry->get_text;
- if ($category_id =~ /^\d+\z/) {
- $yv_obj->set_videoCategoryId($category_id);
- }
- else {
- $yv_obj->set_videoCategoryId();
- }
-
- my @types;
- if ($search_for_playlists_checkbox->get_active) {
- push @types, 'playlist';
- }
-
- if ($search_for_channels_checkbox->get_active) {
- push @types, 'channel';
- }
-
- if ($search_for_videos_checkbox->get_active) {
- push @types, 'video';
- }
-
- my $type = @types ? join(',', @types) : 'video';
+ my $type = $search_for_combobox->get_active_text;
display_results($yv_obj->search_for($type, $keywords));
return 1;
@@ -3127,18 +3067,12 @@ sub play_video {
}
sub list_category {
+
my $iter = $cat_treeview->get_selection->get_selected;
- my $cat_id = $cats_liststore->get($iter, 1) // return;
+ my $cat_id = $cats_liststore->get($iter, 1);
my $type = $cats_liststore->get($iter, 3);
- my $videos =
- $type eq 'edu-cat'
- ? $yv_obj->get_video_lectures_from_category($cat_id)
- : $yv_obj->videos_from_category($cat_id);
-
- if (not $yv_utils->has_entries($videos)) {
- $videos = $yv_obj->trending_videos_from_category($cat_id);
- }
+ my $videos = $yv_obj->trending_videos_from_category($cat_id);
if ($yv_utils->has_entries($videos)) {
$liststore->clear if $CONFIG{clear_search_list};
@@ -3150,6 +3084,7 @@ sub list_category {
}
sub list_tops {
+
my $iter = $tops_treeview->get_selection->get_selected;
my %top_opts;
diff --git a/lib/WWW/FairViewer.pm b/lib/WWW/FairViewer.pm
index d7be54c..8d8abff 100644
--- a/lib/WWW/FairViewer.pm
+++ b/lib/WWW/FairViewer.pm
@@ -50,7 +50,6 @@ my %valid_options = (
v => {valid => q[], default => 3},
page => {valid => qr/^(?!0+\z)\d+\z/, default => 1},
http_proxy => {valid => qr/./, default => undef},
- hl => {valid => qr/^\w+(?:[\-_]\w+)?\z/, default => undef},
maxResults => {valid => [1 .. 50], default => 10},
order => {valid => [qw(relevance rating upload_date view_count)], default => undef},
date => {valid => [qw(hour today week month year)], default => undef},
@@ -283,7 +282,7 @@ sub set_lwp_useragent {
// do { require LWP::UserAgent; 'LWP::UserAgent' }
);
- $self->{lwp} = $lwp->new(
+ my $agent = $lwp->new(
cookie_jar => {}, # temporary cookies
timeout => $self->get_timeout,
@@ -329,7 +328,6 @@ sub set_lwp_useragent {
HTTP::Message::decodable();
};
- my $agent = $self->{lwp};
$agent->ssl_opts(Timeout => $self->get_timeout);
$agent->default_header('Accept-Encoding' => $accepted_encodings);
$agent->conn_cache($cache);
@@ -366,8 +364,9 @@ sub set_lwp_useragent {
$agent->cookie_jar($cookies);
}
- push @{$self->{lwp}->requests_redirectable}, 'POST';
- return $self->{lwp};
+ push @{$agent->requests_redirectable}, 'POST';
+ $self->{lwp} = $agent;
+ return $agent;
}
=head2 prepare_access_token()
@@ -399,7 +398,7 @@ sub _auth_lwp_header {
sub _warn_reponse_error {
my ($resp, $url) = @_;
- warn sprintf("[%s] Error occurred on URL: %s\n", $resp->status_line, $url =~ s/([&?])key=(.*?)&/${1}key=[...]&/r);
+ warn sprintf("[%s] Error occurred on URL: %s\n", $resp->status_line, $url);
}
=head2 lwp_get($url, %opt)
@@ -463,7 +462,7 @@ sub lwp_get {
$opt{depth} ||= 0;
# Try again on 500+ HTTP errors
- if ( $opt{depth} <= 3
+ if ( $opt{depth} < 3
and $response->code() >= 500
and $response->status_line() =~ /(?:Temporary|Server) Error|Timeout|Service Unavailable/i) {
return $self->lwp_get($url, %opt, depth => $opt{depth} + 1);
@@ -581,7 +580,7 @@ sub select_good_invidious_instances {
my %ignored = (
'yewtu.be' => 1,
- 'invidiou.site' => 0,
+ 'invidiou.site' => 1,
'invidious.xyz' => 1,
'vid.mint.lgbt' => 1,
'invidious.ggc-project.de' => 1,
@@ -704,7 +703,6 @@ sub _extract_from_invidious {
require List::Util;
@instances = List::Util::shuffle(map { $_->[0] } @instances);
push @instances, 'invidious.snopyta.org';
- push @instances, 'invidious.13ad.de';
}
else {
@instances = qw(
@@ -712,7 +710,6 @@ sub _extract_from_invidious {
invidious.site
invidious.fdn.fr
invidious.snopyta.org
- invidious.13ad.de
);
}
@@ -1240,6 +1237,8 @@ sub previous_page {
local $ENV{HTTP_PROXY} = $self->{lwp}->proxy('http');
local $ENV{HTTPS_PROXY} = $self->{lwp}->proxy('https');
+ local $" = " ";
+
$name eq 'exec' ? exec(@args)
: $name eq 'system' ? system(@args)
: $name eq 'stdout' ? qx(@args)
diff --git a/lib/WWW/FairViewer/Channels.pm b/lib/WWW/FairViewer/Channels.pm
index c554044..3ee44d4 100644
--- a/lib/WWW/FairViewer/Channels.pm
+++ b/lib/WWW/FairViewer/Channels.pm
@@ -41,6 +41,11 @@ Get the most popular videos for a given channel ID.
sub popular_videos {
my ($self, $channel_id) = @_;
+
+ if (not defined($channel_id)) { # trending popular videos
+ return $self->_get_results($self->_make_feed_url('popular'));
+ }
+
return $self->_get_results($self->_make_feed_url("channels/$channel_id/videos", sort_by => 'popular'));
}
diff --git a/lib/WWW/FairViewer/GuideCategories.pm b/lib/WWW/FairViewer/GuideCategories.pm
index a348abb..cead9f6 100644
--- a/lib/WWW/FairViewer/GuideCategories.pm
+++ b/lib/WWW/FairViewer/GuideCategories.pm
@@ -25,7 +25,7 @@ sub _make_guideCategories_url {
$opts{region} //= $self->get_region;
}
- $self->_make_feed_url('guideCategories', hl => $self->get_hl, %opts);
+ $self->_make_feed_url('guideCategories', %opts);
}
=head2 guide_categories(;$region_id)
diff --git a/lib/WWW/FairViewer/VideoCategories.pm b/lib/WWW/FairViewer/VideoCategories.pm
index 85045fd..4dfc125 100644
--- a/lib/WWW/FairViewer/VideoCategories.pm
+++ b/lib/WWW/FairViewer/VideoCategories.pm
@@ -18,16 +18,6 @@ WWW::FairViewer::VideoCategories - videoCategory resource handler.
=cut
-sub _make_videoCategories_url {
- my ($self, %opts) = @_;
-
- $self->_make_feed_url(
- 'videoCategories',
- hl => $self->get_hl,
- %opts,
- );
-}
-
=head2 video_categories()
Return video categories for a specific region ID.
@@ -37,37 +27,13 @@ Return video categories for a specific region ID.
sub video_categories {
my ($self) = @_;
- require File::Spec;
-
- my $region = $self->get_region() // 'US';
- my $url = $self->_make_videoCategories_url(region => $region);
- my $file = File::Spec->catfile($self->get_config_dir, "categories-$region-" . $self->get_hl() . ".json");
-
- my $json;
- if (open(my $fh, '<:utf8', $file)) {
- local $/;
- $json = <$fh>;
- close $fh;
- }
- else {
- $json = $self->lwp_get($url, simple => 1);
- open my $fh, '>:utf8', $file;
- print {$fh} $json;
- close $fh;
- }
-
- return $self->parse_json_string($json);
-}
-
-=head2 video_category_id_info($cagegory_id)
-
-Return info for the comma-separated specified category ID(s).
-
-=cut
-
-sub video_category_id_info {
- my ($self, $id) = @_;
- return $self->_get_results($self->_make_videoCategories_url(id => $id));
+ return [{id => "music", title => "Music"},
+ {id => "gaming", title => "Gaming"},
+ {id => "news", title => "News"},
+ {id => "movies", title => "Movies"},
+ {id => "trending", title => "Trending"},
+ {id => "popular", title => "Popular"},
+ ];
}
=head1 AUTHOR
diff --git a/lib/WWW/FairViewer/Videos.pm b/lib/WWW/FairViewer/Videos.pm
index aaaacc7..4acd866 100644
--- a/lib/WWW/FairViewer/Videos.pm
+++ b/lib/WWW/FairViewer/Videos.pm
@@ -48,22 +48,6 @@ sub _make_videos_url {
}
}
-=head2 videos_from_category($category_id)
-
-Get videos from a category ID.
-
-=cut
-
-sub videos_from_category {
- my ($self, $cat_id) = @_;
- $self->_get_results(
- $self->_make_videos_url(
- chart => $self->get_chart,
- videoCategoryId => $cat_id,
- )
- );
-}
-
=head2 trending_videos_from_category($category_id)
Get popular videos from a category ID.
@@ -71,14 +55,17 @@ Get popular videos from a category ID.
=cut
sub trending_videos_from_category {
- my ($self, $cat_id) = @_;
+ my ($self, $category) = @_;
+
+ if (defined($category) and $category eq 'popular') {
+ return $self->popular_videos;
+ }
- my $results = do {
- local $self->{videoCategoryId} = $cat_id;
- $self->search_videos("");
- };
+ if (defined($category) and $category eq 'trending') {
+ $category = undef;
+ }
- return $results;
+ return $self->_get_results($self->_make_feed_url('trending', (defined($category) ? (type => $category) : ())));
}
=head2 my_likes()
diff --git a/share/gtk-fair-viewer.glade b/share/gtk-fair-viewer.glade
index 48b3a05..09ecfe5 100644
--- a/share/gtk-fair-viewer.glade
+++ b/share/gtk-fair-viewer.glade
@@ -890,61 +890,39 @@ Author: Jesus E. https://framagit.org/heckyel
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkExpander" id="expander2">
+ <object class="GtkFrame" id="frame14">
<property name="visible">True</property>
- <property name="can_focus">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
- <object class="GtkBox" id="vbox22">
+ <object class="GtkBox" id="vbox9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkCheckButton" id="channels_checkbox">
- <property name="label" translatable="yes">Channels</property>
+ <object class="GtkComboBoxText" id="comboboxtext10">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes">video</item>
+ <item translatable="yes">playlist</item>
+ <item translatable="yes">channel</item>
+ <item translatable="yes">all</item>
+ </items>
</object>
<packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkCheckButton" id="playlists_checkbox">
- <property name="label" translatable="yes">Playlists</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="videos_checkbox">
- <property name="label" translatable="yes">Videos</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
</object>
</child>
</object>
@@ -953,7 +931,8 @@ Author: Jesus E. https://framagit.org/heckyel
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Search for:</property>
+ <property name="label" translatable="yes">&lt;b&gt;Type:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</object>
</child>
</object>
@@ -1383,48 +1362,6 @@ Unless the author name is valid, this field is ignored.</property>
</packing>
</child>
<child>
- <object class="GtkFrame" id="frame25">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="alignment24">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkEntry" id="category_id_entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip_text" translatable="yes">Search in videos uploaded in a specific category.
-Unless the categoryID is valid, this field is ignored.</property>
- <property name="invisible_char">•</property>
- <property name="text" translatable="yes">Insert a valid category ID...</property>
- <property name="primary_icon_activatable">False</property>
- <property name="secondary_icon_activatable">False</property>
- <signal name="activate" handler="search" swapped="no"/>
- <signal name="button-press-event" handler="clear_text" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label33">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">&lt;b&gt;CategoryID:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>