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 <string>
12 #include <sstream>
13 
14 #include <glibmm.h>
15 #include <gtkmm.h>
16 
17 #include "util/helpers.h"
18 #include "api/evetime.h"
19 #include "imagestore.h"
20 #include "gtkhelpers.h"
21 
22 void
create_tooltip(Glib::RefPtr<Gtk::Tooltip> const & tooltip,ApiSkill const * skill,ApiCharSheetSkill * cskill,CharacterPtr character)23 GtkHelpers::create_tooltip (Glib::RefPtr<Gtk::Tooltip> const& tooltip,
24         ApiSkill const* skill, ApiCharSheetSkill* cskill,
25         CharacterPtr character)
26 {
27   tooltip->set_icon(ImageStore::skill);
28 
29   std::stringstream ss;
30 
31   if (cskill != 0)
32     ss << "Name: " << skill->name << " "
33         << Helpers::get_roman_from_int(cskill->level) << "\n";
34   else
35     ss << "Name: " << skill->name << "\n";
36 
37   ss << "Attributes: " << ApiSkillTree::get_attrib_name(skill->primary)
38      << " / " << ApiSkillTree::get_attrib_name(skill->secondary)
39      << "\nRank: " << skill->rank << "\n";
40 
41   if (cskill != 0 && cskill->level != 5)
42   {
43     /* Fill basic information available from the character skill. */
44     int current_sp = cskill->points;
45     double completed = cskill->completed;
46 
47     /* Get more information available from char/training sheet. */
48     double spph = 0.0;
49     time_t time_remaining = 0;
50 
51     if (character.get() != 0 && character->cs->valid)
52     {
53       /* Insert live information if the current skill is in training. */
54       if (character->is_training() && character->training_skill == skill)
55       {
56         /* Fill live information. */
57         current_sp = character->training_skill_sp;
58         completed = character->training_level_done;
59         spph = character->training_spph;
60         time_remaining = character->training_remaining;
61       }
62       else
63       {
64         /* Fill information from char sheet. */
65         int sp_remaining = cskill->points_dest - current_sp;
66         spph = (double)character->cs->get_spph_for_skill(skill);
67         time_remaining = (time_t)(3600.0 * (double)sp_remaining / spph);
68       }
69     }
70 
71     ss << "Skill level from " << Helpers::get_dotted_str_from_int
72         (cskill->points_start) << " to " << Helpers::get_dotted_str_from_int
73         (cskill->points_dest) << " SP\n";
74 
75     if (cskill->points_start != current_sp)
76       ss << "Current SP: " << Helpers::get_dotted_str_from_int
77           (current_sp) << "\n";
78 
79     if (spph != 0.0 && time_remaining != 0)
80     {
81       ss << "SP per hour: " << (int)spph << "\n";
82       if (completed != 0.0)
83         ss << "Remaining time ";
84       else
85         ss << "Training time ";
86       ss << "to level " << Helpers::get_roman_from_int(cskill->level + 1) << ": ";
87       ss << EveTime::get_string_for_timediff(time_remaining, false) << "\n";
88     }
89 
90     for (int level = cskill->level + 2; level <= 5; level++)
91     {
92       time_remaining = (time_t)(3600.0
93         * (double)(ApiCharSheet::calc_dest_sp(
94         level - 1, cskill->details->rank)
95         - ApiCharSheet::calc_start_sp(level - 1,
96         cskill->details->rank)) / spph);
97       ss << "Training time to level "
98         << Helpers::get_roman_from_int(level) << ": "
99         << EveTime::get_string_for_timediff(time_remaining, false) << "\n";
100     }
101 
102     if (completed != 0.0)
103       ss << "Completed: " << Helpers::get_string_from_double
104           (completed * 100.0, 2) << "%\n";
105   }
106 
107 
108 #if 0
109   /* Old version without live SP counting. */
110   if (cskill != 0 && sheet.get() != 0 && sheet->valid && cskill->level != 5)
111   {
112     int sp_to_go = cskill->points_dest - cskill->points;
113     double spph = (double)sheet->get_spph_for_skill(skill);
114     time_t secs_next_level = (time_t)(3600.0 * (double)sp_to_go / spph);
115     std::string next_level_str = EveTime::get_string_for_timediff
116         (secs_next_level, false);
117     if (cskill->completed != 0.0)
118       next_level_str += " (" + Helpers::get_string_from_double
119           (cskill->completed * 100.0, 0) + "% completed)";
120     ss << "SP per hour: " << (int)(spph) << "\n"
121         << "Destination SP: "
122         << Helpers::get_dotted_str_from_int(cskill->points_dest) << "\n"
123         << "Training time: " << next_level_str << "\n";
124   }
125 #endif
126 
127   ss << "\n" << skill->desc;
128   tooltip->set_text(ss.str());
129 }
130 
131 /* ---------------------------------------------------------------- */
132 
133 void
create_tooltip(Glib::RefPtr<Gtk::Tooltip> const & tooltip,ApiCert const * cert)134 GtkHelpers::create_tooltip (Glib::RefPtr<Gtk::Tooltip> const& tooltip,
135     ApiCert const* cert)
136 {
137   Glib::ustring class_name = cert->class_details->name;
138   Glib::ustring cert_grade = ApiCertTree::get_name_for_grade(cert->grade);
139   Glib::ustring cert_desc = cert->desc;
140 
141   tooltip->set_icon(ImageStore::certificate);
142   tooltip->set_text("Name: " + class_name + "\nGrade: " + cert_grade
143       + "\n\n" + cert_desc);
144 }
145 
146 /* ---------------------------------------------------------------- */
147 
148 bool
create_tooltip_from_view(int x,int y,Glib::RefPtr<Gtk::Tooltip> tip,Gtk::TreeView & view,Glib::RefPtr<Gtk::TreeModel> store,Gtk::TreeModelColumn<ApiElement const * > col)149 GtkHelpers::create_tooltip_from_view (int x, int y,
150     Glib::RefPtr<Gtk::Tooltip> tip, Gtk::TreeView& view,
151     Glib::RefPtr<Gtk::TreeModel> store,
152     Gtk::TreeModelColumn<ApiElement const*> col)
153 {
154   Gtk::TreeModel::Path path;
155   Gtk::TreeViewDropPosition pos;
156   bool exists = view.get_dest_row_at_pos(x, y, path, pos);
157   if (!exists)
158     return false;
159 
160   Gtk::TreeIter iter = store->get_iter(path);
161   ApiElement const* elem = (*iter)[col];
162   if (elem == 0)
163     return false;
164 
165   /* Reposition tooltip. */
166   view.set_tooltip_row(tip, path);
167 
168   switch (elem->get_type())
169   {
170     case API_ELEM_SKILL:
171       GtkHelpers::create_tooltip(tip, (ApiSkill const*)elem);
172       break;
173     case API_ELEM_CERT:
174       GtkHelpers::create_tooltip(tip, (ApiCert const*)elem);
175       break;
176     default:
177       return false;
178   }
179 
180   return true;
181 }
182 
183 /* ---------------------------------------------------------------- */
184 
185 Glib::ustring
locale_to_utf8(Glib::ustring const & opsys_string)186 GtkHelpers::locale_to_utf8 (Glib::ustring const& opsys_string)
187 {
188   /* We don't throw the error further away, we'll handle it here. */
189   #define LOCALE_TO_UTF8_ERROR "Error converting string to UTF-8!"
190   #ifdef GLIBMM_EXCEPTIONS_ENABLED
191   try
192   { return Glib::locale_to_utf8(opsys_string); }
193   catch (...)
194   { return LOCALE_TO_UTF8_ERROR; }
195   #else
196   std::auto_ptr<Glib::Error> error;
197   std::string ret = Glib::locale_to_utf8(opsys_string, error);
198   if (error.get())
199     return LOCALE_TO_UTF8_ERROR;
200   return ret;
201   #endif
202 }
203