[gnome-music/wip/jfelder/tag-test: 1/22] tageditordialog: Initial songs support
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/jfelder/tag-test: 1/22] tageditordialog: Initial songs support
- Date: Mon, 29 Jul 2019 16:16:22 +0000 (UTC)
commit ce6f854dc772d4742b9e1bdb4aa673cbd782643d
Author: Sumaid Syed <sumaidsyed gmail com>
Date: Wed Jul 17 15:47:19 2019 +0530
tageditordialog: Initial songs support
Based on the patches by Jean Felder
https://gitlab.gnome.org/GNOME/gnome-music/issues/293
data/org.gnome.Music.gresource.xml | 1 +
data/ui/SelectionToolbar.ui | 14 +
data/ui/TagEditorDialog.ui | 829 +++++++++++++++++++++++++++++++++
gnomemusic/widgets/selectiontoolbar.py | 43 +-
gnomemusic/widgets/tageditordialog.py | 191 ++++++++
gnomemusic/window.py | 22 +
po/POTFILES.in | 2 +
7 files changed, 1097 insertions(+), 5 deletions(-)
---
diff --git a/data/org.gnome.Music.gresource.xml b/data/org.gnome.Music.gresource.xml
index 3992ffa4..a4fc04cc 100644
--- a/data/org.gnome.Music.gresource.xml
+++ b/data/org.gnome.Music.gresource.xml
@@ -25,6 +25,7 @@
<file preprocess="xml-stripblanks">ui/SelectionToolbar.ui</file>
<file preprocess="xml-stripblanks">ui/SidebarRow.ui</file>
<file preprocess="xml-stripblanks">ui/SongWidget.ui</file>
+ <file preprocess="xml-stripblanks">ui/TagEditorDialog.ui</file>
<file preprocess="xml-stripblanks">ui/TwoLineTip.ui</file>
<file preprocess="xml-stripblanks">ui/Window.ui</file>
</gresource>
diff --git a/data/ui/SelectionToolbar.ui b/data/ui/SelectionToolbar.ui
index ec64876c..06ea30e6 100644
--- a/data/ui/SelectionToolbar.ui
+++ b/data/ui/SelectionToolbar.ui
@@ -9,6 +9,7 @@
<property name="label" translatable="yes">_Add to Playlist</property>
<property name="use_underline">True</property>
<property name="visible">True</property>
+ <property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="_on_add_to_playlist_button_clicked" swapped="no"/>
@@ -17,5 +18,18 @@
</style>
</object>
</child>
+ <child>
+ <object class="GtkButton" id="_edit_details_button">
+ <property name="label" translatable="yes">Edit Details</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="_on_edit_tags_button_clicked" swapped="no"/>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
</template>
</interface>
diff --git a/data/ui/TagEditorDialog.ui b/data/ui/TagEditorDialog.ui
new file mode 100644
index 00000000..ee8789c4
--- /dev/null
+++ b/data/ui/TagEditorDialog.ui
@@ -0,0 +1,829 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.16"/>
+ <template class="TagEditorDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog_vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkOverlay" id="overlay">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="media_details">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">12</property>
+ <property name="margin_right">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">18</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkButton" id="_coverart_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="relief">none</property>
+ <signal name="clicked" handler="_choose_cover" swapped="no"/>
+ <child>
+ <object class="CoverStack" id="_cover_stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ </object>
+ </child>
+ <style>
+ <class name="album-cover"/>
+ </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="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="width_request">260</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_right">36</property>
+ <property name="label" translatable="yes">Title</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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="_title_suggestion">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_right">2</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">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="GtkEntry" id="_title_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="album">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_right">36</property>
+ <property name="label" translatable="yes">Album</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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="_album_suggestion">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_right">2</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">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="GtkEntry" id="_album_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </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="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="artist">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_right">36</property>
+ <property name="label" translatable="yes">Artist</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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_suggestion">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_right">2</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">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="GtkEntry" id="_artist_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </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">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="track">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Song</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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="_track_suggestion">
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_right">2</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">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="GtkEntry" id="_track_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">8</property>
+ <property name="max_width_chars">2</property>
+ <property name="input_purpose">number</property>
+ </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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="disc">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Disc</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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="_disc_suggestion">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_right">2</property>
+ <style>
+ <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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="_disc_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">2</property>
+ <property name="width_chars">8</property>
+ <property name="max_width_chars">2</property>
+ <property name="input_purpose">number</property>
+ </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">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="year">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Year</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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="_year_suggestion">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_right">2</property>
+ <style>
+ <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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="_year_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">4</property>
+ <property name="width_chars">10</property>
+ <property name="max_width_chars">4</property>
+ <property name="input_purpose">number</property>
+ </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">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</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="index">-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="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="margin_right">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">end</property>
+ <property name="spacing">6</property>
+ <property name="baseline_position">bottom</property>
+ <child>
+ <object class="GtkSpinner" id="_spinner">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="active">True</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="_spinner_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Fetching metadata...</property>
+ <style>
+ <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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-next-symbolic-rtl</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="_prev_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="sensitive">False</property>
+ <property name="tooltip_text" translatable="yes">Previous Suggestion</property>
+ <signal name="clicked" handler="_on_prev_button_clicked" swapped="no"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="_prev_button_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">go-previous</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="_next_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="sensitive">False</property>
+ <property name="tooltip_text" translatable="yes">Next Suggestion</property>
+ <signal name="clicked" handler="_on_next_button_clicked" swapped="no"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="_next_button_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">go-next</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="_use_suggestion_button">
+ <property name="label" translatable="yes">Use Suggestion</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="_on_use_suggestion_clicked" swapped="no"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="_submit_button">
+ <property name="label" translatable="yes">Submit</property>
+ <property name="visible">True</property>
+ <property name="sensitive">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="_on_submit_clicked" swapped="no"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="location">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_right">36</property>
+ <property name="label" translatable="yes">Location</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-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="_url">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_right">2</property>
+ <property name="max_width_chars">45</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </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">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkHeaderBar" id="_title_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Edit Details</property>
+ <property name="show_close_button">True</property>
+ </object>
+</interface>
diff --git a/gnomemusic/widgets/selectiontoolbar.py b/gnomemusic/widgets/selectiontoolbar.py
index 1d2b775a..c8dd7d28 100644
--- a/gnomemusic/widgets/selectiontoolbar.py
+++ b/gnomemusic/widgets/selectiontoolbar.py
@@ -33,9 +33,11 @@ class SelectionToolbar(Gtk.ActionBar):
__gtype_name__ = 'SelectionToolbar'
_add_to_playlist_button = Gtk.Template.Child()
+ _edit_details_button = Gtk.Template.Child()
__gsignals__ = {
- 'add-to-playlist': (GObject.SignalFlags.RUN_FIRST, None, ())
+ 'add-to-playlist': (GObject.SignalFlags.RUN_FIRST, None, ()),
+ 'edit-details': (GObject.SignalFlags.RUN_FIRST, None, ())
}
selected_items_count = GObject.Property(type=int, default=0, minimum=0)
@@ -47,6 +49,8 @@ class SelectionToolbar(Gtk.ActionBar):
def __init__(self):
super().__init__()
+ self._stack = None
+
self.connect(
'notify::selected-items-count', self._on_item_selection_changed)
@@ -55,9 +59,38 @@ class SelectionToolbar(Gtk.ActionBar):
def _on_add_to_playlist_button_clicked(self, widget):
self.emit('add-to-playlist')
+ @Gtk.Template.Callback()
+ @log
+ def _on_edit_tags_button_clicked(self, widget):
+ self.emit('edit-details')
+
@log
def _on_item_selection_changed(self, widget, data):
- if self.props.selected_items_count > 0:
- self._add_to_playlist_button.props.sensitive = True
- else:
- self._add_to_playlist_button.props.sensitive = False
+ songs_view_visible = (self._stack.props.visible_child_name == 'songs')
+ selection_size = self.props.selected_items_count
+
+ self._add_to_playlist_button.props.sensitive = (selection_size > 0)
+ self._edit_details_button.props.sensitive = (selection_size == 1)
+
+ # FIXME: This is a workaround for not being able to pass the player
+ # object via init when using Gtk.Builder.
+ @GObject.Property(type=Gtk.Stack, default=None)
+ def stack(self):
+ """The main GtkStack of the app
+
+ :return: main stack object
+ :rtype: GtkStack
+ """
+ return self._stack
+
+ @stack.setter
+ def stack(self, stack):
+ """Set the GtkStack object used
+
+ :param GtkStack stack: The GtkStack to use
+ """
+ if (stack is None
+ or (self._stack is not None
+ and self._stack != stack)):
+ return
+ self._stack = stack
diff --git a/gnomemusic/widgets/tageditordialog.py b/gnomemusic/widgets/tageditordialog.py
new file mode 100644
index 00000000..9f7c1b3d
--- /dev/null
+++ b/gnomemusic/widgets/tageditordialog.py
@@ -0,0 +1,191 @@
+# Copyright 2018 The GNOME Music Developers
+#
+# GNOME Music is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+import logging
+from gettext import gettext as _
+
+from gi.repository import Grl, Gtk
+
+from gnomemusic import log
+from gnomemusic.albumartcache import Art
+from gnomemusic.grilo import grilo
+import gnomemusic.utils as utils
+
+logger = logging.getLogger(__name__)
+
+
+@Gtk.Template(resource_path="/org/gnome/Music/ui/TagEditorDialog.ui")
+class TagEditorDialog(Gtk.Dialog):
+ """Tag editor widget
+ A tag editor dialog box that allows storing metadata for music files
+ through editing entries manually or applying automatic fetched tags.
+ """
+
+ __gtype_name__ = 'TagEditorDialog'
+
+ _cover_stack = Gtk.Template.Child()
+ _spinner = Gtk.Template.Child()
+ _spinner_label = Gtk.Template.Child()
+ _title_bar = Gtk.Template.Child()
+
+ # tags entries and labels
+ _album_entry = Gtk.Template.Child()
+ _album_suggestion = Gtk.Template.Child()
+ _artist_entry = Gtk.Template.Child()
+ _artist_suggestion = Gtk.Template.Child()
+ _disc_entry = Gtk.Template.Child()
+ _disc_suggestion = Gtk.Template.Child()
+ _title_entry = Gtk.Template.Child()
+ _title_suggestion = Gtk.Template.Child()
+ _track_entry = Gtk.Template.Child()
+ _track_suggestion = Gtk.Template.Child()
+ _year_entry = Gtk.Template.Child()
+ _year_suggestion = Gtk.Template.Child()
+
+ _prev_button = Gtk.Template.Child()
+ _next_button = Gtk.Template.Child()
+ _use_suggestion_button = Gtk.Template.Child()
+
+ _url = Gtk.Template.Child()
+
+ def __repr__(self):
+ return '<TagEditorDialog>'
+
+ @log
+ def __init__(self, parent, selected_song):
+ """Initialize the tag editor
+ :param parent: The parent widget calling the editor dialog box
+ :param selected_song: The current selected track which is being edited
+ """
+ super().__init__()
+
+ self.props.transient_for = parent
+ self.set_titlebar(self._title_bar)
+
+ self._cover_stack.props.size = Art.Size.MEDIUM
+ self._cover_stack.update(selected_song)
+
+ self._initial_song = selected_song
+ self._init_labels()
+ self._search_tags()
+ self._suggestions = []
+ self._pointer = 0
+
+ @log
+ def _init_labels(self):
+ for field in utils.fields_getter:
+ entry = getattr(self, '_' + field + '_entry')
+ value = utils.fields_getter[field](self._initial_song)
+ if value:
+ entry.props.text = value
+
+ self._url.props.label = self._initial_song.get_url()
+ self._url.props.visible = True
+
+ @log
+ def _start_spinner(self, text):
+ self._spinner.start()
+ self._spinner_label.props.label = text
+
+ @log
+ def _stop_spinner(self):
+ self._spinner.stop()
+ self._spinner_label.props.label = ""
+
+ @log
+ def _search_tags(self):
+ self._start_spinner(_("Fetching metadata…"))
+ new_media = Grl.Media.audio_new()
+ new_media.set_url(self._initial_song.get_url())
+ grilo.get_tags_from_musicbrainz(new_media, self._tags_found)
+
+ @log
+ def _tags_found(self, media, count):
+ if media is None:
+ logger.warning("Unable to find tags for song {}".format(
+ self._initial_song.get_url()))
+ self._stop_spinner()
+ return
+
+ self._use_suggestion_button.props.sensitive = True
+ self._suggestions.append(media)
+
+ if count == 0:
+ self._give_suggestion()
+ self._stop_spinner()
+
+ @log
+ def _give_suggestion(self):
+ media = self._suggestions[self._pointer]
+ for field in utils.fields_getter:
+ suggestion = getattr(self, '_' + field + '_suggestion')
+ value = utils.fields_getter[field](media)
+ if value:
+ suggestion.props.label = value
+ suggestion.props.visible = True
+
+ if self._pointer < len(self._suggestions) - 1:
+ self._next_button.props.sensitive = True
+ else:
+ self._next_button.props.sensitive = False
+
+ if self._pointer > 0:
+ self._prev_button.props.sensitive = True
+ else:
+ self._prev_button.props.sensitive = False
+
+ @Gtk.Template.Callback()
+ @log
+ def _on_next_button_clicked(self, widget):
+ self._pointer += 1
+ self._give_suggestion()
+
+ @Gtk.Template.Callback()
+ @log
+ def _on_prev_button_clicked(self, widget):
+ self._pointer -= 1
+ self._give_suggestion()
+
+ @Gtk.Template.Callback()
+ @log
+ def _on_use_suggestion_clicked(self, widget):
+ media = self._suggestions[self._pointer]
+
+ for field in utils.fields_getter:
+ entry = getattr(self, '_' + field + '_entry')
+ value = utils.fields_getter[field](media)
+ if value:
+ entry.props.text = value
+
+ @Gtk.Template.Callback()
+ @log
+ def _on_submit_clicked(self, widget):
+
+ for field in utils.fields_setter:
+ entry = getattr(self, '_' + field + '_entry')
+ entry_text = entry.props.text
+ if entry_text:
+ utils.fields_setter[field](self._initial_song, entry_text)
+
+ self.destroy()
diff --git a/gnomemusic/window.py b/gnomemusic/window.py
index 7b7141dc..3b1c2d91 100644
--- a/gnomemusic/window.py
+++ b/gnomemusic/window.py
@@ -46,6 +46,7 @@ from gnomemusic.widgets.playertoolbar import PlayerToolbar
from gnomemusic.widgets.playlistdialog import PlaylistDialog
from gnomemusic.widgets.searchbar import SearchBar
from gnomemusic.widgets.selectiontoolbar import SelectionToolbar # noqa: F401
+from gnomemusic.widgets.tageditordialog import TagEditorDialog
from gnomemusic.windowplacement import WindowPlacement
import logging
@@ -145,6 +146,8 @@ class Window(Gtk.ApplicationWindow):
self._player_toolbar = PlayerToolbar()
self._player_toolbar.props.player = self._player
+ self._selection_toolbar.props.stack = self._stack
+
self._headerbar.connect(
'back-button-clicked', self._switch_back_from_childview)
@@ -187,6 +190,7 @@ class Window(Gtk.ApplicationWindow):
self._selection_toolbar.connect(
'add-to-playlist', self._on_add_to_playlist)
+ self._selection_toolbar.connect('edit-details', self._on_edit_tags)
self._search.connect("notify::state", self._on_search_state_changed)
self._headerbar.props.state = HeaderBar.State.MAIN
@@ -507,3 +511,21 @@ class Window(Gtk.ApplicationWindow):
:param bool visible: actionbar visibility
"""
self._player_toolbar.set_visible(visible)
+
+ @log
+ def _on_edit_tags(self, widget):
+ if self._stack.get_visible_child() == self.views[View.PLAYLIST]:
+ return
+
+ def callback(selected_songs):
+ if len(selected_songs) < 1:
+ return
+
+ tags_editor_dialog = TagEditorDialog(self, selected_songs[0])
+ if tags_editor_dialog.run() == Gtk.ResponseType.ACCEPT:
+ return
+
+ self.props.selection_mode = False
+ tags_editor_dialog.destroy()
+
+ self._stack.get_visible_child().get_selected_songs(callback)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0fea8e4b..50a46c2b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -14,6 +14,7 @@ data/ui/PlaylistControls.ui
data/ui/PlaylistDialog.ui
data/ui/SelectionBarMenuButton.ui
data/ui/SelectionToolbar.ui
+data/ui/TagEditorDialog.ui
gnomemusic/__init__.py
gnomemusic/albumartcache.py
gnomemusic/application.py
@@ -40,4 +41,5 @@ gnomemusic/widgets/playlistcontrols.py
gnomemusic/widgets/playlistdialog.py
gnomemusic/widgets/searchbar.py
gnomemusic/widgets/starhandlerwidget.py
+gnomemusic/widgets/tageditordialog.py
gnomemusic/window.py
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]