[gnome-music/bilelmoussaoui/adaptive-ui] WIP: make Music UI adaptive
- From: Bilal Elmoussaoui <bilelmoussaoui src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/bilelmoussaoui/adaptive-ui] WIP: make Music UI adaptive
- Date: Tue, 17 Sep 2019 01:35:21 +0000 (UTC)
commit 94c4d2e09ad07686c8693a41a9f27c96dc2126f4
Author: Bilal Elmoussaoui <bil elmoussaoui gmail com>
Date: Tue Sep 17 03:34:40 2019 +0200
WIP: make Music UI adaptive
data/ui/AlbumWidget.ui | 403 +++++++++++-----------
data/ui/AlbumsView.ui | 8 +-
data/ui/ArtistAlbumWidget.ui | 126 ++++---
data/ui/HeaderBar.ui | 173 +++++++---
data/ui/PlayerToolbar.ui | 551 ++++++++++++++++---------------
data/ui/Window.ui | 54 ++-
gnome-music.in | 5 +-
gnomemusic/utils.py | 6 +
gnomemusic/views/albumsview.py | 20 +-
gnomemusic/views/artistsview.py | 19 +-
gnomemusic/views/baseview.py | 34 +-
gnomemusic/views/playlistsview.py | 54 ++-
gnomemusic/views/songsview.py | 2 +-
gnomemusic/widgets/albumwidget.py | 18 +
gnomemusic/widgets/artistalbumswidget.py | 7 +
gnomemusic/widgets/artistalbumwidget.py | 20 +-
gnomemusic/widgets/headerbar.py | 64 +++-
gnomemusic/widgets/playertoolbar.py | 32 +-
gnomemusic/widgets/searchheaderbar.py | 2 +-
gnomemusic/window.py | 57 +++-
meson.build | 2 +
org.gnome.Music.json | 14 +
22 files changed, 1050 insertions(+), 621 deletions(-)
---
diff --git a/data/ui/AlbumWidget.ui b/data/ui/AlbumWidget.ui
index 7f6b770d..3206d732 100644
--- a/data/ui/AlbumWidget.ui
+++ b/data/ui/AlbumWidget.ui
@@ -1,242 +1,273 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
+ <requires lib="libhandy" version="0.0"/>
<template class="AlbumWidget" parent="GtkEventBox">
<property name="visible">True</property>
- <style>
- <class name="view"/>
- <class name="content-view"/>
- </style>
+ <property name="can_focus">False</property>
<child>
- <object class="GtkBox">
+ <object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
<child>
- <object class="GtkBox" id="albumInfo">
+ <object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="margin_start">32</property>
- <property name="margin_end">32</property>
- <property name="margin_top">64</property>
- <property name="margin_bottom">32</property>
- <property name="vexpand">True</property>
<property name="hexpand">True</property>
+ <property name="shadow_type">none</property>
<child>
- <object class="GtkBox" id="albumDetails">
+ <object class="GtkBox" id="_album_widget">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="valign">start</property>
- <property name="orientation">vertical</property>
- <property name="spacing">18</property>
- <child>
- <object class="CoverStack" id="_cover_stack">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="valign">start</property>
- <property name="margin_start">1</property>
- <property name="margin_end">1</property>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
+ <property name="spacing">6</property>
<child>
- <object class="GtkBox" id="artistBox">
+ <object class="GtkBox" id="_album_info">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">start</property>
- <property name="orientation">vertical</property>
- <property name="spacing">3</property>
+ <property name="hexpand">True</property>
<child>
- <object class="GtkLabel" id="_title_label">
+ <object class="GtkBox" id="albumDetails">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
- <property name="justify">center</property>
- <property name="ellipsize">middle</property>
- <style>
- <class name="title-artist"/>
- </style>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="CoverStack" id="_cover_stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="margin_start">1</property>
+ <property name="margin_end">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="artistBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkLabel" id="_title_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="ellipsize">middle</property>
+ <style>
+ <class name="title-artist"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_artist_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="ellipsize">middle</property>
+ <style>
+ <class name="title-artist"/>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">32</property>
+ <property name="column_homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="released_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Released</property>
+ <property name="use_markup">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="running_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Running Length</property>
+ <property name="use_markup">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_released_info_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label">----</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_running_info_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">--:--</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_composer_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">end</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Composer</property>
+ <property name="use_markup">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_composer_info_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">start</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
</object>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkLabel" id="_artist_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="justify">center</property>
- <property name="ellipsize">middle</property>
- <style>
- <class name="title-artist"/>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
</object>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
- <object class="GtkGrid" id="grid">
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_top">21</property>
- <property name="column_spacing">32</property>
- <property name="column_homogeneous">True</property>
- <child>
- <object class="GtkLabel" id="released_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="margin_top">2</property>
- <property name="margin_bottom">2</property>
- <property name="label" translatable="yes">Released</property>
- <property name="use_markup">True</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="running_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="label" translatable="yes">Running Length</property>
- <property name="use_markup">True</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="_released_info_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="margin_top">2</property>
- <property name="margin_bottom">2</property>
- <property name="label">----</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="_running_info_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label">--:--</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="_composer_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="no_show_all">True</property>
- <property name="halign">end</property>
- <property name="margin_top">2</property>
- <property name="margin_bottom">2</property>
- <property name="label" translatable="yes">Composer</property>
- <property name="use_markup">True</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- </packing>
- </child>
+ <property name="valign">start</property>
<child>
- <object class="GtkLabel" id="_composer_info_label">
+ <object class="HdyColumn">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="no_show_all">True</property>
- <property name="halign">start</property>
- <property name="margin_top">2</property>
- <property name="margin_bottom">2</property>
- <property name="ellipsize">end</property>
+ <property name="hexpand">True</property>
+ <property name="maximum_width">800</property>
+ <property name="linear_growth_width">800</property>
+ <child>
+ <object class="DiscListBox" id="_listbox">
+ <property name="can_focus">False</property>
+ <property name="selection_mode">0</property>
+ <property name="halign">fill</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
</object>
<packing>
- <property name="position">3</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
- <packing>
- <property name="position">0</property>
- </packing>
</child>
</object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledWindow">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="hscrollbar_policy">never</property>
- <child>
- <object class="GtkViewport" id="_viewport">
- <property name="width_request">600</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="hexpand">True</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="DiscListBox" id="_listbox">
- <property name="can_focus">False</property>
- <property name="margin_top">64</property>
- <property name="margin_bottom">64</property>
- <property name="margin_end">32</property>
- <property name="selection_mode">0</property>
- <property name="visible">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
</child>
</object>
</child>
+ <style>
+ <class name="view"/>
+ <class name="content-view"/>
+ </style>
</template>
</interface>
diff --git a/data/ui/AlbumsView.ui b/data/ui/AlbumsView.ui
index 116231fe..30ae439d 100644
--- a/data/ui/AlbumsView.ui
+++ b/data/ui/AlbumsView.ui
@@ -10,11 +10,11 @@
<property name="column_spacing">6</property>
<property name="halign">fill</property>
<property name="hexpand">True</property>
- <property name="homogeneous">True</property>
- <property name="margin">18</property>
- <property name="max-children-per-line">20</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="max-children-per-line">10</property>
<property name="min-children-per-line">1</property>
- <property name="row_spacing">12</property>
+ <property name="row_spacing">6</property>
<property name="selection-mode">none</property>
<property name="valign">start</property>
<property name="visible">True</property>
diff --git a/data/ui/ArtistAlbumWidget.ui b/data/ui/ArtistAlbumWidget.ui
index 54ccb83f..4d9690d4 100644
--- a/data/ui/ArtistAlbumWidget.ui
+++ b/data/ui/ArtistAlbumWidget.ui
@@ -1,68 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
- <template parent="GtkBox" class="ArtistAlbumWidget">
- <property name="margin_top">30</property>
- <property name="margin_right">120</property>
+ <template class="ArtistAlbumWidget" parent="HdyColumn">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="maximum_width">800</property>
+ <property name="margin_top">32</property>
+ <property name="linear_growth_width">800</property>
<child>
- <object class="CoverStack" id="_cover_stack">
- <property name="visible">True</property>
- <property name="margin_top">20</property>
- <property name="margin_right">30</property>
- <property name="margin_bottom">20</property>
- <property name="margin_left">120</property>
- <property name="can_focus">False</property>
- <property name="valign">start</property>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="_album_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox" id="box3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="CoverStack" id="_cover_stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
- <object class="GtkLabel" id="_title_year">
+ <object class="GtkBox" id="_album_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_top">20</property>
- <property name="margin_bottom">20</property>
- <property name="ellipsize">middle</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <style>
- <class name="album-title"/>
- </style>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="_title_year">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">20</property>
+ <property name="margin_bottom">20</property>
+ <property name="ellipsize">middle</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="halign">center</property>
+ <style>
+ <class name="album-title"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="DiscListBox" id="_disc_list_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="selection-mode">0</property>
+ <!-- <property name="orientation">vertical</property> -->
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
</child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="DiscListBox" id="_disc_list_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="selection-mode">0</property>
- <!-- <property name="orientation">vertical</property> -->
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
+ </object>
</child>
</template>
</interface>
diff --git a/data/ui/HeaderBar.ui b/data/ui/HeaderBar.ui
index bf04a328..8bed3be6 100644
--- a/data/ui/HeaderBar.ui
+++ b/data/ui/HeaderBar.ui
@@ -1,64 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
<interface>
- <!-- interface-requires gtk+ 3.10 -->
+ <requires lib="gtk+" version="3.20"/>
+ <requires lib="libhandy" version="0.0"/>
<template class="HeaderBar" parent="GtkHeaderBar">
<property name="visible">True</property>
- <property name="vexpand">False</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="show_close_button">True</property>
<child>
- <object class="GtkMenuButton" id="_menu_button">
+ <object class="GtkButton" id="_back_button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Back</property>
<property name="valign">center</property>
- <property name="sensitive">True</property>
- <property name="tooltip_text" translatable="yes">Menu</property>
+ <signal name="clicked" handler="_on_back_button_clicked" swapped="no"/>
+ <child>
+ <object class="GtkImage" id="_back_button_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
<style>
<class name="image-button"/>
</style>
- <child>
- <object class="GtkImage" id="_menu_button_image">
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child type="center">
+ <object class="HdySqueezer" id="_squeezer">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon-name">open-menu-symbolic</property>
- <property name="icon-size">1</property>
+ <property name="transition_type">crossfade</property>
+ <child>
+ <object class="HdyViewSwitcher" id="_title_wide_switcher">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="policy">wide</property>
+ </object>
+ </child>
+ <child>
+ <object class="HdyViewSwitcher" id="_title_narrow_switcher">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="policy">narrow</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="_title_text">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="_title_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Music</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_subtitle_label">
+ <property name="can_focus">False</property>
+ <style>
+ <class name="subtitle"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
- <property name="pack_type">end</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="_select_button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">center</property>
- <property name="sensitive">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Select</property>
- <style>
- <class name="image-button"/>
- </style>
+ <property name="valign">center</property>
<child>
<object class="GtkImage" id="_select_button_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon-name">object-select-symbolic</property>
- <property name="icon-size">1</property>
+ <property name="icon_name">object-select-symbolic</property>
+ <property name="icon_size">1</property>
</object>
</child>
+ <style>
+ <class name="image-button"/>
+ </style>
</object>
<packing>
<property name="pack_type">end</property>
+ <property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="_cancel_button">
- <property name="visible">False</property>
- <property name="no_show_all">True</property>
- <property name="can_focus">False</property>
<property name="label" translatable="yes">_Cancel</property>
- <property name="use_underline">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="no_show_all">True</property>
<property name="valign">center</property>
- <property name="sensitive">True</property>
+ <property name="use_underline">True</property>
<signal name="clicked" handler="_on_cancel_button_clicked" swapped="no"/>
<style>
<class name="text-button"/>
@@ -66,61 +143,59 @@
</object>
<packing>
<property name="pack_type">end</property>
+ <property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="_search_button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">center</property>
- <property name="sensitive">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Search</property>
- <style>
- <class name="image-button"/>
- </style>
+ <property name="valign">center</property>
<child>
<object class="GtkImage" id="_search_button_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon-name">edit-find-symbolic</property>
- <property name="icon-size">1</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ <property name="icon_size">1</property>
</object>
</child>
+ <style>
+ <class name="image-button"/>
+ </style>
</object>
<packing>
<property name="pack_type">end</property>
+ <property name="position">4</property>
</packing>
</child>
<child>
- <object class="GtkButton" id="_back_button">
+ <object class="GtkMenuButton" id="_menu_button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Menu</property>
<property name="valign">center</property>
- <property name="sensitive">True</property>
- <property name="tooltip_text" translatable="yes">Back</property>
- <signal name="clicked" handler="_on_back_button_clicked" swapped="no"/>
- <style>
- <class name="image-button"/>
- </style>
<child>
- <object class="GtkImage" id="_back_button_image">
+ <object class="GtkImage" id="_menu_button_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon-name">go-previous-symbolic</property>
- <property name="icon-size">1</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ <property name="icon_size">1</property>
</object>
</child>
+ <style>
+ <class name="image-button"/>
+ </style>
</object>
<packing>
- <property name="pack_type">start</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
</packing>
</child>
</template>
<object class="GtkSizeGroup" id="size1">
- <property name="mode">vertical</property>
- <widgets>
- <widget name="_search_button"/>
- <widget name="_cancel_button"/>
- </widgets>
+ <property name="mode">vertical</property>
</object>
</interface>
diff --git a/data/ui/PlayerToolbar.ui b/data/ui/PlayerToolbar.ui
index 3eebcf6e..9c03937f 100644
--- a/data/ui/PlayerToolbar.ui
+++ b/data/ui/PlayerToolbar.ui
@@ -1,47 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
- <menu id="repeatMenu">
- <item>
- <attribute name="label" translatable="yes">Shuffle</attribute>
- <attribute name="action">win.repeat</attribute>
- <attribute name="target">shuffle</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">Repeat All</attribute>
- <attribute name="action">win.repeat</attribute>
- <attribute name="target">all</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">Repeat Song</attribute>
- <attribute name="action">win.repeat</attribute>
- <attribute name="target">song</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes" comments="Causes tracks to play in random
order">Shuffle/Repeat Off</attribute>
- <attribute name="action">win.repeat</attribute>
- <attribute name="target">none</attribute>
- </item>
- </menu>
- <object class="GtkImage" id="next_image">
+ <object class="GtkImage" id="_pause_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">1</property>
- <property name="icon_name">media-skip-forward-symbolic</property>
+ <property name="icon_name">media-playback-pause-symbolic</property>
<property name="icon_size">1</property>
</object>
- <object class="GtkImage" id="_pause_image">
+ <object class="GtkImage" id="_play_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">1</property>
- <property name="icon_name">media-playback-pause-symbolic</property>
+ <property name="icon_name">media-playback-start-symbolic</property>
<property name="icon_size">1</property>
</object>
- <object class="GtkImage" id="_play_image">
+ <object class="GtkImage" id="next_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">1</property>
- <property name="icon_name">media-playback-start-symbolic</property>
+ <property name="icon_name">media-skip-forward-symbolic</property>
<property name="icon_size">1</property>
</object>
<object class="GtkImage" id="previous_image">
@@ -52,240 +31,288 @@
<property name="icon_size">1</property>
</object>
<template class="PlayerToolbar" parent="GtkActionBar">
- <property name="can_focus">False</property>
- <property name="no_show_all">True</property>
- <child>
- <object class="GtkBox" id="buttons">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkButton" id="_prev_button">
- <property name="width_request">42</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">previous_image</property>
- <property name="always_show_image">True</property>
- <property name="tooltip_text" translatable="yes">Previous</property>
- <signal name="clicked" handler="_on_prev_button_clicked" swapped="no"/>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="_play_button">
- <property name="width_request">60</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">_play_image</property>
- <property name="always_show_image">True</property>
- <property name="tooltip_text" translatable="yes">Play</property>
- <signal name="clicked" handler="_on_play_button_clicked" swapped="no"/>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="_next_button">
- <property name="width_request">42</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">next_image</property>
- <property name="always_show_image">True</property>
- <property name="tooltip_text" translatable="yes">Next</property>
- <signal name="clicked" handler="_on_next_button_clicked" swapped="no"/>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <style>
- <class name="linked"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="_song_info_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="has_tooltip">True</property>
- <property name="valign">center</property>
- <property name="spacing">8</property>
- <signal name="query-tooltip" handler="_on_tooltip_query"/>
- <child>
- <object class="CoverStack" id="_cover_stack">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="nowplaying_labels">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="orientation">vertical</property>
- <property name="homogeneous">True</property>
- <child>
- <object class="GtkLabel" id="_title_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="xalign">0</property>
- <property name="ellipsize">middle</property>
- <property name="width_chars">8</property>
- <property name="max_width_chars">42</property>
- <style>
- <class name="player-title-label"/>
- </style>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="_artist_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="xalign">0</property>
- <property name="ellipsize">middle</property>
- <property name="width_chars">8</property>
- <property name="max_width_chars">42</property>
- <style>
- <class name="player-artist-label"/>
- </style>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- <child>
- <object class="SmoothScale" id="_progress_scale">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="valign">center</property>
- <property name="hexpand">True</property>
- <property name="draw_value">False</property>
- <signal name = "value-changed" handler="_on_progress_value_changed" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="timer">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">center</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="_progress_time_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">center</property>
- <property name="label">0:00</property>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="separator">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">center</property>
- <property name="label">/</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="_duration_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">center</property>
- <property name="label">0:00</property>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="menuBox">
- <property name="height_request">34</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="valign">center</property>
- <child>
- <object class="GtkMenuButton" id="menuButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_popover">True</property>
- <property name="menu_model">repeatMenu</property>
- <child>
- <object class="GtkBox" id="replayBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkImage" id="_repeat_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">media-playlist-consecutive-symbolic</property>
- <property name="icon_size">1</property>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="downArrow">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">pan-down-symbolic</property>
- <property name="icon_size">1</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
+ <property name="visible">False</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkBox" id="buttons">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkButton" id="_prev_button">
+ <property name="width_request">42</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Previous</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="image">previous_image</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="_on_prev_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="_play_button">
+ <property name="width_request">60</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Play</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="image">_play_image</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="_on_play_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="_next_button">
+ <property name="width_request">42</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Next</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="image">next_image</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="_on_next_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="_song_info_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="spacing">8</property>
+ <signal name="query-tooltip" handler="_on_tooltip_query" swapped="no"/>
+ <child>
+ <object class="CoverStack" id="_cover_stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="nowplaying_labels">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="_title_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="ellipsize">middle</property>
+ <property name="width_chars">8</property>
+ <property name="max_width_chars">42</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="player-title-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_artist_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="ellipsize">middle</property>
+ <property name="width_chars">8</property>
+ <property name="max_width_chars">42</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="player-artist-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="timer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="_progress_time_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="label">0:00</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="separator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="label">/</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_duration_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="label">0:00</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="SmoothScale" id="_progress_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <signal name="value-changed" handler="_on_progress_value_changed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="_repeat_box">
+ <property name="height_request">34</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkMenuButton" id="menuButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkBox" id="replayBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="_repeat_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">media-playlist-consecutive-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="downArrow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">pan-down-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
</template>
<object class="GtkRadioMenuItem" id="radiomenuitem1">
<property name="visible">True</property>
diff --git a/data/ui/Window.ui b/data/ui/Window.ui
index 558960a5..72fcabb4 100644
--- a/data/ui/Window.ui
+++ b/data/ui/Window.ui
@@ -1,23 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <requires lib="libhandy" version="0.0"/>
<template class="Window" parent="GtkApplicationWindow">
- <property name="default-height">500</property>
- <property name="default-width">300</property>
+ <property name="can_focus">False</property>
+ <property name="default_width">300</property>
+ <property name="default_height">500</property>
+ <child>
+ <placeholder/>
+ </child>
<child>
<object class="GtkBox" id="_box">
- <property name="orientation">vertical</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<child>
<object class="GtkOverlay" id="_overlay">
- <property name="vexpand">True</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
<child type="overlay">
<object class="GtkStack" id="_stack">
- <property name="can-focus">False</property>
- <property name="homogeneous">False</property>
- <property name="transition-duration">100</property>
- <property name="transition-type">crossfade</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <property name="transition_duration">100</property>
+ <property name="transition_type">crossfade</property>
+ <child>
+ <placeholder/>
+ </child>
</object>
</child>
<child type="overlay">
@@ -26,11 +39,36 @@
<property name="transition-type">slide-down</property>
<property name="valign">start</property>
</object>
+ <packing>
+ <property name="index">1</property>
+ </packing>
</child>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="HdyViewSwitcherBar" id="_switcher_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="reveal">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
<child>
<object class="SelectionToolbar" id="_selection_toolbar"/>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
</child>
diff --git a/gnome-music.in b/gnome-music.in
index fe0de970..fda229fa 100755
--- a/gnome-music.in
+++ b/gnome-music.in
@@ -47,9 +47,12 @@ import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GIRepository', '2.0')
gi.require_version('Gst', '1.0')
-from gi.repository import GIRepository, Gio, Gtk, Gst
+gi.require_version('Handy', '0.0')
+from gi.repository import GIRepository, Gio, Gtk, Gst, Handy
Gst.init(None)
+Handy.init(None)
+
LOCALE_DIR = '@localedir@'
PKGDATA_DIR = '@pkgdatadir@'
diff --git a/gnomemusic/utils.py b/gnomemusic/utils.py
index 76310cb6..7cceaf15 100644
--- a/gnomemusic/utils.py
+++ b/gnomemusic/utils.py
@@ -44,6 +44,12 @@ class View(IntEnum):
SEARCH = 5
+class AdaptiveViewMode(IntEnum):
+ MOBILE = 0
+ TABLET = 1
+ DESKTOP = 2
+
+
def get_album_title(item):
"""Returns the album title associated with the media item
diff --git a/gnomemusic/views/albumsview.py b/gnomemusic/views/albumsview.py
index c0f70a91..d69a7334 100644
--- a/gnomemusic/views/albumsview.py
+++ b/gnomemusic/views/albumsview.py
@@ -25,6 +25,7 @@
from gettext import gettext as _
from gi.repository import GObject, Gtk
+from gnomemusic.utils import AdaptiveViewMode
from gnomemusic.widgets.headerbar import HeaderBar
from gnomemusic.widgets.albumcover import AlbumCover
from gnomemusic.widgets.albumwidget import AlbumWidget
@@ -39,6 +40,7 @@ class AlbumsView(Gtk.Stack):
__gtype_name__ = "AlbumsView"
+ adaptive_view = GObject.Property(type=int, default=AdaptiveViewMode.MOBILE)
search_mode_active = GObject.Property(type=bool, default=False)
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
selection_mode = GObject.Property(type=bool, default=False)
@@ -59,6 +61,7 @@ class AlbumsView(Gtk.Stack):
# FIXME: Make these properties.
self.name = "albums"
self.title = _("Albums")
+ self.icon = "media-optical-cd-audio-symbolic"
self._window = application.props.window
self._headerbar = self._window._headerbar
@@ -77,14 +80,25 @@ class AlbumsView(Gtk.Stack):
self._album_widget.bind_property(
"selection-mode", self, "selection-mode",
GObject.BindingFlags.BIDIRECTIONAL)
+ self._album_widget.bind_property(
+ "adaptive-view", self, "adaptive-view",
+ GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE)
self.add(self._album_widget)
+ self.connect("notify::adaptive-view", self._on_adaptive_view_changed)
self.connect(
"notify::search-mode-active", self._on_search_mode_changed)
-
self.show_all()
+ def _on_adaptive_view_changed(self, widget, param):
+ if self.props.adaptive_view == AdaptiveViewMode.MOBILE:
+ self._flowbox.set_max_children_per_line(2)
+ elif self.props.adaptive_view == AdaptiveViewMode.TABLET:
+ self._flowbox.set_max_children_per_line(4)
+ else:
+ self._flowbox.set_max_children_per_line(8)
+
def _on_selection_mode_changed(self, widget, data=None):
if not self.props.selection_mode:
self.unselect_all()
@@ -129,8 +143,8 @@ class AlbumsView(Gtk.Stack):
def _set_album_headerbar(self, corealbum):
self._headerbar.props.state = HeaderBar.State.CHILD
- self._headerbar.props.title = corealbum.props.title
- self._headerbar.props.subtitle = corealbum.props.artist
+ self._headerbar.set_title(corealbum.props.title)
+ self._headerbar.set_subtitle(corealbum.props.artist)
def _toggle_all_selection(self, selected):
"""
diff --git a/gnomemusic/views/artistsview.py b/gnomemusic/views/artistsview.py
index 76f928b6..86a37c26 100644
--- a/gnomemusic/views/artistsview.py
+++ b/gnomemusic/views/artistsview.py
@@ -24,10 +24,11 @@
import logging
from gettext import gettext as _
-from gi.repository import Gdk, Gtk
+from gi.repository import Gdk, Gtk, GObject
from gnomemusic import log
from gnomemusic.views.baseview import BaseView
+from gnomemusic.utils import AdaptiveViewMode
from gnomemusic.widgets.artistalbumswidget import ArtistAlbumsWidget
from gnomemusic.widgets.artisttile import ArtistTile
@@ -53,10 +54,11 @@ class ArtistsView(BaseView):
"""
self._sidebar = Gtk.ListBox()
sidebar_container = Gtk.ScrolledWindow()
+ sidebar_container.props.width_request = 285
sidebar_container.add(self._sidebar)
super().__init__(
- 'artists', _("Artists"), application, sidebar_container)
+ 'artists', _("Artists"), "system-users-symbolic", application, sidebar_container)
self._application = application
self._artists = {}
@@ -71,7 +73,6 @@ class ArtistsView(BaseView):
self._loaded_id = self._coremodel.connect(
"artists-loaded", self._on_artists_loaded)
- sidebar_container.props.width_request = 220
sidebar_container.get_style_context().add_class('sidebar')
self._sidebar.props.selection_mode = Gtk.SelectionMode.SINGLE
self._sidebar.connect('row-activated', self._on_artist_activated)
@@ -127,6 +128,7 @@ class ArtistsView(BaseView):
self._sidebar.select_row(first_row)
first_row.emit("activate")
+ self.view_sidebar()
@log
def _setup_view(self):
@@ -135,13 +137,16 @@ class ArtistsView(BaseView):
self._view = Gtk.Stack(
transition_type=Gtk.StackTransitionType.CROSSFADE,
- vhomogeneous=False)
+ homogeneous=False)
self._view_container.add(self._view)
@log
def _on_artist_activated(self, sidebar, row, data=None):
"""Initializes new artist album widgets"""
artist_tile = row.get_child()
+ if self.props.adaptive_view == AdaptiveViewMode.MOBILE:
+ self.view_content()
+
if self.props.selection_mode:
artist_tile.props.selected = not artist_tile.props.selected
return
@@ -156,6 +161,12 @@ class ArtistsView(BaseView):
self._artist_albums = ArtistAlbumsWidget(
coreartist, self._application, False)
+
+ self.bind_property(
+ 'adaptive-view', self._artist_albums, 'adaptive-view',
+ GObject.BindingFlags.DEFAULT
+ | GObject.BindingFlags.SYNC_CREATE)
+
artist_albums_frame = Gtk.Frame(
shadow_type=Gtk.ShadowType.NONE, hexpand=True)
artist_albums_frame.add(self._artist_albums)
diff --git a/gnomemusic/views/baseview.py b/gnomemusic/views/baseview.py
index 08b9d26f..6a179821 100644
--- a/gnomemusic/views/baseview.py
+++ b/gnomemusic/views/baseview.py
@@ -22,8 +22,11 @@
# code, but you are not obligated to do so. If you do not wish to do so,
# delete this exception statement from your version.
-from gi.repository import GObject, Gtk
+from gi.repository import GObject, Gtk, Handy
+from enum import IntEnum
+from gnomemusic.widgets.headerbar import HeaderBar
+from gnomemusic.utils import AdaptiveViewMode
from gnomemusic import log
@@ -32,37 +35,43 @@ class BaseView(Gtk.Stack):
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
selection_mode = GObject.Property(type=bool, default=False)
+ adaptive_view = GObject.Property(type=int, default=AdaptiveViewMode.MOBILE)
def __repr__(self):
return '<BaseView>'
@log
- def __init__(self, name, title, application, sidebar=None):
+ def __init__(self, name, title, icon, application, sidebar=None):
"""Initialize
:param name: The view name
:param title: The view title
:param GtkApplication application: The application object
:param sidebar: The sidebar object (Default: Gtk.Box)
"""
- super().__init__(transition_type=Gtk.StackTransitionType.CROSSFADE)
+ Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE, homogeneous=False)
+ self._leaflet = Handy.Leaflet()
+ self._leaflet.props.vexpand = True
self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL)
self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
# Setup the main view
self._setup_view()
+ self._sidebar_widget = sidebar
if sidebar:
- self._grid.add(sidebar)
+ self._leaflet.add(sidebar)
- self._grid.add(self._box)
+ self._leaflet.add(self._box)
self._window = application.props.window
self._headerbar = self._window._headerbar
self.name = name
self.title = title
+ self.icon = icon
+ self._grid.add(self._leaflet)
self.add(self._grid)
self.show_all()
@@ -73,6 +82,21 @@ class BaseView(Gtk.Stack):
'selection-mode', self._window, 'selection-mode',
GObject.BindingFlags.BIDIRECTIONAL)
+ def is_folded(self):
+ return self._leaflet.get_folded()
+
+ def view_content(self):
+ self._leaflet.set_visible_child(self._box)
+ self._headerbar.props.state = HeaderBar.State.CHILD
+
+ def view_sidebar(self):
+ if self._sidebar_widget:
+ self._leaflet.set_visible_child(self._sidebar_widget)
+ self._headerbar.props.state = HeaderBar.State.MAIN
+
+ def _back_button_clicked(self, view):
+ self.view_sidebar()
+
@log
def _setup_view(self):
"""Instantiate and set up the view object"""
diff --git a/gnomemusic/views/playlistsview.py b/gnomemusic/views/playlistsview.py
index b7ab67c9..ee9ffe3e 100644
--- a/gnomemusic/views/playlistsview.py
+++ b/gnomemusic/views/playlistsview.py
@@ -24,7 +24,7 @@
from gettext import gettext as _
-from gi.repository import Gdk, GObject, Gio, Gtk
+from gi.repository import Gdk, GObject, Gio, Gtk, Handy
from gnomemusic import log
from gnomemusic.player import PlayerPlaylist
@@ -35,7 +35,7 @@ from gnomemusic.widgets.playlistcontrols import PlaylistControls
from gnomemusic.widgets.playlistdialog import PlaylistDialog
from gnomemusic.widgets.playlisttile import PlaylistTile
from gnomemusic.widgets.songwidget import SongWidget
-
+from gnomemusic.utils import AdaptiveViewMode
class PlaylistsView(BaseView):
"""Main view for playlists"""
@@ -52,18 +52,19 @@ class PlaylistsView(BaseView):
"""
self._sidebar = Gtk.ListBox()
sidebar_container = Gtk.ScrolledWindow()
+ sidebar_container.props.width_request = 285
sidebar_container.add(self._sidebar)
+ self._pl_ctrls = PlaylistControls()
+
super().__init__(
- 'playlists', _("Playlists"), application, sidebar_container)
+ 'playlists', _("Playlists"), "view-list-symbolic", application, sidebar_container)
self._coremodel = application.props.coremodel
self._model = self._coremodel.props.playlists_sort
self._window = application.props.window
self._player = player
- self._pl_ctrls = PlaylistControls()
-
self._song_popover = PlaylistContextMenu(self._view)
play_song = Gio.SimpleAction.new('play_song', None)
@@ -97,17 +98,10 @@ class PlaylistsView(BaseView):
'activate', self._stage_playlist_for_renaming)
self._window.add_action(self._playlist_rename_action)
- self._grid.insert_row(0)
- self._grid.attach(self._pl_ctrls, 1, 0, 1, 1)
-
- sidebar_container.set_size_request(220, -1)
sidebar_container.get_style_context().add_class('sidebar')
self._sidebar.set_selection_mode(Gtk.SelectionMode.SINGLE)
self._sidebar.connect('row-activated', self._on_playlist_activated)
- self._grid.child_set_property(sidebar_container, 'top-attach', 0)
- self._grid.child_set_property(sidebar_container, 'height', 2)
-
self._sidebar.bind_model(self._model, self._add_playlist_to_sidebar)
self._loaded_id = self._coremodel.connect(
@@ -118,18 +112,26 @@ class PlaylistsView(BaseView):
# Selection is only possible from the context menu
self.disconnect(self._selection_mode_id)
+ self.connect(
+ "notify::adaptive-view", self._on_adaptive_view_changed)
self.show_all()
@log
def _setup_view(self):
- view_container = Gtk.ScrolledWindow(hexpand=True, vexpand=True)
- self._box.pack_start(view_container, True, True, 0)
+ main_container = Gtk.ScrolledWindow()
+ main_container.show()
+
+ self._view_container = Handy.Column()
+ self._view_container.set_maximum_width(800)
+ self._view_container.set_linear_growth_width(800)
+
+ container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+ container.show()
+
+ container.add(self._pl_ctrls)
self._view = Gtk.ListBox()
self._view.get_style_context().add_class("songs-list")
- self._view.props.margin_top = 20
- self._view.props.margin_left = 80
- self._view.props.margin_right = 80
self._view.props.valign = Gtk.Align.START
self._controller = Gtk.GestureMultiPress().new(self._view)
@@ -137,7 +139,10 @@ class PlaylistsView(BaseView):
self._controller.props.button = Gdk.BUTTON_SECONDARY
self._controller.connect("pressed", self._on_view_right_clicked)
- view_container.add(self._view)
+ container.add(self._view)
+ self._view_container.add(container)
+ main_container.add(self._view_container)
+ self._box.pack_start(main_container, True, True, 0)
@log
def _add_playlist_to_sidebar(self, playlist):
@@ -149,11 +154,22 @@ class PlaylistsView(BaseView):
row = PlaylistTile(playlist)
return row
+ def _on_adaptive_view_changed(self, widget, param):
+ if self.props.adaptive_view == AdaptiveViewMode.MOBILE:
+ self._view_container.set_margin_top(32)
+ self._view_container.set_margin_right(0)
+ self._view_container.set_margin_left(0)
+ else:
+ self._view_container.set_margin_top(32)
+ self._view_container.set_margin_right(32)
+ self._view_container.set_margin_left(32)
+
def _on_playlists_loaded(self, klass):
self._coremodel.disconnect(self._loaded_id)
first_row = self._sidebar.get_row_at_index(0)
self._sidebar.select_row(first_row)
first_row.emit("activate")
+ self.view_sidebar()
@log
def _on_view_right_clicked(self, gesture, n_press, x, y):
@@ -209,6 +225,8 @@ class PlaylistsView(BaseView):
def _on_playlist_activated(self, sidebar, row, data=None):
"""Update view with content from selected playlist"""
playlist = row.props.playlist
+ if self.props.adaptive_view == AdaptiveViewMode.MOBILE:
+ self.view_content()
if self.rename_active:
self._pl_ctrls.disable_rename_playlist()
diff --git a/gnomemusic/views/songsview.py b/gnomemusic/views/songsview.py
index c56c4dc2..3f5e7359 100644
--- a/gnomemusic/views/songsview.py
+++ b/gnomemusic/views/songsview.py
@@ -54,7 +54,7 @@ class SongsView(BaseView):
:param player: The main player object
"""
self._coremodel = application.props.coremodel
- super().__init__('songs', _("Songs"), application)
+ super().__init__('songs', _("Songs"), "emblem-music-symbolic", application)
self._iter_to_clean = None
diff --git a/gnomemusic/widgets/albumwidget.py b/gnomemusic/widgets/albumwidget.py
index 63856756..bb314de6 100644
--- a/gnomemusic/widgets/albumwidget.py
+++ b/gnomemusic/widgets/albumwidget.py
@@ -4,6 +4,7 @@ from gi.repository import GObject, Grl, Gtk
from gnomemusic import log
from gnomemusic.albumartcache import Art
from gnomemusic.player import PlayerPlaylist
+from gnomemusic.utils import AdaptiveViewMode
from gnomemusic.widgets.disclistboxwidget import DiscBox
from gnomemusic.widgets.disclistboxwidget import DiscListBox # noqa: F401
@@ -27,6 +28,10 @@ class AlbumWidget(Gtk.EventBox):
_running_info_label = Gtk.Template.Child()
_title_label = Gtk.Template.Child()
+ _album_widget = Gtk.Template.Child()
+ _album_info = Gtk.Template.Child()
+
+ adaptive_view = GObject.Property(type=int, default=AdaptiveViewMode.MOBILE)
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
selection_mode = GObject.Property(type=bool, default=False)
@@ -49,6 +54,7 @@ class AlbumWidget(Gtk.EventBox):
self._duration_signal_id = None
self._model_signal_id = None
+ self.connect("notify::adaptive-view", self._on_adaptive_view_changed)
self._cover_stack.props.size = Art.Size.LARGE
self._parent_view = parent_view
self._player = player
@@ -92,6 +98,18 @@ class AlbumWidget(Gtk.EventBox):
self._album_model.items_changed(0, 0, 0)
+ def _on_adaptive_view_changed(self, widget, param):
+ if self.props.adaptive_view == AdaptiveViewMode.MOBILE:
+ self._album_widget.set_orientation(Gtk.Orientation.VERTICAL)
+ self._album_widget.set_margin_top(32)
+ self._album_widget.set_margin_right(0)
+ self._album_widget.set_margin_left(0)
+ else:
+ self._album_widget.set_orientation(Gtk.Orientation.HORIZONTAL)
+ self._album_widget.set_margin_top(32)
+ self._album_widget.set_margin_right(32)
+ self._album_widget.set_margin_left(32)
+
def _create_widget(self, disc):
disc_box = self._create_disc_box(
disc.props.disc_nr, disc.model)
diff --git a/gnomemusic/widgets/artistalbumswidget.py b/gnomemusic/widgets/artistalbumswidget.py
index 114ff46b..4a8a6918 100644
--- a/gnomemusic/widgets/artistalbumswidget.py
+++ b/gnomemusic/widgets/artistalbumswidget.py
@@ -28,6 +28,7 @@ from gi.repository import GObject, Gtk
from gnomemusic import log
from gnomemusic.player import PlayerPlaylist
+from gnomemusic.utils import AdaptiveViewMode
from gnomemusic.widgets.artistalbumwidget import ArtistAlbumWidget
logger = logging.getLogger(__name__)
@@ -43,6 +44,7 @@ class ArtistAlbumsWidget(Gtk.ListBox):
__gtype_name__ = 'ArtistAlbumsWidget'
+ adaptive_view = GObject.Property(type=int, default=AdaptiveViewMode.MOBILE)
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
selection_mode = GObject.Property(type=bool, default=False)
@@ -100,6 +102,11 @@ class ArtistAlbumsWidget(Gtk.ListBox):
GObject.BindingFlags.BIDIRECTIONAL
| GObject.BindingFlags.SYNC_CREATE)
+ self.bind_property(
+ 'adaptive-view', widget, 'adaptive-view',
+ GObject.BindingFlags.BIDIRECTIONAL
+ | GObject.BindingFlags.SYNC_CREATE)
+
row.add(widget)
self._widgets.append(widget)
widget.connect("song-activated", self._song_activated)
diff --git a/gnomemusic/widgets/artistalbumwidget.py b/gnomemusic/widgets/artistalbumwidget.py
index 9d90fb2c..e89510fa 100644
--- a/gnomemusic/widgets/artistalbumwidget.py
+++ b/gnomemusic/widgets/artistalbumwidget.py
@@ -22,16 +22,17 @@
# code, but you are not obligated to do so. If you do not wish to do so,
# delete this exception statement from your version.
-from gi.repository import GObject, Gtk
+from gi.repository import GObject, Gtk, Handy
from gnomemusic import log
from gnomemusic.albumartcache import Art
from gnomemusic.widgets.disclistboxwidget import DiscBox
+from gnomemusic.utils import AdaptiveViewMode
from gnomemusic.widgets.songwidget import SongWidget
@Gtk.Template(resource_path='/org/gnome/Music/ui/ArtistAlbumWidget.ui')
-class ArtistAlbumWidget(Gtk.Box):
+class ArtistAlbumWidget(Handy.Column):
__gtype_name__ = 'ArtistAlbumWidget'
@@ -40,6 +41,7 @@ class ArtistAlbumWidget(Gtk.Box):
_disc_list_box = Gtk.Template.Child()
_title_year = Gtk.Template.Child()
+ adaptive_view = GObject.Property(type=int, default=AdaptiveViewMode.MOBILE)
selection_mode = GObject.Property(type=bool, default=False)
__gsignals__ = {
@@ -54,7 +56,7 @@ class ArtistAlbumWidget(Gtk.Box):
def __init__(
self, corealbum, selection_mode_allowed, size_group=None,
cover_size_group=None):
- super().__init__(orientation=Gtk.Orientation.HORIZONTAL)
+ super().__init__()
self._size_group = size_group
self._cover_size_group = cover_size_group
@@ -90,6 +92,18 @@ class ArtistAlbumWidget(Gtk.Box):
corealbum.props.model, self._create_widget)
corealbum.props.model.items_changed(0, 0, 0)
+ self.connect("notify::adaptive-view", self._on_adaptive_view_changed)
+
+ def _on_adaptive_view_changed(self, widget, param):
+
+ if self.props.adaptive_view == AdaptiveViewMode.MOBILE:
+ self._cover_stack.set_halign(Gtk.Align.CENTER)
+ self.set_margin_right(0)
+ self.set_margin_left(0)
+ else:
+ self._cover_stack.set_halign(Gtk.Align.START)
+ self.set_margin_right(32)
+ self.set_margin_left(32)
def _create_widget(self, disc):
disc_box = self._create_disc_box(disc.props.disc_nr, disc.model)
diff --git a/gnomemusic/widgets/headerbar.py b/gnomemusic/widgets/headerbar.py
index e01d81e1..50a40888 100644
--- a/gnomemusic/widgets/headerbar.py
+++ b/gnomemusic/widgets/headerbar.py
@@ -86,6 +86,16 @@ class HeaderBar(Gtk.HeaderBar):
SEARCH = 2
EMPTY = 3
+ class View(IntEnum):
+ """The three different views of the HeaderBar
+
+ They are switched between using HdySqueezer and
+ on the current visible window width
+ """
+ TITLE = 0
+ NARROW = 1
+ WIDE = 2
+
__gtype_name__ = "HeaderBar"
__gsignals__ = {
@@ -98,6 +108,14 @@ class HeaderBar(Gtk.HeaderBar):
_back_button = Gtk.Template.Child()
_menu_button = Gtk.Template.Child()
+ _squeezer = Gtk.Template.Child()
+ _title_text = Gtk.Template.Child()
+ _title_wide_switcher = Gtk.Template.Child()
+ _title_narrow_switcher = Gtk.Template.Child()
+
+ _title_label = Gtk.Template.Child()
+ _subtitle_label = Gtk.Template.Child()
+
search_mode_active = GObject.Property(type=bool, default=False)
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
selection_mode_allowed = GObject.Property(type=bool, default=True)
@@ -112,10 +130,6 @@ class HeaderBar(Gtk.HeaderBar):
self._selection_mode = False
- self._stack_switcher = Gtk.StackSwitcher(
- can_focus=False, halign="center")
- self._stack_switcher.show()
-
self._selection_menu = SelectionBarMenuButton()
self._menu_button.set_popover(AppMenu())
@@ -133,7 +147,11 @@ class HeaderBar(Gtk.HeaderBar):
"selection-mode", self._select_button, "active",
GObject.BindingFlags.BIDIRECTIONAL)
self.bind_property(
- "stack", self._stack_switcher, "stack",
+ "stack", self._title_wide_switcher, "stack",
+ GObject.BindingFlags.BIDIRECTIONAL
+ | GObject.BindingFlags.SYNC_CREATE)
+ self.bind_property(
+ "stack", self._title_narrow_switcher, "stack",
GObject.BindingFlags.BIDIRECTIONAL
| GObject.BindingFlags.SYNC_CREATE)
self.bind_property(
@@ -148,6 +166,12 @@ class HeaderBar(Gtk.HeaderBar):
"notify::selection-mode-allowed",
self._on_selection_mode_allowed_changed)
+ def set_title(self, title):
+ self._title_label.set_text(title)
+
+ def set_subtitle(self, subtitle):
+ self._subtitle_label.set_text(subtitle)
+
@GObject.Property(type=bool, default=False)
def selection_mode(self):
"""Selection mode
@@ -173,6 +197,28 @@ class HeaderBar(Gtk.HeaderBar):
self._update()
+ @GObject.Property
+ def view(self):
+ return self._view
+
+ @view.setter
+ def view(self, value):
+ """Set view of the of widget
+
+ This influences the look and functionality of the headerbar.
+
+ :param HeaderBar.View value: Widget view
+ """
+ self._view = value
+ if value == HeaderBar.View.WIDE:
+ self._squeezer.set_child_enabled(self._title_wide_switcher,
+ True)
+ elif value == HeaderBar.View.NARROW:
+ self._squeezer.set_child_enabled(self._title_narrow_switcher,
+ True)
+ else:
+ self._squeezer.set_child_enabled(self._title_text, True)
+
@GObject.Property
def state(self):
"""State of the widget
@@ -199,11 +245,11 @@ class HeaderBar(Gtk.HeaderBar):
if value == HeaderBar.State.EMPTY:
self._search_button.props.sensitive = False
self._select_button.props.sensitive = False
- self._stack_switcher.hide()
+ self._squeezer.hide()
else:
self._search_button.props.sensitive = True
self._select_button.props.sensitive = True
- self._stack_switcher.show()
+ self._squeezer.show()
@Gtk.Template.Callback()
@log
@@ -219,10 +265,10 @@ class HeaderBar(Gtk.HeaderBar):
def _update(self):
if self.props.selection_mode:
self.props.custom_title = self._selection_menu
- elif self.props.state != HeaderBar.State.MAIN:
+ elif self.props.state == HeaderBar.State.EMPTY:
self.props.custom_title = None
else:
- self.props.custom_title = self._stack_switcher
+ self.props.custom_title = self._squeezer
self._back_button.props.visible = (
not self.props.selection_mode
diff --git a/gnomemusic/widgets/playertoolbar.py b/gnomemusic/widgets/playertoolbar.py
index d094597f..5f3a9380 100644
--- a/gnomemusic/widgets/playertoolbar.py
+++ b/gnomemusic/widgets/playertoolbar.py
@@ -32,6 +32,7 @@ from gnomemusic.player import Player, RepeatMode
from gnomemusic.widgets.coverstack import CoverStack # noqa: F401
from gnomemusic.widgets.smoothscale import SmoothScale # noqa: F401
from gnomemusic.widgets.twolinetip import TwoLineTip
+from gnomemusic.utils import AdaptiveViewMode
import gnomemusic.utils as utils
@@ -41,9 +42,10 @@ class PlayerToolbar(Gtk.ActionBar):
Contains the ui of playing a song with Music.
"""
-
__gtype_name__ = 'PlayerToolbar'
+ adaptive_view = GObject.Property(type=int, default=AdaptiveViewMode.MOBILE)
+
_artist_label = Gtk.Template.Child()
_cover_stack = Gtk.Template.Child()
_duration_label = Gtk.Template.Child()
@@ -57,6 +59,10 @@ class PlayerToolbar(Gtk.ActionBar):
_repeat_image = Gtk.Template.Child()
_song_info_box = Gtk.Template.Child()
_title_label = Gtk.Template.Child()
+ _repeat_box = Gtk.Template.Child()
+ nowplaying_labels = Gtk.Template.Child()
+ timer = Gtk.Template.Child()
+ buttons = Gtk.Template.Child()
_repeat_dict = {
RepeatMode.ALL: "media-playlist-repeat-symbolic",
@@ -75,6 +81,7 @@ class PlayerToolbar(Gtk.ActionBar):
self._player = None
self._cover_stack.props.size = Art.Size.XSMALL
+ self.connect("notify::adaptive-view", self._on_adaptive_view_changed)
self._tooltip = TwoLineTip()
@@ -110,6 +117,25 @@ class PlayerToolbar(Gtk.ActionBar):
self._sync_repeat_image()
+ def _on_adaptive_view_changed(self, widget, param):
+
+ if self.props.adaptive_view != AdaptiveViewMode.DESKTOP:
+ self._progress_scale.hide()
+ self._repeat_box.hide()
+ self._prev_button.hide()
+ self._next_button.hide()
+ self.timer.hide()
+ self._cover_stack.props.size = Art.Size.XSMALL
+ self.child_set_property(self.buttons, "pack-type", Gtk.PackType.END)
+ else:
+ self._progress_scale.show()
+ self._repeat_box.show()
+ self._prev_button.show()
+ self._next_button.show()
+ self.timer.show()
+ self._cover_stack.props.size = Art.Size.SMALL
+ self.child_set_property(self.buttons, "pack-type", Gtk.PackType.START)
+
@Gtk.Template.Callback()
@log
def _on_progress_value_changed(self, progress_scale):
@@ -125,6 +151,10 @@ class PlayerToolbar(Gtk.ActionBar):
@log
def _on_play_button_clicked(self, button):
self._player.play_pause()
+ if self._player.props.state != Playback.PLAYING:
+ self.hide()
+ else:
+ self.show()
@Gtk.Template.Callback()
@log
diff --git a/gnomemusic/widgets/searchheaderbar.py b/gnomemusic/widgets/searchheaderbar.py
index 0e56443a..27f5abf0 100644
--- a/gnomemusic/widgets/searchheaderbar.py
+++ b/gnomemusic/widgets/searchheaderbar.py
@@ -70,7 +70,7 @@ class SearchHeaderBar(Gtk.HeaderBar):
self._entry = Gd.TaggedEntry()
self._entry.props.halign = Gtk.Align.CENTER
self._entry.props.visible = True
- self._entry.props.width_request = 500
+ # self._entry.props.width_request = 500
self._selection_menu = SelectionBarMenuButton()
diff --git a/gnomemusic/window.py b/gnomemusic/window.py
index d805e992..1580ce58 100644
--- a/gnomemusic/window.py
+++ b/gnomemusic/window.py
@@ -31,7 +31,7 @@ from gnomemusic.mediakeys import MediaKeys
from gnomemusic.player import RepeatMode
from gnomemusic.search import Search
from gnomemusic.trackerwrapper import TrackerState
-from gnomemusic.utils import View
+from gnomemusic.utils import View, AdaptiveViewMode
from gnomemusic.views.albumsview import AlbumsView
from gnomemusic.views.artistsview import ArtistsView
from gnomemusic.views.emptyview import EmptyView
@@ -55,6 +55,7 @@ class Window(Gtk.ApplicationWindow):
__gtype_name__ = "Window"
+ adaptive_view = GObject.Property(type=GObject.TYPE_INT, default=AdaptiveViewMode.MOBILE)
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
selection_mode = GObject.Property(type=bool, default=False)
@@ -64,6 +65,8 @@ class Window(Gtk.ApplicationWindow):
_selection_toolbar = Gtk.Template.Child()
_stack = Gtk.Template.Child()
+ _switcher_bar = Gtk.Template.Child()
+
def __repr__(self):
return '<Window>'
@@ -132,6 +135,8 @@ class Window(Gtk.ApplicationWindow):
"notify::search-mode-active", self._on_search_mode_changed)
self._player_toolbar = PlayerToolbar()
+ self._player_toolbar.bind_property("adaptive-view", self, "adaptive-view",
+ GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.SYNC_CREATE)
self._player_toolbar.props.player = self._player
self._headerbar.connect(
@@ -153,6 +158,7 @@ class Window(Gtk.ApplicationWindow):
"selection-mode", self._search_headerbar, "selection-mode",
GObject.BindingFlags.BIDIRECTIONAL
| GObject.BindingFlags.SYNC_CREATE)
+
self.bind_property(
"selection-mode", self._player_toolbar, "visible",
GObject.BindingFlags.INVERT_BOOLEAN)
@@ -172,7 +178,8 @@ class Window(Gtk.ApplicationWindow):
# bottom line of the searchbar
self._stack.get_style_context().add_class('background')
- self._box.pack_end(self._player_toolbar, False, False, 0)
+ self._box.pack_start(self._player_toolbar, False, False, 0)
+ self._box.reorder_child(self._player_toolbar, 1)
self.set_titlebar(self._headerbar_stack)
@@ -280,6 +287,10 @@ class Window(Gtk.ApplicationWindow):
for i in self.views[View.ALBUM:]:
if i.title:
self._stack.add_titled(i, i.name, i.title)
+ self._stack.child_set_property(i, "icon-name", i.icon)
+ i.bind_property("adaptive-view", self, "adaptive-view",
+ GObject.BindingFlags.BIDIRECTIONAL
+ | GObject.BindingFlags.SYNC_CREATE)
else:
self._stack.add_named(i, i.name)
@@ -295,6 +306,10 @@ class Window(Gtk.ApplicationWindow):
"search-mode-active", self.views[View.ALBUM],
"search-mode-active", GObject.BindingFlags.SYNC_CREATE)
+ # Adaptive View
+ self._switcher_bar.set_stack(self._stack)
+ self.connect("size-allocate", self._on_size_allocate)
+
@log
def _select_all(self, action=None, param=None):
if not self.props.selection_mode:
@@ -487,8 +502,17 @@ class Window(Gtk.ApplicationWindow):
views_with_child = [
self.views[View.ALBUM],
- self.views[View.SEARCH]
+ self.views[View.SEARCH],
]
+
+ is_folded_childs = [
+ self.views[View.ARTIST],
+ self.views[View.PLAYLIST],
+ ]
+ for child in is_folded_childs:
+ if child.is_folded:
+ views_with_child.append(child)
+
if self.curr_view in views_with_child:
self.curr_view._back_button_clicked(self.curr_view)
@@ -496,7 +520,25 @@ class Window(Gtk.ApplicationWindow):
def _on_selection_mode_changed(self, widget, data=None):
if (not self.props.selection_mode
and self._player.state == Playback.STOPPED):
- self._player_toolbar.hide()
+ self._player_toolbar.set_visible_child(False)
+
+ @log
+ def _on_size_allocate(self, widget, allocation):
+ album_view = self.views[View.ALBUM]
+ artists_view = self.views[View.ARTIST]
+
+ if allocation.width < 650:
+ self.props.adaptive_view = AdaptiveViewMode.MOBILE
+ self._headerbar.view = HeaderBar.View.TITLE
+ self._switcher_bar.set_reveal(True)
+ elif allocation.width <= 900:
+ self.props.adaptive_view = AdaptiveViewMode.TABLET
+ self._headerbar.view = HeaderBar.View.NARROW
+ self._switcher_bar.set_reveal(False)
+ else:
+ self._headerbar.view = HeaderBar.View.WIDE
+ self.props.adaptive_view = AdaptiveViewMode.DESKTOP
+ self._switcher_bar.set_reveal(False)
@log
def _on_add_to_playlist(self, widget):
@@ -516,10 +558,3 @@ class Window(Gtk.ApplicationWindow):
self.props.selection_mode = False
playlist_dialog.destroy()
- @log
- def set_player_visible(self, visible):
- """Set PlayWidget action visibility
-
- :param bool visible: actionbar visibility
- """
- self._player_toolbar.set_visible(visible)
diff --git a/meson.build b/meson.build
index b0261a5e..6229156b 100644
--- a/meson.build
+++ b/meson.build
@@ -47,6 +47,8 @@ dependency('pygobject-3.0', version: '>= 3.29.1')
dependency('py3cairo', version: '>= 1.14.0')
dependency('grilo-0.3', version: '>= 0.3.9')
dependency('grilo-plugins-0.3', version: '>= 0.3.9')
+dependency('libhandy-0.0', version: '>= 0.0.10')
+
subproject('libgd',
default_options: [
diff --git a/org.gnome.Music.json b/org.gnome.Music.json
index ebfdf477..416b30ca 100644
--- a/org.gnome.Music.json
+++ b/org.gnome.Music.json
@@ -135,6 +135,20 @@
],
"cleanup": [ "/include" ]
},
+ {
+ "name": "libhandy",
+ "buildsystem": "meson",
+ "config-opts": [
+ "-Dvapi=false",
+ "-Dtests=false",
+ "-Dexamples=false",
+ "-Dglade_catalog=disabled"
+ ],
+ "sources": [{
+ "type": "git",
+ "url": "https://source.puri.sm/Librem5/libhandy.git"
+ }]
+ },
{
"name": "gnome-music",
"config-opts" : [
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]