[gnome-control-center/wip/feborges/new-users-panel: 71/73] user-accounts: Introduce carousel (UmCarousel)
- From: Felipe Borges <felipeborges src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/feborges/new-users-panel: 71/73] user-accounts: Introduce carousel (UmCarousel)
- Date: Fri, 5 Aug 2016 12:10:26 +0000 (UTC)
commit d7cc0878926fc0907e91707066b649b1435a5470
Author: Felipe Borges <felipeborges gnome org>
Date: Mon Aug 1 14:38:55 2016 +0200
user-accounts: Introduce carousel (UmCarousel)
UmCarousel is a widget directly tied to UmArrowFrame. It is not
designed to be populated directly as a container but to be binded
to a GListModel.
https://bugzilla.gnome.org/show_bug.cgi?id=767065
panels/user-accounts/Makefile.am | 2 +
panels/user-accounts/data/carousel.ui | 84 +++
panels/user-accounts/data/user-accounts-dialog.ui | 588 ++++++++++-----------
panels/user-accounts/um-arrow-frame.c | 367 +++++++++++++-
panels/user-accounts/um-arrow-frame.h | 5 +
panels/user-accounts/um-carousel.c | 370 +++++++++++++
panels/user-accounts/um-carousel.h | 49 ++
panels/user-accounts/um-user-image.c | 2 -
panels/user-accounts/um-user-panel.c | 503 +++---------------
panels/user-accounts/user-accounts.gresource.xml | 1 +
10 files changed, 1224 insertions(+), 747 deletions(-)
---
diff --git a/panels/user-accounts/Makefile.am b/panels/user-accounts/Makefile.am
index b0ad1e0..c39be08 100644
--- a/panels/user-accounts/Makefile.am
+++ b/panels/user-accounts/Makefile.am
@@ -33,6 +33,8 @@ libuser_accounts_la_SOURCES = \
um-account-dialog.c \
um-arrow-frame.h \
um-arrow-frame.c \
+ um-carousel.h \
+ um-carousel.c \
um-password-dialog.h \
um-password-dialog.c \
pw-utils.h \
diff --git a/panels/user-accounts/data/carousel.ui b/panels/user-accounts/data/carousel.ui
new file mode 100644
index 0000000..c5ae114
--- /dev/null
+++ b/panels/user-accounts/data/carousel.ui
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <template class="UmCarousel" parent="GtkGrid">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkOverlay">
+ <property name="visible">True</property>
+ <property name="expand">True</property>
+ <property name="border_width">30</property>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <property name="transition_type">slide-left</property>
+ <property name="transition_duration">400</property>
+ <style>
+ <class name="inline-toolbar"/>
+ </style>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ <property name="border_width">12</property>
+ <child>
+ <object class="GtkButton" id="go_back_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="circular"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-size">4</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ </object>
+ </child>
+ <signal name="clicked" handler="um_carousel_go_back_button_clicked" object="UmCarousel"
swapped="no"/>
+ <signal name="clicked" handler="um_carousel_page_changed" object="UmCarousel" swapped="no"/>
+ </object>
+ <packing>
+ <property name="pack_type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="go_next_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="circular"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-size">4</property>
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ <signal name="clicked" handler="um_carousel_go_next_button_clicked" object="UmCarousel"
swapped="no"/>
+ <signal name="clicked" handler="um_carousel_page_changed" object="UmCarousel" swapped="no"/>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="pass-through">True</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/user-accounts/data/user-accounts-dialog.ui
b/panels/user-accounts/data/user-accounts-dialog.ui
index e8fb410..2703d54 100644
--- a/panels/user-accounts/data/user-accounts-dialog.ui
+++ b/panels/user-accounts/data/user-accounts-dialog.ui
@@ -48,7 +48,12 @@
<object class="GtkVBox" id="accounts-vbox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
- <property name="border_width">12</property>
+ <child>
+ <object class="UmCarousel" id="carousel">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
<child>
<object class="UmArrowFrame" id="arrow-frame">
<property name="visible">True</property>
@@ -56,400 +61,357 @@
<class name="background"/>
</style>
<child>
- <object class="GtkHBox" id="hbox2">
+ <object class="GtkBox" id="hbox2">
<property name="visible">True</property>
+ <property name="border_width">18</property>
<property name="spacing">18</property>
+ <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
<child>
- <object class="GtkVBox" id="userlist-vbox">
+ <object class="GtkGrid" id="main-user-vbox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">0</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">10</property>
+ <property name="row_spacing">10</property>
+ <property name="halign">GTK_ALIGN_CENTER</property>
<child>
- <object class="GtkScrolledWindow" id="list-scrolledwindow">
+ <object class="GtkButton" id="account-fingerprint-button">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="list-treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- </object>
- </child>
+ <property name="hexpand">True</property>
</object>
<packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="main-user-vbox">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
<child>
- <object class="GtkGrid" id="grid1">
+ <object class="GtkBox" id="account-type-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="column_spacing">10</property>
- <property name="row_spacing">10</property>
+ <property name="sensitive">False</property>
+ <style>
+ <class name="linked"/>
+ </style>
<child>
- <object class="GtkButton" id="account-fingerprint-button">
+ <object class="GtkRadioButton" id="account-type-standard">
<property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Standard</property>
+ <property name="draw_indicator">False</property>
<property name="hexpand">True</property>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">5</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
<child>
- <object class="GtkBox" id="account-type-box">
+ <object class="GtkRadioButton" id="account-type-admin">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="sensitive">False</property>
- <style>
- <class name="linked"/>
- </style>
- <child>
- <object class="GtkRadioButton" id="account-type-standard">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Standard</property>
- <property name="draw_indicator">False</property>
- <property name="hexpand">True</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="account-type-admin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Administrator</property>
- <property name="draw_indicator">False</property>
- <property name="group">account-type-standard</property>
- <property name="hexpand">True</property>
- </object>
- </child>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Administrator</property>
+ <property name="draw_indicator">False</property>
+ <property name="group">account-type-standard</property>
+ <property name="hexpand">True</property>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="account-type-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Account _Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">account-type-box</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox10">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="account-type-label">
+ <object class="GtkEntry" id="full-name-entry">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Account _Type</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">account-type-box</property>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="width-chars">30</property>
+ <property name="max-width-chars">30</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">account-password-button</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="account-password-button">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="text-button"/>
+ </style>
<child>
- <object class="GtkVBox" id="vbox10">
+ <object class="GtkLabel" id="account-password-button-label">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkEntry" id="full-name-entry">
- <property name="visible">True</property>
- <property name="width-chars">30</property>
- <property name="max-width-chars">30</property>
- <property name="valign">GTK_ALIGN_CENTER</property>
- </object>
- <packing>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="halign">GTK_ALIGN_START</property>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="autologin-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">A_utomatic Login</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">autologin-switch</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="autologin-box">
+ <property name="visible">True</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<child>
- <object class="GtkLabel" id="password-label">
+ <object class="GtkSwitch" id="autologin-switch">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Password</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">account-password-button</property>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="valign">GTK_ALIGN_CENTER</property>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">3</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkButton" id="account-password-button">
- <property name="visible">True</property>
- <property name="hexpand">True</property>
- <style>
- <class name="text-button"/>
- </style>
- <child>
- <object class="GtkLabel" id="account-password-button-label">
- <property name="visible">True</property>
- <property name="halign">GTK_ALIGN_START</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">3</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
+ <placeholder/>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="account-fingerprint-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Fingerprint Login</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">account-fingerprint-button</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
<child>
- <object class="GtkLabel" id="autologin-label">
+ <object class="GtkLabel" id="label4">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">A_utomatic Login</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">autologin-switch</property>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="hexpand">True</property>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">4</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="autologin-box">
+ <object class="UmUserImage" id="user-icon-image">
<property name="visible">True</property>
- <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
- <child>
- <object class="GtkSwitch" id="autologin-switch">
- <property name="visible">True</property>
- <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="icon_name">avatar-default</property>
+ <property name="icon-size">6</property>
+ <property name="halign">end</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="user-icon-image-a11y">
+ <property name="accessible-name" translatable="yes">User Icon</property>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
</child>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">4</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="account-fingerprint-label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Fingerprint Login</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">account-fingerprint-button</property>
- <style>
- <class name="dim-label"/>
- </style>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">5</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox5">
+ <object class="GtkToggleButton" id="user-icon-button">
<property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="hexpand">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="user-icon-image2-a11y">
+ <property name="accessible-name" translatable="yes">User Icon</property>
</object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
</child>
<child>
- <object class="UmUserImage" id="user-icon-image">
+ <object class="UmUserImage" id="user-icon-image2">
<property name="visible">True</property>
<property name="icon_name">avatar-default</property>
<property name="icon-size">6</property>
- <property name="halign">end</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="user-icon-image-a11y">
- <property name="accessible-name" translatable="yes">User Icon</property>
- </object>
- </child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkToggleButton" id="user-icon-button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="relief">none</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="user-icon-image2-a11y">
- <property name="accessible-name" translatable="yes">User Icon</property>
- </object>
- </child>
- <child>
- <object class="UmUserImage" id="user-icon-image2">
- <property name="visible">True</property>
- <property name="icon_name">avatar-default</property>
- <property name="icon-size">6</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
</child>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="language-label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Language</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">account-language-button</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="account-language-button">
- <property name="visible">True</property>
- <property name="hexpand">True</property>
- <style>
- <class name="text-button"/>
- </style>
- <child>
- <object class="GtkLabel" id="account-language-button-label">
- <property name="visible">True</property>
- <property name="halign">GTK_ALIGN_START</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="language-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Language</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">account-language-button</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="account-language-button">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="text-button"/>
+ </style>
<child>
- <object class="GtkLabel" id="last-login-label">
+ <object class="GtkLabel" id="account-language-button-label">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Last Login</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">last-login-button</property>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="halign">GTK_ALIGN_START</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">6</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="last-login-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Last Login</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">last-login-button</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="last-login-button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <style>
+ <class name="text-button"/>
+ </style>
<child>
- <object class="GtkButton" id="last-login-button">
+ <object class="GtkLabel" id="last-login-button-label">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <style>
- <class name="text-button"/>
- </style>
- <child>
- <object class="GtkLabel" id="last-login-button-label">
- <property name="visible">True</property>
- <property name="halign">GTK_ALIGN_START</property>
- </object>
- </child>
+ <property name="halign">GTK_ALIGN_START</property>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">6</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
</object>
<packing>
- <property name="expand">True</property>
+ <property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">1</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
@@ -464,7 +426,7 @@
</style>
</object>
<packing>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
diff --git a/panels/user-accounts/um-arrow-frame.c b/panels/user-accounts/um-arrow-frame.c
index 379b463..b20ab3e 100644
--- a/panels/user-accounts/um-arrow-frame.c
+++ b/panels/user-accounts/um-arrow-frame.c
@@ -17,23 +17,325 @@
*
* Writen by: Felipe Borges <felipeborges gnome org>,
* Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
*/
#include "um-arrow-frame.h"
-typedef struct {
- GtkWidget *item;
-} UmArrowFramePrivate;
+#define ARROW_HEIGHT 16
+#define ARROW_WIDTH 36
+#define HANDLE_GAP (ARROW_HEIGHT + 5)
struct _UmArrowFrame {
GtkFrame parent;
- UmArrowFramePrivate *priv;
+ UmCarousel *carousel;
+ GtkWidget *item;
+
+ GdkWindow *handle_window;
+ gint margin_top;
};
-G_DEFINE_TYPE_WITH_PRIVATE (UmArrowFrame, um_arrow_frame, GTK_TYPE_FRAME)
+G_DEFINE_TYPE (UmArrowFrame, um_arrow_frame, GTK_TYPE_FRAME)
+
+static void um_arrow_frame_set_item (UmCarousel *carousel, GtkToggleButton *item, UmArrowFrame *frame);
+
+static gint
+um_arrow_frame__get_row_x (UmArrowFrame *frame)
+{
+ GtkWidget *widget;
+ GtkWidget *row;
+ gint row_width;
+ gint dest_x;
+
+ widget = GTK_WIDGET (frame);
+
+ if (!frame->item)
+ return gtk_widget_get_allocated_width (widget) / 2;
+
+ row = GTK_WIDGET (frame->item);
+ row_width = gtk_widget_get_allocated_width (row);
+
+ gtk_widget_translate_coordinates (row,
+ widget,
+ row_width / 2,
+ 0,
+ &dest_x,
+ NULL);
+
+ return CLAMP (dest_x,
+ 0,
+ gtk_widget_get_allocated_width (widget));
+}
+
+static void
+um_arrow_frame__draw_arrow (UmArrowFrame *frame,
+ cairo_t *cr)
+{
+ GtkWidget *widget = GTK_WIDGET (frame);
+ GtkStyleContext *context;
+ GtkAllocation alloc;
+ GtkStateFlags state;
+ GtkBorder border;
+ GdkRGBA border_color;
+ gint border_width;
+ gint start_x;
+ gint start_y;
+ gint tip_x;
+ gint tip_y;
+ gint end_x;
+ gint end_y;
+
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (context);
+
+ gtk_style_context_get_border (context,
+ state,
+ &border);
+
+ gtk_style_context_get (context,
+ state,
+ GTK_STYLE_PROPERTY_BORDER_COLOR, &border_color,
+ NULL);
+
+ /* widget size */
+ gtk_widget_get_allocation (widget, &alloc);
+
+ tip_x = um_arrow_frame__get_row_x (frame);
+ start_x = tip_x - (ARROW_WIDTH / 2);
+ end_x = tip_x + (ARROW_WIDTH / 2);
+
+ start_y = end_y = border.top + ARROW_HEIGHT;
+ tip_y = 0;
+ border_width = border.top;
+
+ /* draw arrow */
+ cairo_save (cr);
+
+ cairo_set_line_width (cr, 1.0);
+ cairo_move_to (cr, start_x, start_y);
+ cairo_line_to (cr, tip_x, tip_y);
+ cairo_line_to (cr, end_x, end_y);
+
+ /*
+ * * Don't allow that gtk_render_background renders
+ * * anything out of (tip_x, start_y) (end_x, end_y).
+ * */
+ cairo_clip (cr);
+
+ /* render the arrow background */
+ gtk_render_background (context,
+ cr,
+ 0,
+ 0,
+ alloc.width,
+ alloc.height);
+
+ /* draw the border */
+ if (border_width > 0)
+ {
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+ gtk_style_context_get_border_color (context,
+ state,
+ &border_color);
+
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ gdk_cairo_set_source_rgba (cr, &border_color);
+
+ cairo_set_line_width (cr, 1);
+ cairo_move_to (cr, start_x, start_y);
+ cairo_line_to (cr, tip_x, tip_y);
+ cairo_line_to (cr, end_x, end_y);
+
+ cairo_set_line_width (cr, border_width + 1);
+ cairo_stroke (cr);
+ }
+
+ cairo_restore (cr);
+}
+
+static void
+um_arrow_frame__draw_background (UmArrowFrame *frame,
+ cairo_t *cr)
+{
+ GtkWidget *widget = GTK_WIDGET (frame);
+ GtkStyleContext *context;
+ GtkAllocation alloc;
+ GtkStateFlags state;
+ GtkBorder margin;
+ gint start_x;
+ gint start_y;
+ gint start_gap;
+ gint end_x;
+ gint end_y;
+ gint end_gap;
+
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (context);
+
+ /* widget size */
+ gtk_widget_get_allocation (widget, &alloc);
+
+ /* margin */
+ gtk_style_context_get_margin (context,
+ state,
+ &margin);
+
+ start_x = margin.left;
+ end_x = alloc.width + margin.right;
+
+ start_y = margin.top + ARROW_HEIGHT;
+ end_y = alloc.height + margin.bottom;
+
+ start_gap = ((end_y - start_y + ARROW_WIDTH) / 2);
+ end_gap = ((end_y - start_y + ARROW_WIDTH) / 2);
+
+ gtk_render_background (context,
+ cr,
+ start_x,
+ start_y,
+ end_x,
+ end_y);
+ gtk_render_frame_gap (context,
+ cr,
+ start_x,
+ start_y,
+ end_x,
+ end_y,
+ GTK_POS_TOP,
+ start_gap,
+ end_gap);
+}
+
+static gboolean
+um_arrow_frame_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ UmArrowFrame *frame = UM_ARROW_FRAME (widget);
+ GtkWidget *child;
+
+ um_arrow_frame__draw_background (frame, cr);
+ um_arrow_frame__draw_arrow (frame, cr);
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+
+ if (child)
+ {
+ gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
+ }
+
+ return TRUE;
+}
+
+static void
+um_arrow_frame_compute_child_allocation (GtkFrame *frame,
+ GtkAllocation *allocation)
+{
+ allocation->height += HANDLE_GAP;
+ GTK_FRAME_CLASS (um_arrow_frame_parent_class)->compute_child_allocation (frame, allocation);
+}
+
+static void
+um_arrow_frame_get_preferred_height (GtkWidget *widget,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GTK_WIDGET_CLASS (um_arrow_frame_parent_class)->get_preferred_height (widget,
+ minimum_height,
+ natural_height);
+
+ *minimum_height += ARROW_HEIGHT;
+ *natural_height += ARROW_HEIGHT;
+ *natural_height = MAX (*minimum_height, *natural_height + HANDLE_GAP);
+}
+
+static void
+um_arrow_frame_realize (GtkWidget *widget)
+{
+ UmArrowFrame *self = UM_ARROW_FRAME (widget);
+ GtkAllocation allocation;
+ GdkWindowAttr attributes = { 0 };
+ GdkDisplay *display;
+ GdkWindow *parent_window;
+ gint attributes_mask;
+
+ display = gtk_widget_get_display (widget);
+ parent_window = gtk_widget_get_parent_window (widget);
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ gtk_widget_set_window (widget, parent_window);
+ g_object_ref (parent_window);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.cursor = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK);
-GtkWidget*
+ attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
+
+ self->handle_window = gdk_window_new (parent_window,
+ &attributes,
+ attributes_mask);
+
+ gtk_widget_register_window (widget, self->handle_window);
+
+ g_clear_object (&attributes.cursor);
+}
+
+static void
+um_arrow_frame_unrealize (GtkWidget *widget)
+{
+ UmArrowFrame *self = UM_ARROW_FRAME (widget);
+
+ if (self->handle_window)
+ {
+ gdk_window_hide (self->handle_window);
+ gtk_widget_unregister_window (widget, self->handle_window);
+ g_clear_pointer (&self->handle_window, gdk_window_destroy);
+ }
+
+ GTK_WIDGET_CLASS (um_arrow_frame_parent_class)->unrealize (widget);
+}
+
+static void
+um_arrow_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ UmArrowFrame *self = UM_ARROW_FRAME (widget);
+
+ GTK_WIDGET_CLASS (um_arrow_frame_parent_class)->size_allocate (widget, allocation);
+
+ allocation->y = self->margin_top - ARROW_HEIGHT;
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (gtk_widget_get_realized (widget))
+ {
+ gdk_window_move_resize (self->handle_window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+
+ gdk_window_raise (self->handle_window);
+ }
+}
+
+GtkWidget *
um_arrow_frame_new (void)
{
return g_object_new (UM_TYPE_ARROW_FRAME, NULL);
@@ -50,14 +352,65 @@ um_arrow_frame_class_init (UmArrowFrameClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkFrameClass *frame_class = GTK_FRAME_CLASS (klass);
object_class->finalize = um_arrow_frame_finalize;
+ widget_class->draw = um_arrow_frame_draw;
+ widget_class->get_preferred_height = um_arrow_frame_get_preferred_height;
+ widget_class->realize = um_arrow_frame_realize;
+ widget_class->unrealize = um_arrow_frame_unrealize;
+ widget_class->size_allocate = um_arrow_frame_size_allocate;
+
+ frame_class->compute_child_allocation = um_arrow_frame_compute_child_allocation;
+
gtk_widget_class_set_css_name (widget_class, "arrow-frame");
}
static void
um_arrow_frame_init (UmArrowFrame *self)
{
- self->priv = um_arrow_frame_get_instance_private (self);
+ GtkStyleProvider *provider;
+
+ provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+ gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), "* {border-top: solid 1px; border-color:
@borders }", -1, NULL);
+ gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (self)),
+ provider,
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ g_object_unref (provider);
+
+}
+
+static void
+um_arrow_frame_set_item (UmCarousel *carousel,
+ GtkToggleButton *item,
+ UmArrowFrame *frame)
+{
+ g_return_if_fail (UM_IS_ARROW_FRAME (frame));
+
+ frame->item = GTK_WIDGET (item);
+
+ gtk_widget_queue_draw (GTK_WIDGET (frame));
+}
+
+static void
+um_arrow_frame_set_margin_top (GtkWidget *widget,
+ GtkAllocation *allocation,
+ UmArrowFrame *frame)
+{
+ frame->margin_top = allocation->height;
+}
+
+void
+um_arrow_frame_set_carousel (UmArrowFrame *frame,
+ UmCarousel *carousel)
+{
+ if (carousel == NULL)
+ return;
+
+ frame->carousel = carousel;
+
+ g_signal_connect (carousel, "size-allocate", G_CALLBACK (um_arrow_frame_set_margin_top), frame);
+ g_signal_connect (carousel, "item-activated", G_CALLBACK (um_arrow_frame_set_item), frame);
}
diff --git a/panels/user-accounts/um-arrow-frame.h b/panels/user-accounts/um-arrow-frame.h
index 972ad0c..9e858ad 100644
--- a/panels/user-accounts/um-arrow-frame.h
+++ b/panels/user-accounts/um-arrow-frame.h
@@ -24,6 +24,8 @@
#include <gtk/gtk.h>
+#include "um-carousel.h"
+
G_BEGIN_DECLS
#define UM_TYPE_ARROW_FRAME (um_arrow_frame_get_type())
@@ -32,6 +34,9 @@ G_DECLARE_FINAL_TYPE (UmArrowFrame, um_arrow_frame, UM, ARROW_FRAME, GtkFrame)
GtkWidget* um_arrow_frame_new (void);
+void um_arrow_frame_set_carousel (UmArrowFrame *frame,
+ UmCarousel *carousel);
+
G_END_DECLS
#endif /* UM_ARROW_FRAME_H */
diff --git a/panels/user-accounts/um-carousel.c b/panels/user-accounts/um-carousel.c
new file mode 100644
index 0000000..c36a47d
--- /dev/null
+++ b/panels/user-accounts/um-carousel.c
@@ -0,0 +1,370 @@
+/* um-carousel.c
+ *
+ * Copyright (C) 2016 Red Hat, Inc,
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Writen by: Felipe Borges <felipeborges gnome org>
+ *
+ */
+
+#include "um-carousel.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define ITEMS_PER_PAGE 3
+
+struct _UmCarousel {
+ GtkGrid parent;
+
+ GSequence *pages;
+ GSequence *children;
+ gint current_page;
+
+ GList *model;
+ UmCarouselCreateWidgetFunc create_widget_func;
+ gpointer create_widget_func_data;
+ GDestroyNotify create_widget_func_data_destroy;
+
+ /* Widgets */
+ GtkStack *stack;
+ GtkRadioButton *current_button;
+ GtkWidget *go_back_button;
+ GtkWidget *go_next_button;
+};
+
+G_DEFINE_TYPE (UmCarousel, um_carousel, GTK_TYPE_GRID)
+
+enum {
+ ITEM_ACTIVATED,
+ NUM_SIGNALS
+};
+
+static guint signals[NUM_SIGNALS] = { 0, };
+
+static GtkWidget *
+get_item_at_index (UmCarousel *self,
+ gint index)
+{
+ GSequenceIter *iter;
+
+ iter = g_sequence_get_iter_at_pos (self->children, index);
+ if (!g_sequence_iter_is_end (iter))
+ return g_sequence_get (iter);
+
+ return NULL;
+}
+
+static GtkWidget *
+get_page (UmCarousel *self)
+{
+ GSequenceIter *iter = NULL;
+ GtkWidget *box;
+ gint num_of_children;
+
+ num_of_children = g_sequence_get_length (self->children);
+ if (num_of_children % ITEMS_PER_PAGE == 0) {
+ gchar *page_name;
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ page_name = g_strdup_printf ("%d", g_sequence_get_length (self->pages));
+ gtk_stack_add_named (self->stack, box, page_name);
+
+ g_sequence_append (self->pages, box);
+ } else {
+ iter = g_sequence_get_end_iter (self->pages);
+ iter = g_sequence_iter_prev (iter);
+ box = g_sequence_get (iter);
+ }
+
+ return box;
+}
+
+static void
+set_visible_page (UmCarousel *self,
+ gint page)
+{
+ gchar *page_name;
+
+ self->current_page = page;
+ page_name = g_strdup_printf ("%d", self->current_page);
+ gtk_stack_set_visible_child_name (self->stack, page_name);
+
+ g_free (page_name);
+}
+
+static void
+on_item_toggled (GtkToggleButton *item,
+ gpointer user_data)
+{
+ g_signal_emit (user_data, signals[ITEM_ACTIVATED], 0, item);
+}
+
+static GtkWidget *
+create_item (UmCarousel *self,
+ GtkWidget *child,
+ gint position)
+{
+ GtkStyleProvider *provider;
+ GtkWidget *item;
+
+ item = gtk_radio_button_new (NULL);
+
+ provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+ gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), "* {border: 0; background: none }", -1,
NULL);
+ gtk_style_context_add_provider (gtk_widget_get_style_context (item), provider,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ g_object_unref (provider);
+
+ g_object_set_data (G_OBJECT (item), "position", GINT_TO_POINTER (position));
+ g_signal_connect (item, "toggled", G_CALLBACK (on_item_toggled), self);
+
+ if (self->current_button == NULL) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item), TRUE);
+ } else {
+ gtk_radio_button_join_group (GTK_RADIO_BUTTON (item), self->current_button);
+ }
+ self->current_button = GTK_RADIO_BUTTON (item);
+
+ gtk_container_add (GTK_CONTAINER (item), child);
+ gtk_widget_show (GTK_WIDGET (child));
+
+ gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
+ gtk_style_context_add_class (gtk_widget_get_style_context (item), "flat");
+ gtk_widget_set_valign (item, GTK_ALIGN_CENTER);
+
+ return item;
+}
+
+static void
+forall_items (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_target)
+{
+ UmCarousel *self = UM_CAROUSEL (container);
+ GSequenceIter *iter;
+ GtkWidget *item;
+
+ iter = g_sequence_get_begin_iter (self->children);
+ while (!g_sequence_iter_is_end (iter)) {
+ item = g_sequence_get (iter);
+ iter = g_sequence_iter_next (iter);
+ callback (GTK_WIDGET (item), callback_target);
+ }
+}
+
+static void
+insert_item (UmCarousel *self,
+ GtkWidget *child,
+ gint position)
+{
+ GtkWidget *item, *box;
+
+ box = get_page (self);
+ item = create_item (self, child, position);
+
+ if (position == 0) {
+ g_sequence_prepend (self->children, item);
+ gtk_box_pack_start (GTK_BOX (box), item, TRUE, FALSE, 10);
+ } else if (position == -1) {
+ g_sequence_append (self->children, item);
+ gtk_box_pack_end (GTK_BOX (box), item, TRUE, FALSE, 10);
+ } else {
+ GSequenceIter *iter;
+
+ iter = g_sequence_get_iter_at_pos (self->children, position);
+ iter = g_sequence_insert_before (iter, item);
+
+ gtk_box_pack_start (GTK_BOX (box), item, TRUE, FALSE, 10);
+ gtk_box_reorder_child (GTK_BOX (box), item, position);
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item), TRUE);
+ gtk_widget_show_all (box);
+}
+
+void
+um_carousel_select_item (UmCarousel *self,
+ gint position)
+{
+ self->current_button = GTK_RADIO_BUTTON (get_item_at_index (self, position));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->current_button), TRUE);
+
+ self->current_page = floor (position / ITEMS_PER_PAGE);
+ set_visible_page (self, self->current_page);
+}
+
+static void
+model_changed (GListModel *list,
+ guint position,
+ guint removed,
+ guint added,
+ gpointer user_data)
+{
+ UmCarousel *self = user_data;
+ gboolean have_more_pages;
+ gint i;
+
+ while (removed--) {
+ GtkWidget *item;
+
+ um_carousel_select_item (self, 0);
+
+ item = get_item_at_index (self, position);
+ gtk_widget_destroy (GTK_WIDGET (item));
+ }
+
+ for (i = 0; i < added; i++) {
+ GObject *item;
+ GtkWidget *widget;
+
+ item = g_list_model_get_item (list, position + i);
+ widget = self->create_widget_func (item, self->create_widget_func_data);
+
+ if (g_object_is_floating (widget))
+ g_object_ref_sink (widget);
+
+ gtk_widget_show (widget);
+ insert_item (self, widget, position + i);
+
+ g_object_unref (widget);
+ g_object_unref (item);
+
+ /* Jump to last page when a new item gets appended. */
+ set_visible_page (self, g_sequence_get_length (self->pages) -1);
+ }
+
+ have_more_pages = (g_sequence_get_length (self->pages) > 1);
+ gtk_widget_set_sensitive (self->go_back_button, have_more_pages);
+ gtk_widget_set_sensitive (self->go_next_button, have_more_pages);
+}
+
+void
+um_carousel_bind_model (UmCarousel *self,
+ GListModel *model,
+ UmCarouselCreateWidgetFunc create_widget_func,
+ gpointer user_data,
+ GDestroyNotify user_data_free_func)
+{
+ if (self->model) {
+ if (self->create_widget_func_data_destroy) {
+ self->create_widget_func_data_destroy (self->create_widget_func_data);
+ }
+
+ g_signal_handlers_disconnect_by_func (self->model, model_changed, self);
+ g_clear_object (&self->model);
+ }
+
+ forall_items (GTK_CONTAINER (self), (GtkCallback) gtk_widget_destroy, NULL);
+
+ if (model == NULL)
+ return;
+
+ self->model = g_object_ref (model);
+ self->create_widget_func = create_widget_func;
+ self->create_widget_func_data = user_data;
+ self->create_widget_func_data_destroy = user_data_free_func;
+
+ g_signal_connect (self->model, "items-changed", G_CALLBACK (model_changed), self);
+ model_changed (model, 0, 0, g_list_model_get_n_items (model), self);
+}
+
+static void
+um_carousel_page_changed (GtkButton *button,
+ gpointer user_data)
+{
+ UmCarousel *self = UM_CAROUSEL (user_data);
+
+ set_visible_page (self, self->current_page);
+ um_carousel_select_item (self, self->current_page * ITEMS_PER_PAGE);
+
+}
+
+static void
+um_carousel_go_back_button_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ UmCarousel *self = UM_CAROUSEL (user_data);
+
+ self->current_page--;
+ if (self->current_page < 0) {
+ self->current_page = g_sequence_get_length (self->pages) - 1;
+ }
+}
+
+static void
+um_carousel_go_next_button_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ UmCarousel *self = UM_CAROUSEL (user_data);
+
+ self->current_page++;
+ if (self->current_page >= g_sequence_get_length (self->pages)) {
+ self->current_page = 0;
+ }
+}
+
+UmCarousel *
+um_carousel_new (void)
+{
+ return g_object_new (UM_TYPE_CAROUSEL, NULL);
+}
+
+static void
+um_carousel_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (um_carousel_parent_class)->finalize (object);
+}
+
+static void
+um_carousel_class_init (UmCarouselClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = um_carousel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/user-accounts/carousel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, UmCarousel, stack);
+ gtk_widget_class_bind_template_child (widget_class, UmCarousel, go_back_button);
+ gtk_widget_class_bind_template_child (widget_class, UmCarousel, go_next_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, um_carousel_go_back_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, um_carousel_go_next_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, um_carousel_page_changed);
+
+ signals[ITEM_ACTIVATED] = g_signal_new ("item-activated",
+ UM_TYPE_CAROUSEL,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_TOGGLE_BUTTON);
+}
+
+static void
+um_carousel_init (UmCarousel *self)
+{
+ self->pages = g_sequence_new (NULL);
+ self->current_page = 0;
+ self->children = g_sequence_new (NULL);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->current_button = NULL;
+}
diff --git a/panels/user-accounts/um-carousel.h b/panels/user-accounts/um-carousel.h
new file mode 100644
index 0000000..5ada721
--- /dev/null
+++ b/panels/user-accounts/um-carousel.h
@@ -0,0 +1,49 @@
+/* um-carousel.c
+ *
+ * Copyright (C) 2016 Red Hat, Inc,
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Writen by: Felipe Borges <felipeborges gnome org>
+ *
+ */
+
+#ifndef UM_CAROUSEL_H
+#define UM_CAROUSEL_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define UM_TYPE_CAROUSEL (um_carousel_get_type())
+
+G_DECLARE_FINAL_TYPE (UmCarousel, um_carousel, UM, CAROUSEL, GtkGrid)
+
+typedef GtkWidget * (*UmCarouselCreateWidgetFunc) (gpointer item,
+ gpointer user_data);
+
+UmCarousel *um_carousel_new (void);
+void um_carousel_bind_model (UmCarousel *self,
+ GListModel *model,
+ UmCarouselCreateWidgetFunc create_widget_func,
+ gpointer user_data,
+ GDestroyNotify user_data_free_func);
+
+void um_carousel_select_item (UmCarousel *self,
+ gint position);
+
+G_END_DECLS
+
+#endif /* UM_CAROUSEL_H */
diff --git a/panels/user-accounts/um-user-image.c b/panels/user-accounts/um-user-image.c
index 9bb8f31..4e78cce 100644
--- a/panels/user-accounts/um-user-image.c
+++ b/panels/user-accounts/um-user-image.c
@@ -68,8 +68,6 @@ um_user_image_finalize (GObject *object)
{
UmUserImage *image = UM_USER_IMAGE (object);
- g_clear_object (&image->priv->user);
-
G_OBJECT_CLASS (um_user_image_parent_class)->finalize (object);
}
diff --git a/panels/user-accounts/um-user-panel.c b/panels/user-accounts/um-user-panel.c
index ade84c4..a242025 100644
--- a/panels/user-accounts/um-user-panel.c
+++ b/panels/user-accounts/um-user-panel.c
@@ -43,6 +43,7 @@
#include "um-cell-renderer-user-image.h"
#include "um-arrow-frame.h"
#include "um-account-dialog.h"
+#include "um-carousel.h"
#include "cc-language-chooser.h"
#include "um-password-dialog.h"
#include "um-photo-dialog.h"
@@ -71,6 +72,8 @@ struct _CcUserPanelPrivate {
GSettings *login_screen_settings;
GtkWidget *headerbar_buttons;
+ UmCarousel *carousel;
+ UmArrowFrame *arrow_frame;
GtkWidget *main_box;
GPermission *permission;
GtkWidget *language_chooser;
@@ -80,7 +83,8 @@ struct _CcUserPanelPrivate {
UmHistoryDialog *history_dialog;
gint other_accounts;
- GtkTreeIter *other_iter;
+ GListStore *users_list;
+ ActUser *selected_user;
UmAccountDialog *account_dialog;
};
@@ -94,16 +98,6 @@ get_widget (CcUserPanelPrivate *d, const char *name)
#define PAGE_LOCK "_lock"
#define PAGE_ADDUSER "_adduser"
-enum {
- USER_COL,
- NAME_COL,
- USER_ROW_COL,
- TITLE_COL,
- HEADING_ROW_COL,
- SORT_KEY_COL,
- NUM_USER_LIST_COLS
-};
-
static void show_restart_notification (CcUserPanelPrivate *d, const gchar *locale);
typedef struct {
@@ -147,21 +141,7 @@ show_error_dialog (CcUserPanelPrivate *d,
static ActUser *
get_selected_user (CcUserPanelPrivate *d)
{
- GtkTreeView *tv;
- GtkTreeIter iter;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- ActUser *user;
-
- tv = (GtkTreeView *)get_widget (d, "list-treeview");
- selection = gtk_tree_view_get_selection (tv);
-
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (model, &iter, USER_COL, &user, -1);
- return user;
- }
-
- return NULL;
+ return d->selected_user;
}
static const gchar *
@@ -176,204 +156,89 @@ get_real_or_user_name (ActUser *user)
return name;
}
-static char *
-get_name_col_str (ActUser *user)
-{
- return g_markup_printf_escaped ("<b>%s</b>\n<small>%s</small>",
- get_real_or_user_name (user),
- act_user_get_user_name (user));
-}
-
static void show_user (ActUser *user, CcUserPanelPrivate *d);
static void
-user_added (ActUserManager *um, ActUser *user, CcUserPanelPrivate *d)
+item_toggled (UmCarousel *carousel,
+ GtkToggleButton *item,
+ CcUserPanelPrivate *d)
{
- GtkWidget *widget;
- GtkTreeModel *model;
- GtkListStore *store;
- GtkTreeIter iter;
- GtkTreeIter dummy;
- gchar *text, *title;
- GtkTreeSelection *selection;
- gint sort_key;
+ ActUser *user;
+ gint position;
- if (act_user_is_system_account (user)) {
- return;
+ position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "position"));
+ user = g_list_model_get_item (G_LIST_MODEL (d->users_list), position);
+
+ if (ACT_IS_USER (user)) {
+ show_user (user, d);
+ gtk_widget_set_sensitive (get_widget (d, "main-user-vbox"), TRUE);
+ } else {
+ gtk_widget_set_sensitive (get_widget (d, "main-user-vbox"), FALSE);
}
+}
- g_debug ("user added: %d %s\n", act_user_get_uid (user), get_real_or_user_name (user));
- widget = get_widget (d, "list-treeview");
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
- store = GTK_LIST_STORE (model);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+static GtkWidget *
+create_user_item (gpointer item,
+ gpointer user_data)
+{
+ ActUser *user = ACT_USER (item);
+ GtkWidget *widget, *grid;
- text = get_name_col_str (user);
+ grid = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
+ widget = um_user_image_new ();
+ um_user_image_set_user (UM_USER_IMAGE (widget), user);
+ gtk_grid_attach (GTK_GRID (grid), widget, 0, 0, 1, 1);
- if (act_user_get_uid (user) == getuid ()) {
- sort_key = 1;
- }
- else {
- d->other_accounts++;
- sort_key = 3;
- }
- gtk_list_store_append (store, &iter);
-
- gtk_list_store_set (store, &iter,
- USER_COL, user,
- NAME_COL, text,
- USER_ROW_COL, TRUE,
- TITLE_COL, NULL,
- HEADING_ROW_COL, FALSE,
- SORT_KEY_COL, sort_key,
- -1);
- g_free (text);
-
- if (sort_key == 1 &&
- !gtk_tree_selection_get_selected (selection, &model, &dummy)) {
- gtk_tree_selection_select_iter (selection, &iter);
- }
-
- /* Show heading for other accounts if new one have been added. */
- if (d->other_accounts == 1 && sort_key == 3) {
- title = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>", _("Other
Accounts"));
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- TITLE_COL, title,
- HEADING_ROW_COL, TRUE,
- SORT_KEY_COL, 2,
- -1);
- d->other_iter = gtk_tree_iter_copy (&iter);
- g_free (title);
- }
+ widget = gtk_label_new (get_real_or_user_name (user));
+ gtk_grid_attach (GTK_GRID (grid), widget, 0, 1, 1, 1);
+
+ return grid;
}
static void
-get_previous_user_row (GtkTreeModel *model,
- GtkTreeIter *iter,
- GtkTreeIter *prev)
+user_added (ActUserManager *um, ActUser *user, CcUserPanelPrivate *d)
{
- GtkTreePath *path;
- ActUser *user;
-
- path = gtk_tree_model_get_path (model, iter);
- while (gtk_tree_path_prev (path)) {
- gtk_tree_model_get_iter (model, prev, path);
- gtk_tree_model_get (model, prev, USER_COL, &user, -1);
- if (user) {
- g_object_unref (user);
- break;
- }
+ if (act_user_is_system_account (user)) {
+ return;
}
- gtk_tree_path_free (path);
-}
-static gboolean
-get_next_user_row (GtkTreeModel *model,
- GtkTreeIter *iter,
- GtkTreeIter *next)
-{
- ActUser *user;
+ g_debug ("user added: %d %s\n", act_user_get_uid (user), get_real_or_user_name (user));
- *next = *iter;
- while (gtk_tree_model_iter_next (model, next)) {
- gtk_tree_model_get (model, next, USER_COL, &user, -1);
- if (user) {
- g_object_unref (user);
- return TRUE;
- }
+ d->other_accounts++;
+ if (d->other_accounts > 0) {
+ um_arrow_frame_set_carousel (d->arrow_frame, d->carousel);
}
- return FALSE;
+ g_list_store_append (d->users_list, user);
}
static void
user_removed (ActUserManager *um, ActUser *user, CcUserPanelPrivate *d)
{
- GtkTreeView *tv;
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GtkListStore *store;
- GtkTreeIter iter, next;
ActUser *u;
- gint key;
+ gint i;
g_debug ("user removed: %s\n", act_user_get_user_name (user));
- tv = (GtkTreeView *)get_widget (d, "list-treeview");
- selection = gtk_tree_view_get_selection (tv);
- model = gtk_tree_view_get_model (tv);
- store = GTK_LIST_STORE (model);
- if (gtk_tree_model_get_iter_first (model, &iter)) {
- do {
- gtk_tree_model_get (model, &iter, USER_COL, &u, SORT_KEY_COL, &key, -1);
-
- if (u != NULL) {
- if (act_user_get_uid (user) == act_user_get_uid (u)) {
- if (!get_next_user_row (model, &iter, &next))
- get_previous_user_row (model, &iter, &next);
- if (key == 3) {
- d->other_accounts--;
- }
- gtk_list_store_remove (store, &iter);
- gtk_tree_selection_select_iter (selection, &next);
- g_object_unref (u);
- break;
- }
- g_object_unref (u);
- }
- } while (gtk_tree_model_iter_next (model, &iter));
- }
- /* Hide heading for other accounts if last one have been removed. */
- if (d->other_iter != NULL && d->other_accounts == 0 && key == 3) {
- gtk_list_store_remove (store, d->other_iter);
- gtk_tree_iter_free (d->other_iter);
- d->other_iter = NULL;
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (d->users_list)); i++) {
+ u = g_list_model_get_item (G_LIST_MODEL (d->users_list), i);
+ if (u != NULL && (act_user_get_uid (u) == act_user_get_uid (user))) {
+ g_list_store_remove (d->users_list, i);
+ d->other_accounts--;
+ break;
+ }
}
}
static void
user_changed (ActUserManager *um, ActUser *user, CcUserPanelPrivate *d)
{
- GtkTreeView *tv;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
ActUser *current;
- char *text;
-
- tv = (GtkTreeView *)get_widget (d, "list-treeview");
- model = gtk_tree_view_get_model (tv);
- selection = gtk_tree_view_get_selection (tv);
-
- g_assert (gtk_tree_model_get_iter_first (model, &iter));
- do {
- gtk_tree_model_get (model, &iter, USER_COL, ¤t, -1);
- if (current == user) {
- text = get_name_col_str (user);
-
- gtk_list_store_set (GTK_LIST_STORE (model), &iter,
- USER_COL, user,
- NAME_COL, text,
- -1);
- g_free (text);
- g_object_unref (current);
- break;
- }
- if (current)
- g_object_unref (current);
-
- } while (gtk_tree_model_iter_next (model, &iter));
-
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (model, &iter, USER_COL, ¤t, -1);
-
- if (current == user) {
- show_user (user, d);
- }
- if (current)
- g_object_unref (current);
+ current = get_selected_user (d);
+ if (current == user) {
+ show_user (user, d);
}
}
@@ -384,14 +249,7 @@ select_created_user (GObject *object,
{
CcUserPanelPrivate *d = user_data;
UmAccountDialog *dialog;
- GtkTreeView *tv;
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GtkTreeIter iter;
- ActUser *current;
- GtkTreePath *path;
ActUser *user;
- uid_t user_uid;
dialog = UM_ACCOUNT_DIALOG (object);
user = um_account_dialog_finish (dialog, result);
@@ -401,26 +259,7 @@ select_created_user (GObject *object,
if (user == NULL)
return;
- tv = (GtkTreeView *)get_widget (d, "list-treeview");
- model = gtk_tree_view_get_model (tv);
- selection = gtk_tree_view_get_selection (tv);
- user_uid = act_user_get_uid (user);
-
- g_assert (gtk_tree_model_get_iter_first (model, &iter));
- do {
- gtk_tree_model_get (model, &iter, USER_COL, ¤t, -1);
- if (current) {
- if (user_uid == act_user_get_uid (current)) {
- path = gtk_tree_model_get_path (model, &iter);
- gtk_tree_view_scroll_to_cell (tv, path, NULL, FALSE, 0.0, 0.0);
- gtk_tree_selection_select_path (selection, path);
- gtk_tree_path_free (path);
- g_object_unref (current);
- break;
- }
- g_object_unref (current);
- }
- } while (gtk_tree_model_iter_next (model, &iter));
+ d->selected_user = user;
g_object_unref (user);
}
@@ -483,8 +322,6 @@ delete_user_response (GtkWidget *dialog,
NULL,
(GAsyncReadyCallback)delete_user_done,
d);
-
- g_object_unref (user);
}
static void
@@ -735,8 +572,6 @@ delete_user (GtkButton *button, CcUserPanel *self)
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_present (GTK_WINDOW (dialog));
-
- g_object_unref (user);
}
static const gchar *
@@ -879,6 +714,8 @@ show_user (ActUser *user, CcUserPanelPrivate *d)
gboolean show, enable;
ActUser *current;
+ d->selected_user = user;
+
image = get_widget (d, "user-icon-image");
um_user_image_set_user (UM_USER_IMAGE (image), user);
image = get_widget (d, "user-icon-image2");
@@ -977,23 +814,6 @@ show_user (ActUser *user, CcUserPanelPrivate *d)
}
static void
-selected_user_changed (GtkTreeSelection *selection, CcUserPanelPrivate *d)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- ActUser *user;
-
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (model, &iter, USER_COL, &user, -1);
- show_user (user, d);
- gtk_widget_set_sensitive (get_widget (d, "main-user-vbox"), TRUE);
- g_object_unref (user);
- } else {
- gtk_widget_set_sensitive (get_widget (d, "main-user-vbox"), FALSE);
- }
-}
-
-static void
change_name_done (GtkWidget *entry,
CcUserPanelPrivate *d)
{
@@ -1035,11 +855,10 @@ account_type_changed (GtkToggleButton *button,
if (account_type != act_user_get_account_type (user)) {
act_user_set_account_type (user, account_type);
+ show_user (user, d);
if (self_selected)
show_restart_notification (d, NULL);
}
-
- g_object_unref (user);
}
static void
@@ -1224,55 +1043,6 @@ show_history (GtkButton *button, CcUserPanelPrivate *d)
g_object_unref (user);
}
-static gint
-sort_users (GtkTreeModel *model,
- GtkTreeIter *a,
- GtkTreeIter *b,
- gpointer data)
-{
- ActUser *ua, *ub;
- gint sa, sb;
- gint result;
-
- gtk_tree_model_get (model, a, USER_COL, &ua, SORT_KEY_COL, &sa, -1);
- gtk_tree_model_get (model, b, USER_COL, &ub, SORT_KEY_COL, &sb, -1);
-
- if (sa < sb) {
- result = -1;
- }
- else if (sa > sb) {
- result = 1;
- }
- else {
- result = act_user_collate (ua, ub);
- }
-
- if (ua) {
- g_object_unref (ua);
- }
- if (ub) {
- g_object_unref (ub);
- }
-
- return result;
-}
-
-static gboolean
-dont_select_headings (GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean selected,
- gpointer data)
-{
- GtkTreeIter iter;
- gboolean is_user;
-
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (model, &iter, USER_ROW_COL, &is_user, -1);
-
- return is_user;
-}
-
static void
users_loaded (ActUserManager *manager,
GParamSpec *pspec,
@@ -1303,17 +1073,20 @@ users_loaded (ActUserManager *manager,
g_signal_connect (d->um, "user-changed", G_CALLBACK (user_changed), d);
g_signal_connect (d->um, "user-is-logged-in-changed", G_CALLBACK (user_changed), d);
+ g_signal_connect (d->um, "user-added", G_CALLBACK (user_added), d);
+ g_signal_connect (d->um, "user-removed", G_CALLBACK (user_removed), d);
for (l = list; l; l = l->next) {
user = l->data;
g_debug ("adding user %s\n", get_real_or_user_name (user));
user_added (d->um, user, d);
}
- show_user (list->data, d);
- g_slist_free (list);
- g_signal_connect (d->um, "user-added", G_CALLBACK (user_added), d);
- g_signal_connect (d->um, "user-removed", G_CALLBACK (user_removed), d);
+ /* Present the first user account (administrator). */
+ d->selected_user = ACT_USER (list->data);
+ show_user (d->selected_user, d);
+ um_carousel_select_item (d->carousel, 0);
+ g_slist_free (list);
}
static void
@@ -1364,8 +1137,6 @@ on_permission_changed (GPermission *permission,
}
is_authorized = g_permission_get_allowed (G_PERMISSION (d->permission));
- self_selected = act_user_get_uid (user) == geteuid ();
-
gtk_stack_set_visible_child_name (GTK_STACK (d->headerbar_buttons), is_authorized ? PAGE_ADDUSER :
PAGE_LOCK);
widget = get_widget (d, "add-user-toolbutton");
@@ -1389,6 +1160,7 @@ on_permission_changed (GPermission *permission,
}
widget = get_widget (d, "remove-user-toolbutton");
+ self_selected = act_user_get_uid (user) == geteuid ();
gtk_widget_set_sensitive (widget, is_authorized && !self_selected
&& !would_demote_only_admin (user));
if (is_authorized) {
@@ -1485,145 +1257,25 @@ on_permission_changed (GPermission *permission,
g_object_unref (user);
}
-static gboolean
-match_user (GtkTreeModel *model,
- gint column,
- const gchar *key,
- GtkTreeIter *iter,
- gpointer search_data)
-{
- ActUser *user;
- const gchar *name;
- gchar *normalized_key = NULL;
- gchar *normalized_name = NULL;
- gchar *case_normalized_key = NULL;
- gchar *case_normalized_name = NULL;
- gchar *p;
- gboolean result = TRUE;
- gint i;
-
- gtk_tree_model_get (model, iter, USER_COL, &user, -1);
-
- if (!user) {
- goto out;
- }
-
- normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
- if (!normalized_key) {
- goto out;
- }
-
- case_normalized_key = g_utf8_casefold (normalized_key, -1);
-
- for (i = 0; i < 2; i++) {
- if (i == 0) {
- name = act_user_get_real_name (user);
- }
- else {
- name = act_user_get_user_name (user);
- }
- g_free (normalized_name);
- normalized_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
- if (normalized_name) {
- g_free (case_normalized_name);
- case_normalized_name = g_utf8_casefold (normalized_name, -1);
- p = strstr (case_normalized_name, case_normalized_key);
-
- /* poor man's \b */
- if (p == case_normalized_name || (p && p[-1] == ' ')) {
- result = FALSE;
- break;
- }
- }
- }
-
- out:
- if (user) {
- g_object_unref (user);
- }
- g_free (normalized_key);
- g_free (case_normalized_key);
- g_free (normalized_name);
- g_free (case_normalized_name);
-
- return result;
-}
-
static void
setup_main_window (CcUserPanel *self)
{
CcUserPanelPrivate *d = self->priv;
- GtkWidget *userlist;
- GtkTreeModel *model;
- GtkListStore *store;
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell;
- GtkTreeSelection *selection;
GtkWidget *button;
- GtkTreeIter iter;
- gint expander_size;
- gchar *title;
GIcon *icon;
GError *error = NULL;
gchar *names[3];
gboolean loaded;
- userlist = get_widget (d, "list-treeview");
- store = gtk_list_store_new (NUM_USER_LIST_COLS,
- ACT_TYPE_USER,
- G_TYPE_STRING,
- G_TYPE_BOOLEAN,
- G_TYPE_STRING,
- G_TYPE_BOOLEAN,
- G_TYPE_INT);
- model = (GtkTreeModel *)store;
- gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model), sort_users, NULL, NULL);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
- gtk_tree_view_set_model (GTK_TREE_VIEW (userlist), model);
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (userlist), USER_COL);
- gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (userlist),
- match_user, NULL, NULL);
- g_object_unref (model);
-
- gtk_widget_style_get (userlist, "expander-size", &expander_size, NULL);
- gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (userlist), - (expander_size + 6));
-
- title = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>", _("My Account"));
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- TITLE_COL, title,
- HEADING_ROW_COL, TRUE,
- SORT_KEY_COL, 0,
- -1);
- g_free (title);
-
+ d->selected_user = NULL;
d->other_accounts = 0;
- d->other_iter = NULL;
-
- column = gtk_tree_view_column_new ();
- cell = um_cell_renderer_user_image_new (userlist);
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column), cell, FALSE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (column), cell, "user", USER_COL);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (column), cell, "visible", USER_ROW_COL);
- cell = gtk_cell_renderer_text_new ();
- g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column), cell, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (column), cell, "markup", NAME_COL);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (column), cell, "visible", USER_ROW_COL);
- cell = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column), cell, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (column), cell, "markup", TITLE_COL);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (column), cell, "visible", HEADING_ROW_COL);
-
- gtk_tree_view_append_column (GTK_TREE_VIEW (userlist), column);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (userlist));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
- g_signal_connect (selection, "changed", G_CALLBACK (selected_user_changed), d);
- gtk_tree_selection_set_select_function (selection, dont_select_headings, NULL, NULL);
-
- gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (get_widget (d,
"list-scrolledwindow")), 300);
- gtk_widget_set_size_request (get_widget (d, "list-scrolledwindow"), 200, -1);
+
+ d->arrow_frame = UM_ARROW_FRAME (get_widget (d, "arrow-frame"));
+ d->carousel = UM_CAROUSEL (get_widget (d, "carousel"));
+ g_signal_connect (d->carousel, "item-activated", G_CALLBACK (item_toggled), d);
+ d->users_list = g_list_store_new (act_user_get_type ());
+ um_carousel_bind_model (d->carousel, G_LIST_MODEL (d->users_list),
+ create_user_item, NULL, NULL);
button = get_widget (d, "add-user-toolbutton");
g_signal_connect (button, "clicked", G_CALLBACK (add_user), d);
@@ -1745,6 +1397,7 @@ cc_user_panel_init (CcUserPanel *self)
/* register types that the builder might need */
type = um_arrow_frame_get_type ();
+ type = um_carousel_get_type ();
type = um_user_image_get_type ();
type = um_cell_renderer_user_image_get_type ();
@@ -1772,6 +1425,7 @@ cc_user_panel_init (CcUserPanel *self)
d->main_box = get_widget (d, "accounts-vbox");
gtk_container_add (GTK_CONTAINER (self), get_widget (d, "overlay"));
d->history_dialog = um_history_dialog_new ();
+
setup_main_window (self);
}
@@ -1817,9 +1471,8 @@ cc_user_panel_dispose (GObject *object)
g_object_unref (priv->permission);
priv->permission = NULL;
}
- if (priv->other_iter) {
- gtk_tree_iter_free (priv->other_iter);
- priv->other_iter = NULL;
+ if (priv->selected_user) {
+ g_object_unref (priv->selected_user);
}
G_OBJECT_CLASS (cc_user_panel_parent_class)->dispose (object);
}
diff --git a/panels/user-accounts/user-accounts.gresource.xml
b/panels/user-accounts/user-accounts.gresource.xml
index ad57a8a..4bedc2d 100644
--- a/panels/user-accounts/user-accounts.gresource.xml
+++ b/panels/user-accounts/user-accounts.gresource.xml
@@ -7,6 +7,7 @@
<file alias="password-dialog.ui" preprocess="xml-stripblanks">data/password-dialog.ui</file>
<file alias="history-dialog.ui" preprocess="xml-stripblanks">data/history-dialog.ui</file>
<file alias="user-accounts-dialog.ui" preprocess="xml-stripblanks">data/user-accounts-dialog.ui</file>
+ <file alias="carousel.ui" preprocess="xml-stripblanks">data/carousel.ui</file>
<file alias="left-index-finger.png">data/icons/left-index-finger.png</file>
<file alias="left-middle-finger.png">data/icons/left-middle-finger.png</file>
<file alias="left-little-finger.png">data/icons/left-little-finger.png</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]