[shotwell/wip/enhanced-profiles] Add UI for the profile feature




commit ec2ffd2c0cebbca1736eff7bb94e93994d69b071
Author: Jens Georg <mail jensge org>
Date:   Sat Aug 13 12:08:47 2022 +0200

    Add UI for the profile feature

 data/ui/preferences_dialog.ui   | 389 +++++++++++++++++++++++-----------------
 src/ProfileBrowser.vala         | 133 ++++++++++++++
 src/Profiles.vala               |  87 ++++++++-
 src/config/GSettingsEngine.vala |   5 +-
 src/dialogs/Preferences.vala    |   2 +
 src/main.vala                   |  18 ++
 src/meson.build                 |   1 +
 7 files changed, 465 insertions(+), 170 deletions(-)
---
diff --git a/data/ui/preferences_dialog.ui b/data/ui/preferences_dialog.ui
index f020c974..12c20387 100644
--- a/data/ui/preferences_dialog.ui
+++ b/data/ui/preferences_dialog.ui
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.38.2 -->
 <interface domain="shotwell">
   <requires lib="gtk+" version="3.18"/>
   <template class="PreferencesDialog" parent="GtkDialog">
-    <property name="can_focus">False</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="type_hint">dialog</property>
-    <property name="skip_taskbar_hint">True</property>
+    <property name="can-focus">False</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-vbox3">
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
+        <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>
+            <property name="can-focus">False</property>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -25,44 +25,45 @@
         <child>
           <object class="GtkNotebook" id="preferences_notebook">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="show_border">False</property>
+            <property name="can-focus">True</property>
+            <property name="show-border">False</property>
             <child>
+              <!-- n-columns=3 n-rows=15 -->
               <object class="GtkGrid" id="table1">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
-                <property name="border_width">6</property>
-                <property name="row_spacing">4</property>
-                <property name="column_spacing">8</property>
+                <property name="border-width">6</property>
+                <property name="row-spacing">4</property>
+                <property name="column-spacing">8</property>
                 <child>
                   <object class="GtkFileChooserButton" id="library_dir_button">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="action">select-folder</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">4</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">4</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkComboBoxText" id="default_raw_developer_combo">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">14</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">14</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label5">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_bottom">3</property>
+                    <property name="margin-bottom">3</property>
                     <property name="hexpand">True</property>
                     <property name="label" translatable="yes">Display</property>
                     <attributes>
@@ -70,18 +71,18 @@
                     </attributes>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="library location">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_top">14</property>
-                    <property name="margin_bottom">3</property>
+                    <property name="margin-top">14</property>
+                    <property name="margin-bottom">3</property>
                     <property name="hexpand">True</property>
                     <property name="label" translatable="yes">Library Location</property>
                     <attributes>
@@ -89,50 +90,50 @@
                     </attributes>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">3</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">3</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label4">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
+                    <property name="margin-left">10</property>
                     <property name="label" translatable="yes">_Import photos to:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">library_dir_button</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">library_dir_button</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">4</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">4</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="autoimport">
                     <property name="label" translatable="yes">_Watch library directory for new 
files</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
+                    <property name="margin-left">10</property>
+                    <property name="use-underline">True</property>
+                    <property name="draw-indicator">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">5</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">5</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="importing">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_top">14</property>
-                    <property name="margin_bottom">3</property>
+                    <property name="margin-top">14</property>
+                    <property name="margin-bottom">3</property>
                     <property name="hexpand">True</property>
                     <property name="label" translatable="yes">Importing</property>
                     <attributes>
@@ -140,71 +141,71 @@
                     </attributes>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">6</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">6</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="dir_structure_label">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
+                    <property name="margin-left">10</property>
                     <property name="label" translatable="yes">_Directory structure:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">dir_pattern_combo</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">dir_pattern_combo</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">7</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">7</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="dir_pattern_example">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">34</property>
+                    <property name="margin-left">34</property>
                     <property name="label" translatable="yes">Example:</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">9</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">9</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="lowercase">
                     <property name="label" translatable="yes">R_ename imported files to lowercase</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
+                    <property name="margin-left">10</property>
+                    <property name="use-underline">True</property>
+                    <property name="draw-indicator">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">10</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">10</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label10">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_top">14</property>
-                    <property name="margin_bottom">3</property>
+                    <property name="margin-top">14</property>
+                    <property name="margin-bottom">3</property>
                     <property name="label" translatable="yes">Metadata</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">11</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">11</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
@@ -212,99 +213,99 @@
                   <object class="GtkCheckButton" id="write_metadata">
                     <property name="label" translatable="yes">Write tags, titles, and other _metadata to 
photo files</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
+                    <property name="margin-left">10</property>
+                    <property name="use-underline">True</property>
+                    <property name="draw-indicator">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">12</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">12</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label3">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_top">14</property>
-                    <property name="margin_bottom">3</property>
+                    <property name="margin-top">14</property>
+                    <property name="margin-bottom">3</property>
                     <property name="label" translatable="yes">RAW Developer</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">13</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">13</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label6">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
+                    <property name="margin-left">10</property>
                     <property name="label" translatable="yes">De_fault:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">default_raw_developer_combo</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">default_raw_developer_combo</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">14</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">14</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkComboBoxText" id="dir_pattern_combo">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">7</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">7</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkEntry" id="dir_pattern_entry">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">•</property>
-                    <property name="primary_icon_activatable">False</property>
-                    <property name="secondary_icon_activatable">False</property>
+                    <property name="can-focus">True</property>
+                    <property name="invisible-char">•</property>
+                    <property name="primary-icon-activatable">False</property>
+                    <property name="secondary-icon-activatable">False</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">8</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">8</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="dynamic example">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
                     <property name="hexpand">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">9</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">9</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkBox" id="hbox1">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <child>
                       <object class="GtkLabel" id="patern">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="halign">start</property>
-                        <property name="margin_left">34</property>
+                        <property name="margin-left">34</property>
                         <property name="label" translatable="yes">_Pattern:</property>
-                        <property name="use_underline">True</property>
+                        <property name="use-underline">True</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -315,7 +316,7 @@
                     <child>
                       <object class="GtkLabel" id="pattern_help">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <attributes>
                           <attribute name="underline" value="True"/>
                         </attributes>
@@ -328,39 +329,39 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">8</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">8</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="tooltip_text" translatable="yes">When viewing images that are 
transparent, they will be drawn against this background.</property>
+                    <property name="can-focus">False</property>
+                    <property name="tooltip-text" translatable="yes">When viewing images that are 
transparent, they will be drawn against this background.</property>
                     <property name="halign">start</property>
                     <property name="valign">start</property>
-                    <property name="margin_left">10</property>
+                    <property name="margin-left">10</property>
                     <property name="label" translatable="yes">Transparent Background:</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">2</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkBox">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkRadioButton" id="transparent_checker_radio">
                         <property name="label" translatable="yes">Checkered</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
                         <property name="halign">start</property>
                         <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="draw-indicator">True</property>
                         <property name="group">transparent_solid_radio</property>
                       </object>
                       <packing>
@@ -372,16 +373,16 @@
                     <child>
                       <object class="GtkBox" id="box1">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <child>
                           <object class="GtkRadioButton" id="transparent_solid_radio">
                             <property name="label" translatable="yes">Solid color</property>
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
+                            <property name="can-focus">True</property>
+                            <property name="receives-default">False</property>
                             <property name="halign">start</property>
                             <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="draw-indicator">True</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -392,13 +393,13 @@
                         <child>
                           <object class="GtkColorButton" id="transparent_solid_color">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="receives-default">True</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="fill">True</property>
-                            <property name="pack_type">end</property>
+                            <property name="pack-type">end</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
@@ -413,11 +414,11 @@
                       <object class="GtkRadioButton" id="transparent_none_radio">
                         <property name="label" translatable="yes">None</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
                         <property name="halign">start</property>
                         <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="draw-indicator">True</property>
                         <property name="group">transparent_solid_radio</property>
                       </object>
                       <packing>
@@ -428,70 +429,115 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">2</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">2</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="halign">start</property>
-                    <property name="margin_left">10</property>
+                    <property name="margin-left">10</property>
                     <property name="label" translatable="yes">Use dark theme:</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">1</property>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">1</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkSwitch" id="switch_dark">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
+                    <property name="can-focus">True</property>
                     <property name="halign">start</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">1</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">1</property>
                   </packing>
                 </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
               </object>
             </child>
             <child type="tab">
               <object class="GtkLabel" id="library-tab">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="label" translatable="yes">Library</property>
               </object>
               <packing>
-                <property name="tab_fill">False</property>
+                <property name="tab-fill">False</property>
               </packing>
             </child>
             <child>
               <object class="GtkBox" id="hbox4">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="valign">start</property>
-                <property name="border_width">6</property>
+                <property name="border-width">6</property>
                 <child>
                   <object class="GtkBox" id="vbox2">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_left">6</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-left">6</property>
                     <property name="orientation">vertical</property>
                     <property name="spacing">6</property>
                     <child>
                       <object class="GtkLabel" id="label7">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="halign">start</property>
-                        <property name="margin_left">4</property>
-                        <property name="margin_right">4</property>
+                        <property name="margin-left">4</property>
+                        <property name="margin-right">4</property>
                         <property name="hexpand">True</property>
                         <property name="label" translatable="yes">E_xternal photo editor:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">photo_editor_combo</property>
+                        <property name="use-underline">True</property>
+                        <property name="mnemonic-widget">photo_editor_combo</property>
                       </object>
                       <packing>
                         <property name="expand">True</property>
@@ -502,13 +548,13 @@
                     <child>
                       <object class="GtkLabel" id="label8">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="halign">start</property>
-                        <property name="margin_left">4</property>
-                        <property name="margin_right">4</property>
+                        <property name="margin-left">4</property>
+                        <property name="margin-right">4</property>
                         <property name="label" translatable="yes">External _RAW editor:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">raw_editor_combo</property>
+                        <property name="use-underline">True</property>
+                        <property name="mnemonic-widget">raw_editor_combo</property>
                       </object>
                       <packing>
                         <property name="expand">True</property>
@@ -526,13 +572,13 @@
                 <child>
                   <object class="GtkBox" id="vbox3">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="orientation">vertical</property>
                     <property name="spacing">6</property>
                     <child>
                       <object class="GtkComboBox" id="photo_editor_combo">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                       </object>
                       <packing>
                         <property name="expand">True</property>
@@ -543,7 +589,7 @@
                     <child>
                       <object class="GtkComboBox" id="raw_editor_combo">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                       </object>
                       <packing>
                         <property name="expand">True</property>
@@ -566,19 +612,19 @@
             <child type="tab">
               <object class="GtkLabel" id="external-editors-tab">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="label" translatable="yes">External Editors</property>
               </object>
               <packing>
                 <property name="position">1</property>
-                <property name="tab_fill">False</property>
+                <property name="tab-fill">False</property>
               </packing>
             </child>
             <child>
               <object class="GtkBox">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">12</property>
+                <property name="can-focus">False</property>
+                <property name="border-width">12</property>
                 <property name="orientation">vertical</property>
                 <child>
                   <placeholder/>
@@ -591,19 +637,38 @@
             <child type="tab">
               <object class="GtkLabel" id="plugins-tab">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="label" translatable="yes">Plugins</property>
               </object>
               <packing>
                 <property name="position">2</property>
-                <property name="tab_fill">False</property>
+                <property name="tab-fill">False</property>
               </packing>
             </child>
             <child>
-              <placeholder/>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="border-width">12</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">3</property>
+              </packing>
             </child>
             <child type="tab">
-              <placeholder/>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Profiles</property>
+              </object>
+              <packing>
+                <property name="position">3</property>
+                <property name="tab-fill">False</property>
+              </packing>
             </child>
           </object>
           <packing>
@@ -617,9 +682,9 @@
     <child type="titlebar">
       <object class="GtkHeaderBar" id="headerbar">
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
+        <property name="can-focus">False</property>
         <property name="title" translatable="yes">Shotwell Preferences</property>
-        <property name="show_close_button">True</property>
+        <property name="show-close-button">True</property>
       </object>
     </child>
   </template>
diff --git a/src/ProfileBrowser.vala b/src/ProfileBrowser.vala
new file mode 100644
index 00000000..4678bff3
--- /dev/null
+++ b/src/ProfileBrowser.vala
@@ -0,0 +1,133 @@
+// SPDX-FileCopyrightText: Jens Georg <mail jensge org>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+namespace Shotwell {
+    class ProfileBrowser : Gtk.Box {
+        public ProfileBrowser() {
+            Object(orientation: Gtk.Orientation.VERTICAL, vexpand: true, hexpand: true);
+        }
+
+        public signal void profile_activated(string? profile);
+
+        public override void constructed() {
+            var scrollable = new Gtk.ScrolledWindow(null, null);
+            scrollable.hexpand = true;
+            scrollable.vexpand = true;
+
+            var list_box = new Gtk.ListBox();
+            list_box.activate_on_single_click = false;
+            list_box.row_activated.connect((list_box, row) => {
+                var index = row.get_index();
+                var profile = (Profile) ProfileManager.get_instance().get_item(index);
+                if (profile.id == "__shotwell_default_system") {
+                    profile_activated(null);
+                } else {
+                    profile_activated(profile.name);
+                }
+            });
+            list_box.get_style_context().add_class("rich-list");
+            list_box.hexpand = true;
+            list_box.vexpand = true;
+            scrollable.add (list_box);
+            list_box.bind_model(ProfileManager.get_instance(), on_widget_create);
+            list_box.set_header_func(on_header);
+
+            add(scrollable);
+            show_all();
+        }
+
+        private Gtk.Widget on_widget_create(Object item) {
+            var p = (Profile) item;
+            var row = new Gtk.ListBoxRow();
+            var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
+            box.margin_top = 6;
+            box.margin_bottom = 6;
+            box.margin_start = 6;
+            box.margin_end = 6;
+            box.halign = Gtk.Align.START;
+
+            var a = new Gtk.Box(Gtk.Orientation.VERTICAL, 6);
+            a.hexpand = true;
+
+            var label = new Gtk.Label(null);
+            label.set_markup("<b>%s</b>".printf(p.name));
+            label.halign = Gtk.Align.START;
+            label.xalign = 0.0f;
+            a.pack_start(label);
+
+            label = new Gtk.Label(p.data_dir);
+            label.get_style_context().add_class("dim-label");
+            label.halign = Gtk.Align.START;
+            label.xalign = 0.0f;
+            a.pack_end(label);
+            label.set_ellipsize(Pango.EllipsizeMode.MIDDLE);
+
+            Gtk.Image i;
+            if (p.active) {
+                i = new Gtk.Image.from_icon_name ("emblem-default-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
+                i.set_tooltip_text(_("This is the currently active profile"));
+            } else {
+                i = new Gtk.Image();
+            }
+
+            i.set_pixel_size(16);
+            i.valign = Gtk.Align.START;
+            i.halign = Gtk.Align.START;
+            i.margin_top = 6;
+            i.margin_bottom = 6;
+            i.margin_start = 6;
+            i.margin_end = 6;
+            i.hexpand = false;
+
+            box.pack_start(i);
+
+            box.pack_start(a);
+
+            if (p.id != "__shotwell_default_system" && ! p.active) {
+                var b = new Gtk.Button.from_icon_name("window-close-symbolic", Gtk.IconSize.BUTTON);
+                b.margin_top = 6;
+                b.margin_bottom = 6;
+                b.margin_start = 6;
+                b.margin_end = 6;
+                b.set_tooltip_text(_("Remove this profile"));
+                b.hexpand = false;
+                b.halign = Gtk.Align.END;
+                b.get_style_context().add_class("flat");
+                box.pack_end(b);
+                b.clicked.connect(() => {
+                    var flags = Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL;
+                    if (Resources.use_header_bar() == 1) {
+                        flags |= Gtk.DialogFlags.USE_HEADER_BAR;
+                    }
+
+                    var d = new Gtk.MessageDialog((Gtk.Window) this.get_toplevel(), flags, 
Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, null);
+                    var title = _("Remove profile “%s”").printf(p.name);
+                    var subtitle = _("None of the options will remove any of the images associated with this 
profile");
+                    d.set_markup(_("<b><span size=\"larger\">%s</span></b>\n<span 
weight=\"light\">%s</span>").printf(title, subtitle));
+
+                    d.add_buttons(_("Remove profile and files"), Gtk.ResponseType.OK, _("Remove profile 
only"), Gtk.ResponseType.ACCEPT, _("Cancel"), Gtk.ResponseType.CANCEL);
+                    
d.get_widget_for_response(Gtk.ResponseType.OK).get_style_context().add_class("destructive-action");
+                    var response = d.run();
+                    d.destroy();
+                    if (response == Gtk.ResponseType.OK || response == Gtk.ResponseType.ACCEPT) {
+                        ProfileManager.get_instance().remove(p.id, response == Gtk.ResponseType.OK);
+                    }
+                });
+            }
+
+            row.add (box);
+
+            return row;
+        }
+
+        private void on_header(Gtk.ListBoxRow row, Gtk.ListBoxRow? before) {
+            if (before == null || row.get_header() != null) {
+                return;
+            }
+
+            var separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
+            separator.show();
+            row.set_header(separator);
+        }
+    }
+}
diff --git a/src/Profiles.vala b/src/Profiles.vala
index 52b2e3b4..52bf5802 100644
--- a/src/Profiles.vala
+++ b/src/Profiles.vala
@@ -5,7 +5,45 @@
  */
 
 namespace Shotwell {
-    class ProfileManager : Object {
+    class Profile : Object {
+        public Profile(string name, string id, string data_dir, bool active) {
+            Object(name: name, id: id, data_dir: data_dir, active: active);
+        }
+        public string name {get; construct;}
+        public string id {get; construct;}
+        public string data_dir {get; construct;}
+        public bool active {get; construct;}
+    }
+
+    class ProfileManager : Object, GLib.ListModel {
+        // ListModel implementations
+        Type get_item_type() {
+            return typeof(Profile);
+        }
+
+        uint get_n_items() {
+            // All that is in the ini file plus one for the default profile
+            return profiles.get_groups().length + 1;
+        }
+
+        GLib.Object? get_item (uint position) {
+            if (position == 0) {
+                return new Profile(_("System Profile"), "__shotwell_default_system",
+                            Path.build_path(Path.DIR_SEPARATOR_S, Environment.get_user_data_dir(), 
"shotwell"),
+                            this.profile == null);
+            }
+
+            var group = profiles.get_groups()[position - 1];
+            var id = profiles.get_value(group, "Id");
+            var name = profiles.get_value(group, "Name");
+            var active = this.profile == name;
+            return new Profile(profiles.get_value(group, "Name"),
+                               id,
+                               get_data_dir_for_profile(id, group),
+                               active);
+
+        }
+
         private static ProfileManager instance;
         public static ProfileManager get_instance() {
             if (instance == null)
@@ -50,6 +88,7 @@ namespace Shotwell {
         }
 
         public void set_profile(string profile) {
+            message("Using profile %s for this session", profile);
             assert(this.profile == null);
 
             this.profile = profile;
@@ -91,7 +130,7 @@ namespace Shotwell {
 
         public string id() {
             // We are not running on any profile
-            if (profile == null)
+            if (profile == null || profile == "")
                 return "";
 
             try {
@@ -101,6 +140,14 @@ namespace Shotwell {
             }
         }
 
+        private string get_data_dir_for_profile(string id, string group) {
+            if ("DataDir" in profiles.get_keys(group)) {
+                return profiles.get_value(group, "DataDir");
+            } else {
+                return Path.build_filename(Environment.get_user_data_dir(), "shotwell", "profiles", id);
+            }
+        }
+
         public void print_profiles() {
             print("Available profiles:\n");
             print("-------------------\n");
@@ -109,16 +156,42 @@ namespace Shotwell {
                     print("Profile name: %s\n", profiles.get_value(group, "Name"));
                     var id = profiles.get_value(group, "Id");
                     print("Profile Id: %s\n", id);
-                    if ("DataDir" in profiles.get_keys(group)) {
-                        print("Data dir: %s\n", profiles.get_value(group, "DataDir"));
-                    } else {
-                        print("Data dir: %s\n", Path.build_filename(Environment.get_user_data_dir(), 
"profiles", id));
-                    }
+                    print("Data dir: %s\n", get_data_dir_for_profile(id, group));
                     print("\n");
                 }
             } catch (Error error) {
                 print("Failed to print profiles: %s", error.message);
             }
         }
+
+        public void remove(string id, bool remove_all) {
+            debug("Request to remove profile %s, with files? %s", id, remove_all.to_string());
+            int index = 1;
+            string group = null;
+            bool found = false;
+            foreach (var g in profiles.get_groups()) {
+                if (profiles.get_value(g, "Id") == id) {
+                    group = g;
+                    break;
+                }
+                index++;
+            }
+
+            if (group != null) {
+                // Remove profile
+                var data_dir = get_data_dir_for_profile(id, group);
+                profiles.remove_comment(group, null);
+                profiles.remove_group(group);
+
+                // TODO: Remove gsettings
+
+                if (remove_all) {
+                // TODO: Remove folder
+                }
+
+                items_changed(index, 1, 0);
+                write();
+            }
+        }
     }
 }
diff --git a/src/config/GSettingsEngine.vala b/src/config/GSettingsEngine.vala
index e822d385..5c7ebeff 100644
--- a/src/config/GSettingsEngine.vala
+++ b/src/config/GSettingsEngine.vala
@@ -244,7 +244,10 @@ public class GSettingsConfigurationEngine : ConfigurationEngine, GLib.Object {
 
         Settings schema_object = get_settings(schema);
 
-        return schema_object.get_int(key);
+        var v = schema_object.get_int(key);
+        print("Getting int %s %s -> %d\n", schema, key, v);
+
+        return v;
     }
     
     private void set_gs_int(string schema, string key, int value) throws ConfigurationError {
diff --git a/src/dialogs/Preferences.vala b/src/dialogs/Preferences.vala
index c6d63868..87b169f0 100644
--- a/src/dialogs/Preferences.vala
+++ b/src/dialogs/Preferences.vala
@@ -127,6 +127,8 @@ public class PreferencesDialog : Gtk.Dialog {
         lowercase.toggled.connect(on_lowercase_toggled);
 
         ((Gtk.Container) preferences_notebook.get_nth_page (2)).add (plugins_mediator);
+        ((Gtk.Container) preferences_notebook.get_nth_page (3)).add (new Shotwell.ProfileBrowser());
+
 
         populate_preference_options();
 
diff --git a/src/main.vala b/src/main.vala
index 014b0b54..2ae3199f 100644
--- a/src/main.vala
+++ b/src/main.vala
@@ -343,6 +343,7 @@ bool show_metadata = false;
 string? profile = null;
 bool create_profile = false;
 bool list_profiles = false;
+bool browse_profiles = false;
 
 const OptionEntry[] entries = {
     { "datadir", 'd', 0, OptionArg.FILENAME, ref data_dir, N_("Path to Shotwell’s private data"), 
N_("DIRECTORY") },
@@ -352,6 +353,7 @@ const OptionEntry[] entries = {
     { "fullscreen", 'f', 0, OptionArg.NONE, ref fullscreen, N_("Start the application in fullscreen mode"), 
null },
     { "show-metadata", 'p', 0, OptionArg.NONE, ref show_metadata, N_("Print the metadata of the image 
file"), null },
     { "profile", 'i', 0, OptionArg.STRING, ref profile, N_("Name for a custom profile"), N_("PROFILE") },
+    { "profile-browser", 'b', 0, OptionArg.NONE, ref browse_profiles, N_("Start with a browser of available 
profiles"), null },
     { "create", 'c', 0, OptionArg.NONE, ref create_profile, N_("If PROFILE given with --profile does not 
exist, create it"), null },
     { "list-profiles", 'l', 0, OptionArg.NONE, ref list_profiles, N_("Show available profiles"), null },
     { null, 0, 0, 0, null, null, null }
@@ -394,6 +396,20 @@ void main(string[] args) {
         return;
     }
 
+    if (CommandlineOptions.browse_profiles) {
+        var window = new Gtk.Dialog();
+        window.set_title (_("Choose Shotwell's profile"));
+        var browser = new Shotwell.ProfileBrowser();
+        browser.profile_activated.connect((profile) => {
+            CommandlineOptions.profile = profile;
+            window.response(Gtk.ResponseType.OK);
+        });
+        window.get_content_area().add(browser);
+        window.set_default_size(800, 600);
+        var response = window.run();
+        window.destroy();
+    }
+
     // Setup profile manager
     if (CommandlineOptions.profile != null) {
         var manager = Shotwell.ProfileManager.get_instance();
@@ -407,6 +423,8 @@ void main(string[] args) {
         }
         manager.set_profile(CommandlineOptions.profile);
         CommandlineOptions.data_dir = manager.derive_data_dir(CommandlineOptions.data_dir);
+    } else {
+        message("Starting session with system profile");
     }
 
     if (CommandlineOptions.show_version) {
diff --git a/src/meson.build b/src/meson.build
index bdd63864..e043db3c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -239,6 +239,7 @@ executable(
         'dialogs/TextEntry.vala',
         'dialogs/WelcomeDialog.vala',
         'Profiles.vala',
+        'ProfileBrowser.vala',
         '.unitize/_UnitInternals.vala',
         '.unitize/_UtilInternals.vala',
         '.unitize/_ThreadsInternals.vala',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]