Hi. I made attached widgets about a year ago.They implement an Open Office style file and directory select dialogs (file_select_dialog.cxx and directory_select_dialog.cxx).
Other files are helper wrappers over wt's widgets. tracked_table.cxx provides sort-on-header-click functionality. link.cxx provides mouse hover functionality for IE. This could be used a follows:CSVSelectDialog f("spool"); if(f.exec() == Wt::WDialog::Rejected) return;
std::string s = f.get_file_path().native_file_string(); After all this s contains path to file. I don't know if this is still relevant. Maybe someone will find this useful (maybe even wt authors).Don't blame me much for the code - this stuff was made in couple of nights (but it works without problems).
-- Andrii Arsirii Streamco http://streamco.org.ua
#include <WApplication>
#include "csv_select_dialog.hpp"
CSVSelectDialog::CSVSelectDialog(const boost::filesystem::path& path)
{
std::vector<std::string> v;
v.push_back(".csv");
set_extensions(v);
chroot(path);
list();
}
#ifndef CSV_SELECT_DIALOG_HPP
#define CSV_SELECT_DIALOG_HPP
#include "file_select_dialog.hpp"
class CSVSelectDialog : public FileSelectDialog
{
public:
CSVSelectDialog(const boost::filesystem::path& path);
};
#endif
#include "data_table.hpp"
DataTable::DataTable(Wt::WContainerWidget* parent) : TrackedTable(parent)
{
setStyleClass("data");
};
#ifndef DATA_TABLE_HPP
#define DATA_TABLE_HPP
#include "tracked_table.hpp"
class DataTable : public TrackedTable
{
public:
DataTable(Wt::WContainerWidget* parent = NULL);
};
#endif
#include <WText>
#include <WSignalMapper>
#include <WCssDecorationStyle>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <fstream>
#include <WAnchor>
#include <WImage>
#include <WPushButton>
#include <WApplication>
#include <WEnvironment>
#include "directory_select_dialog.hpp"
#include "data_table.hpp"
#include "link.hpp"
DirectorySelectDialog::DirectorySelectDialog(const boost::filesystem::path&
path) : Wt::WDialog(Wt::WString::tr("Directory Selection")),
m_width(400)
{
m_container = new Wt::WContainerWidget(contents());
m_container->setMaximumSize(Wt::WLength(m_width, Wt::WLength::Pixel),
Wt::WLength(300, Wt::WLength::Pixel));
m_container->resize(Wt::WLength(m_width, Wt::WLength::Pixel),
Wt::WLength(300, Wt::WLength::Pixel));
m_container->setOverflow(Wt::WContainerWidget::OverflowAuto);
m_container->setMargin(Wt::WLength(5, Wt::WLength::Pixel), Wt::Bottom);
Wt::WPushButton* ok = new Wt::WPushButton(Wt::WString::tr("Ok"),
contents());
ok->clicked.connect(SLOT(this, DirectorySelectDialog::on_ok));
Wt::WPushButton* cancel = new Wt::WPushButton(Wt::WString::tr("Cancel"),
contents());
cancel->clicked.connect(SLOT(this, Wt::WDialog::reject));
list(path);
}
void DirectorySelectDialog::list(const boost::filesystem::path& path)
{
m_container->clear();
m_path_to_text_map.clear();
m_path = path;
DataTable* table = new DataTable(m_container);
if(Wt::WApplication::instance()->environment().agentIE())
table->resize(Wt::WLength(m_width, Wt::WLength::Pixel), Wt::WLength(1,
Wt::WLength::Pixel));
new Wt::WText(Wt::WString::tr("file"), table->currentCell());
new Wt::WText(Wt::WString::tr("modified date"),
table->nextCellOfCurrentRow());
table->currentRow()->setStyleClass("header");
Wt::WSignalMapper<boost::filesystem::path>* directoryMapper = new
Wt::WSignalMapper<boost::filesystem::path>(table);
directoryMapper->mapped.connect(SLOT(this,
DirectorySelectDialog::on_directory_click));
if(path.has_branch_path())
{
new Wt::WImage("images/folder.gif", table->firstCellOfNextRow());
Link* link = new Link("..", table->currentCell());
boost::filesystem::path p = path;
directoryMapper->mapConnect(link->clicked, p.branch_path());
boost::posix_time::ptime
ptime(boost::posix_time::from_time_t(boost::filesystem::last_write_time(p.branch_path())));
std::ostringstream time;
time << to_iso_extended_string(ptime.date()) << " " <<
ptime.time_of_day();
new Wt::WText(time.str(), table->nextCellOfCurrentRow());
}
typedef boost::filesystem::directory_iterator DirectoryIterator;
DirectoryIterator end;
for(DirectoryIterator i(path);i != end; i++)
{
if(boost::filesystem::is_regular(i->status()))
{
new Wt::WImage("images/document.gif", table->firstCellOfNextRow());
Wt::WText* text = new Wt::WText(i->path().leaf(),
table->currentCell());
}
else if(boost::filesystem::is_directory(i->status()))
{
new Wt::WImage("images/folder.gif", table->firstCellOfNextRow());
Link* link = new Link(i->path().leaf(), table->currentCell());
directoryMapper->mapConnect(link->clicked, i->path());
}
else
continue;
boost::posix_time::ptime
ptime(boost::posix_time::from_time_t(boost::filesystem::last_write_time(i->path())));
std::ostringstream time;
time << to_iso_extended_string(ptime.date()) << " " <<
ptime.time_of_day();
new Wt::WText(time.str(), table->nextCellOfCurrentRow());
}
}
void DirectorySelectDialog::on_directory_click(boost::filesystem::path path)
{
list(path);
}
void DirectorySelectDialog::on_ok()
{
accept();
}
boost::filesystem::path DirectorySelectDialog::get_directory_path() const
{
return m_path.native_file_string();
}
void DirectorySelectDialog::on_activated()
{
list(m_path);
}
#ifndef DIRECTORY_SELECT_DIALOG_HPP
#define DIRECTORY_SELECT_DIALOG_HPP
#include <WLineEdit>
#include <WFileUpload>
#include <boost/filesystem/path.hpp>
#include <WDialog>
#include <map>
#include <WText>
#include "tracked_combo_box.hpp"
class DirectorySelectDialog : public Wt::WDialog
{
public:
DirectorySelectDialog(const boost::filesystem::path& path);
boost::filesystem::path get_directory_path() const;
private:
void list(const boost::filesystem::path& path);
void on_directory_click(boost::filesystem::path path);
void on_ok();
void on_activated();
boost::filesystem::path m_path;
std::map<boost::filesystem::path, Wt::WText*> m_path_to_text_map;
Wt::WContainerWidget* m_container;
const unsigned m_width;
};
#endif
#include <WText>
#include <WSignalMapper>
#include <WCssDecorationStyle>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <fstream>
#include <WAnchor>
#include <WImage>
#include <WPushButton>
#include <WApplication>
#include <WEnvironment>
#include "file_select_dialog.hpp"
#include "data_table.hpp"
#include "link.hpp"
FileSelectDialog::FileSelectDialog() : Wt::WDialog(Wt::WString::tr("File
Select")),
m_width(400)
{
m_container = new Wt::WContainerWidget(contents());
m_container->setMaximumSize(Wt::WLength(m_width, Wt::WLength::Pixel),
Wt::WLength(300, Wt::WLength::Pixel));
m_container->resize(Wt::WLength(m_width, Wt::WLength::Pixel),
Wt::WLength(300, Wt::WLength::Pixel));
m_container->setOverflow(Wt::WContainerWidget::OverflowAuto);
m_container->setMargin(Wt::WLength(5, Wt::WLength::Pixel), Wt::Bottom);
DataTable* table = new DataTable(contents());
m_name = new Wt::WText(Wt::WString::tr("name"), table->currentCell());
m_file = new Wt::WLineEdit(table->nextCellOfCurrentRow());
new Wt::WText(Wt::WString::tr("extension"), table->firstCellOfNextRow());
m_extension = new TrackedComboBox(table->nextCellOfCurrentRow());
m_extension->activated.connect(SLOT(this, FileSelectDialog::on_activated));
Wt::WPushButton* ok = new Wt::WPushButton(Wt::WString::tr("Ok"),
contents());
ok->clicked.connect(SLOT(this, FileSelectDialog::on_ok));
Wt::WPushButton* cancel = new Wt::WPushButton(Wt::WString::tr("Cancel"),
contents());
cancel->clicked.connect(SLOT(this, Wt::WDialog::reject));
}
boost::filesystem::path FileSelectDialog::get_current_path() const
{
boost::filesystem::path path = m_root.native_file_string();
if(!m_bias.native_file_string().empty())
path = path.native_file_string() + m_bias.native_file_string();
return path;
}
void FileSelectDialog::chroot(const boost::filesystem::path& path)
{
set_root(path);
set_bias("");
}
void FileSelectDialog::set_root(const boost::filesystem::path& path)
{
m_root = path;
}
void FileSelectDialog::set_bias(const boost::filesystem::path& path)
{
if(path.native_file_string() == "/")
m_bias = "";
else
m_bias = path;
}
void FileSelectDialog::set_extensions(const std::vector<std::string>&
extensions)
{
for(std::vector<std::string>::const_iterator i = extensions.begin();
i != extensions.end(); i++)
m_extension->addItem(*i);
m_extension->setSelected();
}
void FileSelectDialog::list()
{
m_container->clear();
m_path_to_text_map.clear();
DataTable* table = new DataTable(m_container);
if(Wt::WApplication::instance()->environment().agentIE())
table->resize(Wt::WLength(m_width, Wt::WLength::Pixel), Wt::WLength(1,
Wt::WLength::Pixel));
new Wt::WText(Wt::WString::tr("file"), table->currentCell());
new Wt::WText(Wt::WString::tr("modified date"),
table->nextCellOfCurrentRow());
table->currentRow()->setStyleClass("header");
Wt::WSignalMapper<boost::filesystem::path>* directoryMapper = new
Wt::WSignalMapper<boost::filesystem::path>(table);
directoryMapper->mapped.connect(SLOT(this,
FileSelectDialog::on_directory_click));
Wt::WSignalMapper<boost::filesystem::path>* fileMapper = new
Wt::WSignalMapper<boost::filesystem::path>(table);
fileMapper->mapped.connect(SLOT(this, FileSelectDialog::on_file_click));
if(m_bias.has_branch_path())
{
new Wt::WImage("images/folder.gif", table->firstCellOfNextRow());
Link* link = new Link("..", table->currentCell());
directoryMapper->mapConnect(link->clicked, "..");
}
typedef boost::filesystem::directory_iterator DirectoryIterator;
DirectoryIterator end;
for(DirectoryIterator i(get_current_path());i != end; i++)
{
if(boost::filesystem::is_regular(i->status()))
{
if(m_extension->currentText() != ".*" &&
extension(i->path()) != m_extension->currentText())
continue;
new Wt::WImage("images/document.gif", table->firstCellOfNextRow());
Wt::WText* text = new Wt::WText(i->path().leaf(),
table->currentCell());
table->currentCell()->decorationStyle().setCursor(Wt::PointingHandCursor);
fileMapper->mapConnect(text->clicked, i->path());
m_path_to_text_map.insert(std::make_pair(i->path(), text));
}
else if(boost::filesystem::is_directory(i->status()))
{
new Wt::WImage("images/folder.gif", table->firstCellOfNextRow());
Link* link = new Link(i->path().leaf(), table->currentCell());
directoryMapper->mapConnect(link->clicked, i->path().leaf());
}
else
continue;
boost::posix_time::ptime
ptime(boost::posix_time::from_time_t(boost::filesystem::last_write_time(i->path())));
std::ostringstream time;
time << to_iso_extended_string(ptime.date()) << " " <<
ptime.time_of_day();
new Wt::WText(time.str(), table->nextCellOfCurrentRow());
}
}
void FileSelectDialog::on_directory_click(boost::filesystem::path path)
{
if(path == "..")
set_bias(m_bias.branch_path());
else
set_bias(m_bias.native_file_string() + "/" +
path.native_file_string());
list();
}
void FileSelectDialog::on_file_click(boost::filesystem::path path)
{
m_file->setText(path.leaf());
for(std::map<boost::filesystem::path, Wt::WText*>::iterator i =
m_path_to_text_map.begin();
i != m_path_to_text_map.end();
i++)
{
i->second->decorationStyle().setBackgroundColor(Wt::WColor());
if(i->first == path)
i->second->decorationStyle().setBackgroundColor(Wt::WColor(0x90,
0x90, 0x90));
}
}
void FileSelectDialog::on_ok()
{
if(!m_file->text().toUTF8().empty())
accept();
else
{
m_name->decorationStyle().setForegroundColor(Wt::WColor(0xff, 0x0,
0x0));
m_name->decorationStyle().font().setWeight(Wt::WFont::Bold);
m_name->decorationStyle().font().setStyle(Wt::WFont::Italic);
}
}
boost::filesystem::path FileSelectDialog::get_file_path() const
{
std::string res = get_current_path().native_file_string();
if(!res.empty())
res += "/";
res += m_file->text().toUTF8();
if(extension(boost::filesystem::path(m_file->text().toUTF8())).empty())
res += m_extension->currentText().toUTF8();
return res;
}
void FileSelectDialog::on_activated()
{
list();
}
#ifndef FILE_SELECT_DIALOG_HPP
#define FILE_SELECT_DIALOG_HPP
#include <WLineEdit>
#include <WFileUpload>
#include <boost/filesystem/path.hpp>
#include <WDialog>
#include <map>
#include <WText>
#include <vector>
#include "tracked_combo_box.hpp"
class FileSelectDialog : public Wt::WDialog
{
public:
FileSelectDialog();
boost::filesystem::path get_file_path() const;
protected:
void set_extensions(const std::vector<std::string>& extensions);
void chroot(const boost::filesystem::path& path);
void list();
private:
void set_root(const boost::filesystem::path& path);
void set_bias(const boost::filesystem::path& path);
void on_directory_click(boost::filesystem::path path);
void on_file_click(boost::filesystem::path path);
void on_ok();
void on_activated();
boost::filesystem::path get_current_path() const;
boost::filesystem::path m_bias;
boost::filesystem::path m_root;
Wt::WLineEdit* m_file;
std::map<boost::filesystem::path, Wt::WText*> m_path_to_text_map;
Wt::WContainerWidget* m_container;
Wt::WText* m_name;
TrackedComboBox* m_extension;
const unsigned m_width;
};
#endif
#include "tracked_combo_box.hpp"
TrackedComboBox::TrackedComboBox(Wt::WContainerWidget* parent) :
Wt::WComboBox(parent),
m_current_index(0)
{
}
void TrackedComboBox::addItem(const Wt::WString &text)
{
Wt::WComboBox::addItem(text);
m_current_index++;
}
void TrackedComboBox::setSelected()
{
setCurrentIndex(m_current_index);
}
void TrackedComboBox::clear()
{
Wt::WComboBox::clear();
m_current_index = 0;
}
#ifndef TRACKED_COMBO_BOX_HPP
#define TRACKED_COMBO_BOX_HPP
#include <WComboBox>
class TrackedComboBox : public Wt::WComboBox
{
public:
TrackedComboBox(Wt::WContainerWidget* parent);
void addItem(const Wt::WString &text);
void setSelected();
void clear();
private:
unsigned m_current_index;
};
#endif
#include <map>
#include <WText>
#include <WCssDecorationStyle>
#include <WImage>
#include <WAnchor>
#include "tracked_table.hpp"
TrackedTable::TrackedTable(Wt::WContainerWidget* parent) : Wt::WTable(parent),
m_row(0),
m_column(0),
m_header_mapper(new
Wt::WSignalMapper<Wt::WTableCell*>(this)),
m_last_clicked(NULL)
{
m_header_mapper->mapped.connect(SLOT(this,
TrackedTable::on_header_item_clicked));
}
TrackedTable::~TrackedTable()
{
}
Wt::WTableCell* TrackedTable::currentCell()
{
return elementAt(m_row, m_column);
}
void TrackedTable::setCurrentColumnSortable()
{
Wt::WTableCell* cell = elementAt(0, m_column);
cell->setStyleClass("sortable");
// cell->decorationStyle().setCursor(Wt::PointingHandCursor);
if(!cell->clicked.isConnected())
m_header_mapper->mapConnect(cell->clicked, cell);
}
Wt::WTableRow* TrackedTable::currentRow()
{
rowAt(m_row);
}
Wt::WTableCell* TrackedTable::nextCellOfCurrentColumn()
{
m_row++;
return currentCell();
}
Wt::WTableCell* TrackedTable::firstCellOfNextRow()
{
m_row++;
clearColumn();
return currentCell();
}
Wt::WTableRow* TrackedTable::nextRow()
{
m_row++;
}
Wt::WTableCell* TrackedTable::nextCellOfCurrentRow()
{
m_column++;
return currentCell();
}
Wt::WTableCell* TrackedTable::previousCellOfCurrentRow()
{
assert(m_column > 0);
m_column--;
return currentCell();
}
void TrackedTable::clearColumn()
{
m_column = 0;
}
void TrackedTable::clearRow()
{
m_row = 0;
}
std::vector<Wt::WWidget*> TrackedTable::getRowContent(unsigned row)
{
std::vector<Wt::WWidget*> result;
for(unsigned i = 0; i < numColumns(); i++)
{
Wt::WWidget* widget = NULL;
Wt::WTableCell* cell = elementAt(row, i);
if(cell->children().size())
widget = cell->children()[0];
result.push_back(widget);
}
return result;
}
void TrackedTable::setRowContent(unsigned row, const std::vector<Wt::WWidget*>&
widgets)
{
for(unsigned i = 0; i < widgets.size(); i++)
{
Wt::WWidget* widget = widgets[i];
if(widget)
{
Wt::WTableCell* cell = elementAt(row, i);
if(cell->children().size())
{
Wt::WWidget* content = cell->children()[0];
cell->removeWidget(content);
}
cell->addWidget(widget);
}
}
}
void TrackedTable::on_header_item_clicked(Wt::WTableCell* cell)
{
if(m_last_clicked && m_last_clicked != cell)
m_last_clicked->setStyleClass("sortable");
m_last_clicked = cell;
if(cell->styleClass().toUTF8() == "sortable")
{
cell->setStyleClass("sortable asc");
sort(cell, std::less<std::string>());
}
else if(cell->styleClass().toUTF8() == "sortable asc")
{
cell->setStyleClass("sortable desc");
sort(cell, std::greater<std::string>());
}
else if(cell->styleClass().toUTF8() == "sortable desc")
{
cell->setStyleClass("sortable asc");
sort(cell, std::less<std::string>());
}
else
throw std::runtime_error(Wt::WString::tr("Sorting class is not
supported").toUTF8());
}
template<class T>
void TrackedTable::sort(Wt::WTableCell* cell, T)
{
std::multimap<std::string, std::vector<Wt::WWidget*>, T> content_to_row_map;
for(unsigned i = 1; i < numRows(); i++)
{
Wt::WObject* object = elementAt(i, cell->column())->children()[0];
std::string index_text;
if(Wt::WText* text = dynamic_cast<Wt::WText*>(object))
index_text = text->text().toUTF8();
else if(Wt::WImage* image = dynamic_cast<Wt::WImage*>(object))
index_text = image->alternateText().toUTF8();
else if(Wt::WAnchor* anchor = dynamic_cast<Wt::WAnchor*>(object))
index_text = anchor->text().toUTF8();
else
throw std::runtime_error(Wt::WString::tr("Sorting is not supported
for this type of data").toUTF8());
content_to_row_map.insert(std::make_pair(index_text,
getRowContent(i)));
}
// clear();
m_row = 1;
m_column = 0;
for(std::multimap<std::string, std::vector<Wt::WWidget*> >::const_iterator
i = content_to_row_map.begin();
i != content_to_row_map.end();
i++)
{
setRowContent(m_row, i->second);
m_row++;
}
}
#ifndef TRACKED_TABLE_HPP
#define TRACKED_TABLE_HPP
#include <WTable>
#include <vector>
#include <WSignalMapper>
class TrackedTable : public Wt::WTable
{
public:
TrackedTable(Wt::WContainerWidget* parent = 0);
virtual ~TrackedTable();
Wt::WTableCell* currentCell();
Wt::WTableRow* currentRow();
Wt::WTableCell* nextCellOfCurrentColumn();
Wt::WTableCell* firstCellOfNextRow();
Wt::WTableRow* nextRow();
Wt::WTableCell* nextCellOfCurrentRow();
Wt::WTableCell* previousCellOfCurrentRow();
void clearColumn();
void clearRow();
void setCurrentColumnSortable();
private:
std::vector<Wt::WWidget*> getRowContent(unsigned row);
void setRowContent(unsigned row, const std::vector<Wt::WWidget*>& widgets);
void on_header_item_clicked(Wt::WTableCell* cell);
template<class T> void sort(Wt::WTableCell* cell, T);
Wt::WTableCell* m_last_clicked;
Wt::WSignalMapper<Wt::WTableCell*>* m_header_mapper;
unsigned m_row;
unsigned m_column;
};
#endif
#include <WEnvironment>
#include <WApplication>
#include "link.hpp"
Link::Link(const Wt::WString &text, Wt::WContainerWidget *parent) :
Wt::WText(text, parent)
{
if(Wt::WApplication::instance()->environment().agentIE())
{
m_on_mouse_went_over.setJavaScript("function(obj, event)
{obj.style.color=\"#aaaaaa\"}");
m_on_mouse_went_out.setJavaScript("function(obj, event)
{obj.style.color=\"#121246\"}");
mouseWentOver.connect(m_on_mouse_went_over);
mouseWentOut.connect(m_on_mouse_went_out);
decorationStyle().setCursor(Wt::PointingHandCursor);
}
else
{
setStyleClass("link");
}
}
#ifndef LINK_HPP
#define LINK_HPP
#include <WText>
#include <WJavaScript>
class Link : public Wt::WText
{
public:
Link(const Wt::WString &text, Wt::WContainerWidget *parent=0);
private:
Wt::JSlot m_on_mouse_went_over;
Wt::JSlot m_on_mouse_went_out;
};
#endif
------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________ witty-interest mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/witty-interest
