Wt examples  3.3.8
Composer.C
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 #include <iostream>
7 
8 #include "AddresseeEdit.h"
9 #include "AttachmentEdit.h"
10 #include "Composer.h"
11 #include "ContactSuggestions.h"
12 #include "Label.h"
13 #include "Option.h"
14 #include "OptionList.h"
15 
16 #include <Wt/WContainerWidget>
17 #include <Wt/WImage>
18 #include <Wt/WLineEdit>
19 #include <Wt/WPushButton>
20 #include <Wt/WText>
21 #include <Wt/WTable>
22 #include <Wt/WTableCell>
23 #include <Wt/WStringUtil>
24 
26  : WCompositeWidget(parent),
27  saving_(false),
28  sending_(false)
29 {
31 
32  createUi();
33 }
34 
35 void Composer::setTo(const std::vector<Contact>& to)
36 {
38 }
39 
41 {
42  subject_->setText(subject);
43 }
44 
46 {
47  message_->setText(message);
48 }
49 
50 std::vector<Contact> Composer::to() const
51 {
52  return toEdit_->addressees();
53 }
54 
55 std::vector<Contact> Composer::cc() const
56 {
57  return ccEdit_->addressees();
58 }
59 
60 std::vector<Contact> Composer::bcc() const
61 {
62  return bccEdit_->addressees();
63 }
64 
65 void Composer::setAddressBook(const std::vector<Contact>& contacts)
66 {
68 }
69 
70 const WString& Composer::subject() const
71 {
72  return subject_->text();
73 }
74 
75 std::vector<Attachment> Composer::attachments() const
76 {
77  std::vector<Attachment> attachments;
78 
79  for (unsigned i = 0; i < attachments_.size() - 1; ++i) {
80  std::vector<Attachment> toadd = attachments_[i]->attachments();
81 
82  attachments.insert(attachments.end(), toadd.begin(), toadd.end());
83  }
84 
85  return attachments;
86 }
87 
88 const WString& Composer::message() const
89 {
90  return message_->text();
91 }
92 
94 {
95  setStyleClass("darker");
96 
97  // horizontal layout container, used for top and bottom buttons.
98  WContainerWidget *horiz;
99 
100  /*
101  * Top buttons
102  */
103  horiz = new WContainerWidget(layout_);
104  horiz->setPadding(5);
105  topSendButton_ = new WPushButton(tr("msg.send"), horiz);
106  topSendButton_->setStyleClass("default"); // default action
107  topSaveNowButton_ = new WPushButton(tr("msg.savenow"), horiz);
108  topDiscardButton_ = new WPushButton(tr("msg.discard"), horiz);
109 
110  // Text widget which shows status messages, next to the top buttons.
111  statusMsg_ = new WText(horiz);
112  statusMsg_->setMargin(15, Left);
113 
114  /*
115  * To, Cc, Bcc, Subject, Attachments
116  *
117  * They are organized in a two-column table: left column for
118  * labels, and right column for the edit.
119  */
120  edits_ = new WTable(layout_);
121  edits_->setStyleClass("lighter");
122  edits_->resize(WLength(100, WLength::Percentage), WLength::Auto);
123  edits_->elementAt(0, 0)->resize(WLength(1, WLength::Percentage),
124  WLength::Auto);
125 
126  /*
127  * To, Cc, Bcc
128  */
129  toEdit_ = new AddresseeEdit(tr("msg.to"), edits_->elementAt(0, 1),
130  edits_->elementAt(0, 0));
131  // add some space above To:
132  edits_->elementAt(0, 1)->setMargin(5, Top);
133  ccEdit_ = new AddresseeEdit(tr("msg.cc"), edits_->elementAt(1, 1),
134  edits_->elementAt(1, 0));
135  bccEdit_ = new AddresseeEdit(tr("msg.bcc"), edits_->elementAt(2, 1),
136  edits_->elementAt(2, 0));
137 
138  ccEdit_->hide();
139  bccEdit_->hide();
140 
141  /*
142  * Addressbook suggestions popup
143  */
145 
148  contactSuggestions_->forEdit(bccEdit_);
149 
150  /*
151  * We use an OptionList widget to show the expand options for
152  * ccEdit_ and bccEdit_ nicely next to each other, separated
153  * by pipe characters.
154  */
155  options_ = new OptionList(edits_->elementAt(3, 1));
156 
157  options_->add(addcc_ = new Option(tr("msg.addcc")));
158  options_->add(addbcc_ = new Option(tr("msg.addbcc")));
159 
160  /*
161  * Subject
162  */
163  new Label(tr("msg.subject"), edits_->elementAt(4, 0));
164  subject_ = new WLineEdit(edits_->elementAt(4, 1));
165  subject_->resize(WLength(99, WLength::Percentage), WLength::Auto);
166 
167  /*
168  * Attachments
169  */
170  new WImage("icons/paperclip.png", edits_->elementAt(5, 0));
172  edits_->elementAt(5, 0)->setPadding(3);
173 
174  // Attachment edits: we always have the next attachmentedit ready
175  // but hidden. This improves the response time, since the show()
176  // and hide() slots are stateless.
177  attachments_.push_back(new AttachmentEdit(this, edits_->elementAt(5, 1)));
178  attachments_.back()->hide();
179 
180  /*
181  * Two options for attaching files. The first does not say 'another'.
182  */
183  attachFile_ = new Option(tr("msg.attachfile"),
184  edits_->elementAt(5, 1));
185  attachOtherFile_ = new Option(tr("msg.attachanother"),
186  edits_->elementAt(5, 1));
187  attachOtherFile_->hide();
188 
189  /*
190  * Message
191  */
192  message_ = new WTextArea(layout_);
193  message_->setColumns(80);
194  message_->setRows(10); // should be 20, but let's keep it smaller
195  message_->setMargin(10);
196 
197  /*
198  * Bottom buttons
199  */
200  horiz = new WContainerWidget(layout_);
201  horiz->setPadding(5);
202  botSendButton_ = new WPushButton(tr("msg.send"), horiz);
203  botSendButton_->setStyleClass("default");
204  botSaveNowButton_ = new WPushButton(tr("msg.savenow"), horiz);
205  botDiscardButton_ = new WPushButton(tr("msg.discard"), horiz);
206 
207  /*
208  * Button events.
209  */
210  topSendButton_->clicked().connect(this, &Composer::sendIt);
211  botSendButton_->clicked().connect(this, &Composer::sendIt);
212  topSaveNowButton_->clicked().connect(this, &Composer::saveNow);
213  botSaveNowButton_->clicked().connect(this, &Composer::saveNow);
214  topDiscardButton_->clicked().connect(this, &Composer::discardIt);
215  botDiscardButton_->clicked().connect(this, &Composer::discardIt);
216 
217  /*
218  * Option events to show the cc or Bcc edit.
219  *
220  * Clicking on the option should both show the corresponding edit, and
221  * hide the option itself.
222  */
223  addcc_->item()->clicked().connect(ccEdit_, &WWidget::show);
224  addcc_->item()->clicked().connect(addcc_, &WWidget::hide);
225  addcc_->item()->clicked().connect(options_, &OptionList::update);
226  addcc_->item()->clicked().connect(ccEdit_, &WWidget::setFocus);
227 
228  addbcc_->item()->clicked().connect(bccEdit_, &WWidget::show);
229  addbcc_->item()->clicked().connect(addbcc_, &WWidget::hide);
231  addbcc_->item()->clicked().connect(bccEdit_, &WWidget::setFocus);
232 
233  /*
234  * Option event to attach the first attachment.
235  *
236  * We show the first attachment, and call attachMore() to prepare the
237  * next attachment edit that will be hidden.
238  *
239  * In addition, we need to show the 'attach More' option, and hide the
240  * 'attach' option.
241  */
242  attachFile_->item()->clicked().connect(attachments_.back(), &WWidget::show);
243  attachFile_->item()->clicked().connect(attachOtherFile_, &WWidget::show);
244  attachFile_->item()->clicked().connect(attachFile_, &WWidget::hide);
245  attachFile_->item()->clicked().connect(this, &Composer::attachMore);
246  attachOtherFile_->item()->clicked().connect(this, &Composer::attachMore);
247 }
248 
250 {
251  /*
252  * Create and append the next AttachmentEdit, that will be hidden.
253  */
254  AttachmentEdit *edit = new AttachmentEdit(this);
256  attachments_.push_back(edit);
257  attachments_.back()->hide();
258 
259  // Connect the attachOtherFile_ option to show this attachment.
261  .connect(attachments_.back(), &WWidget::show);
262 }
263 
265 {
266  /*
267  * Remove the given attachment from the attachments list.
268  */
269  std::vector<AttachmentEdit *>::iterator i
270  = std::find(attachments_.begin(), attachments_.end(), attachment);
271 
272  if (i != attachments_.end()) {
273  attachments_.erase(i);
274  delete attachment;
275 
276  if (attachments_.size() == 1) {
277  /*
278  * This was the last visible attachment, thus, we should switch
279  * the option control again.
280  */
282  attachFile_->show();
283  attachFile_->item()->clicked()
284  .connect(attachments_.back(), &WWidget::show);
285  }
286  }
287 }
288 
290 {
291  if (!sending_) {
292  sending_ = true;
293 
294  /*
295  * First save -- this will check for the sending_ state
296  * signal if successfull.
297  */
298  saveNow();
299  }
300 }
301 
303 {
304  if (!saving_) {
305  saving_ = true;
306 
307  /*
308  * Check if any attachments still need to be uploaded.
309  * This may be the case when fileupload change events could not
310  * be caught (for example in Konqueror).
311  */
313 
314  for (unsigned i = 0; i < attachments_.size() - 1; ++i) {
315  if (attachments_[i]->uploadNow()) {
317 
318  // this will trigger attachmentDone() when done, see
319  // the AttachmentEdit constructor.
320  }
321  }
322 
323  std::cerr << "Attachments pending: " << attachmentsPending_ << std::endl;
325  setStatus(tr("msg.uploading"), "status");
326  else
327  saved();
328  }
329 }
330 
332 {
333  if (saving_) {
335  std::cerr << "Attachments still: " << attachmentsPending_ << std::endl;
336 
337  if (attachmentsPending_ == 0)
338  saved();
339  }
340 }
341 
342 void Composer::setStatus(const WString& text, const WString& style)
343 {
344  statusMsg_->setText(text);
345  statusMsg_->setStyleClass(style);
346 }
347 
349 {
350  /*
351  * All attachments have been processed.
352  */
353 
354  bool attachmentsFailed = false;
355  for (unsigned i = 0; i < attachments_.size() - 1; ++i)
356  if (attachments_[i]->uploadFailed()) {
357  attachmentsFailed = true;
358  break;
359  }
360 
361  if (attachmentsFailed) {
362  setStatus(tr("msg.attachment.failed"), "error");
363  } else {
364 #ifndef WIN32
365  time_t t = time(0);
366  struct tm td;
367  gmtime_r(&t, &td);
368  char buffer[100];
369  strftime(buffer, 100, "%H:%M", &td);
370 #else
371  char buffer[] = "server"; // Should fix this; for now just make sense
372 #endif
373  setStatus(tr("msg.ok"), "status");
374  statusMsg_->setText(std::string("Draft saved at ") + buffer);
375 
376  if (sending_) {
377  send.emit();
378  return;
379  }
380  }
381 
382  saving_ = false;
383  sending_ = false;
384 }
385 
387 {
388  discard.emit();
389 }
void createUi()
Definition: Composer.C:93
A clickable option.
Definition: Option.h:31
AddresseeEdit * bccEdit_
Bcc: Addressees edit.
Definition: Composer.h:113
virtual void setText(const WString &text)
void emit(A1 a1=NoClass::none, A2 a2=NoClass::none, A3 a3=NoClass::none, A4 a4=NoClass::none, A5 a5=NoClass::none, A6 a6=NoClass::none) const
std::vector< Contact > to() const
Get the To: contacts.
Definition: Composer.C:50
WInteractWidget * item()
Returns the clickable part.
Definition: Option.h:44
AddresseeEdit * toEdit_
To: Addressees edit.
Definition: Composer.h:109
virtual void resize(const WLength &width, const WLength &height)
WTable * edits_
Definition: Composer.h:106
void discardIt()
Slot attached to the Discard button.
Definition: Composer.C:386
WContainerWidget * layout_
Definition: Composer.h:100
void setPadding(const WLength &padding, WFlags< Side > sides=All)
EventSignal< WMouseEvent > & clicked()
Option * attachOtherFile_
Option for attaching another file.
Definition: Composer.h:131
Option * addbcc_
Option for editing Bcc:
Definition: Composer.h:127
static WString tr(const char *key)
An edit field for an email attachment.
const WString & text() const
Composer(WContainerWidget *parent=0)
Construct a new Composer.
Definition: Composer.C:25
void saved()
All attachments have been processed, determine the result of saving the message.
Definition: Composer.C:348
WPushButton * botSaveNowButton_
Definition: Composer.h:103
std::vector< AttachmentEdit * > attachments_
Array which holds all the attachments, including one extra invisible one.
Definition: Composer.h:134
WTextArea * message_
WTextArea for the main message.
Definition: Composer.h:137
std::vector< Contact > cc() const
Get the Cc: contacts.
Definition: Composer.C:55
void setImplementation(WWidget *widget)
Wt::Signal< void > send
The message is ready to be sent...
Definition: Composer.h:93
const WString & subject() const
Get the subject.
Definition: Composer.C:70
void setContentAlignment(WFlags< AlignmentFlag > contentAlignment)
Wt::Signal< void > discard
The message must be discarded.
Definition: Composer.h:97
void setSubject(const WString &subject)
Set subject.
Definition: Composer.C:40
void removeAttachment(AttachmentEdit *attachment)
Remove the given attachment edit.
Definition: Composer.C:264
bool setText(const WString &text)
void saveNow()
Slot attached to the Save now button.
Definition: Composer.C:302
void update()
Updates the stateless implementations after an Option has been hidden or shown.
Definition: OptionList.C:30
void setAddressBook(const std::vector< Contact > &contacts)
Set the address book.
A label.
Definition: Label.h:24
virtual void insertBefore(WWidget *widget, WWidget *before)
WTableCell * elementAt(int row, int column)
virtual void setStyleClass(const WString &styleClass)
WPushButton * botSendButton_
Definition: Composer.h:103
WPushButton * topDiscardButton_
Definition: Composer.h:102
virtual void setMargin(const WLength &margin, WFlags< Side > sides=All)
void sendIt()
Slot attached to the Send button.
Definition: Composer.C:289
A list of options, separated by &#39;|&#39;.
Definition: OptionList.h:40
void setAddressBook(const std::vector< Contact > &addressBook)
Set the address book, for autocomplete suggestions.
Definition: Composer.C:65
void setAddressees(const std::vector< Contact > &contacts)
Set a list of addressees.
Definition: AddresseeEdit.C:27
void setColumns(int cols)
std::vector< Contact > bcc() const
Get the Bc: contacts.
Definition: Composer.C:60
virtual void setText(const WString &text)
An edit field for an email addressee.
Definition: AddresseeEdit.h:31
WPushButton * botDiscardButton_
Definition: Composer.h:103
const WString & message() const
Get the message.
Definition: Composer.C:88
const WString & text() const
A suggestion popup suggesting contacts from an addressbook.
AlignTop
AlignRight
bool saving_
state when waiting asyncrhonously for attachments to be uploaded
Definition: Composer.h:140
Option * attachFile_
Option for attaching a file.
Definition: Composer.h:129
void forEdit(WFormWidget *edit, WFlags< PopupTrigger > popupTriggers=Editing)
std::vector< Attachment > attachments() const
Get the list of attachments.
Definition: Composer.C:75
WPushButton * topSaveNowButton_
Definition: Composer.h:102
friend class AttachmentEdit
Definition: Composer.h:194
virtual void setStyleClass(const WString &styleClass)
WLineEdit * subject_
The subject line edit.
Definition: Composer.h:119
WPushButton * topSendButton_
Definition: Composer.h:102
void attachmentDone()
Slotcalled when an attachment has been uploaded.
Definition: Composer.C:331
Option * addcc_
Option for editing Cc:
Definition: Composer.h:125
ContactSuggestions * contactSuggestions_
The suggestions popup for the addressee edits.
Definition: Composer.h:116
void setMessage(const WString &message)
Set the message.
Definition: Composer.C:45
void setTo(const std::vector< Contact > &to)
Set message To: contacts.
Definition: Composer.C:35
void attachMore()
Add an attachment edit.
Definition: Composer.C:249
AddresseeEdit * ccEdit_
Cc: Addressees edit.
Definition: Composer.h:111
int attachmentsPending_
number of attachments waiting to be uploaded during saving
Definition: Composer.h:143
OptionList * options_
OptionsList for editing Cc or Bcc.
Definition: Composer.h:122
void setRows(int rows)
WText * statusMsg_
Definition: Composer.h:104
std::vector< Contact > addressees() const
Get a list of addressees.
Definition: AddresseeEdit.C:74
bool sending_
Definition: Composer.h:140
void add(Option *option)
Add an Option to the list.
Definition: OptionList.C:18
void setStatus(const WString &text, const WString &style)
Set the status, and apply the given style.
Definition: Composer.C:342

Generated on Mon Sep 4 2017 for the C++ Web Toolkit (Wt) by doxygen 1.8.11