Wittyshare  0.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WsModImagesGallery.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2006-Today Guy Deleeuw
3 *
4 * See the LICENSE file for terms of use.
5 */
6 
7 #include <dlfcn.h>
8 #include <stdio.h>
9 
10 #include <iostream>
11 
12 #include <boost/algorithm/string/replace.hpp>
13 #include <boost/filesystem.hpp>
14 
15 #include <Wt/WLogger>
16 #include <Wt/WTheme>
17 
18 #include <gdcore/gdCore.h>
19 
20 #include <Logger/WsLogger.h>
21 
22 #include <Main/WsApplication.h>
23 
24 #include "WsModImagesGallery.h"
25 
26 extern "C" {
28  {
29  void* hndl = dlopen("libwt.so", RTLD_NOW | RTLD_GLOBAL);
30  if ( hndl == NULL ) {
31  fprintf(stderr, "cannot load libwt.so shared library! %s\n", dlerror());
32  return;
33  }
34  }
35 }
36 
37 using namespace Wt;
38 
39 // Class WsImagesGallery
40 // ==================
41 WsImagesGallery::WsImagesGallery(WContainerWidget* parent)
42  : WContainerWidget(parent), m_nStartImage(0), m_nMaxImages(3), m_pTimerThumb(0), m_pTimerImage(0), m_nCurrentImage(0), m_pImages2(0), m_pImages2Text(0), m_cwThumb(0)
43 {
44  addStyleClass("WsImagesGallery");
45 }
46 
48 {
49 }
50 
52 {
53  WContainerWidget::load();
54  WsUser* pUser = WsApp->wsUser();
55  std::string sWithoutPrefix = WsApp->WsModules().pathWithoutPrefix(WsApp->internalPath());
56  NodePtr startNode = pUser->getAccessRoot();
57  if ( !startNode ) return;
58  NodePtr curNode = startNode.get()->eatPath(sWithoutPrefix);
59  std::string title = curNode.get()->getDisplayName(true);
60  WText* pTitle = new WText(title);
61  pTitle->addStyleClass("WsTitle");
62  addWidget(pTitle);
63  int nMaxImages = asNumber(option("maxImages"));
64  if ( nMaxImages > 0 )
65  setMaxImages(nMaxImages);
66  buildVector();
68  renderButtons();
69  renderThumb();
70  renderImage();
71  m_pTimerImage = new WTimer(this);
72  m_pTimerImage->setInterval(asNumber(option("image_delay")));
73  m_pTimerImage->timeout().connect(SLOT(this, WsImagesGallery::doTimeoutImage));
74  if ( m_vImages.size() > m_nMaxImages && asString(option("useThumbTimer")).toUTF8() != "false" ) {
75  m_pTimerThumb = new WTimer(this);
76  m_pTimerThumb->setInterval(asNumber(option("image_delay")));
77  m_pTimerThumb->timeout().connect(SLOT(this, WsImagesGallery::doTimeoutThumb));
78  m_pTimerThumb->start();
79  }
80 }
81 
83 {
84  std::string imgPath = asString(option("imagesPath")).toUTF8();
85  boost::algorithm::replace_all(imgPath, "&amp;", "&");
86  if ( imgPath.size() < 1 ) return;
87  WsUser* pUser = WsApp->wsUser();
88  std::string sWithoutPrefix = WsApp->WsModules().pathWithoutPrefix(WsApp->internalPath());
89  boost::filesystem::directory_iterator end_itr;
90  try {
91  for (boost::filesystem::directory_iterator itr_dir(pUser->getRootPath() + imgPath); itr_dir != end_itr; ++itr_dir) {
92  if ( ! ( itr_dir->path().extension() == ".jpeg"
93  || itr_dir->path().extension() == ".jpg"
94  || itr_dir->path().extension() == ".png"
95  ) ) continue;
96  if ( gdcore_isPathHidden(itr_dir->path()) ) continue;
97  if ( gdcore_isPathSymLink(itr_dir->path()) ) continue;
98  if ( boost::filesystem::is_directory(itr_dir->status()) ) continue;
99  m_vImages.push_back(itr_dir->path().string());
100  }
101  } catch (boost::filesystem::filesystem_error& e) {
102  wApp->log("ERROR") << "WsImagesGallery::buildVector() bad image path =" << imgPath << " error = " << e.what();
103  return;
104  }
105 }
106 
108 {
109  for (int curImg = 0; curImg < m_vImages.size(); ++curImg) {
110  std::string urlSized = m_vImages[curImg];
111  std::string sResize = asString(option("resize")).toUTF8();
112  if ( sResize.size() < 1 ) sResize = "100*75";
113  // boost::algorithm::replace_last(urlSized, "/images/", "/thumbnails/"); // TODO : Improve by path.parent_path
114  Magick::Blob rBlob;
115  int status = gdImage_resizeImage(m_vImages[curImg], rBlob, sResize);
116  // int status = gdImage_resizeImage(m_vImages[curImg], urlSized, sResize); // TODO : Use Blob
117  if ( status ) {
118  wApp->log("notice") << "WsImagesGallery::buildThumbnails() : cannot resize to Blob = " << urlSized << " status = " << status << " url source " << m_vImages[curImg];
119  continue;
120  }
121  m_vThumbnails.push_back(rBlob);
122  // m_vThumbnails.push_back(urlSized);
123  }
124 }
125 
127 {
128  if ( (m_nStartImage + 1) >= (m_vImages.size() - m_nMaxImages) ) m_nStartImage = 0;
129  else ++m_nStartImage;
130  renderThumb();
131 }
132 
134 {
135  if ( (m_nCurrentImage + 1) >= m_vImages.size() ) m_nCurrentImage = 0;
136  else ++m_nCurrentImage;
137  renderImage();
138 }
139 
141 {
142  WContainerWidget* cw = new WContainerWidget();
143  cw->addStyleClass("WsPlayer");
144  WPushButton* button = new WPushButton("", cw);
145  button->setIcon(WLink(WLink::Url, wApp->theme()->resourcesUrl() + "wittyshare/Icons/previous.png"));
146  button->clicked().connect(boost::bind(&WsImagesGallery::doPrevious, this, button));
147  button = new WPushButton("", cw);
148  button->setIcon(WLink(WLink::Url, wApp->theme()->resourcesUrl() + "wittyshare/Icons/play.png"));
149  button->clicked().connect(boost::bind(&WsImagesGallery::doPlay, this, button));
150  button = new WPushButton("", cw);
151  button->setIcon(WLink(WLink::Url, wApp->theme()->resourcesUrl() + "wittyshare/Icons/next.png"));
152  button->clicked().connect(boost::bind(&WsImagesGallery::doNext, this, button));
153  addWidget(cw);
154 }
155 
157 {
158  if ( m_pTimerThumb )
159  m_pTimerThumb->stop();
160  bool bNewThumb = false;
161  if ( !m_cwThumb ) {
162  bNewThumb = true;
163  m_cwThumb = new WContainerWidget();
164  m_cwThumb->addStyleClass("WsThumbnails");
165  } else
166  m_cwThumb->clear();
167  int maxImg = m_nMaxImages;
168  if ( (m_nStartImage + maxImg) > m_vImages.size() )
169  maxImg = m_vImages.size() - m_nStartImage;
170  for (int countDir = m_nStartImage; countDir < (m_nStartImage + maxImg); ++countDir) {
171  if ( countDir > m_vImages.size() ) {
172  WApplication::instance()->log("notice") << "WsImagesGallery::renderThumb : OH OH anormal break !!!!";
173  break;
174  }
175  WImage* pImage = new WImage();
176  pImage->addStyleClass("thumbnails");
177  if ( countDir == m_nCurrentImage ) {
178  pImage->addStyleClass("WsSelected");
179  }
180  pImage->addStyleClass("WsClickable");
181  std::string imglnk = "data:image/jpeg;base64," + m_vThumbnails[countDir].base64();
182  pImage->setImageLink(imglnk);
183  pImage->clicked().connect(boost::bind(&WsImagesGallery::doThumbClicked, this, countDir));
184  m_cwThumb->addWidget(pImage);
185  }
186  if ( bNewThumb )
187  addWidget(m_cwThumb);
188  if ( m_pTimerThumb )
189  m_pTimerThumb->start();
190 }
191 
193 {
194  std::string imgPath = m_vImages[m_nCurrentImage];
195  boost::algorithm::replace_first(imgPath, wApp->docRoot(), "");
196  int idxImg2 = -1;
197  if ( m_pImages2 ) {
198  idxImg2 = indexOf(m_pImages2);
199  removeWidget(m_pImages2);
200  removeWidget(m_pImages2Text);
201  delete m_pImages2;
202  delete m_pImages2Text;
203  m_pImages2 = 0;
204  m_pImages2Text = 0;
205  }
206  m_pImages2 = new WsImages2();
208  m_pImages2->setOption("useImageTitle", std::string("false"));
209  m_pImages2->setOption("imagesPath", imgPath);
210  m_pImages2->setOption("textWidget", std::string("false"));
211  m_pImages2->build();
212  m_pImages2Text = new WText(m_pImages2->text());
213  m_pImages2Text->addStyleClass("WsImagesGalleryText");
214  // if ( idxImg2 != -1 ) { // si thumbnail en dessous de l'image et du texte
215  if ( false ) {
216  insertBefore(m_pImages2 , m_cwThumb);
217  insertBefore(m_pImages2Text, m_cwThumb);
218  } else {
219  addWidget(m_pImages2);
220  addWidget(m_pImages2Text);
221  }
222  // TODO : WImage vector + removeStyleClass WsSelected + addStyleClass WsSelected and remove next line
223  renderThumb();
224 }
225 
226 void WsImagesGallery::setMaxImages(int nMaxImages)
227 {
228  m_nMaxImages = nMaxImages;
229 }
230 
232 {
233  m_pTimerImage->stop();
234  m_nCurrentImage = nImageId;
235  renderImage();
236 }
237 
238 void WsImagesGallery::doPrevious(Wt::WPushButton* pButton)
239 {
240  m_pTimerImage->stop();
241  if ( (m_nCurrentImage - 1) < 0 ) m_nCurrentImage = m_vImages.size() - 1;
242  else --m_nCurrentImage;
243  renderImage();
244 }
245 
246 void WsImagesGallery::doPlay(Wt::WPushButton* pButton)
247 {
248  std::string state = pButton->icon().url();
249  if ( state == wApp->theme()->resourcesUrl() + "wittyshare/Icons/play.png") {
250  pButton->setIcon(WLink(WLink::Url, wApp->theme()->resourcesUrl() + "wittyshare/Icons/pause.png"));
251  m_pTimerImage->start();
252  } else {
253  pButton->setIcon(WLink(WLink::Url, wApp->theme()->resourcesUrl() + "wittyshare/Icons/play.png"));
254  m_pTimerImage->stop();
255  }
256 }
257 
258 void WsImagesGallery::doNext(Wt::WPushButton* pButton)
259 {
260  m_pTimerImage->stop();
261  if ( (m_nCurrentImage + 1) >= m_vImages.size() ) m_nCurrentImage = 0;
262  else ++m_nCurrentImage;
263  renderImage();
264 }
265 
266 
267 // Class WsModImagesGallery
268 // =====================
270  : WsModule()
271 {
272 }
273 
275 {
276 }
277 
278 WWidget* WsModImagesGallery::createContentsMenuBar(WContainerWidget* parent) const
279 {
280  return 0;
281 }
282 
283 WWidget* WsModImagesGallery::createContents(WContainerWidget* parent) const
284 {
285  WsImagesGallery* pImgGal = new WsImagesGallery(parent);
286  pImgGal->setOptions(options());
287  return pImgGal;
288 }
289 
290 WsEditorWidget* WsModImagesGallery::createEditor(WContainerWidget* parent) const
291 {
292  return 0;
293 }
294 
295 WWidget* WsModImagesGallery::createAdmin(WContainerWidget* parent) const
296 {
297  return 0;
298 }
299 
301 {
302  return true;
303 }
304 
306 {
307  return "WsModImagesGallery wittyShare module";
308 }
309 
boost::shared_ptr< WsAbstractNode > NodePtr
void WsModImagesGalleryInit(void)
void build()
Build the vector.
Definition: WsImages2.cpp:96
WsEditorWidget * createEditor(Wt::WContainerWidget *parent=0) const
Create the contents for an editor (create a view of options).
std::vector< Magick::Blob > m_vThumbnails
void doThumbClicked(int nImageId)
void setMaxImages(int nMaxImages)
Set the number of images in the menu. If the number of images is more than this value a timer rotate ...
WsImages2 * m_pImages2
a wittyShare module
const std::vector< WsOption > & options() const
Get all options.
Definition: WsOption.cpp:70
Interface that provides differents methods for accessing the FsTree as well as other features...
Definition: WsUser.h:33
void doPlay(Wt::WPushButton *pButton)
void doPrevious(Wt::WPushButton *pButton)
void setOption(const std::string &attribute, boost::any value)
Set an options if previously set, update the value.
Definition: WsOption.cpp:47
WsImagesGallery(Wt::WContainerWidget *parent=0)
CTor.
const boost::any & option(const std::string &attribute) const
Get an options value.
Definition: WsOption.cpp:62
Wt::WText * m_pImages2Text
std::string description() const
Return the description of the module.
std::vector< std::string > m_vImages
const std::string getRootPath()
return the root path of the filesystem tree, example : /var/www/demo_site
Definition: WsUser.cpp:55
#define WsApp
Define a shortcut to the application instance.
Definition: WsApplication.h:62
WContainerWidget * m_cwThumb
void setOptions(const std::vector< WsOption > &vOptions)
Set all options.
Definition: WsOption.cpp:57
const std::string & text()
Return the text of the current image.
Definition: WsImages2.cpp:266
NodePtr getAccessRoot()
return the root node of the access tree starting from the root
Definition: WsUser.cpp:50
Wt::WWidget * createAdmin(Wt::WContainerWidget *parent=0) const
Create the contents for an administrator.
Wt::WTimer * m_pTimerThumb
Wt::WWidget * createContentsMenuBar(Wt::WContainerWidget *parent=0) const
Create the functionalities.
Wt::WTimer * m_pTimerImage
Wt::WWidget * createContents(Wt::WContainerWidget *parent=0) const
Create the contents.
void doNext(Wt::WPushButton *pButton)