1 /*******************************************************
2 Copyright (C) 2006 Madhan Kanagavel
3 Copyright (C) 2013-2015 Nikolay
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ********************************************************/
19
20 #include "util.h"
21 #include "validators.h"
22 #include "model/Model_Currency.h"
23 #include "model/Model_Infotable.h"
24 #include "model/Model_Setting.h"
25 #include <wx/sstream.h>
26 //----------------------------------------------------------------------------
27
CaseInsensitiveCmp(const wxString & s1,const wxString & s2)28 int CaseInsensitiveCmp(const wxString &s1, const wxString &s2)
29 {
30 return s1.CmpNoCase(s2);
31 }
32
33 //----------------------------------------------------------------------------
correctEmptyFileExt(const wxString & ext,wxString & fileName)34 void correctEmptyFileExt(const wxString& ext, wxString & fileName)
35 {
36 wxFileName tempFileName(fileName);
37 if (tempFileName.GetExt().IsEmpty())
38 fileName += "." + ext;
39 }
40
inQuotes(const wxString & l,const wxString & delimiter)41 const wxString inQuotes(const wxString& l, const wxString& delimiter)
42 {
43 wxString label = l;
44 if (label.Contains(delimiter) || label.Contains("\""))
45 {
46 label.Replace("\"","\"\"", true);
47 label = wxString() << "\"" << label << "\"";
48 }
49
50 label.Replace("\t"," ", true);
51 label.Replace("\n"," ", true);
52 return label;
53 }
54
mmLoadColorsFromDatabase()55 void mmLoadColorsFromDatabase()
56 {
57 mmColors::userDefColor1 = Model_Infotable::instance().GetColourSetting("USER_COLOR1", wxColour(255, 0, 0));
58 mmColors::userDefColor2 = Model_Infotable::instance().GetColourSetting("USER_COLOR2", wxColour(255, 165, 0));
59 mmColors::userDefColor3 = Model_Infotable::instance().GetColourSetting("USER_COLOR3", wxColour(255, 255, 0));
60 mmColors::userDefColor4 = Model_Infotable::instance().GetColourSetting("USER_COLOR4", wxColour(0, 255, 0));
61 mmColors::userDefColor5 = Model_Infotable::instance().GetColourSetting("USER_COLOR5", wxColour(0, 255, 255));
62 mmColors::userDefColor6 = Model_Infotable::instance().GetColourSetting("USER_COLOR6", wxColour(0, 0, 255));
63 mmColors::userDefColor7 = Model_Infotable::instance().GetColourSetting("USER_COLOR7", wxColour(0, 0, 128));
64 }
65
66 /* Set the default colors */
67 wxColour mmColors::listAlternativeColor0 = wxColour(225, 237, 251);
68 wxColour mmColors::listAlternativeColor1 = wxColour(255, 255, 255);
69 wxColour mmColors::listBackColor = wxColour(255, 255, 255);
70 wxColour mmColors::navTreeBkColor = wxColour(255, 255, 255);
71 wxColour mmColors::listBorderColor = wxColour(0, 0, 0);
72 wxColour mmColors::listDetailsPanelColor = wxColour(244, 247, 251);
73 wxColour mmColors::listFutureDateColor = wxColour(116, 134, 168);
74
75 wxColour mmColors::userDefColor1;
76 wxColour mmColors::userDefColor2;
77 wxColour mmColors::userDefColor3;
78 wxColour mmColors::userDefColor4;
79 wxColour mmColors::userDefColor5;
80 wxColour mmColors::userDefColor6;
81 wxColour mmColors::userDefColor7;
82
83 //*-------------------------------------------------------------------------*//
84
site_content(const wxString & sSite,wxString & sOutput)85 int site_content(const wxString& sSite, wxString& sOutput)
86 {
87 wxString proxyName = Model_Setting::instance().GetStringSetting("PROXYIP", "");
88 if (!proxyName.empty())
89 {
90 int proxyPort = Model_Setting::instance().GetIntSetting("PROXYPORT", 0);
91 const wxString& proxySettings = wxString::Format("%s:%d", proxyName, proxyPort);
92 wxURL::SetDefaultProxy(proxySettings);
93 }
94 else
95 wxURL::SetDefaultProxy(""); // Remove prior proxy
96
97 wxURL url(sSite);
98 int err_code = url.GetError();
99 if (err_code == wxURL_NOERR)
100 {
101 int networkTimeout = Model_Setting::instance().GetIntSetting("NETWORKTIMEOUT", 10); // default 10 secs
102 url.GetProtocol().SetTimeout(networkTimeout);
103 wxInputStream* in_stream = url.GetInputStream();
104 if (in_stream)
105 {
106 wxStringOutputStream out_stream(&sOutput);
107 in_stream->Read(out_stream);
108 }
109 else
110 err_code = -1; //Cannot get data from WWW!
111 delete in_stream;
112 }
113
114 if (err_code != wxURL_NOERR)
115 {
116 if (err_code == wxURL_SNTXERR ) sOutput = _("Syntax error in the URL string");
117 else if (err_code == wxURL_NOPROTO ) sOutput = _("Found no protocol which can get this URL");
118 else if (err_code == wxURL_NOHOST ) sOutput = _("A host name is required for this protocol");
119 else if (err_code == wxURL_NOPATH ) sOutput = _("A path is required for this protocol");
120 else if (err_code == wxURL_CONNERR ) sOutput = _("Connection error");
121 else if (err_code == wxURL_PROTOERR) sOutput = _("An error occurred during negotiation");
122 else if (err_code == -1) sOutput = _("Cannot get data from WWW!");
123 else sOutput = _("Unknown error");
124 }
125 return err_code;
126 }
127
download_file(const wxString & site,const wxString & path)128 bool download_file(const wxString& site, const wxString& path)
129 {
130 wxFileSystem fs;
131 wxFileSystem::AddHandler(new wxInternetFSHandler());
132 wxFSFile *file = fs.OpenFile(site);
133 if (file != NULL)
134 {
135 wxInputStream *in = file->GetStream();
136 if (in != NULL)
137 {
138 wxFileOutputStream output(path);
139 output.Write(*file->GetStream());
140 output.Close();
141 delete in;
142 return true;
143 }
144 }
145
146 return false;
147 }
148
149 //* Date Functions----------------------------------------------------------*//
mmGetNiceDateSimpleString(const wxDateTime & dt)150 const wxString mmGetNiceDateSimpleString(const wxDateTime &dt)
151 {
152 wxString dateFmt = mmOptions::instance().dateFormat_;
153 dateFmt.Replace("%Y%m%d", "%Y %m %d");
154 dateFmt.Replace(".", " ");
155 dateFmt.Replace(",", " ");
156 dateFmt.Replace("/", " ");
157 dateFmt.Replace("-", " ");
158 dateFmt.Replace("%d", wxString::Format("%d", dt.GetDay()));
159 dateFmt.Replace("%Y", wxString::Format("%d", dt.GetYear()));
160 dateFmt.Replace("%y", wxString::Format("%d", dt.GetYear()).Mid(2,2));
161 dateFmt.Replace("%m", wxGetTranslation(wxDateTime::GetEnglishMonthName(dt.GetMonth())));
162
163 return dateFmt;
164 }
165
mmGetDateForDisplay(const wxDateTime & dt)166 const wxString mmGetDateForDisplay(const wxDateTime &dt)
167 {
168 return dt.Format(mmOptions::instance().dateFormat_);
169 }
170
mmParseDisplayStringToDate(wxDateTime & date,wxString sDate,const wxString & sDateMask)171 bool mmParseDisplayStringToDate(wxDateTime& date, wxString sDate, const wxString &sDateMask)
172 {
173 if (date_formats_regex().count(sDateMask) == 0)
174 return false;
175
176 const wxString regex = date_formats_regex().at(sDateMask);
177 wxRegEx pattern(regex);
178
179 if (pattern.Matches(sDate))
180 {
181 sDate = pattern.GetMatch(sDate);
182 wxString::const_iterator end;
183 return date.ParseFormat(sDate, sDateMask, &end);
184 }
185 return false;
186 }
187
mmGetStorageStringAsDate(const wxString & str)188 const wxDateTime mmGetStorageStringAsDate(const wxString& str)
189 {
190 wxDateTime dt;
191 if (str.IsEmpty() || !dt.ParseDate(str))
192 dt = wxDateTime::Today();
193 int year = dt.GetYear();
194 if (year < 50)
195 dt.Add(wxDateSpan::Years(2000));
196 else if (year < 100)
197 dt.Add(wxDateSpan::Years(1900));
198 return dt;
199 }
200
date_formats_regex()201 const std::map<wxString,wxString> date_formats_regex()
202 {
203 const wxString dd = "((([0 ][1-9])|([1-2][0-9])|(3[0-1]))|([1-9]))";
204 const wxString mm = "((([0 ][1-9])|(1[0-2]))|([1-9]))";
205 const wxString yy = "([0-9]{2})";
206 const wxString yyyy = "(((19)|([2]([0]{1})))([0-9]{2}))";
207 std::map<wxString, wxString> date_regex;
208 date_regex["%d/%m/%y"] = wxString::Format("^%s/%s/%s*", dd, mm, yy);
209 date_regex["%d/%m/%Y"] = wxString::Format("^%s/%s/%s*", dd, mm, yyyy);
210 date_regex["%d-%m-%y"] = wxString::Format("^%s-%s-%s*", dd, mm, yy);
211 date_regex["%d-%m-%Y"] = wxString::Format("^%s-%s-%s*", dd, mm, yyyy);
212 date_regex["%d.%m.%y"] = wxString::Format("^%s\x2E%s\x2E%s*", dd, mm, yy);
213 date_regex["%d.%m.%Y"] = wxString::Format("^%s\x2E%s\x2E%s*", dd, mm, yyyy);
214 date_regex["%d,%m,%y"] = wxString::Format("^%s,%s,%s*", dd, mm, yy);
215 date_regex["%d/%m'%Y"] = wxString::Format("^%s/%s'%s*", dd, mm, yyyy);
216 date_regex["%d/%m %Y"] = wxString::Format("^%s/%s %s*", dd, mm, yyyy);
217 date_regex["%m/%d/%y"] = wxString::Format("^%s/%s/%s*", mm, dd, yy);
218 date_regex["%m/%d/%Y"] = wxString::Format("^%s/%s/%s*", mm, dd, yyyy);
219 date_regex["%m-%d-%y"] = wxString::Format("^%s-%s-%s*", mm, dd, yy);
220 date_regex["%m-%d-%Y"] = wxString::Format("^%s-%s-%s*", mm, dd, yyyy);
221 date_regex["%m/%d'%y"] = wxString::Format("^%s/%s'%s*", mm, dd, yy);
222 date_regex["%m/%d'%Y"] = wxString::Format("^%s/%s'%s*", mm, dd, yyyy);
223 date_regex["%y/%m/%d"] = wxString::Format("^%s/%s/%s*", yy, mm, dd);
224 date_regex["%y-%m-%d"] = wxString::Format("^%s-%s-%s*", yy, mm, dd);
225 date_regex["%Y/%m/%d"] = wxString::Format("^%s/%s/%s*", yyyy, mm, dd);
226 date_regex["%Y-%m-%d"] = wxString::Format("^%s-%s-%s*", yyyy, mm, dd);
227 date_regex["%Y.%m.%d"] = wxString::Format("^%s\x2E%s\x2E%s*", yyyy, mm, dd);
228 date_regex["%Y %m %d"] = wxString::Format("^%s %s %s*", yyyy, mm, dd);
229 date_regex["%Y%m%d"] = wxString::Format("^%s%s%s*", yyyy, mm, dd);
230
231 return date_regex;
232 }
233
234 const std::map<wxString, wxString> g_date_formats_map = {
235 { "%Y-%m-%d", "YYYY-MM-DD" }
236 , { "%d/%m/%y", "DD/MM/YY" }
237 , { "%d/%m/%Y", "DD/MM/YYYY" }
238 , { "%d-%m-%y", "DD-MM-YY" }
239 , { "%d-%m-%Y", "DD-MM-YYYY" }
240 , { "%d.%m.%y", "DD.MM.YY" }
241 , { "%d.%m.%Y", "DD.MM.YYYY" }
242 , { "%d,%m,%y", "DD,MM,YY" }
243 , { "%d/%m'%Y", "DD/MM'YYYY" }
244 , { "%d/%m %Y", "DD/MM YYYY" }
245 , { "%m/%d/%y", "MM/DD/YY" }
246 , { "%m/%d/%Y", "MM/DD/YYYY" }
247 , { "%m-%d-%y", "MM-DD-YY" }
248 , { "%m-%d-%Y", "MM-DD-YYYY" }
249 , { "%m/%d'%y", "MM/DD'YY" }
250 , { "%m/%d'%Y", "MM/DD'YYYY" }
251 , { "%y/%m/%d", "YY/MM/DD" }
252 , { "%y-%m-%d", "YY-MM-DD" }
253 , { "%Y/%m/%d", "YYYY/MM/DD" }
254 , { "%Y.%m.%d", "YYYY.MM.DD" }
255 , { "%Y %m %d", "YYYY MM DD" }
256 , { "%Y%m%d", "YYYYMMDD" }
257 };
258
259 static const wxString MONTHS[12] =
260 {
261 wxTRANSLATE("January"), wxTRANSLATE("February"), wxTRANSLATE("March")
262 , wxTRANSLATE("April"), wxTRANSLATE("May"), wxTRANSLATE("June")
263 , wxTRANSLATE("July"), wxTRANSLATE("August"), wxTRANSLATE("September")
264 , wxTRANSLATE("October"), wxTRANSLATE("November"), wxTRANSLATE("December")
265 };
266
267 static const wxString MONTHS_SHORT[12] =
268 {
269 wxTRANSLATE("Jan"), wxTRANSLATE("Feb"), wxTRANSLATE("Mar")
270 , wxTRANSLATE("Apr"), wxTRANSLATE("May"), wxTRANSLATE("Jun")
271 , wxTRANSLATE("Jul"), wxTRANSLATE("Aug"), wxTRANSLATE("Sep")
272 , wxTRANSLATE("Oct"), wxTRANSLATE("Nov"), wxTRANSLATE("Dec")
273 };
274
275 static const wxString gDaysInWeek[7] =
276 {
277 wxTRANSLATE("Sunday"), wxTRANSLATE("Monday"), wxTRANSLATE("Tuesday")
278 , wxTRANSLATE("Wednesday"), wxTRANSLATE("Thursday"), wxTRANSLATE("Friday")
279 , wxTRANSLATE("Saturday")
280 };
281
282 //
mmPlatformType()283 const wxString mmPlatformType()
284 {
285 return wxPlatformInfo::Get().GetOperatingSystemFamilyName().substr(0, 3);
286 }
287
getURL(const wxString & file)288 const wxString getURL(const wxString& file)
289 {
290 wxString index = file;
291 #ifdef __WXGTK__
292 index.Prepend("file://");
293 #endif
294 return index;
295 }
296
windowsFreezeThaw(wxWindow * w)297 void windowsFreezeThaw(wxWindow* w)
298 {
299 #ifdef __WXGTK__
300 return;
301 #endif
302
303 if (w->IsFrozen())
304 w->Thaw();
305 else
306 w->Freeze();
307 }
308
309 #if 1
310 // ----------------------------------------------------------------------------
311 // mmCalcValidator
312 // Same as previous, but substitute dec char according to currency configuration
313 // ----------------------------------------------------------------------------
314
IMPLEMENT_DYNAMIC_CLASS(mmCalcValidator,wxTextValidator)315 IMPLEMENT_DYNAMIC_CLASS(mmCalcValidator, wxTextValidator)
316 BEGIN_EVENT_TABLE(mmCalcValidator, wxTextValidator)
317 EVT_CHAR(mmCalcValidator::OnChar)
318 END_EVENT_TABLE()
319
320 mmCalcValidator::mmCalcValidator() : wxTextValidator(wxFILTER_INCLUDE_CHAR_LIST)
321 {
322 wxArrayString list;
323 for (const auto& c : " 1234567890.,(/+-*)")
324 {
325 list.Add(c);
326 }
327 SetIncludes(list);
328 const Model_Currency::Data *base_currency = Model_Currency::instance().GetBaseCurrency();
329 if (base_currency)
330 m_decChar = base_currency->DECIMAL_POINT[0];
331 }
332
OnChar(wxKeyEvent & event)333 void mmCalcValidator::OnChar(wxKeyEvent& event)
334 {
335 if (!m_validatorWindow)
336 {
337 event.Skip();
338 return;
339 }
340
341 int keyCode = event.GetKeyCode();
342
343 // we don't filter special keys and delete
344 if (keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode >= WXK_START)
345 {
346 event.Skip();
347 return;
348 }
349
350 const wxString str((wxUniChar)keyCode, 1);
351 if (!(wxIsdigit(str[0]) || wxString("+-.,*/ ()").Contains(str)))
352 {
353 if ( !wxValidator::IsSilent() )
354 wxBell();
355
356 // eat message
357 return;
358 }
359 // only if it's a wxTextCtrl
360 if (!m_validatorWindow || !wxDynamicCast(m_validatorWindow, wxTextCtrl))
361 {
362 event.Skip();
363 return;
364 }
365 // if decimal point, check if it's already in the string
366 if (str == '.' || str == ',')
367 {
368 const wxString value = ((wxTextCtrl*)m_validatorWindow)->GetValue();
369 size_t ind = value.rfind(m_decChar);
370 if (ind < value.Length())
371 {
372 // check if after last decimal point there is an operation char (+-/*)
373 if (value.find('+', ind+1) >= value.Length() && value.find('-', ind+1) >= value.Length() &&
374 value.find('*', ind+1) >= value.Length() && value.find('/', ind+1) >= value.Length())
375 return;
376 }
377 #ifdef _MSC_VER
378 if (str != m_decChar)
379 {
380 const wxChar vk = m_decChar == '.' ? 0x6e : 0xbc;
381 keybd_event(vk, 0xb3, 0, 0);
382 keybd_event(vk, 0xb3, KEYEVENTF_KEYUP, 0);
383 return;
384 }
385 #endif
386 }
387 event.Skip();
388 }
389 #endif
390