#include <fstream>
#include <iostream>
#include <sstream>
+#include <vector>
+#include <algorithm>
#include "bbs_detail_base.hxx"
#include "thread_list_model.hxx"
#include "board_subject_idx.hxx"
#include "http_date.hxx"
#include "misc.hxx"
+#include "board_window_state.hxx"
+#include "thread_idx.hxx"
+#include "thread_window.hxx"
namespace dialektos {
+namespace {
+struct LessSecond {
+ template <typename PairType>
+ bool operator()(const PairType& lhs, const PairType& rhs) const {
+ return lhs.second < rhs.second;
+ }
+};
+}
+
void BoardWindow::create(std::auto_ptr<bbs_detail::Base> bbs) {
regist(new BoardWindow(bbs));
tree_view_.signal_button_press_event().connect_notify(
sigc::mem_fun(*this, &BoardWindow::on_child_button_press));
- set_default_size(400,300);
scrolled_.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
add(scrolled_);
tree_view_.set_fixed_height_mode(true);
tree_view_.set_rules_hint(true);
- tree_view_.append_column(*Gtk::manage(new view_column::Number));
- tree_view_.append_column(*Gtk::manage(new view_column::Title));
- tree_view_.append_column(*Gtk::manage(new view_column::ResNum));
- tree_view_.append_column(*Gtk::manage(new view_column::LineCount));
- tree_view_.append_column(*Gtk::manage(new view_column::Average));
- tree_view_.append_column(*Gtk::manage(new view_column::StartTime));
+ BoardWindowState state;
+ state.from_xml(boost::filesystem::path(bbs_->get_board_state_path()));
+
+ add_column<view_column::Number>(state);
+ add_column<view_column::Title>(state);
+ add_column<view_column::ResNum>(state);
+ add_column<view_column::LineCount>(state);
+ add_column<view_column::Average>(state);
+ add_column<view_column::StartTime>(state);
+
+ set_default_size(state.width, state.height);
+ if (state.menubar) menubar_->show();
+ if (state.toolbar) toolbar_->show();
+ if (state.statusbar) statusbar_.show();
+
+ // set columns widths
+ BOOST_FOREACH(Gtk::TreeViewColumn* kolumn, tree_view_.get_columns()) {
+ view_column::Base* column =
+ dynamic_cast<view_column::Base*>(kolumn);
+
+ assert(column);
+ BoardWindowState::ColumnInfo info = state.columns[column->get_id()];
+ if (info.width > 0) column->set_fixed_width(info.width);
+ }
+
+ // set columns order.
+ typedef std::pair<Gtk::TreeViewColumn*, int> PairType;
+ std::vector<PairType> column_order;
+ BOOST_FOREACH(Gtk::TreeViewColumn* kolumn, tree_view_.get_columns()) {
+ view_column::Base* column =
+ dynamic_cast<view_column::Base*>(kolumn);
+
+ assert(column);
+ BoardWindowState::ColumnInfo info = state.columns[column->get_id()];
+ column_order.push_back(std::make_pair(column, info.order));
+ }
+ std::sort(column_order.begin(), column_order.end(), LessSecond());
+
+ Gtk::TreeViewColumn* previous_column = 0;
+ BOOST_FOREACH(PairType& pair, column_order) {
+ if (!previous_column) tree_view_.move_column_to_start(*pair.first);
+ else tree_view_.move_column_after(*pair.first, *previous_column);
+ previous_column = pair.first;
+ }
using namespace boost::posix_time;
ptime start = microsec_clock::local_time();
BoardWindow::~BoardWindow() {
}
+void BoardWindow::on_informed_from(const bbs_detail::Base& bbs,
+ const ThreadIdx& idx) {
+ if (!bbs.belongs_to(*bbs_)) return;
+
+ ModelColumns cols;
+ model_column::field<model_column::Title>(cols) = idx.title_;
+ model_column::field<model_column::ID>(cols) = bbs.get_thread_id();
+ model_column::field<model_column::LineCount>(cols) = idx.line_count_;
+ tree_model_->update_row(cols);
+}
+
void BoardWindow::on_row_activated(const Gtk::TreeModel::Path& path,
Gtk::TreeViewColumn* /*col*/) {
Gtk::TreeIter iter = tree_model_->get_iter(path);
boost::filesystem::path(bbs_->get_board_subject_idx_path()));
merge_subject_txt(subjects, buffer);
- }
+ } else
+ on_action_view_refresh();
tree_model_->set_buffer(buffer);
}
boost::posix_time::ptime last_modified;
try {
- last_modified = rfc1123_to_ptime(idx_.last_modified_);
+ if (!idx_.last_modified_.empty())
+ last_modified = rfc1123_to_ptime(idx_.last_modified_);
+ else
+ last_modified = boost::posix_time::second_clock::universal_time();
} catch (const HTTPDateError& e) {
std::cerr << e.what() << std::endl;
last_modified = boost::posix_time::second_clock::universal_time();
model_column::field<model_column::ID>(cols) = item.id_;
model_column::field<model_column::ResNum>(cols) = item.res_num_;
+ // avoid some threads like '9242006007'
+ if (item.id_.size() == 10 && item.id_[0] == '9') continue;
+
try {
const std::time_t _start = boost::lexical_cast<std::time_t>(item.id_);
const boost::posix_time::ptime start = boost::posix_time::from_time_t(_start);
std::cout << "file open activated" << std::endl;
}
+void BoardWindow::on_action_edit_copy() {
+ Glib::RefPtr<const Gtk::TreeSelection> selection =
+ tree_view_.get_selection();
+
+ std::vector<Gtk::TreeModel::Path> paths = selection->get_selected_rows();
+ if (paths.empty()) return;
+
+ std::string selected;
+ BOOST_FOREACH(Gtk::TreeModel::Path path, paths) {
+ Gtk::TreeRow row = *(tree_model_->get_iter(path));
+ std::string id;
+ row.get_value(boost::mpl::find<model_column::List,
+ model_column::ID>::type::pos::value, id);
+ if (id.empty()) continue;
+ if (!selected.empty()) selected += "\n";
+ selected += bbs_->get_another_thread_uri(id);
+ }
+ Gtk::Clipboard::get()->set_text(selected);
+}
+
void BoardWindow::on_action_view_refresh() {
if (http_getter_) return;
unmerge_subject_txt(buffer);
merge_subject_txt(subjects, buffer);
tree_model_->set_buffer(buffer);
+
+ inform_to_threads(buffer);
}
void BoardWindow::on_refresh_end(const http::StatusLine& status,
statusbar_.push(message);
}
+void BoardWindow::save_state() const{
+ BoardWindowState state;
+ state.width = get_width();
+ state.height = get_height();
+ state.menubar = menubar_->is_visible();
+ state.toolbar = toolbar_->is_visible();
+ state.statusbar = statusbar_.is_visible();
+
+ int order = 0;
+ BOOST_FOREACH(const Gtk::TreeViewColumn* kolumn, tree_view_.get_columns()) {
+ const view_column::Base* column =
+ dynamic_cast<const view_column::Base*>(kolumn);
+
+ assert(column);
+
+ BoardWindowState::ColumnInfo info;
+ info.width = column->get_width();
+ info.order = order;
+ state.columns[column->get_id()] = info;
+ ++order;
+
+ if (column->get_sort_indicator()) {
+ state.sort.column = column->get_id();
+ state.sort.ascendant = column->get_sort_order() == Gtk::SORT_ASCENDING;
+ }
+ }
+
+ state.to_xml(boost::filesystem::path(bbs_->get_board_state_path()));
+}
+
+void BoardWindow::inform_to_threads(
+ boost::unordered_map<std::string, ModelColumns>& buffer) const {
+ typedef boost::unordered_map<std::string, ModelColumns> MapType;
+ typedef MapType::const_iterator Iter;
+
+ BOOST_FOREACH(ApplicationWindow& window, windows) {
+ if (ThreadWindow* thread_window = dynamic_cast<ThreadWindow*>(&window)) {
+ const bbs_detail::Base& bbs = thread_window->get_bbs_detail();
+ if (!bbs.belongs_to(*bbs_)) continue;
+
+ const std::string thread = bbs.get_thread_id();
+ Iter it = buffer.find(thread);
+ int res = 0;
+ if (it != buffer.end())
+ res = model_column::field<model_column::ResNum>(it->second);
+ inform_to_thread(*thread_window, res);
+ }
+ }
+}
+
+void BoardWindow::inform_to_thread(ThreadWindow& window, int res_num) const {
+ window.on_informed_from_board(res_num);
+}
+
+
} // namespace dialektos