Revision: 7420
          http://mahogany.svn.sourceforge.net/mahogany/?rev=7420&view=rev
Author:   vadz
Date:     2008-04-20 18:59:12 -0700 (Sun, 20 Apr 2008)

Log Message:
-----------
allow adding custom headers to be shown in the message view

Modified Paths:
--------------
    trunk/M/CHANGES
    trunk/M/include/gui/wxSelectionDlg.h
    trunk/M/src/gui/wxHeadersDialogs.cpp
    trunk/M/src/gui/wxMDialogs.cpp

Modified: trunk/M/CHANGES
===================================================================
--- trunk/M/CHANGES     2008-04-19 23:59:00 UTC (rev 7419)
+++ trunk/M/CHANGES     2008-04-21 01:59:12 UTC (rev 7420)
@@ -9,6 +9,7 @@
 Release 0.68 '' September xx, 2007
 ---------------------------------------
 
+2008-04-21 VZ: Allow adding custom headers to show in the message view
 2007-08-04 VZ: Allow autocollecting addresses in outgoing messages only
 2007-04-26 VZ: Add the possibility to treat different addresses as equivalent
 2007-01-10 VZ: Show the message subject in the composer window title bar

Modified: trunk/M/include/gui/wxSelectionDlg.h
===================================================================
--- trunk/M/include/gui/wxSelectionDlg.h        2008-04-19 23:59:00 UTC (rev 
7419)
+++ trunk/M/include/gui/wxSelectionDlg.h        2008-04-21 01:59:12 UTC (rev 
7420)
@@ -19,15 +19,31 @@
 // wxSelectionsOrderDialog
 // ----------------------------------------------------------------------------
 
-// helper class used by MDialog_GetSelectionsInOrder and
-// wxMsgViewHeadersDialog elsewhere
+// helper class used by MDialog_GetSelectionsInOrder and wxMsgViewHeadersDialog
+// elsewhere: it allows to show to the user the list of strings which can be
+// individually checked/unchecked and reordered and, possibly, edited (added,
+// changed or removed) by user
 class wxSelectionsOrderDialog : public wxManuallyLaidOutDialog
 {
 public:
+   // flags for optional features
+   enum
+   {
+      // default: the list of strings can't be modified at all
+      Allow_Nothing = 0,
+
+      // allow adding user-defined strings to the list (virtual OnItemAdd() is
+      // called to validate them)
+      Allow_Add = 1
+
+      // add Allow_Edit/Delete later if needed
+   };
+
    wxSelectionsOrderDialog(wxWindow *parent,
                            const wxString& message,
                            const wxString& caption,
-                           const wxString& profileKey);
+                           const wxString& profileKey,
+                           int extraFeatures = Allow_Nothing);
 
    // did anything really changed?
    bool HasChanges() const { return m_hasChanges; }
@@ -37,8 +53,24 @@
    virtual bool TransferDataToWindow() = 0;
    virtual bool TransferDataFromWindow() = 0;
 
-   // implementation only from now on
+protected:
+   // can be overridden if the derived class wants to know when the 2 items in
+   // the check list box are exchanged (after this has happened)
+   virtual void OnItemSwap(size_t /* item1 */, size_t /* item2 */) { }
 
+   // can be overridden to validate the string before adding it to the
+   // checklistbox; the string is not added if this method returns false
+   //
+   // the base class version checks if the string is already present in the
+   // list and returns false if it is, so make sure to call it from the derived
+   // class unless this check is undesirable
+   //
+   // notice that it is only called if Allow_Add was used
+   virtual bool OnItemAdd(const wxString& item);
+
+
+   // event handlers
+
    // check list box event handler
    void OnCheckLstBoxToggle(wxCommandEvent&) { m_hasChanges = TRUE; }
 
@@ -48,18 +80,24 @@
    // up/down buttons notifications
    void OnButtonUp(wxCommandEvent&) { OnButtonMove(TRUE); }
    void OnButtonDown(wxCommandEvent&) { OnButtonMove(FALSE); }
+   void OnButtonMove(bool up);
 
-protected:
-   // can be overridden if the derived class wants to know when the 2 items in
-   // the check list box are exchanged (after this has happened)
-   virtual void OnItemSwap(size_t /* item1 */, size_t /* item2 */) { }
+   // handlers for the controls used for adding items: notice that it's ok to
+   // dereference m_textAdd here without checking that it's non-NULL as these
+   // handlers are only connected if it is being used
+   void OnAdd(wxCommandEvent&) { DoAddItem(m_textAdd->GetValue()); }
+   void OnUpdateAddButton(wxUpdateUIEvent& event)
+   {
+      event.Enable( !m_textAdd->IsEmpty() );
+   }
 
-   // real button events handler
-   void OnButtonMove(bool up);
-
    // update the buttons state to reflect the selection in the checklistbox
    void UpdateButtons(int sel);
 
+   // add a new item to the list box
+   void DoAddItem(const wxString& item);
+
+
    // the box around all our controls (here for wxFolderViewColumnsDialog only)
    wxStaticBox    *m_box;
 
@@ -67,6 +105,9 @@
    wxButton       *m_btnUp,
                   *m_btnDown;
 
+   // the text containing the new item to add (only !NULL if Allow_Add used)
+   wxTextCtrl *m_textAdd;
+
    // the check list box containing the items we reorder
    wxCheckListBox *m_checklstBox;
 

Modified: trunk/M/src/gui/wxHeadersDialogs.cpp
===================================================================
--- trunk/M/src/gui/wxHeadersDialogs.cpp        2008-04-19 23:59:00 UTC (rev 
7419)
+++ trunk/M/src/gui/wxHeadersDialogs.cpp        2008-04-21 01:59:12 UTC (rev 
7420)
@@ -110,6 +110,51 @@
 };
 
 // ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+namespace
+{
+
+/**
+   Checks if the given string is a valid header name conforming to RFC 2822.
+
+   @param header The string to check.
+   @param reason If non-NULL, filled with the explanation of why the header
+                 name is invalid if the function returns false.
+   @return true if the header name is valid, false otherwise
+ */
+bool IsValidHeaderName(const wxString& header, wxString *reason)
+{
+   for ( wxString::const_iterator p = header.begin(); p != header.end(); ++p )
+   {
+      // RFC 822 allows '/' but we don't because it has a special meaning for
+      // the profiles/wxConfig; other characters are excluded in accordance
+      // with the definition of the header name in the section 2.2 of RFC 2822
+      wxChar c = *p;
+      if ( c < 32 || c > 126 )
+      {
+         if ( reason )
+            *reason = "only ASCII characters are allowed";
+
+         return false;
+      }
+
+      if ( c == ':' )
+      {
+         if ( reason )
+            *reason = "colons are not allowed";
+
+         return false;
+      }
+   }
+
+   return true;
+}
+
+} // anonymous namespace
+
+// ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
 
@@ -166,6 +211,10 @@
    virtual bool TransferDataToWindow();
    virtual bool TransferDataFromWindow();
 
+protected:
+   // validate the header names
+   virtual bool OnItemAdd(const wxString& item);
+
 private:
    Profile *m_profile;
 
@@ -485,16 +534,19 @@
 
 wxMsgViewHeadersDialog::wxMsgViewHeadersDialog(Profile *profile,
                                                wxWindow *parent)
-                      : wxSelectionsOrderDialog(parent,
-                                               _("&Headers"),
-                                               _("Configure headers to show "
-                                                 "in message view"),
-                                               _T("MsgViewHeaders"))
+                      : wxSelectionsOrderDialog
+                        (
+                           parent,
+                           _("&Headers to show in message view"),
+                           _("Configure message view headers"),
+                           _T("MsgViewHeaders"),
+                           Allow_Add
+                        )
 {
    m_profile = profile;
    SafeIncRef(profile);
 
-   SetDefaultSize(3*wBtn, 10*hBtn);
+   SetDefaultSize(6*wBtn, 10*hBtn);
 }
 
 wxMsgViewHeadersDialog::~wxMsgViewHeadersDialog()
@@ -502,6 +554,23 @@
    SafeDecRef(m_profile);
 }
 
+bool wxMsgViewHeadersDialog::OnItemAdd(const wxString& item)
+{
+   if ( !wxSelectionsOrderDialog::OnItemAdd(item) )
+      return false;
+
+   wxString reason;
+   if ( !IsValidHeaderName(item, &reason) )
+   {
+      wxLogWarning(_("\"%s\" is not a valid header name: %s."),
+                   item.c_str(), reason.c_str());
+
+      return false;
+   }
+
+   return true;
+}
+
 bool wxMsgViewHeadersDialog::TransferDataToWindow()
 {
    // colon separated list of all the headers (even if they're not all shown)
@@ -749,20 +818,23 @@
    m_headerName = m_textctrlName->GetValue();
 
    // check that this is a valid header name
-   for ( const wxChar *pc = m_headerName.c_str(); *pc; pc++ )
+   wxString reason;
+   if ( IsValidHeaderName(m_headerName, &reason) )
    {
-      // RFC 822 allows '/' but we don't because it has a special meaning for
-      // the profiles/wxConfig; other characters are excluded in accordance
-      // with the definition of the header name in the RFC
-      wxChar c = *pc;
-      if ( c < 32 || c > 126 || c == ':' || c == '/' )
+      // in addition to the standard RFC checks we also forbid slashes as this
+      // string is used as profile key
+      if ( m_headerName.find('/') != wxString::npos )
       {
-         wxLogError(_("The character '%c' is invalid in the header name, "
-                      "please replace or remove it."), c);
-         return false;
+         reason = "slashes are not allowed in this context";
       }
    }
 
+   if ( !reason.empty() )
+   {
+      wxLogError(_("Specified header name is invalid: %s."), reason.c_str());
+      return false;
+   }
+
    m_headerValue = m_textctrlValue->GetValue();
 
    if ( m_checkboxRemember )
@@ -1119,7 +1191,7 @@
 
 void wxCustomHeadersDialog::OnDelete(wxCommandEvent& WXUNUSED(event))
 {
-   size_t sel = 0; // inititialize it to fix compiler warnings
+   size_t sel = 0; // initialize it to fix compiler warnings
    CHECK_RET( GetSelection(&sel), _T("button should be disabled") );
 
    m_listctrl->DeleteItem(sel);

Modified: trunk/M/src/gui/wxMDialogs.cpp
===================================================================
--- trunk/M/src/gui/wxMDialogs.cpp      2008-04-19 23:59:00 UTC (rev 7419)
+++ trunk/M/src/gui/wxMDialogs.cpp      2008-04-21 01:59:12 UTC (rev 7420)
@@ -2399,15 +2399,21 @@
    return selections->GetCount();
 }
 
-// ----------------------------------------------------------------------------
+// ============================================================================
 // wxSelectionsOrderDialog
+// ============================================================================
+
 // ----------------------------------------------------------------------------
+// event table
+// ----------------------------------------------------------------------------
 
 // control ids for wxSelectionsOrderDialog
 enum
 {
    Button_Up = 1000,
-   Button_Down
+   Button_Down,
+   Button_Add,
+   Text_Add
 };
 
 BEGIN_EVENT_TABLE(wxSelectionsOrderDialog, wxManuallyLaidOutDialog)
@@ -2419,13 +2425,19 @@
    EVT_LISTBOX(-1, wxSelectionsOrderDialog::OnCheckLstBoxSelChanged)
 END_EVENT_TABLE()
 
+// ----------------------------------------------------------------------------
+// wxSelectionsOrderDialog ctor
+// ----------------------------------------------------------------------------
+
 wxSelectionsOrderDialog::wxSelectionsOrderDialog(wxWindow *parent,
                                                  const wxString& message,
                                                  const wxString& caption,
-                                                 const wxString& profileKey)
+                                                 const wxString& profileKey,
+                                                 int extraFeatures)
                        : wxManuallyLaidOutDialog(parent, caption, profileKey)
 {
    m_hasChanges = false;
+   m_textAdd = NULL;
 
    // layout the controls
    // -------------------
@@ -2454,13 +2466,56 @@
    c->height.AsIs();
    m_btnUp->SetConstraints(c);
 
+   // optional controls for string editing below the list box
+   wxControl *ctrlBelow = NULL;
+   if ( extraFeatures & Allow_Add )
+   {
+      wxStaticText *labelAdd = new wxStaticText(this, -1, _("&Add another:"));
+      c = new wxLayoutConstraints();
+      c->left.SameAs(m_box, wxLeft, 2*LAYOUT_X_MARGIN);
+      c->bottom.SameAs(m_box, wxBottom, 2*LAYOUT_Y_MARGIN);
+      c->width.AsIs();
+      c->height.AsIs();
+      labelAdd->SetConstraints(c);
+
+      m_textAdd = new wxTextCtrl(this, Text_Add, "",
+                                 wxDefaultSize, wxDefaultPosition,
+                                 wxTE_PROCESS_ENTER);
+      c = new wxLayoutConstraints();
+      c->left.RightOf(labelAdd, LAYOUT_X_MARGIN);
+      c->centreY.SameAs(labelAdd, wxCentreY);
+      c->right.LeftOf(m_btnDown, 2*LAYOUT_X_MARGIN);
+      c->height.AsIs();
+      m_textAdd->SetConstraints(c);
+
+      wxButton *btnAdd = new wxButton(this, Button_Add, _("A&dd"));
+      c = new wxLayoutConstraints();
+      c->left.RightOf(m_textAdd, LAYOUT_Y_MARGIN);
+      c->centreY.SameAs(m_textAdd, wxCentreY);
+      c->width.SameAs(m_btnDown, wxWidth);
+      c->height.AsIs();
+      btnAdd->SetConstraints(c);
+
+      ctrlBelow = btnAdd;
+
+      Connect(Button_Add, wxEVT_COMMAND_BUTTON_CLICKED,
+               wxCommandEventHandler(wxSelectionsOrderDialog::OnAdd));
+      Connect(Text_Add, wxEVT_COMMAND_TEXT_ENTER,
+               wxCommandEventHandler(wxSelectionsOrderDialog::OnAdd));
+      Connect(Button_Add, wxEVT_UPDATE_UI,
+               
wxUpdateUIEventHandler(wxSelectionsOrderDialog::OnUpdateAddButton));
+   }
+
    // a checklistbox with headers on the space which is left
    m_checklstBox = new wxCheckListBox(this, -1);
    c = new wxLayoutConstraints();
    c->left.SameAs(m_box, wxLeft, 2*LAYOUT_X_MARGIN);
    c->right.LeftOf(m_btnDown, 2*LAYOUT_X_MARGIN);
    c->top.SameAs(m_box, wxTop, 4*LAYOUT_Y_MARGIN);
-   c->bottom.SameAs(m_box, wxBottom, 2*LAYOUT_Y_MARGIN);
+   if ( ctrlBelow )
+      c->bottom.SameAs(ctrlBelow, wxTop, 2*LAYOUT_Y_MARGIN);
+   else
+      c->bottom.SameAs(m_box, wxBottom, 2*LAYOUT_Y_MARGIN);
    m_checklstBox->SetConstraints(c);
 
    UpdateButtons(m_checklstBox->GetSelection());
@@ -2469,6 +2524,43 @@
    SetDefaultSize(3*wBtn, 7*hBtn);
 }
 
+// ----------------------------------------------------------------------------
+// wxSelectionsOrderDialog handling adding items
+// ----------------------------------------------------------------------------
+
+bool wxSelectionsOrderDialog::OnItemAdd(const wxString& item)
+{
+   int count = m_checklstBox->GetCount();
+   for ( int n = 0; n < count; n++ )
+   {
+      if ( m_checklstBox->GetString(n) == item )
+      {
+         wxLogWarning(_("The string \"%s\" is already present in the list."),
+                      item.c_str());
+
+         return false;
+      }
+   }
+
+   return true;
+}
+
+void wxSelectionsOrderDialog::DoAddItem(const wxString& item)
+{
+   if ( OnItemAdd(item) )
+   {
+      const int pos = m_checklstBox->Append(item);
+
+      // we consider that the new item was added in order to be used, so be
+      // smart and do it by default
+      m_checklstBox->Check(pos);
+   }
+}
+
+// ----------------------------------------------------------------------------
+// wxSelectionsOrderDialog event handlers
+// ----------------------------------------------------------------------------
+
 void wxSelectionsOrderDialog::UpdateButtons(int sel)
 {
    // only enable buttons if there is something selected and also if pressing


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Mahogany-cvsupdates mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to