First crack at merging contact changes
authorepage <eopage@byu.net>
Fri, 18 Jul 2008 00:59:35 +0000 (00:59 +0000)
committerepage <eopage@byu.net>
Fri, 18 Jul 2008 00:59:35 +0000 (00:59 +0000)
git-svn-id: file:///svnroot/gc-dialer/trunk@96 c39d3808-3fe2-4d86-a59f-b7f623ee9f21

gc_dialer/gc.png [new file with mode: 0644]
gc_dialer/gc_dialer.glade
gc_dialer/gc_dialer.py
gc_dialer/gcbackend.py

diff --git a/gc_dialer/gc.png b/gc_dialer/gc.png
new file mode 100644 (file)
index 0000000..df50c66
Binary files /dev/null and b/gc_dialer/gc.png differ
index 8b173ad..fc1bb55 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Sat Jul 12 08:37:28 2008 -->
+<!--Generated with glade3 3.4.5 on Thu Jul 17 19:50:07 2008 -->
 <glade-interface>
   <widget class="GtkWindow" id="Dialpad">
     <property name="width_request">400</property>
                     <property name="n_columns">3</property>
                     <property name="homogeneous">True</property>
                     <child>
-                      <widget class="GtkButton" id="dial">
+                      <widget class="GtkButton" id="digit1">
                         <property name="visible">True</property>
-                        <property name="has_default">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
-                        <signal name="clicked" handler="on_dial_clicked"/>
-                        <accelerator key="Return" modifiers="" signal="clicked"/>
+                        <signal name="clicked" handler="on_digit_clicked"/>
+                        <accelerator key="1" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkHBox" id="hbox1">
+                          <widget class="GtkLabel" id="label12">
                             <property name="visible">True</property>
-                            <child>
-                              <widget class="GtkImage" id="image1">
-                                <property name="visible">True</property>
-                                <property name="xalign">1</property>
-                                <property name="stock">gtk-yes</property>
-                              </widget>
-                            </child>
-                            <child>
-                              <widget class="GtkLabel" id="label8">
-                                <property name="visible">True</property>
-                                <property name="xalign">0</property>
-                                <property name="xpad">5</property>
-                                <property name="label" translatable="yes">&lt;span size="17000" weight="bold"&gt;Dial&lt;/span&gt;</property>
-                                <property name="use_markup">True</property>
-                              </widget>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
+                            <property name="label" translatable="yes">&lt;span size="33000" weight="bold"&gt;1&lt;/span&gt;
+&lt;span size="9000"&gt;  &lt;/span&gt;</property>
+                            <property name="use_markup">True</property>
                           </widget>
                         </child>
                       </widget>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit0">
+                      <widget class="GtkButton" id="digit2">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="0" modifiers="" signal="clicked"/>
+                        <accelerator key="2" modifiers="" signal="clicked"/>
+                        <accelerator key="a" modifiers="" signal="clicked"/>
+                        <accelerator key="b" modifiers="" signal="clicked"/>
+                        <accelerator key="c" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label19">
+                          <widget class="GtkLabel" id="label10">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="33000" weight="bold"&gt;0&lt;/span&gt;
-&lt;span size="9000"&gt;&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;2&lt;/span&gt;
+&lt;span size="12000"&gt;ABC&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkButton" id="back">
-                        <property name="visible">True</property>
-                        <property name="focus_on_click">False</property>
-                        <property name="response_id">0</property>
-                        <signal name="clicked" handler="on_back_clicked"/>
-                        <accelerator key="BackSpace" modifiers="" signal="clicked"/>
-                        <child>
-                          <widget class="GtkHBox" id="hbox2">
-                            <property name="visible">True</property>
-                            <child>
-                              <widget class="GtkImage" id="image2">
-                                <property name="visible">True</property>
-                                <property name="xalign">1</property>
-                                <property name="stock">gtk-no</property>
-                              </widget>
-                            </child>
-                            <child>
-                              <widget class="GtkLabel" id="label9">
-                                <property name="visible">True</property>
-                                <property name="xalign">0</property>
-                                <property name="xpad">5</property>
-                                <property name="label" translatable="yes">&lt;span size="17000" weight="Bold"&gt;Back&lt;/span&gt;</property>
-                                <property name="use_markup">True</property>
-                              </widget>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit9">
+                      <widget class="GtkButton" id="digit3">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="z" modifiers="" signal="clicked"/>
-                        <accelerator key="y" modifiers="" signal="clicked"/>
-                        <accelerator key="x" modifiers="" signal="clicked"/>
-                        <accelerator key="w" modifiers="" signal="clicked"/>
-                        <accelerator key="9" modifiers="" signal="clicked"/>
+                        <accelerator key="3" modifiers="" signal="clicked"/>
+                        <accelerator key="d" modifiers="" signal="clicked"/>
+                        <accelerator key="e" modifiers="" signal="clicked"/>
+                        <accelerator key="f" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label18">
+                          <widget class="GtkLabel" id="label11">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;9&lt;/span&gt;
-&lt;span size="12000"&gt;WXYZ&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold" stretch="ultraexpanded"&gt;3&lt;/span&gt;
+&lt;span size="12000"&gt;DEF&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                       <packing>
                         <property name="left_attach">2</property>
                         <property name="right_attach">3</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit8">
+                      <widget class="GtkButton" id="digit4">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="v" modifiers="" signal="clicked"/>
-                        <accelerator key="u" modifiers="" signal="clicked"/>
-                        <accelerator key="t" modifiers="" signal="clicked"/>
-                        <accelerator key="8" modifiers="" signal="clicked"/>
+                        <accelerator key="4" modifiers="" signal="clicked"/>
+                        <accelerator key="g" modifiers="" signal="clicked"/>
+                        <accelerator key="h" modifiers="" signal="clicked"/>
+                        <accelerator key="i" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label17">
+                          <widget class="GtkLabel" id="label13">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;8&lt;/span&gt;
-&lt;span size="12000"&gt;TUV&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;4&lt;/span&gt;
+&lt;span size="12000"&gt;GHI&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                         </child>
                       </widget>
                       <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit7">
+                      <widget class="GtkButton" id="digit5">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="s" modifiers="" signal="clicked"/>
-                        <accelerator key="r" modifiers="" signal="clicked"/>
-                        <accelerator key="q" modifiers="" signal="clicked"/>
-                        <accelerator key="p" modifiers="" signal="clicked"/>
-                        <accelerator key="7" modifiers="" signal="clicked"/>
+                        <accelerator key="5" modifiers="" signal="clicked"/>
+                        <accelerator key="j" modifiers="" signal="clicked"/>
+                        <accelerator key="k" modifiers="" signal="clicked"/>
+                        <accelerator key="l" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label16">
+                          <widget class="GtkLabel" id="label14">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;7&lt;/span&gt;
-&lt;span size="12000"&gt;PQRS&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;5&lt;/span&gt;
+&lt;span size="12000"&gt;JKL&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                         </child>
                       </widget>
                       <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
                       </packing>
                     </child>
                     <child>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="o" modifiers="" signal="clicked"/>
-                        <accelerator key="n" modifiers="" signal="clicked"/>
-                        <accelerator key="m" modifiers="" signal="clicked"/>
                         <accelerator key="6" modifiers="" signal="clicked"/>
+                        <accelerator key="m" modifiers="" signal="clicked"/>
+                        <accelerator key="n" modifiers="" signal="clicked"/>
+                        <accelerator key="o" modifiers="" signal="clicked"/>
                         <child>
                           <widget class="GtkLabel" id="label15">
                             <property name="visible">True</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit5">
+                      <widget class="GtkButton" id="digit7">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="l" modifiers="" signal="clicked"/>
-                        <accelerator key="k" modifiers="" signal="clicked"/>
-                        <accelerator key="j" modifiers="" signal="clicked"/>
-                        <accelerator key="5" modifiers="" signal="clicked"/>
+                        <accelerator key="7" modifiers="" signal="clicked"/>
+                        <accelerator key="p" modifiers="" signal="clicked"/>
+                        <accelerator key="q" modifiers="" signal="clicked"/>
+                        <accelerator key="r" modifiers="" signal="clicked"/>
+                        <accelerator key="s" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label14">
+                          <widget class="GtkLabel" id="label16">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;5&lt;/span&gt;
-&lt;span size="12000"&gt;JKL&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;7&lt;/span&gt;
+&lt;span size="12000"&gt;PQRS&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                         </child>
                       </widget>
                       <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit4">
+                      <widget class="GtkButton" id="digit8">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="i" modifiers="" signal="clicked"/>
-                        <accelerator key="h" modifiers="" signal="clicked"/>
-                        <accelerator key="g" modifiers="" signal="clicked"/>
-                        <accelerator key="4" modifiers="" signal="clicked"/>
+                        <accelerator key="8" modifiers="" signal="clicked"/>
+                        <accelerator key="t" modifiers="" signal="clicked"/>
+                        <accelerator key="u" modifiers="" signal="clicked"/>
+                        <accelerator key="v" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label13">
+                          <widget class="GtkLabel" id="label17">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;4&lt;/span&gt;
-&lt;span size="12000"&gt;GHI&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;8&lt;/span&gt;
+&lt;span size="12000"&gt;TUV&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                         </child>
                       </widget>
                       <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit3">
+                      <widget class="GtkButton" id="digit9">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="f" modifiers="" signal="clicked"/>
-                        <accelerator key="e" modifiers="" signal="clicked"/>
-                        <accelerator key="d" modifiers="" signal="clicked"/>
-                        <accelerator key="3" modifiers="" signal="clicked"/>
+                        <accelerator key="9" modifiers="" signal="clicked"/>
+                        <accelerator key="w" modifiers="" signal="clicked"/>
+                        <accelerator key="x" modifiers="" signal="clicked"/>
+                        <accelerator key="y" modifiers="" signal="clicked"/>
+                        <accelerator key="z" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label11">
+                          <widget class="GtkLabel" id="label18">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold" stretch="ultraexpanded"&gt;3&lt;/span&gt;
-&lt;span size="12000"&gt;DEF&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;9&lt;/span&gt;
+&lt;span size="12000"&gt;WXYZ&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                       <packing>
                         <property name="left_attach">2</property>
                         <property name="right_attach">3</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit2">
+                      <widget class="GtkButton" id="back">
+                        <property name="visible">True</property>
+                        <property name="focus_on_click">False</property>
+                        <property name="response_id">0</property>
+                        <signal name="clicked" handler="on_back_clicked"/>
+                        <accelerator key="BackSpace" modifiers="" signal="clicked"/>
+                        <child>
+                          <widget class="GtkHBox" id="hbox2">
+                            <property name="visible">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image2">
+                                <property name="visible">True</property>
+                                <property name="xalign">1</property>
+                                <property name="stock">gtk-no</property>
+                              </widget>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="label9">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="xpad">5</property>
+                                <property name="label" translatable="yes">&lt;span size="17000" weight="Bold"&gt;Back&lt;/span&gt;</property>
+                                <property name="use_markup">True</property>
+                              </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkButton" id="digit0">
                         <property name="visible">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
                         <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="c" modifiers="" signal="clicked"/>
-                        <accelerator key="b" modifiers="" signal="clicked"/>
-                        <accelerator key="a" modifiers="" signal="clicked"/>
-                        <accelerator key="2" modifiers="" signal="clicked"/>
+                        <accelerator key="0" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label10">
+                          <widget class="GtkLabel" id="label19">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="30000" weight="bold"&gt;2&lt;/span&gt;
-&lt;span size="12000"&gt;ABC&lt;/span&gt;</property>
+                            <property name="label" translatable="yes">&lt;span size="33000" weight="bold"&gt;0&lt;/span&gt;
+&lt;span size="9000"&gt;&lt;/span&gt;</property>
                             <property name="use_markup">True</property>
                             <property name="justify">GTK_JUSTIFY_CENTER</property>
                           </widget>
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="digit1">
+                      <widget class="GtkButton" id="dial">
                         <property name="visible">True</property>
+                        <property name="has_default">True</property>
                         <property name="focus_on_click">False</property>
                         <property name="response_id">0</property>
-                        <signal name="clicked" handler="on_digit_clicked"/>
-                        <accelerator key="1" modifiers="" signal="clicked"/>
+                        <signal name="clicked" handler="on_dial_clicked"/>
+                        <accelerator key="Return" modifiers="" signal="clicked"/>
                         <child>
-                          <widget class="GtkLabel" id="label12">
+                          <widget class="GtkHBox" id="hbox1">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;span size="33000" weight="bold"&gt;1&lt;/span&gt;
-&lt;span size="9000"&gt;  &lt;/span&gt;</property>
-                            <property name="use_markup">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="xalign">1</property>
+                                <property name="stock">gtk-yes</property>
+                              </widget>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="label8">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="xpad">5</property>
+                                <property name="label" translatable="yes">&lt;span size="17000" weight="bold"&gt;Dial&lt;/span&gt;</property>
+                                <property name="use_markup">True</property>
+                              </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
                           </widget>
                         </child>
                       </widget>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="right_attach">3</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                      </packing>
                     </child>
                   </widget>
                   <packing>
               </packing>
             </child>
             <child>
+              <widget class="GtkScrolledWindow" id="scrolledwindow2">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+                <child>
+                  <widget class="GtkTreeView" id="contactsview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="headers_visible">False</property>
+                    <property name="enable_search">False</property>
+                    <property name="fixed_height_mode">True</property>
+                    <property name="enable_grid_lines">GTK_TREE_VIEW_GRID_LINES_HORIZONTAL</property>
+                    <property name="enable_tree_lines">True</property>
+                    <signal name="row_activated" handler="on_contactsview_row_activated"/>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+                <property name="tab_expand">True</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="contacts">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Contacts</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="position">1</property>
+                <property name="tab_expand">True</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
               <widget class="GtkScrolledWindow" id="scrolledwindow1">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                   <placeholder/>
                 </child>
                 <child>
-                  <widget class="GtkLabel" id="label1">
+                  <widget class="GtkComboBoxEntry" id="callbackcombo">
                     <property name="visible">True</property>
-                    <property name="xalign">1</property>
-                    <property name="xpad">5</property>
-                    <property name="label" translatable="yes">GrandCentral
-Number:</property>
-                    <property name="justify">GTK_JUSTIFY_RIGHT</property>
+                    <child internal-child="entry">
+                      <widget class="GtkEntry" id="comboboxentry-entry2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <signal name="changed" handler="on_callbackentry_changed"/>
+                      </widget>
+                    </child>
                   </widget>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
                 </child>
                 <child>
-                  <widget class="GtkLabel" id="gcnumberlabel">
+                  <widget class="GtkLabel" id="label3">
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">&lt;span size="15000" weight="bold"&gt;(518) 555-1212&lt;/span&gt;</property>
-                    <property name="use_markup">True</property>
+                    <property name="xalign">1</property>
+                    <property name="xpad">5</property>
+                    <property name="label" translatable="yes">Callback Number:</property>
                   </widget>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options"></property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
                   </packing>
                 </child>
                 <child>
@@ -554,36 +600,26 @@ must reauthenticate</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="GtkLabel" id="label3">
+                  <widget class="GtkLabel" id="gcnumberlabel">
                     <property name="visible">True</property>
-                    <property name="xalign">1</property>
-                    <property name="xpad">5</property>
-                    <property name="label" translatable="yes">Callback Number:</property>
+                    <property name="label" translatable="yes">&lt;span size="15000" weight="bold"&gt;(518) 555-1212&lt;/span&gt;</property>
+                    <property name="use_markup">True</property>
                   </widget>
                   <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="GtkComboBoxEntry" id="callbackcombo">
+                  <widget class="GtkLabel" id="label1">
                     <property name="visible">True</property>
-                    <child internal-child="entry">
-                      <widget class="GtkEntry" id="comboboxentry-entry2">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <signal name="changed" handler="on_callbackentry_changed"/>
-                      </widget>
-                    </child>
+                    <property name="xalign">1</property>
+                    <property name="xpad">5</property>
+                    <property name="label" translatable="yes">GrandCentral
+Number:</property>
+                    <property name="justify">GTK_JUSTIFY_RIGHT</property>
                   </widget>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
                 </child>
               </widget>
               <packing>
@@ -686,17 +722,14 @@ Copyright 2008</property>
             <property name="n_rows">2</property>
             <property name="n_columns">2</property>
             <child>
-              <widget class="GtkLabel" id="label5">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Username</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label6">
+              <widget class="GtkEntry" id="passwordentry">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">Password</property>
+                <property name="can_focus">True</property>
+                <property name="visibility">False</property>
               </widget>
               <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
                 <property name="top_attach">1</property>
                 <property name="bottom_attach">2</property>
               </packing>
@@ -712,18 +745,21 @@ Copyright 2008</property>
               </packing>
             </child>
             <child>
-              <widget class="GtkEntry" id="passwordentry">
+              <widget class="GtkLabel" id="label6">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="visibility">False</property>
+                <property name="label" translatable="yes">Password</property>
               </widget>
               <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
                 <property name="top_attach">1</property>
                 <property name="bottom_attach">2</property>
               </packing>
             </child>
+            <child>
+              <widget class="GtkLabel" id="label5">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Username</property>
+              </widget>
+            </child>
           </widget>
           <packing>
             <property name="position">1</property>
@@ -765,4 +801,67 @@ Copyright 2008</property>
       </widget>
     </child>
   </widget>
+  <widget class="GtkDialog" id="phonetype_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Select Phone Type</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="skip_pager_hint">True</property>
+    <property name="deletable">False</property>
+    <property name="transient_for">Dialpad</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox3">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkTreeView" id="phonetypes">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="headers_clickable">True</property>
+            <signal name="row_activated" handler="on_phonetype_select"/>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="select_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="label" translatable="yes">Select</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_phonetype_select"/>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="cancel_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label" translatable="yes">Cancel</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_phonetype_cancel"/>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>
index 6133dd5..c862d6e 100755 (executable)
@@ -117,6 +117,62 @@ def make_pretty(phonenumber):
        return prettynumber
 
 
+class PhoneTypeSelector(object):
+
+       def __init__(self, widgetTree, gcBackend):
+               self._gcBackend = gcBackend
+               self._widgetTree = widgetTree
+               self._dialog = self._widgetTree.get_widget("phonetype_dialog")
+
+               self._selectButton = self._widgetTree.get_widget("select_button")
+               self._selectButton.connect("clicked", self._on_phonetype_select)
+
+               self._cancelButton = self._widgetTree.get_widget("cancel_button")
+               self._cancelButton.connect("clicked", self._on_phonetype_cancel)
+
+               self._typemodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+               self._typeviewselection = None
+
+               typeview = self._widgetTree.get_widget("phonetypes")
+               typeview.connect("row-activated", self._on_phonetype_select)
+               typeview.set_model(self._typemodel)
+               textrenderer = gtk.CellRendererText()
+
+               # Add the column to the treeview
+               column = gtk.TreeViewColumn("Phone Numbers", textrenderer, text=1)
+               column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+
+               typeview.append_column(column)
+
+               self._typeviewselection = typeview.get_selection()
+               self._typeviewselection.set_mode(gtk.SELECTION_SINGLE)
+
+       def run(self, contactDetails):
+               self._typemodel.clear()
+
+               for phoneType, phoneNumber in contactDetails:
+                       self._typemodel.append((phoneNumber, "%s - %s" % (make_pretty(phoneNumber), phoneType)))
+
+               userResponse = self._dialog.run()
+
+               if userResponse == gtk.RESPONSE_OK:
+                       model, itr = self._typeviewselection.get_selected()
+                       if itr:
+                               phoneNumber = self._typemodel.get_value(itr, 0)
+               else:
+                       phoneNumber = ""
+
+               self._typeviewselection.unselect_all()
+               self._dialog.hide()
+               return phoneNumber
+       
+       def _on_phonetype_select(self, *args):
+               self._dialog.response(gtk.RESPONSE_OK)
+
+       def _on_phonetype_cancel(self, *args):
+               self._dialog.response(gtk.RESPONSE_CANCEL)
+
+
 class Dialpad(object):
 
        __app_name__ = "gc_dialer"
@@ -138,10 +194,15 @@ class Dialpad(object):
 
                self._deviceIsOnline = True
                self._callbackNeedsSetup = True
+
                self._recenttime = 0.0
                self._recentmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
                self._recentviewselection = None
 
+               self._contactsmodel = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+               self._contactsviewselection = None
+               self._contactsNeedSetup = True
+
                for path in Dialpad._glade_files:
                        if os.path.isfile(path):
                                self._widgetTree = gtk.glade.XML(path)
@@ -151,7 +212,8 @@ class Dialpad(object):
                        gtk.main_quit()
                        return
 
-               self._widgetTree.get_widget("about_title").set_label(self._widgetTree.get_widget("about_title").get_label()+"\nVersion "+Dialpad.__version__)
+               aboutHeader = self._widgetTree.get_widget("about_title")
+               aboutHeader.set_label("%s\nVersion %s" % (aboutHeader.get_label(), Dialpad.__version__))
 
                #Get the buffer associated with the number display
                self._numberdisplay = self._widgetTree.get_widget("numberdisplay")
@@ -220,6 +282,7 @@ class Dialpad(object):
                        "on_clearcookies_clicked": self._on_clearcookies_clicked,
                        "on_notebook_switch_page": self._on_notebook_switch_page,
                        "on_recentview_row_activated": self._on_recentview_row_activated,
+                       "on_contactsview_row_activated" : self._on_contactsview_row_activated,
 
                        "on_digit_clicked": self._on_digit_clicked,
                        "on_back_clicked": self._on_backspace,
@@ -234,10 +297,11 @@ class Dialpad(object):
 
                self._gcBackend = GCDialer()
 
+               self._phoneTypeSelector = PhoneTypeSelector(self._widgetTree, self._gcBackend)
                self.attempt_login(2)
                gobject.idle_add(self._init_grandcentral)
-               # Defer initalization of recent view
                gobject.idle_add(self._init_recent_view)
+               gobject.idle_add(self._init_contacts_view)
 
        def _init_grandcentral(self):
                """ Deferred initalization of the grandcentral info """
@@ -267,6 +331,51 @@ class Dialpad(object):
 
                return False
 
+       def _init_contacts_view(self):
+               """ deferred initalization of the contacts view treeview """
+
+               contactsview = self._widgetTree.get_widget("contactsview")
+               contactsview.set_model(self._contactsmodel)
+
+               # Add the column to the treeview
+               column = gtk.TreeViewColumn("Contact")
+
+               iconrenderer = gtk.CellRendererPixbuf()
+               column.pack_start(iconrenderer, expand=False)
+               column.add_attribute(iconrenderer, 'pixbuf', 0)
+
+               textrenderer = gtk.CellRendererText()
+               column.pack_start(textrenderer, expand=True)
+               column.add_attribute(textrenderer, 'text', 1)
+
+               textrenderer = gtk.CellRendererText()
+               column.pack_start(textrenderer, expand=True)
+               column.add_attribute(textrenderer, 'text', 4)
+
+               column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+               column.set_sort_column_id(1)
+               column.set_visible(True)
+               contactsview.append_column(column)
+
+               #textrenderer = gtk.CellRendererText()
+               #column = gtk.TreeViewColumn("Location", textrenderer, text=2)
+               #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+               #column.set_sort_column_id(2)
+               #column.set_visible(True)
+               #contactsview.append_column(column)
+
+               #textrenderer = gtk.CellRendererText()
+               #column = gtk.TreeViewColumn("Phone", textrenderer, text=3)
+               #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+               #column.set_sort_column_id(3)
+               #column.set_visible(True)
+               #contactsview.append_column(column)
+
+               self._contactsviewselection = contactsview.get_selection()
+               self._contactsviewselection.set_mode(gtk.SELECTION_SINGLE)
+
+               return False
+
        def _setup_callback_combo(self):
                combobox = self._widgetTree.get_widget("callbackcombo")
                self.callbacklist = gtk.ListStore(gobject.TYPE_STRING)
@@ -280,6 +389,7 @@ class Dialpad(object):
 
        def populate_recentview(self):
                self._recentmodel.clear()
+
                for personsName, phoneNumber, date, action in self._gcBackend.get_recent():
                        item = (phoneNumber, "%s on %s from/to %s - %s" % (action.capitalize(), date, personsName, phoneNumber))
                        self._recentmodel.append(item)
@@ -287,6 +397,26 @@ class Dialpad(object):
 
                return False
 
+       def populate_contactsview(self):
+               self._contactsmodel.clear()
+
+               # completely disable updating the treeview while we populate the data
+               contactsview = self._widgetTree.get_widget("contactsview")
+               contactsview.freeze_child_notify()
+               contactsview.set_model(None)
+
+        # get gc icon
+               gc_icon = gtk.gdk.pixbuf_new_from_file_at_size('gc.png', 16, 16)
+               for contactId, contactName in self._gcBackend.get_contacts():
+                       self._contactsmodel.append((gc_icon,) + (contactName, "", contactId) + ("",))
+
+               # restart the treeview data rendering
+               contactsview.set_model(self._contactsmodel)
+               contactsview.thaw_child_notify()
+
+               self._contactsNeedSetup = False
+               return False
+
        def attempt_login(self, numOfAttempts = 1):
                assert 0 < numOfAttempts, "That was pointless having 0 or less login attempts"
                dialog = self._widgetTree.get_widget("login_dialog")
@@ -373,13 +503,13 @@ class Dialpad(object):
                        else:
                                self._window.fullscreen()
 
-       def _on_loginbutton_clicked(self, data=None):
+       def _on_loginbutton_clicked(self, *args):
                self._widgetTree.get_widget("login_dialog").response(gtk.RESPONSE_OK)
 
-       def _on_loginclose_clicked(self, data=None):
+       def _on_loginclose_clicked(self, *args):
                sys.exit(0)
 
-       def _on_clearcookies_clicked(self, data=None):
+       def _on_clearcookies_clicked(self, *args):
                self._gcBackend.reset()
                self._callbackNeedsSetup = True
                self._recenttime = 0.0
@@ -390,7 +520,7 @@ class Dialpad(object):
                self.attempt_login(2)
                gobject.idle_add(self._init_grandcentral)
 
-       def _on_callbackentry_changed(self, data=None):
+       def _on_callbackentry_changed(self, *args):
                """
                @todo Potential blocking on web access, maybe we should defer this or put up a dialog?
                """
@@ -411,10 +541,34 @@ class Dialpad(object):
                self._notebook.set_current_page(0)
                self._recentviewselection.unselect_all()
 
+       def _on_contactsview_row_activated(self, treeview, path, view_column):
+               model, itr = self._contactsviewselection.get_selected()
+               if not itr:
+                       return
+
+               contactId = self._contactsmodel.get_value(itr, 3)
+               contactDetails = self._gcBackend.get_contact_details(contactId)
+               contactDetails = [phoneNumber for phoneNumber in contactDetails]
+
+               if len(contactDetails) == 0:
+                       phoneNumber = ""
+               elif len(contactDetails) == 1:
+                       phoneNumber = contactDetails[0][1]
+               else:
+                       phoneNumber = self._phoneTypeSelector.run(contactDetails)
+
+               if 0 < len(phoneNumber):
+                       self.set_number(phoneNumber)
+                       self._notebook.set_current_page(0)
+
+               self._contactsviewselection.unselect_all()
+
        def _on_notebook_switch_page(self, notebook, page, page_num):
-               if page_num == 1 and (time.time() - self._recenttime) > 300:
+               if page_num == 1 and self._contactsNeedSetup:
+                       gobject.idle_add(self.populate_contactsview)
+               elif page_num == 2 and 300 < (time.time() - self._recenttime):
                        gobject.idle_add(self.populate_recentview)
-               elif page_num ==2 and self._callbackNeedsSetup:
+               elif page_num == 3 and self._callbackNeedsSetup:
                        gobject.idle_add(self._setup_callback_combo)
 
                if hildon:
@@ -444,12 +598,12 @@ class Dialpad(object):
                self._recentmodel.clear()
                self._recenttime = 0.0
 
-       def _on_paste(self, data=None):
+       def _on_paste(self, *args):
                contents = self._clipboard.wait_for_text()
                phoneNumber = re.sub('\D', '', contents)
                self.set_number(phoneNumber)
 
-       def _on_clear_number(self, data=None):
+       def _on_clear_number(self, *args):
                self.set_number("")
 
        def _on_digit_clicked(self, widget):
@@ -489,12 +643,12 @@ if __name__ == "__main__":
        if optparse is not None:
                parser = optparse.OptionParser()
                parser.add_option("-t", "--test", action="store_true", dest="test", help="Run tests")
-               (options, args) = parser.parse_args()
+               (commandOptions, commandArgs) = parser.parse_args()
        else:
-               args = []
-               options = DummyOptions()
+               commandOptions = DummyOptions()
+               commandArgs = []
 
-       if options.test:
+       if commandOptions.test:
                run_doctest()
        else:
                run_dialpad()
index e0c7dda..55e8c2e 100644 (file)
@@ -17,9 +17,6 @@ import warnings
 from browser_emu import MozillaEmulator
 
 
-_validateRe = re.compile("^[0-9]{10,}$")
-
-
 class GCDialer(object):
        """
        This class encapsulates all of the knowledge necessary to interace with the grandcentral servers
@@ -32,12 +29,20 @@ class GCDialer(object):
        _callbackRe = re.compile(r"""name="default_number" value="(\d+)" />\s+(.*)\s$""", re.M)
        _accountNumRe = re.compile(r"""<img src="/images/mobile/inbox_logo.gif" alt="GrandCentral" />\s*(.{14})\s*&nbsp""", re.M)
        _inboxRe = re.compile(r"""<td>.*?(voicemail|received|missed|call return).*?</td>\s+<td>\s+<font size="2">\s+(.*?)\s+&nbsp;\|&nbsp;\s+<a href="/mobile/contacts/.*?">(.*?)\s?</a>\s+<br/>\s+(.*?)\s?<a href=""", re.S)
+       _contactsRe = re.compile(r"""<a href="/mobile/contacts/detail/(\d+)">(.*?)</a>""", re.S)
+       _contactsNextRe = re.compile(r""".*<a href="/mobile/contacts(\?page=\d+)">Next</a>""", re.S)
+       _contactDetailGroupRe   = re.compile(r"""Group:\s*(\w*)""", re.S)
+       _contactDetailPhoneRe   = re.compile(r"""(\w+):[0-9\-\(\) \t]*?<a href="/mobile/calls/click_to_call\?destno=(\d+).*?">call</a>""", re.S)
+
+       _validateRe = re.compile("^[0-9]{10,}$")
 
        _forwardselectURL = "http://www.grandcentral.com/mobile/settings/forwarding_select"
        _loginURL = "https://www.grandcentral.com/mobile/account/login"
        _setforwardURL = "http://www.grandcentral.com/mobile/settings/set_forwarding?from=settings"
        _clicktocallURL = "http://www.grandcentral.com/mobile/calls/click_to_call?a_t=%s&destno=%s"
        _inboxallURL = "http://www.grandcentral.com/mobile/messages/inbox?types=all"
+       _contactsURL = "http://www.grandcentral.com/mobile/contacts"
+       _contactDetailURL = "http://www.grandcentral.com/mobile/contacts/detail"
 
        def __init__(self, cookieFile = None):
                # Important items in this function are the setup of the browser emulation and cookie file
@@ -147,7 +152,7 @@ class GCDialer(object):
                """
                @returns If This number be called ( syntax validation only )
                """
-               return _validateRe.match(number) is not None
+               return self._validateRe.match(number) is not None
 
        def get_account_number(self):
                """
@@ -235,6 +240,27 @@ class GCDialer(object):
                        personsName = match.group(3)
                        yield personsName, phoneNumber, date, action
 
+       def get_contacts(self):
+               contactsPagesUrls = [GCDialer._contactsURL]
+               for contactsPageUrl in contactsPagesUrls:
+                       print contactsPageUrl
+                       contactsPage = self._browser.download(contactsPageUrl)
+                       for contact_match in self._contactsRe.finditer(contactsPage):
+                               contactId = contact_match.group(1)
+                               contactName = contact_match.group(2)
+                               yield contactId, contactName
+                       next_match = self._contactsNextRe.match(contactsPage)
+                       if next_match is not None:
+                               newContactsPageUrl = self._contactsURL + next_match.group(1)
+                               contactsPagesUrls.append(newContactsPageUrl)
+       
+       def get_contact_details(self, contactId):
+               detailPage = self._browser.download(GCDialer._contactDetailURL + '/' + contactId)
+               for detail_match in self._contactDetailPhoneRe.finditer(detailPage):
+                       phoneType = detail_match.group(1)
+                       phoneNumber = detail_match.group(2)
+                       yield (phoneType, phoneNumber)
+
        def _grab_token(self, data):
                "Pull the magic cookie from the datastream"
                atGroup = GCDialer._accessTokenRe.search(data)