Evolution had the same problem, so steal their fix.
The spinning image comes out a good bit lighter than GtkSpinner. This may have something to do with how gtk processes symbolic icons? I don't know. I put the steps I took to create the png into a comment in the widget code. Something weird and dumb is going on with what gtk thinks a color is and if anyone can fix that that would be great.
From: David Shea dshea@redhat.com
GtkSpinner chews up CPU cycles like candy, which is especially noticable on a VM, so steal a workaround from Evolution. --- pyanaconda/ui/gui/hubs/progress.glade | 7 +- pyanaconda/ui/gui/spokes/advstorage/dasd.glade | 36 +-- pyanaconda/ui/gui/spokes/advstorage/fcoe.glade | 13 +- pyanaconda/ui/gui/spokes/advstorage/iscsi.glade | 57 ++-- pyanaconda/ui/gui/spokes/advstorage/zfcp.glade | 45 +--- pyanaconda/ui/gui/spokes/lib/dasdfmt.glade | 28 +- pyanaconda/ui/gui/spokes/lib/refresh.glade | 31 +-- widgets/data/pixmaps/working.png | Bin 0 -> 14513 bytes widgets/glade/AnacondaWidgets.xml | 37 ++- widgets/src/Makefile.am | 4 +- widgets/src/Spinner.c | 330 ++++++++++++++++++++++++ widgets/src/Spinner.h | 60 +++++ 12 files changed, 515 insertions(+), 133 deletions(-) create mode 100644 widgets/data/pixmaps/working.png create mode 100644 widgets/src/Spinner.c create mode 100644 widgets/src/Spinner.h
diff --git a/pyanaconda/ui/gui/hubs/progress.glade b/pyanaconda/ui/gui/hubs/progress.glade index b072e32..01af1b1 100644 --- a/pyanaconda/ui/gui/hubs/progress.glade +++ b/pyanaconda/ui/gui/hubs/progress.glade @@ -2,7 +2,7 @@ <!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.0"/> - <requires lib="AnacondaWidgets" version="3.0"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="AnacondaHubWindow" id="progressWindow"> <property name="can_focus">False</property> <property name="window_name" translatable="yes">CONFIGURATION</property> @@ -23,9 +23,6 @@ <child> <placeholder/> </child> - <child> - <placeholder/> - </child> </object> </child> </object> @@ -72,7 +69,7 @@ <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <object class="GtkSpinner" id="progressSpinner"> + <object class="AnacondaSpinner" id="progressSpinner"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="active">True</property> diff --git a/pyanaconda/ui/gui/spokes/advstorage/dasd.glade b/pyanaconda/ui/gui/spokes/advstorage/dasd.glade index 2246829..588a1e6 100644 --- a/pyanaconda/ui/gui/spokes/advstorage/dasd.glade +++ b/pyanaconda/ui/gui/spokes/advstorage/dasd.glade @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.16.1 --> +<!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.0"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="GtkDialog" id="dasdDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> @@ -22,8 +23,8 @@ <property name="label" translatable="yes" context="GUI|Advanced Storage|DASD|Configure">_Cancel</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="use_underline">True</property> <property name="receives_default">True</property> + <property name="use_underline">True</property> </object> <packing> <property name="expand">False</property> @@ -37,8 +38,8 @@ <property name="visible">True</property> <property name="sensitive">False</property> <property name="can_focus">True</property> - <property name="use_underline">True</property> <property name="receives_default">True</property> + <property name="use_underline">True</property> </object> <packing> <property name="expand">False</property> @@ -64,8 +65,8 @@ <object class="GtkLabel" id="label1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">ADD DASD STORAGE TARGET</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -93,15 +94,14 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_bottom">6</property> - <property name="xalign">0</property> <property name="label" translatable="yes">To use DASD disks, you must provide the device number.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> <property name="top_attach">0</property> <property name="width">3</property> - <property name="height">1</property> </packing> </child> <child> @@ -114,23 +114,20 @@ <property name="left_attach">1</property> <property name="top_attach">1</property> <property name="width">2</property> - <property name="height">1</property> </packing> </child> <child> <object class="GtkLabel" id="label6"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|DASD|Configure">_Device number:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">deviceEntry</property> + <property name="xalign">0</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> </packing> </child> <child> @@ -164,7 +161,7 @@ <property name="halign">center</property> <property name="spacing">5</property> <child> - <object class="GtkSpinner" id="waitSpinner"> + <object class="AnacondaSpinner" id="waitSpinner"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="active">True</property> @@ -212,16 +209,14 @@ <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="label14"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Device discovery failed.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -229,37 +224,31 @@ <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="label22"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">The following error occurred discovering DASD devices. Please double check your configuration information and try again.</property> <property name="wrap">True</property> + <property name="xalign">0</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> <child> <object class="GtkLabel" id="deviceErrorLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label">Error message goes here.</property> + <property name="xalign">0</property> </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> @@ -276,8 +265,6 @@ <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> @@ -302,7 +289,6 @@ <property name="left_attach">0</property> <property name="top_attach">2</property> <property name="width">3</property> - <property name="height">1</property> </packing> </child> </object> diff --git a/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade b/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade index cec4717..63e78f8 100644 --- a/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade +++ b/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade @@ -2,6 +2,7 @@ <!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.0"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="GtkDialog" id="fcoeDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> @@ -52,9 +53,9 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_bottom">6</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Please select the network interface which is connected to your FCoE switch.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -66,10 +67,10 @@ <object class="GtkLabel" id="label2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|FCoE">_NIC:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">nicCombo</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -126,7 +127,7 @@ <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <object class="GtkSpinner" id="addSpinner"> + <object class="AnacondaSpinner" id="addSpinner"> <property name="can_focus">False</property> <property name="no_show_all">True</property> <property name="halign">end</property> @@ -183,8 +184,8 @@ <object class="GtkLabel" id="label3"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Error adding FCoE SAN.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -198,9 +199,9 @@ <object class="GtkLabel" id="errorLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label">Error message goes here.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> @@ -211,9 +212,9 @@ <object class="GtkLabel" id="label4"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">The following error occurred while attempting to add an FCoE SAN. Please check your configuration and try again</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> diff --git a/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade b/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade index 203a66f..4e83342 100644 --- a/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade +++ b/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade @@ -2,6 +2,7 @@ <!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.0"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="GtkListStore" id="nodeStore"> <columns> <!-- column-name nodeSelected --> @@ -82,8 +83,8 @@ <object class="GtkLabel" id="label1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">ADD iSCSI STORAGE TARGET</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -111,9 +112,9 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_bottom">6</property> - <property name="xalign">0</property> <property name="label" translatable="yes">To use iSCSI disks, you must provide the address of your iSCSI target and the iSCSI initiator name you've configured for your host.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -138,10 +139,10 @@ <object class="GtkLabel" id="label6"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure">_Target IP Address:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">targetEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -165,10 +166,10 @@ <object class="GtkLabel" id="label7"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure">iSCSI _Initiator Name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">initiatorEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -198,10 +199,10 @@ <object class="GtkLabel" id="label8"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure">_Discovery Authentication Type:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">authTypeCombo</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -213,9 +214,9 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes"><span size="small"><b>Example:</b> iqn.2012-09.com.example:diskarrays-sn-a8675309</span></property> <property name="use_markup">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">2</property> @@ -258,10 +259,10 @@ <object class="GtkLabel" id="label2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure|CHAP">CHAP _User name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">chapUsernameEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -272,10 +273,10 @@ <object class="GtkLabel" id="label3"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure|CHAP">CHAP _Password:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">chapPasswordEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -378,10 +379,10 @@ <object class="GtkLabel" id="label4"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure|Reverse CHAP">CHAP _User name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">rchapUsernameEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -392,10 +393,10 @@ <object class="GtkLabel" id="label10"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure|Reverse CHAP">CHAP _Password:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">rchapPasswordEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -406,10 +407,10 @@ <object class="GtkLabel" id="label11"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure|Reverse CHAP">Reverse CHAP User _name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">rchapReverseUsername</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -420,10 +421,10 @@ <object class="GtkLabel" id="label12"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Configure|Reverse CHAP">Reverse CHAP Pass_word:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">rchapReversePassword</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -476,7 +477,7 @@ <property name="halign">center</property> <property name="spacing">5</property> <child> - <object class="GtkSpinner" id="waitSpinner"> + <object class="AnacondaSpinner" id="waitSpinner"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="active">True</property> @@ -530,8 +531,8 @@ <object class="GtkLabel" id="label14"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Discovery login rejected.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -545,9 +546,9 @@ <object class="GtkLabel" id="label22"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">The following error occurred discovering iSCSI targets. Please double check your authorization information and try again.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> @@ -558,8 +559,8 @@ <object class="GtkLabel" id="discoveryErrorLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label">Error message goes here.</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> @@ -642,10 +643,10 @@ <object class="GtkLabel" id="discoveredLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label">The following nodes have been discovered using the iSCSI initiator <b>%(initiatorName)s</b> using the target IP address <b>%(targetAddress)s</b>. Please select which nodes you wish to log into:</property> <property name="use_markup">True</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -733,10 +734,10 @@ <object class="GtkLabel" id="loginAuthTypeLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login">_Node Login Authentication Type:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginAuthTypeCombo</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -785,10 +786,10 @@ <object class="GtkLabel" id="label15"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login|CHAP">CHAP _User name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginChapUsernameEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -799,10 +800,10 @@ <object class="GtkLabel" id="label16"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login|CHAP">CHAP _Password:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginChapPasswordEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -905,10 +906,10 @@ <object class="GtkLabel" id="label17"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login|Reverse CHAP">CHAP _User name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginRchapUsernameEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -919,10 +920,10 @@ <object class="GtkLabel" id="label18"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login|Reverse CHAP">CHAP _Password:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginRchapPasswordEntry</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -933,10 +934,10 @@ <object class="GtkLabel" id="label19"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login|Reverse CHAP">_Reverse CHAP User name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginRchapReverseUsername</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -947,10 +948,10 @@ <object class="GtkLabel" id="label20"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|iSCSI|Login|Reverse CHAP">Reverse CHAP Pass_word:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">loginRchapReversePassword</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -1012,7 +1013,7 @@ </packing> </child> <child> - <object class="GtkSpinner" id="loginSpinner"> + <object class="AnacondaSpinner" id="loginSpinner"> <property name="can_focus">False</property> <property name="no_show_all">True</property> <property name="active">True</property> @@ -1051,8 +1052,8 @@ <object class="GtkLabel" id="label21"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Node login failed.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -1066,9 +1067,9 @@ <object class="GtkLabel" id="label23"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">The following error occurred logging into the selected iSCSI node. Please double check your authorization information and try again</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> @@ -1079,8 +1080,8 @@ <object class="GtkLabel" id="loginErrorLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label">Error message goes here.</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> diff --git a/pyanaconda/ui/gui/spokes/advstorage/zfcp.glade b/pyanaconda/ui/gui/spokes/advstorage/zfcp.glade index 56b95a5..8883561 100644 --- a/pyanaconda/ui/gui/spokes/advstorage/zfcp.glade +++ b/pyanaconda/ui/gui/spokes/advstorage/zfcp.glade @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.18.3 --> <interface> - <!-- interface-requires gtk+ 3.0 --> + <requires lib="gtk+" version="3.0"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="GtkListStore" id="nodeStore"> <columns> <!-- column-name nodeSelected --> @@ -78,8 +80,8 @@ <object class="GtkLabel" id="label1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">ADD zFCP STORAGE TARGET</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -107,15 +109,14 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_bottom">6</property> - <property name="xalign">0</property> <property name="label" translatable="yes">To use zFCP disks, you must provide the device number, WWPN, and LUN configured for the device.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> <property name="top_attach">0</property> <property name="width">3</property> - <property name="height">1</property> </packing> </child> <child> @@ -128,23 +129,20 @@ <property name="left_attach">1</property> <property name="top_attach">1</property> <property name="width">2</property> - <property name="height">1</property> </packing> </child> <child> <object class="GtkLabel" id="label6"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="GUI|Advanced Storage|zFCP|Device Number">_Device number:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">deviceEntry</property> + <property name="xalign">0</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> </packing> </child> <child> @@ -157,23 +155,19 @@ <property name="left_attach">1</property> <property name="top_attach">2</property> <property name="width">2</property> - <property name="height">1</property> </packing> </child> <child> <object class="GtkLabel" id="label7"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">WWPN:</property> - <property name="use_underline">False</property> <property name="mnemonic_widget">wwpnEntry</property> + <property name="xalign">0</property> </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> @@ -207,7 +201,7 @@ <property name="halign">center</property> <property name="spacing">5</property> <child> - <object class="GtkSpinner" id="waitSpinner"> + <object class="AnacondaSpinner" id="waitSpinner"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="active">True</property> @@ -255,16 +249,14 @@ <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="label14"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Device discovery failed.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -272,37 +264,31 @@ <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="label22"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">The following error occurred discovering zFCP devices. Please double check your configuration information and try again.</property> <property name="wrap">True</property> + <property name="xalign">0</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> <child> <object class="GtkLabel" id="deviceErrorLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label">Error message goes here.</property> + <property name="xalign">0</property> </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> @@ -319,8 +305,6 @@ <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> @@ -345,23 +329,19 @@ <property name="left_attach">0</property> <property name="top_attach">7</property> <property name="width">3</property> - <property name="height">1</property> </packing> </child> <child> <object class="GtkLabel" id="label2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">LUN:</property> - <property name="use_underline">False</property> <property name="mnemonic_widget">lunEntry</property> + <property name="xalign">0</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> </packing> </child> <child> @@ -374,7 +354,6 @@ <property name="left_attach">1</property> <property name="top_attach">3</property> <property name="width">2</property> - <property name="height">1</property> </packing> </child> <child> diff --git a/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade b/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade index f93bcbc..d362e20 100644 --- a/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade +++ b/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade @@ -2,6 +2,7 @@ <!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.6"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="GtkDialog" id="unformattedDasdDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> @@ -179,17 +180,6 @@ <property name="row_spacing">18</property> <property name="column_spacing">6</property> <child> - <object class="GtkSpinner" id="spinner4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="active">True</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> <object class="GtkLabel" id="formatLabel"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -217,6 +207,17 @@ installation options while formatting completes.</property> <property name="width">2</property> </packing> </child> + <child> + <object class="AnacondaSpinner" id="spinner4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> </object> <packing> <property name="position">1</property> @@ -243,8 +244,8 @@ installation options while formatting completes.</property> <object class="GtkLabel" id="label18"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Disk formatting complete.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -266,6 +267,9 @@ installation options while formatting completes.</property> <property name="height">2</property> </packing> </child> + <child> + <placeholder/> + </child> </object> <packing> <property name="position">3</property> diff --git a/pyanaconda/ui/gui/spokes/lib/refresh.glade b/pyanaconda/ui/gui/spokes/lib/refresh.glade index 08ecb20..56ef52e 100644 --- a/pyanaconda/ui/gui/spokes/lib/refresh.glade +++ b/pyanaconda/ui/gui/spokes/lib/refresh.glade @@ -2,6 +2,7 @@ <!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.0"/> + <requires lib="AnacondaWidgets" version="3.2"/> <object class="GtkDialog" id="refreshDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> @@ -67,8 +68,8 @@ <object class="GtkLabel" id="label1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">RESCAN DISKS</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -83,9 +84,9 @@ <object class="GtkLabel" id="label2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">You can remove or insert additional disks at this time and press 'Rescan Disks' below for the changes to take effect.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="expand">False</property> @@ -195,17 +196,6 @@ <property name="row_spacing">18</property> <property name="column_spacing">6</property> <child> - <object class="GtkSpinner" id="spinner2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="active">True</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> <object class="GtkLabel" id="label8"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -233,6 +223,17 @@ installation options while this scan completes.</property> <property name="width">2</property> </packing> </child> + <child> + <object class="AnacondaSpinner" id="spinner2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> </object> <packing> <property name="position">2</property> @@ -250,8 +251,8 @@ installation options while this scan completes.</property> <object class="GtkLabel" id="label11"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Disk rescan complete.</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -265,9 +266,9 @@ installation options while this scan completes.</property> <object class="GtkLabel" id="label12"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Pressing 'OK' below will take you to the disk selection screen where you will need to re-select your disks.</property> <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> diff --git a/widgets/data/pixmaps/working.png b/widgets/data/pixmaps/working.png new file mode 100644 index 0000000000000000000000000000000000000000..629d60ef9621ab16816fe2e813654a709a8e7200 GIT binary patch literal 14513 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
literal 0 HcmV?d00001
diff --git a/widgets/glade/AnacondaWidgets.xml b/widgets/glade/AnacondaWidgets.xml index 673101d..bb7769f 100644 --- a/widgets/glade/AnacondaWidgets.xml +++ b/widgets/glade/AnacondaWidgets.xml @@ -142,14 +142,34 @@ </properties> </glade-widget-class>
- <glade-widget-class title="Layout Indicator" - name="AnacondaLayoutIndicator" - icon-name="widget-gtk-label" - generic-name="AnacondaLayoutIndicator"> - <properties> - <property id="label-width" default="12" /> - </properties> - </glade-widget-class> + <glade-widget-class title="Layout Indicator" + name="AnacondaLayoutIndicator" + icon-name="widget-gtk-label" + generic-name="AnacondaLayoutIndicator"> + <properties> + <property id="label-width" default="12" /> + </properties> + </glade-widget-class> + + <glade-widget-class title="Spinner" + name="AnacondaSpinner" + icon-name="widget-gtk-spinner" + generic-name="AnacondaSpinner" + since="3.2"> + <properties> + <!-- Remove properties inherited from GtkImage --> + <!-- Setting disabled doesn't hide them in the glade interface + (nor does setting visible, oddly), but it keeps them being + saved and that's almost as good. --> + <property id="stock" disabled="True"/> + <property id="icon-name" disabled="True"/> + <property id="use-fallback" disabled="True"/> + <property id="pixbuf" disabled="True"/> + <property id="resource" disabled="True"/> + <property id="pixel-size" disabled="True"/> + </properties> + </glade-widget-class> + </glade-widget-classes>
<glade-widget-group name="anaconda-windows" title="Anaconda Windows"> @@ -165,5 +185,6 @@ <glade-widget-group name="anaconda-misc-widgets" title="Anaconda Miscellaneous Widgets"> <glade-widget-class-ref name="AnacondaSpokeSelector" /> <glade-widget-class-ref name="AnacondaLayoutIndicator" /> + <glade-widget-class-ref name="AnacondaSpinner" /> </glade-widget-group> </glade-catalog> diff --git a/widgets/src/Makefile.am b/widgets/src/Makefile.am index e5b3097..c0ecbcc 100644 --- a/widgets/src/Makefile.am +++ b/widgets/src/Makefile.am @@ -34,6 +34,7 @@ GISOURCES = BaseWindow.c \ StandaloneWindow.c \ LayoutIndicator.c \ BaseStandalone.c \ + Spinner.c \ widgets-common.c
GIHDRS = BaseWindow.h \ @@ -45,6 +46,7 @@ GIHDRS = BaseWindow.h \ StandaloneWindow.h \ LayoutIndicator.h \ BaseStandalone.h \ + Spinner.h \ widgets-common.h
NONGISOURCES = @@ -63,7 +65,7 @@ lib_LTLIBRARIES = libAnacondaWidgets.la libAnacondaWidgets_la_CFLAGS = $(GTK_CFLAGS) $(GLADEUI_CFLAGS) $(LIBXKLAVIER_CFLAGS) -Wall -g\ -DWIDGETS_DATADIR=$(WIDGETSDATA) libAnacondaWidgets_la_LIBADD = $(GTK_LIBS) $(GLADEUI_LIBS) $(LIBXKLAVIER_LIBS) -libAnacondaWidgets_la_LDFLAGS = $(LTLIBINTL) -version-info 3:1:1 +libAnacondaWidgets_la_LDFLAGS = $(LTLIBINTL) -version-info 4:0:2 libAnacondaWidgets_la_SOURCES = $(SOURCES) $(HDRS) \ glade-adaptor.c
diff --git a/widgets/src/Spinner.c b/widgets/src/Spinner.c new file mode 100644 index 0000000..46e2668 --- /dev/null +++ b/widgets/src/Spinner.c @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation. + * + * 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 Lesser General Public License + * along with this program; if not, see http://www.gnu.org/licenses/. + * + * Authors: Milan Crha mcrha@redhat.com + */ + +/* NOTE FROM ANACONDA: + * This widget is a search/replace of ESpinner from Evolution (LGPL, see + * above), because GtkSpinner doesn't run so good in a VM. See + * https://bugzilla.gnome.org/show_bug.cgi?id=732180 and + * https://bugzilla.gnome.org/show_bug.cgi?id=732199. + * + * The source of the animation is a PNG containing each frame to animate, + * arranged in a 7x5 grid. It was created with Inkscape by doing the following: + * - Load process-working-symbolic.svg from adwaita-icon-theme + * - In File->Document Properties, change the background to transparent (alpha 0) + * - Select the spinner, Edit->Clone->Create Tiled Clones... + * * Set the clone to 5x7 rows, columns + * * There's a rotation option here, but it acted kind of weird, so I left it alone + * - Rotate each object by the appropriate multiple of 360 / 35 degrees using Object->Transform + * * You can select more than one at once with shift+click so it doesn't take that long + * - File->Export PNG Image... + * * Choose Drawing, and 112x80 for the image size + * * Size has to match FRAME_SIZE below + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtk.h> + +#include "Spinner.h" +#include "widgets-common.h" + +#define MAIN_IMAGE_FILENAME "working.png" +#define FRAME_SIZE 16 +#define FRAME_TIMEOUT_MS 100 + +struct _AnacondaSpinnerPrivate +{ + GSList *pixbufs; + GSList *current_frame; /* link of 'pixbufs' */ + gboolean active; + guint timeout_id; +}; + +enum { + PROP_0, + PROP_ACTIVE +}; + +G_DEFINE_TYPE (AnacondaSpinner, anaconda_spinner, GTK_TYPE_IMAGE) + +static gboolean +anaconda_spinner_update_frame_cb (gpointer user_data) +{ + AnacondaSpinner *spinner = user_data; + + g_return_val_if_fail (ANACONDA_IS_SPINNER (spinner), FALSE); + + if (spinner->priv->current_frame) + spinner->priv->current_frame = spinner->priv->current_frame->next; + if (!spinner->priv->current_frame) + spinner->priv->current_frame = spinner->priv->pixbufs; + + if (!spinner->priv->current_frame) { + g_warn_if_reached (); + return FALSE; + } + + gtk_image_set_from_pixbuf (GTK_IMAGE (spinner), spinner->priv->current_frame->data); + + return TRUE; +} + +static void +anaconda_spinner_enable_spin (AnacondaSpinner *spinner) +{ + spinner->priv->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, FRAME_TIMEOUT_MS, anaconda_spinner_update_frame_cb, spinner, NULL); +} + +static void +anaconda_spinner_disable_spin (AnacondaSpinner *spinner) +{ + if (spinner->priv->timeout_id) + { + g_source_remove (spinner->priv->timeout_id); + spinner->priv->timeout_id = 0; + } +} + +static void +anaconda_spinner_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE: + anaconda_spinner_set_active ( + ANACONDA_SPINNER (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +anaconda_spinner_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE: + g_value_set_boolean ( + value, + anaconda_spinner_get_active (ANACONDA_SPINNER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +anaconda_spinner_constructed (GObject *object) +{ + AnacondaSpinner *spinner; + GdkPixbuf *main_pixbuf; + gint xx, yy, width, height; + GError *error = NULL; + gchar *filename; + + /* Chain up to parent's method. */ + G_OBJECT_CLASS (anaconda_spinner_parent_class)->constructed (object); + + spinner = ANACONDA_SPINNER (object); + + filename = g_strdup_printf("%s/pixmaps/%s", anaconda_get_widgets_datadir(), MAIN_IMAGE_FILENAME); + main_pixbuf = gdk_pixbuf_new_from_file (filename, &error); + g_free(filename); + + if (!main_pixbuf) { + g_warning ("%s: Failed to load image: %s", error ? error->message : "Unknown error", G_STRFUNC); + g_clear_error (&error); + return; + } + + width = gdk_pixbuf_get_width (main_pixbuf); + height = gdk_pixbuf_get_height (main_pixbuf); + + for (yy = 0; yy < height; yy += FRAME_SIZE) { + for (xx = 0; xx < width; xx+= FRAME_SIZE) { + GdkPixbuf *frame; + + frame = gdk_pixbuf_new_subpixbuf (main_pixbuf, xx, yy, FRAME_SIZE, FRAME_SIZE); + if (frame) + spinner->priv->pixbufs = g_slist_prepend (spinner->priv->pixbufs, frame); + } + } + + g_object_unref (main_pixbuf); + + spinner->priv->pixbufs = g_slist_reverse (spinner->priv->pixbufs); + + spinner->priv->current_frame = spinner->priv->pixbufs; + if (spinner->priv->pixbufs) + gtk_image_set_from_pixbuf (GTK_IMAGE (spinner), spinner->priv->pixbufs->data); +} + +static void +anaconda_spinner_dispose (GObject *object) +{ + /* This resets the timeout_id too */ + anaconda_spinner_set_active (ANACONDA_SPINNER (object), FALSE); + + /* Chain up to parent's method. */ + G_OBJECT_CLASS (anaconda_spinner_parent_class)->dispose (object); +} + +static void +anaconda_spinner_finalize (GObject *object) +{ + AnacondaSpinner *spinner = ANACONDA_SPINNER (object); + + g_slist_free_full (spinner->priv->pixbufs, g_object_unref); + spinner->priv->pixbufs = NULL; + spinner->priv->current_frame = NULL; + + g_warn_if_fail (spinner->priv->timeout_id == 0); + + /* Chain up to parent's method. */ + G_OBJECT_CLASS (anaconda_spinner_parent_class)->finalize (object); +} + +static void +anaconda_spinner_realize (GtkWidget *widget) +{ + AnacondaSpinner *spinner = ANACONDA_SPINNER(widget); + + /* Chain up to the parent class first, then enable the spinner + * after the widget is realized + */ + GTK_WIDGET_CLASS(anaconda_spinner_parent_class)->realize(widget); + + if (spinner->priv->active) + { + anaconda_spinner_enable_spin(spinner); + } +} + +static void +anaconda_spinner_unrealize (GtkWidget *widget) +{ + AnacondaSpinner *spinner = ANACONDA_SPINNER(widget); + + /* Disable the spinner before chaining up to the parent class */ + anaconda_spinner_disable_spin(spinner); + + GTK_WIDGET_CLASS(anaconda_spinner_parent_class)->unrealize(widget); +} + +static void +anaconda_spinner_class_init (AnacondaSpinnerClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + g_type_class_add_private (klass, sizeof (AnacondaSpinnerPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->set_property = anaconda_spinner_set_property; + object_class->get_property = anaconda_spinner_get_property; + object_class->dispose = anaconda_spinner_dispose; + object_class->finalize = anaconda_spinner_finalize; + object_class->constructed = anaconda_spinner_constructed; + + widget_class = GTK_WIDGET_CLASS(klass); + widget_class->realize = anaconda_spinner_realize; + widget_class->unrealize = anaconda_spinner_unrealize; + + /** + * AnacondaSpinner:active: + * + * Whether the animation is active. + **/ + g_object_class_install_property ( + object_class, + PROP_ACTIVE, + g_param_spec_boolean ( + "active", + "Active", + "Whether the animation is active", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +anaconda_spinner_init (AnacondaSpinner *spinner) +{ + spinner->priv = G_TYPE_INSTANCE_GET_PRIVATE (spinner, ANACONDA_TYPE_SPINNER, AnacondaSpinnerPrivate); +} + +GtkWidget * +anaconda_spinner_new (void) +{ + return g_object_new (ANACONDA_TYPE_SPINNER, NULL); +} + +gboolean +anaconda_spinner_get_active (AnacondaSpinner *spinner) +{ + g_return_val_if_fail (ANACONDA_IS_SPINNER (spinner), FALSE); + + return spinner->priv->active; +} + +void +anaconda_spinner_set_active (AnacondaSpinner *spinner, + gboolean active) +{ + g_return_if_fail (ANACONDA_IS_SPINNER (spinner)); + + if ((spinner->priv->active ? 1 : 0) == (active ? 1 : 0)) + return; + + spinner->priv->active = active; + + if (gtk_widget_get_realized(GTK_WIDGET(spinner))) + { + if (active) + { + anaconda_spinner_enable_spin (spinner); + } + else + { + anaconda_spinner_disable_spin (spinner); + } + } + + g_object_notify (G_OBJECT (spinner), "active"); +} + +void +anaconda_spinner_start (AnacondaSpinner *spinner) +{ + anaconda_spinner_set_active (spinner, TRUE); +} + +void +anaconda_spinner_stop (AnacondaSpinner *spinner) +{ + anaconda_spinner_set_active (spinner, FALSE); +} diff --git a/widgets/src/Spinner.h b/widgets/src/Spinner.h new file mode 100644 index 0000000..fb65e23 --- /dev/null +++ b/widgets/src/Spinner.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation. + * + * 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 Lesser General Public License + * along with this program; if not, see http://www.gnu.org/licenses/. + * + * Authors: Milan Crha mcrha@redhat.com + */ + +#ifndef ANACONDA_SPINNER_H +#define ANACONDA_SPINNER_H + +#include <gtk/gtk.h> + +#define ANACONDA_TYPE_SPINNER (anaconda_spinner_get_type ()) +#define ANACONDA_SPINNER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ANACONDA_TYPE_SPINNER, AnacondaSpinner)) +#define ANACONDA_SPINNER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), ANACONDA_TYPE_SPINNER, AnacondaSpinnerClass)) +#define ANACONDA_IS_SPINNER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANACONDA_TYPE_SPINNER)) +#define ANACONDA_IS_SPINNER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ANACONDA_TYPE_SPINNER)) +#define ANACONDA_SPINNER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANACONDA_TYPE_SPINNER, AnacondaSpinnerClass)) + +G_BEGIN_DECLS + +typedef struct _AnacondaSpinner AnacondaSpinner; +typedef struct _AnacondaSpinnerClass AnacondaSpinnerClass; +typedef struct _AnacondaSpinnerPrivate AnacondaSpinnerPrivate; + +struct _AnacondaSpinner +{ + GtkImage parent; + + /*< private >*/ + AnacondaSpinnerPrivate *priv; +}; + +struct _AnacondaSpinnerClass +{ + GtkImageClass parent_class; +}; + +GType anaconda_spinner_get_type (void); + +GtkWidget * anaconda_spinner_new (void); +gboolean anaconda_spinner_get_active (AnacondaSpinner *spinner); +void anaconda_spinner_set_active (AnacondaSpinner *spinner, gboolean active); +void anaconda_spinner_start (AnacondaSpinner *spinner); +void anaconda_spinner_stop (AnacondaSpinner *spinner); + +G_END_DECLS + +#endif /* E_SPINNER_H */
In case anyone tries to compare Spinner.c with the code in Evolution, it's not quite the simple search/replace that I claimed. Setting the "active" property at construct time didn't work because it started the animation before the widget was shown, or something along those lines, so I added the realize/unrealize bits. I will forward those changes back to Evolution.
@@ -265,9 +266,9 @@ installation options while this scan completes.</property> <object class="GtkLabel" id="label12"> <property name="visible">True</property> <property name="can_focus">False</property>
<property name="xalign">0</property> <property name="label" translatable="yes">Pressing 'OK' below will take you to the disk selection screen where you will need to re-select your disks.</property> <property name="wrap">True</property>
<property name="xalign">0</property>
Looking at this change and many of the above changes -- would you mind separating the two steps of "*save everything with new glade*" and "*do the changes*" into two separate commits?
@@ -142,14 +142,34 @@ </properties> </glade-widget-class>
- <glade-widget-class title="Layout Indicator"
name="AnacondaLayoutIndicator"
icon-name="widget-gtk-label"
generic-name="AnacondaLayoutIndicator">
<properties>
<property id="label-width" default="12" />
</properties>
</glade-widget-class>
<glade-widget-class title="Layout Indicator"
name="AnacondaLayoutIndicator"
icon-name="widget-gtk-label"
generic-name="AnacondaLayoutIndicator">
<properties>
<property id="label-width" default="12" />
</properties>
</glade-widget-class>
Same here, I think this change should not be part of the commit or should be mentioned in the commit message.
@@ -142,14 +142,34 @@ </properties> </glade-widget-class>
- <glade-widget-class title="Layout Indicator"
name="AnacondaLayoutIndicator"
icon-name="widget-gtk-label"
generic-name="AnacondaLayoutIndicator">
<properties>
<property id="label-width" default="12" />
</properties>
</glade-widget-class>
<glade-widget-class title="Layout Indicator"
name="AnacondaLayoutIndicator"
icon-name="widget-gtk-label"
generic-name="AnacondaLayoutIndicator">
<properties>
<property id="label-width" default="12" />
</properties>
</glade-widget-class>
<glade-widget-class title="Spinner"
name="AnacondaSpinner"
icon-name="widget-gtk-spinner"
generic-name="AnacondaSpinner"
since="3.2">
<properties>
<!-- Remove properties inherited from GtkImage -->
<!-- Setting disabled doesn't hide them in the glade interface
(nor does setting visible, oddly), but it keeps them being
"...keeps them **from** being saved"?
@@ -0,0 +1,330 @@ +/*
- Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation.
- 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 Lesser General Public License
- along with this program; if not, see http://www.gnu.org/licenses/.
- Authors: Milan Crha mcrha@redhat.com
- */
+/* NOTE FROM ANACONDA:
- This widget is a search/replace of ESpinner from Evolution (LGPL, see
- above), because GtkSpinner doesn't run so good in a VM. See
- The source of the animation is a PNG containing each frame to animate,
- arranged in a 7x5 grid. It was created with Inkscape by doing the following:
- Load process-working-symbolic.svg from adwaita-icon-theme
- In File->Document Properties, change the background to transparent (alpha 0)
- Select the spinner, Edit->Clone->Create Tiled Clones...
- Set the clone to 5x7 rows, columns
- There's a rotation option here, but it acted kind of weird, so I left it alone
- Rotate each object by the appropriate multiple of 360 / 35 degrees using Object->Transform
- You can select more than one at once with shift+click so it doesn't take that long
- File->Export PNG Image...
- Choose Drawing, and 112x80 for the image size
- Size has to match FRAME_SIZE below
- */
+#ifdef HAVE_CONFIG_H +#include <config.h> +#endif
+#include <gtk/gtk.h>
+#include "Spinner.h" +#include "widgets-common.h"
+#define MAIN_IMAGE_FILENAME "working.png" +#define FRAME_SIZE 16 +#define FRAME_TIMEOUT_MS 100
+struct _AnacondaSpinnerPrivate +{
- GSList *pixbufs;
- GSList *current_frame; /* link of 'pixbufs' */
- gboolean active;
- guint timeout_id;
+};
+enum {
- PROP_0,
- PROP_ACTIVE
+};
+G_DEFINE_TYPE (AnacondaSpinner, anaconda_spinner, GTK_TYPE_IMAGE)
+static gboolean +anaconda_spinner_update_frame_cb (gpointer user_data) +{
- AnacondaSpinner *spinner = user_data;
- g_return_val_if_fail (ANACONDA_IS_SPINNER (spinner), FALSE);
- if (spinner->priv->current_frame)
spinner->priv->current_frame = spinner->priv->current_frame->next;
- if (!spinner->priv->current_frame)
spinner->priv->current_frame = spinner->priv->pixbufs;
- if (!spinner->priv->current_frame) {
g_warn_if_reached ();
return FALSE;
- }
- gtk_image_set_from_pixbuf (GTK_IMAGE (spinner), spinner->priv->current_frame->data);
- return TRUE;
+}
+static void +anaconda_spinner_enable_spin (AnacondaSpinner *spinner) +{
- spinner->priv->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, FRAME_TIMEOUT_MS, anaconda_spinner_update_frame_cb, spinner, NULL);
+}
+static void +anaconda_spinner_disable_spin (AnacondaSpinner *spinner) +{
- if (spinner->priv->timeout_id)
- {
g_source_remove (spinner->priv->timeout_id);
spinner->priv->timeout_id = 0;
- }
+}
+static void +anaconda_spinner_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
+{
- switch (property_id) {
case PROP_ACTIVE:
anaconda_spinner_set_active (
ANACONDA_SPINNER (object),
g_value_get_boolean (value));
return;
- }
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+static void +anaconda_spinner_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
+{
- switch (property_id) {
case PROP_ACTIVE:
g_value_set_boolean (
value,
anaconda_spinner_get_active (ANACONDA_SPINNER (object)));
return;
- }
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+static void +anaconda_spinner_constructed (GObject *object) +{
- AnacondaSpinner *spinner;
- GdkPixbuf *main_pixbuf;
- gint xx, yy, width, height;
- GError *error = NULL;
gchar *filename;
extra space at the beginning of the line
@@ -0,0 +1,330 @@ +/*
- Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation.
- 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 Lesser General Public License
- along with this program; if not, see http://www.gnu.org/licenses/.
- Authors: Milan Crha mcrha@redhat.com
- */
+/* NOTE FROM ANACONDA:
- This widget is a search/replace of ESpinner from Evolution (LGPL, see
- above), because GtkSpinner doesn't run so good in a VM. See
- The source of the animation is a PNG containing each frame to animate,
- arranged in a 7x5 grid. It was created with Inkscape by doing the following:
- Load process-working-symbolic.svg from adwaita-icon-theme
- In File->Document Properties, change the background to transparent (alpha 0)
- Select the spinner, Edit->Clone->Create Tiled Clones...
- Set the clone to 5x7 rows, columns
- There's a rotation option here, but it acted kind of weird, so I left it alone
- Rotate each object by the appropriate multiple of 360 / 35 degrees using Object->Transform
- You can select more than one at once with shift+click so it doesn't take that long
- File->Export PNG Image...
- Choose Drawing, and 112x80 for the image size
- Size has to match FRAME_SIZE below
- */
+#ifdef HAVE_CONFIG_H +#include <config.h> +#endif
+#include <gtk/gtk.h>
+#include "Spinner.h" +#include "widgets-common.h"
+#define MAIN_IMAGE_FILENAME "working.png" +#define FRAME_SIZE 16 +#define FRAME_TIMEOUT_MS 100
+struct _AnacondaSpinnerPrivate +{
- GSList *pixbufs;
- GSList *current_frame; /* link of 'pixbufs' */
- gboolean active;
- guint timeout_id;
+};
+enum {
- PROP_0,
- PROP_ACTIVE
+};
+G_DEFINE_TYPE (AnacondaSpinner, anaconda_spinner, GTK_TYPE_IMAGE)
+static gboolean +anaconda_spinner_update_frame_cb (gpointer user_data) +{
- AnacondaSpinner *spinner = user_data;
- g_return_val_if_fail (ANACONDA_IS_SPINNER (spinner), FALSE);
- if (spinner->priv->current_frame)
spinner->priv->current_frame = spinner->priv->current_frame->next;
- if (!spinner->priv->current_frame)
spinner->priv->current_frame = spinner->priv->pixbufs;
- if (!spinner->priv->current_frame) {
g_warn_if_reached ();
return FALSE;
- }
- gtk_image_set_from_pixbuf (GTK_IMAGE (spinner), spinner->priv->current_frame->data);
- return TRUE;
+}
+static void +anaconda_spinner_enable_spin (AnacondaSpinner *spinner) +{
- spinner->priv->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, FRAME_TIMEOUT_MS, anaconda_spinner_update_frame_cb, spinner, NULL);
+}
+static void +anaconda_spinner_disable_spin (AnacondaSpinner *spinner) +{
- if (spinner->priv->timeout_id)
- {
g_source_remove (spinner->priv->timeout_id);
spinner->priv->timeout_id = 0;
- }
+}
+static void +anaconda_spinner_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
+{
- switch (property_id) {
case PROP_ACTIVE:
anaconda_spinner_set_active (
ANACONDA_SPINNER (object),
g_value_get_boolean (value));
return;
- }
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+static void +anaconda_spinner_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
+{
- switch (property_id) {
case PROP_ACTIVE:
g_value_set_boolean (
value,
anaconda_spinner_get_active (ANACONDA_SPINNER (object)));
return;
- }
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+static void +anaconda_spinner_constructed (GObject *object) +{
- AnacondaSpinner *spinner;
- GdkPixbuf *main_pixbuf;
- gint xx, yy, width, height;
- GError *error = NULL;
gchar *filename;
- /* Chain up to parent's method. */
- G_OBJECT_CLASS (anaconda_spinner_parent_class)->constructed (object);
- spinner = ANACONDA_SPINNER (object);
filename = g_strdup_printf("%s/pixmaps/%s", anaconda_get_widgets_datadir(), MAIN_IMAGE_FILENAME);
main_pixbuf = gdk_pixbuf_new_from_file (filename, &error);
g_free(filename);
same here
@@ -0,0 +1,330 @@ +/*
- Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation.
- 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 Lesser General Public License
- along with this program; if not, see http://www.gnu.org/licenses/.
- Authors: Milan Crha mcrha@redhat.com
- */
+/* NOTE FROM ANACONDA:
- This widget is a search/replace of ESpinner from Evolution (LGPL, see
- above), because GtkSpinner doesn't run so good in a VM. See
- The source of the animation is a PNG containing each frame to animate,
- arranged in a 7x5 grid. It was created with Inkscape by doing the following:
- Load process-working-symbolic.svg from adwaita-icon-theme
- In File->Document Properties, change the background to transparent (alpha 0)
- Select the spinner, Edit->Clone->Create Tiled Clones...
- Set the clone to 5x7 rows, columns
- There's a rotation option here, but it acted kind of weird, so I left it alone
- Rotate each object by the appropriate multiple of 360 / 35 degrees using Object->Transform
- You can select more than one at once with shift+click so it doesn't take that long
- File->Export PNG Image...
- Choose Drawing, and 112x80 for the image size
- Size has to match FRAME_SIZE below
- */
+#ifdef HAVE_CONFIG_H +#include <config.h> +#endif
+#include <gtk/gtk.h>
+#include "Spinner.h" +#include "widgets-common.h"
+#define MAIN_IMAGE_FILENAME "working.png" +#define FRAME_SIZE 16 +#define FRAME_TIMEOUT_MS 100
+struct _AnacondaSpinnerPrivate +{
- GSList *pixbufs;
- GSList *current_frame; /* link of 'pixbufs' */
- gboolean active;
- guint timeout_id;
+};
+enum {
- PROP_0,
- PROP_ACTIVE
+};
+G_DEFINE_TYPE (AnacondaSpinner, anaconda_spinner, GTK_TYPE_IMAGE)
+static gboolean +anaconda_spinner_update_frame_cb (gpointer user_data) +{
- AnacondaSpinner *spinner = user_data;
- g_return_val_if_fail (ANACONDA_IS_SPINNER (spinner), FALSE);
- if (spinner->priv->current_frame)
spinner->priv->current_frame = spinner->priv->current_frame->next;
- if (!spinner->priv->current_frame)
spinner->priv->current_frame = spinner->priv->pixbufs;
- if (!spinner->priv->current_frame) {
g_warn_if_reached ();
return FALSE;
- }
- gtk_image_set_from_pixbuf (GTK_IMAGE (spinner), spinner->priv->current_frame->data);
- return TRUE;
+}
+static void +anaconda_spinner_enable_spin (AnacondaSpinner *spinner) +{
- spinner->priv->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, FRAME_TIMEOUT_MS, anaconda_spinner_update_frame_cb, spinner, NULL);
+}
+static void +anaconda_spinner_disable_spin (AnacondaSpinner *spinner) +{
- if (spinner->priv->timeout_id)
- {
g_source_remove (spinner->priv->timeout_id);
spinner->priv->timeout_id = 0;
- }
+}
+static void +anaconda_spinner_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
+{
- switch (property_id) {
case PROP_ACTIVE:
anaconda_spinner_set_active (
ANACONDA_SPINNER (object),
g_value_get_boolean (value));
return;
- }
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+static void +anaconda_spinner_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
+{
- switch (property_id) {
case PROP_ACTIVE:
g_value_set_boolean (
value,
anaconda_spinner_get_active (ANACONDA_SPINNER (object)));
return;
- }
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+static void +anaconda_spinner_constructed (GObject *object) +{
- AnacondaSpinner *spinner;
- GdkPixbuf *main_pixbuf;
- gint xx, yy, width, height;
- GError *error = NULL;
gchar *filename;
- /* Chain up to parent's method. */
- G_OBJECT_CLASS (anaconda_spinner_parent_class)->constructed (object);
- spinner = ANACONDA_SPINNER (object);
filename = g_strdup_printf("%s/pixmaps/%s", anaconda_get_widgets_datadir(), MAIN_IMAGE_FILENAME);
main_pixbuf = gdk_pixbuf_new_from_file (filename, &error);
g_free(filename);
- if (!main_pixbuf) {
g_warning ("%s: Failed to load image: %s", error ? error->message : "Unknown error", G_STRFUNC);
g_clear_error (&error);
return;
- }
- width = gdk_pixbuf_get_width (main_pixbuf);
- height = gdk_pixbuf_get_height (main_pixbuf);
- for (yy = 0; yy < height; yy += FRAME_SIZE) {
for (xx = 0; xx < width; xx+= FRAME_SIZE) {
GdkPixbuf *frame;
frame = gdk_pixbuf_new_subpixbuf (main_pixbuf, xx, yy, FRAME_SIZE, FRAME_SIZE);
if (frame)
spinner->priv->pixbufs = g_slist_prepend (spinner->priv->pixbufs, frame);
}
- }
- g_object_unref (main_pixbuf);
- spinner->priv->pixbufs = g_slist_reverse (spinner->priv->pixbufs);
- spinner->priv->current_frame = spinner->priv->pixbufs;
- if (spinner->priv->pixbufs)
gtk_image_set_from_pixbuf (GTK_IMAGE (spinner), spinner->priv->pixbufs->data);
+}
+static void +anaconda_spinner_dispose (GObject *object) +{
- /* This resets the timeout_id too */
- anaconda_spinner_set_active (ANACONDA_SPINNER (object), FALSE);
- /* Chain up to parent's method. */
- G_OBJECT_CLASS (anaconda_spinner_parent_class)->dispose (object);
+}
+static void +anaconda_spinner_finalize (GObject *object) +{
- AnacondaSpinner *spinner = ANACONDA_SPINNER (object);
- g_slist_free_full (spinner->priv->pixbufs, g_object_unref);
- spinner->priv->pixbufs = NULL;
- spinner->priv->current_frame = NULL;
If I remember that correctly, ``finalize`` is class' finalization and ``dispose`` is instance's finalization so the three lines above should go to ``dispose`` as these resources are per-instance.
Apart from the comments above this looks good to me. I'm just hesitating to give it an ACK because we are (once again) working around a serious bug (and regression) in Gtk. And the fact that we were able to take the code from **Evolution** which is part of the GNOME project only makes me feel more sad about this. How many other tools/applications are going to copy&paste&modify this code to work around the bug/regression? I don't like doing such hacks just because somebody else is reluctant to fix their bug even if it's that serious regression.Thus not an ACK from me at this point.
@@ -142,14 +142,34 @@ </properties> </glade-widget-class>
- <glade-widget-class title="Layout Indicator"
name="AnacondaLayoutIndicator"
icon-name="widget-gtk-label"
generic-name="AnacondaLayoutIndicator">
<properties>
<property id="label-width" default="12" />
</properties>
</glade-widget-class>
<glade-widget-class title="Layout Indicator"
name="AnacondaLayoutIndicator"
icon-name="widget-gtk-label"
generic-name="AnacondaLayoutIndicator">
<properties>
<property id="label-width" default="12" />
</properties>
</glade-widget-class>
<glade-widget-class title="Spinner"
name="AnacondaSpinner"
icon-name="widget-gtk-spinner"
generic-name="AnacondaSpinner"
since="3.2">
<properties>
<!-- Remove properties inherited from GtkImage -->
<!-- Setting disabled doesn't hide them in the glade interface
(nor does setting visible, oddly), but it keeps them being
Yes. The spinner derives from GtkImage, but none of the GtkImage properties should be applied to the spinner.
Closed.
anaconda-patches@lists.fedorahosted.org