1 // This file is part of GtkEveMon.
2 //
3 // GtkEveMon is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // You should have received a copy of the GNU General Public License
9 // along with GtkEveMon. If not, see <http://www.gnu.org/licenses/>.
10
11 #include <gtkmm.h>
12
13 #include "util/helpers.h"
14 #include "api/evetime.h"
15 #include "api/apiskilltree.h"
16 #include "api/apiskillqueue.h"
17 #include "bits/config.h"
18 #include "imagestore.h"
19 #include "gtkhelpers.h"
20 #include "gtkdefines.h"
21 #include "gtkskillqueue.h"
22 #include "guiskill.h"
23
GtkSkillQueueViewCols(Gtk::TreeView * view,GtkSkillQueueColumns * cols)24 GtkSkillQueueViewCols::GtkSkillQueueViewCols (Gtk::TreeView* view,
25 GtkSkillQueueColumns* cols)
26 : GtkColumnsBase(view),
27 position("Position", cols->queue_pos),
28 start_sp("Start SP", cols->start_sp),
29 end_sp("Dest SP", cols->end_sp),
30 start_time("Start time", cols->start_time),
31 end_time("Finish time", cols->end_time),
32 duration("Duration", cols->duration),
33 training("Training", cols->training),
34 attribs("Attribs", cols->attribs)
35 {
36 this->skill_name.set_title("Skill name");
37 this->skill_name.pack_start(cols->skill_icon, false);
38 this->skill_name.pack_start(cols->skill_name, true);
39
40 this->position.set_resizable(false);
41
42 this->append_column(&this->position,
43 GtkColumnOptions(false, true, true, ImageStore::columnconf[1]));
44 this->append_column(&this->skill_name, GtkColumnOptions(false, false, true));
45 this->append_column(&this->start_sp, GtkColumnOptions(true, false, true));
46 this->append_column(&this->end_sp, GtkColumnOptions(true, false, true));
47 this->append_column(&this->start_time, GtkColumnOptions(true, false, true));
48 this->append_column(&this->end_time, GtkColumnOptions(true, false, true));
49 this->append_column(&this->duration, GtkColumnOptions(true, false, true));
50 this->append_column(&this->training, GtkColumnOptions(true, false, true));
51 this->append_column(&this->attribs, GtkColumnOptions(true, false, true));
52
53 this->position.get_first_cell()->set_property("xalign", 1.0f);
54 this->skill_name.set_expand(true);
55 this->start_sp.get_first_cell()->set_property("xalign", 1.0f);
56 this->end_sp.get_first_cell()->set_property("xalign", 1.0f);
57 }
58
59 /* ================================================================ */
60
GtkSkillQueue(void)61 GtkSkillQueue::GtkSkillQueue (void)
62 : queue_store(Gtk::ListStore::create(queue_cols)),
63 queue_view(queue_store),
64 queue_view_cols(&queue_view, &queue_cols)
65 {
66 /* Setup EVE API fetcher. */
67 Gtk::ScrolledWindow* scwin = MK_SCWIN;
68 scwin->add(this->queue_view);
69 scwin->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
70 scwin->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
71
72 this->queue_view_cols.position.signal_clicked().connect(sigc::mem_fun
73 (this->queue_view_cols, &GtkColumnsBase::toggle_edit_context));
74
75 this->set_border_width(5);
76 this->pack_start(*scwin, true, true, 0);
77
78 //this->queue_view_cols.set_format("+0 +1 +2 +3 +4 +5 +6 +7");
79 this->init_from_config();
80 this->queue_view_cols.setup_columns_normal();
81
82 this->queue_view.signal_row_activated().connect(sigc::mem_fun
83 (*this, &GtkSkillQueue::on_row_activated));
84 }
85
86 /* ---------------------------------------------------------------- */
87
~GtkSkillQueue(void)88 GtkSkillQueue::~GtkSkillQueue (void)
89 {
90 this->store_to_config();
91 Config::save_to_file();
92 }
93
94 /* ---------------------------------------------------------------- */
95
96 void
set_character(CharacterPtr character)97 GtkSkillQueue::set_character (CharacterPtr character)
98 {
99 this->character = character;
100 this->character->signal_skill_queue_updated().connect
101 (sigc::mem_fun(*this, &GtkSkillQueue::on_apidata_available));
102 this->character->signal_cached_warning().connect(sigc::bind
103 (sigc::mem_fun(*this, &GtkSkillQueue::on_api_problems), true));
104 this->character->signal_request_error().connect(sigc::bind
105 (sigc::mem_fun(*this, &GtkSkillQueue::on_api_problems), false));
106 }
107
108 /* ---------------------------------------------------------------- */
109
110 void
refresh(void)111 GtkSkillQueue::refresh (void)
112 {
113 if (this->character->valid_training_sheet())
114 this->on_apidata_available();
115 else
116 this->character->request_skillqueue();
117 }
118
119 /* ---------------------------------------------------------------- */
120
121 void
init_from_config(void)122 GtkSkillQueue::init_from_config (void)
123 {
124 ConfSectionPtr skillqueue = Config::conf.get_section("skillqueue");
125 ConfValuePtr columns_format = skillqueue->get_value("columns_format");
126 this->queue_view_cols.set_format(**columns_format);
127 }
128
129 /* ---------------------------------------------------------------- */
130
131 void
store_to_config(void)132 GtkSkillQueue::store_to_config (void)
133 {
134 ConfSectionPtr skillqueue = Config::conf.get_section("skillqueue");
135 ConfValuePtr columns_format = skillqueue->get_value("columns_format");
136 columns_format->set(this->queue_view_cols.get_format());
137 }
138
139 /* ---------------------------------------------------------------- */
140
141 #include <iostream>
142
143 void
on_apidata_available(void)144 GtkSkillQueue::on_apidata_available (void)
145 {
146 ApiSkillQueuePtr sq = this->character->sq;
147
148 /* Debugging. */
149 //sq->debug_dump();
150
151 /* FIXME: Pay attention to training times. */
152
153 this->queue_store->clear();
154 ApiSkillTreePtr tree = ApiSkillTree::request();
155 time_t training = 0;
156 for (std::size_t i = 0; i < sq->queue.size(); ++i)
157 {
158 ApiSkillQueueItem const& item = sq->queue[i];
159
160 time_t duration = item.end_time_t - item.start_time_t;
161 //time_t duration = item.end_time_t - EveTime::get_eve_time(); //FIX?
162 training += duration;
163
164 ApiSkill const* skill = tree->get_skill_for_id(item.skill_id);
165 std::string skill_name = (skill == 0
166 ? Helpers::get_string_from_int(item.skill_id) : skill->name);
167 skill_name += " ";
168 skill_name += Helpers::get_roman_from_int(item.to_level);
169
170 Gtk::TreeModel::Row row = *this->queue_store->append();
171 row[this->queue_cols.queue_pos] = item.queue_pos;
172 row[this->queue_cols.skill_name] = skill_name;
173 row[this->queue_cols.skill_icon] = ImageStore::skillicons[1];
174 row[this->queue_cols.start_sp] = item.start_sp;
175 row[this->queue_cols.end_sp] = item.end_sp;
176 row[this->queue_cols.start_time]
177 = EveTime::get_local_time_string(item.start_time_t, true);
178 row[this->queue_cols.end_time]
179 = EveTime::get_local_time_string(item.end_time_t, true);
180 row[this->queue_cols.duration]
181 = EveTime::get_string_for_timediff(duration, true);
182 row[this->queue_cols.training]
183 = EveTime::get_string_for_timediff(training, true);
184
185 Glib::ustring attribs;
186 attribs += ApiSkillTree::get_attrib_short_name(skill->primary);
187 attribs += " / ";
188 attribs += ApiSkillTree::get_attrib_short_name(skill->secondary);
189 row[this->queue_cols.attribs]
190 = attribs;
191
192 row[this->queue_cols.skill_id] = item.skill_id;
193 }
194 }
195
196 /* ---------------------------------------------------------------- */
197
198 void
on_api_problems(EveApiDocType sheet,std::string error,bool cache)199 GtkSkillQueue::on_api_problems (EveApiDocType sheet,
200 std::string error, bool cache)
201 {
202 if (sheet != API_DOCTYPE_SKILLQUEUE)
203 return;
204 this->raise_error(error, cache);
205 }
206
207 /* ---------------------------------------------------------------- */
208
209 void
raise_error(std::string const & error,bool cached)210 GtkSkillQueue::raise_error (std::string const& error, bool cached)
211 {
212 Gtk::MessageType message_type;
213 Glib::ustring message;
214 if (cached)
215 {
216 message = "Using cached version of the skill queue!";
217 message_type = Gtk::MESSAGE_WARNING;
218 }
219 else
220 {
221 message = "Error retrieving skill queue!";
222 message_type = Gtk::MESSAGE_ERROR;
223 }
224
225 Gtk::Window* win = (Gtk::Window*)this->get_toplevel();
226 Gtk::MessageDialog md(*win, message, false, message_type, Gtk::BUTTONS_OK);
227 md.set_secondary_text("There was an error while requesting the skill "
228 "queue from the EVE API. The EVE API is either offline, or the "
229 "requested document is not understood by GtkEveMon. "
230 "The error message is:\n\n" + GtkHelpers::locale_to_utf8(error));
231 md.set_title("Error - GtkEveMon");
232 md.run();
233 }
234
on_row_activated(Gtk::TreeModel::Path const & path,Gtk::TreeViewColumn *)235 void GtkSkillQueue::on_row_activated(Gtk::TreeModel::Path const& path,
236 Gtk::TreeViewColumn* /*col*/)
237 {
238 Gtk::TreeModel::iterator iter = this->queue_store->get_iter(path);
239 Gtk::TreeModel::Row row = *iter;
240 int skill_id = row[this->queue_cols.skill_id];
241 if (skill_id >= 0)
242 {
243 GuiSkill* skillgui = new GuiSkill();
244 skillgui->set_skill(skill_id);
245 }
246 }
247