Wt examples  4.10.4
AttachmentEdit.C
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 
7 #include <fstream>
8 #ifndef WIN32
9 #include <unistd.h>
10 #endif
11 
12 #include <iostream>
13 
14 #include <Wt/WAnchor.h>
15 #include <Wt/WApplication.h>
16 #include <Wt/WCheckBox.h>
17 #include <Wt/WCssDecorationStyle.h>
18 #include <Wt/WFileResource.h>
19 #include <Wt/WLink.h>
20 #include <Wt/WFileUpload.h>
21 #include <Wt/WProgressBar.h>
22 #include <Wt/WText.h>
23 
24 #include "Attachment.h"
25 #include "AttachmentEdit.h"
26 #include "Composer.h"
27 #include "Option.h"
28 
30  : WContainerWidget(),
31  info_(f)
32 {
33  /*
34  * Include the file ?
35  */
36  keep_ = this->addWidget(std::make_unique<WCheckBox>());
37  keep_->setChecked();
38 
39  /*
40  * Give information on the file uploaded.
41  */
42  std::streamsize fsize = 0;
43  {
44  std::ifstream theFile(info_.spoolFileName().c_str());
45  theFile.seekg(0, std::ios_base::end);
46  fsize = theFile.tellg();
47  theFile.seekg(0);
48  }
49  std::u32string size;
50  if (fsize < 1024)
51  size = WString(std::to_string(fsize)) + U" bytes";
52  else
53  size = WString(std::to_string((int)(fsize / 1024)))
54  + U"kb";
55 
56  std::u32string fn = static_cast<std::u32string>
57  (escapeText(WString(info_.clientFileName())));
58 
60  = this->addWidget(std::make_unique<WAnchor>("", fn + U" (<i>" + WString(info_.contentType())
61  + U"</i>) " + size));
62 
63  auto res = std::make_shared<WFileResource>(info_.contentType(),info_.spoolFileName());
64  res->suggestFileName(info_.clientFileName());
66 }
67 
69  : WContainerWidget(),
70  composer_(composer),
71  uploadDone_(),
72  uploadFailed_(false)
73 {
74  /*
75  * The file upload itself.
76  */
77  upload_ = this->addWidget(std::make_unique<WFileUpload>());
78  upload_->setMultiple(true);
80 
81  /*
82  * A progress bar
83  */
84  std::unique_ptr<WProgressBar> progress = std::make_unique<WProgressBar>();
85  progress->setFormat(WString::Empty);
86  progress->setVerticalAlignment(AlignmentFlag::Middle);
87  upload_->setProgressBar(std::move(progress));
88 
89  /*
90  * The 'remove' option.
91  */
92  remove_ = this->addWidget(std::make_unique<Option>(tr("msg.remove")));
93  upload_->decorationStyle().font().setSize(FontSize::Smaller);
94  upload_->setVerticalAlignment(AlignmentFlag::Middle);
95  remove_->setMargin(5, Side::Left);
96  remove_->item()->clicked().connect(this, &WWidget::hide);
98 
99  // The error message.
100  error_ = this->addWidget(std::make_unique<WText>(""));
101  error_->setStyleClass("error");
102  error_->setMargin(WLength(5), Side::Left);
103 
104  /*
105  * React to events.
106  */
107 
108  // Try to catch the fileupload change signal to trigger an upload.
109  // We could do like google and at a delay with a WTimer as well...
110  upload_->changed().connect(upload_, &WFileUpload::upload);
111 
112  // React to a succesfull upload.
114 
115  // React to a fileupload problem.
117 
118  /*
119  * Connect the uploadDone signal to the Composer's attachmentDone,
120  * so that the Composer can keep track of attachment upload progress,
121  * if it wishes.
122  */
124 }
125 
127 {
128  /*
129  * See if this attachment still needs to be uploaded,
130  * and return if a new asynchronous upload is started.
131  */
132  if (upload_) {
133  if (upload_->canUpload()) {
134  upload_->upload();
135  return true;
136  } else
137  return false;
138  } else
139  return false;
140 }
141 
143 {
144  std::vector<Http::UploadedFile> files = upload_->uploadedFiles();
145 
146  if (!files.empty()) {
147  /*
148  * Delete this widgets since we have a succesfull upload.
149  */
150  upload_ = 0;
151  this->removeWidget(remove_);
152  remove_ = 0;
153  this->removeWidget(error_);
154  error_ = 0;
155 
156  for (unsigned i = 0; i < files.size(); ++i) {
157  UploadInfo *info = this->addWidget(std::make_unique<UploadInfo>(files[i]));
158  uploadInfo_.push_back(info);
159  }
160  } else {
161  error_->setText(tr("msg.file-empty"));
162  uploadFailed_ = true;
163  }
164 
165  /*
166  * Signal to the Composer that a new asynchronous file upload was processed.
167  */
168  uploadDone_.emit();
169 }
170 
172 {
174 }
175 
176 void AttachmentEdit::fileTooLarge(::int64_t size)
177 {
178  error_->setText(tr("msg.file-too-large")
179  .arg(size / 1024)
180  .arg(WApplication::instance()->maximumRequestSize() / 1024));
181  uploadFailed_ = true;
182 
183  /*
184  * Signal to the Composer that a new asyncrhonous file upload was processed.
185  */
186  uploadDone_.emit();
187 }
188 
189 std::vector<Attachment> AttachmentEdit::attachments()
190 {
191  std::vector<Attachment> result;
192 
193  for (unsigned i = 0; i < uploadInfo_.size(); ++i) {
194  if (uploadInfo_[i]->keep_->isChecked()) {
195  Http::UploadedFile& f = uploadInfo_[i]->info_;
196  f.stealSpoolFile();
197  result.push_back(Attachment
198  (WString(f.clientFileName()),
199  WString(f.contentType()),
200  f.spoolFileName()));
201  }
202  }
203 
204  return result;
205 }
WCheckBox * keep_
The check box to keep or discard the uploaded file.
WAnchor * downloadLink_
Anchor referencing the file.
UploadInfo(const Http::UploadedFile &f)
Http::UploadedFile info_
bool uploadNow()
Updates the file now.
void remove()
Slot triggered when the users wishes to remove this attachment edit.
WText * error_
The text box to display an error (empty or too big file)
Composer * composer_
Option * remove_
The option to cancel the file upload.
bool uploadFailed_
The state of the last upload process.
void uploaded()
Slot triggered when the WFileUpload completed an upload.
std::vector< Attachment > attachments()
Returns the attachment.
WFileUpload * upload_
The WFileUpload control.
std::vector< UploadInfo * > uploadInfo_
AttachmentEdit(Composer *composer)
Creates an attachment edit field.
void fileTooLarge(::int64_t size)
Slot triggered when the WFileUpload received an oversized file.
An email attachment.
Definition: Attachment.h:20
An E-mail composer widget.
Definition: Composer.h:41
void attachmentDone()
Slotcalled when an attachment has been uploaded.
Definition: Composer.C:338
void removeAttachment(AttachmentEdit *attachment)
Remove the given attachment edit.
Definition: Composer.C:271
WInteractWidget * item()
Returns the clickable part.
Definition: Option.h:44
Wt::Signals::connection connect(F function)
const std::string & spoolFileName() const
const std::string & clientFileName() const
void stealSpoolFile() const
const std::string & contentType() const
Wt::Signals::connection connect(F function)
void emit(A... args) const
virtual Wt::Signals::connection connect(WObject *target, WObject::Method method) override
void setChecked(bool checked)
void setLink(const WLink &link)
virtual std::unique_ptr< WWidget > removeWidget(WWidget *widget) override
virtual void addWidget(std::unique_ptr< WWidget > widget)
void setMultiple(bool multiple)
EventSignal & changed()
void setProgressBar(WProgressBar *progressBar)
JSignal< ::int64_t > & fileTooLarge()
EventSignal & uploaded()
bool canUpload() const
void setFileTextSize(int chars)
const std::vector< Http::UploadedFile > & uploadedFiles() const
void setSize(FontSize size)
EventSignal< WMouseEvent > & clicked()
bool setText(const WString &text)
virtual void setMargin(const WLength &margin, WFlags< Side > sides=AllSides) override
virtual void setVerticalAlignment(AlignmentFlag alignment, const WLength &length=WLength()) override
virtual void setStyleClass(const WString &styleClass) override
virtual WCssDecorationStyle & decorationStyle() override
static WString tr(const char *key)