/* Weather Protocol plugin for Miranda IM Copyright (c) 2012 Miranda NG team Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved Copyright (c) 2002-2005 Calvin Che This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* This file contain the source that is related to display contact information, including the one shows in user detail and the brief information */ #include "stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // dialog for more data in the user info window static unsigned tabstops = 48; static int GetWeatherDataFromDB(const char *szSetting, void *lparam) { auto *pList = (OBJLIST*)lparam; pList->insert(newStr(szSetting)); return 0; } class CBriefInfoDlg : public CWeatherDlgBase { MCONTACT hContact; wchar_t m_buf[4098]; int iOldItem = -1; UI_MESSAGE_MAP(CBriefInfoDlg, CWeatherDlgBase); UI_MESSAGE(WM_UPDATEDATA, OnUpdate); UI_MESSAGE_MAP_END(); CTimer m_timer; CCtrlButton btnUpdate, btnWebpage, btnToggle; CCtrlListView m_list; public: CBriefInfoDlg(CWeatherProto *ppro, MCONTACT _1) : CWeatherDlgBase(ppro, IDD_BRIEF), hContact(_1), m_list(this, IDC_DATALIST), m_timer(this, 1), btnToggle(this, IDC_MTOGGLE), btnUpdate(this, IDC_MUPDATE), btnWebpage(this, IDC_MWEBPAGE) { SetMinSize(350, 300); m_list.OnHotTrack = Callback(this, &CBriefInfoDlg::onList_Track); m_timer.OnEvent = Callback(this, &CBriefInfoDlg::onTimer); btnToggle.OnClick = Callback(this, &CBriefInfoDlg::onClick_Toggle); btnUpdate.OnClick = Callback(this, &CBriefInfoDlg::onClick_Update); btnWebpage.OnClick = Callback(this, &CBriefInfoDlg::onClick_Webpage); } bool OnInitDialog() override { SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_AUTOURLDETECT, (WPARAM)TRUE, 0); SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_SETEVENTMASK, 0, ENM_LINK); SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_SETMARGINS, EC_LEFTMARGIN, 5); SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_SETTABSTOPS, 1, (LPARAM)&tabstops); // get the list to display { RECT aRect = {}; GetClientRect(m_list.GetHwnd(), &aRect); // managing styles DWORD dwStyle = LVS_EX_FULLROWSELECT; m_list.SetExtendedListViewStyleEx(dwStyle, dwStyle); // inserting columns LV_COLUMN lvc = {}; lvc.mask = LVCF_WIDTH | LVCF_TEXT; lvc.cx = LIST_COLUMN; lvc.pszText = TranslateT("Variable"); m_list.InsertColumn(0, &lvc); lvc.cx = aRect.right - LIST_COLUMN - GetSystemMetrics(SM_CXVSCROLL) - 3; lvc.pszText = TranslateT("Information"); m_list.InsertColumn(1, &lvc); // insert data OnUpdate(); } // prevent dups of the window WindowList_Add(hDataWindowList, m_hwnd, hContact); // restore window position Utils_RestoreWindowPositionNoMove(m_hwnd, NULL, MODULENAME, "BriefInfo_"); return true; } void OnDestroy() override { DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, 0)); DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, 0)); Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "BriefInfo_"); WindowList_Remove(hDataWindowList, m_hwnd); } int Resizer(UTILRESIZECONTROL *urc) override { switch (urc->wId) { case IDC_HEADERBAR: return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH; case IDC_MTEXT: return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; case IDC_DATALIST: m_list.SetColumnWidth(1, urc->dlgNewSize.cx - m_list.GetColumnWidth(0) - GetSystemMetrics(SM_CXVSCROLL)); return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; case IDC_MUPDATE: return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; case IDC_MTOGGLE: case IDC_MWEBPAGE: case IDCANCEL: return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; } return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; } INT_PTR OnUpdate(UINT = 0, WPARAM = 0, LPARAM = 0) { m_list.DeleteAllItems(); // load weather information from the contact into the WEATHERINFO struct WEATHERINFO winfo = m_proto->LoadWeatherInfo(hContact); // check if data exist. If not, display error message box if (!m_proto->getByte(hContact, "IsUpdated")) SetDlgItemTextW(m_hwnd, IDC_MTEXT, TranslateT("No information available.\r\nPlease update weather condition first.")); else { // set the display text and show the message box SetDlgItemTextW(m_hwnd, IDC_MTEXT, GetDisplay(&winfo, m_proto->GetTextValue('B'))); } SetWindowTextW(m_hwnd, winfo.city); SetDlgItemTextW(m_hwnd, IDC_HEADERBAR, GetDisplay(&winfo, L"%c, %t")); // get all the settings and store them in a temporary list LIST arSettings(10); db_enum_settings(hContact, GetWeatherDataFromDB, WEATHERCONDITION, &arSettings); auto T = arSettings.rev_iter(); for (auto &it: T) { CMStringW wszText(db_get_wsm(hContact, WEATHERCONDITION, it)); if (wszText.IsEmpty()) continue; // skip the "WeatherInfo" variable if (!mir_strcmp(it, "WeatherInfo") || !mir_strcmp(it, "Ignore") || it[0] == '#') continue; wszText.Replace(L"; ", L";\r\n "); _A2T strW(it); LV_ITEM lvi = {}; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.lParam = T.indexOf(&it); lvi.pszText = TranslateW(strW); lvi.iItem = m_list.InsertItem(&lvi); lvi.pszText = wszText.GetBuffer(); m_list.SetItemText(lvi.iItem, 1, wszText); } // set icons HICON hIcon = m_proto->GetStatusIconBig(hContact); DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, LPARAM(hIcon))); DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, LPARAM(hIcon))); RedrawWindow(GetDlgItem(m_hwnd, IDC_HEADERBAR), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW); return 0; } void onList_Track(CCtrlListView::TEventInfo *ev) { auto *nlv = ev->nmlv; if (nlv->iItem == -1 || nlv->iItem == iOldItem || nlv->iSubItem != 1) return; iOldItem = nlv->iItem; m_list.GetItemText(nlv->iItem, nlv->iSubItem, m_buf, _countof(m_buf)); m_timer.Start(100); } void onTimer(CTimer *pTimer) { pTimer->Stop(); if (wcslen(m_buf) > 50) { CLCINFOTIP ti = {}; ti.cbSize = sizeof(TOOLINFO); ti.hItem = (HANDLE)iOldItem; Tipper_ShowTip(m_buf, &ti); } else Tipper_Hide(); } void onClick_Update(CCtrlButton *) { // update current data // set the text to "updating" SetDlgItemText(m_hwnd, IDC_MTEXT, TranslateT("Retrieving new data, please wait...")); m_list.DeleteAllItems(); LV_ITEM lvi = {}; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.lParam = 1; lvi.pszText = L""; lvi.iItem = m_list.InsertItem(&lvi); lvi.pszText = TranslateT("Retrieving new data, please wait..."); m_list.SetItemText(lvi.iItem, 1, lvi.pszText); m_proto->UpdateSingleStation(hContact, 0); } void onClick_Webpage(CCtrlButton *) { m_proto->LoadForecast(hContact, 0); // read complete forecast } void onClick_Toggle(CCtrlButton *) { if (IsWindowVisible(m_list.GetHwnd())) SetDlgItemText(m_hwnd, IDC_MTOGGLE, TranslateT("More Info")); else SetDlgItemText(m_hwnd, IDC_MTOGGLE, TranslateT("Brief Info")); ShowWindow(m_list.GetHwnd(), (int)!IsWindowVisible(m_list.GetHwnd())); ShowWindow(GetDlgItem(m_hwnd, IDC_MTEXT), (int)!IsWindowVisible(GetDlgItem(m_hwnd, IDC_MTEXT))); } }; INT_PTR CWeatherProto::BriefInfo(WPARAM hContact, LPARAM) { // make sure that the contact is actually a weather one if (!IsMyContact(hContact)) return 0; HWND hMoreDataDlg = WindowList_Find(hDataWindowList, hContact); if (hMoreDataDlg != nullptr) { SetForegroundWindow(hMoreDataDlg); SetFocus(hMoreDataDlg); } else { auto *pDlg = new CBriefInfoDlg(this, hContact); pDlg->Create(); hMoreDataDlg = pDlg->GetHwnd(); } ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 0); ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 1); SetDlgItemText(hMoreDataDlg, IDC_MTOGGLE, TranslateT("More Info")); return 1; } int CWeatherProto::BriefInfoEvt(WPARAM wParam, LPARAM) { return BriefInfo(wParam, 0); } ///////////////////////////////////////////////////////////////////////////////////////// // User info dialog class WeatherUserInfoDlg : public CUserInfoPageDlg { CCtrlButton btnDetail; CWeatherProto *ppro; public: WeatherUserInfoDlg() : CUserInfoPageDlg(g_plugin, IDD_USERINFO), btnDetail(this, IDC_MOREDETAIL) { btnDetail.OnClick = Callback(this, &WeatherUserInfoDlg::onClick_Detail); } bool OnInitDialog() override { SendDlgItemMessage(m_hwnd, IDC_MOREDETAIL, BUTTONSETASFLATBTN, TRUE, 0); ppro = (CWeatherProto *)Proto_GetContactInstance(m_hContact); // load weather info for the contact WEATHERINFO w = ppro->LoadWeatherInfo(m_hContact); SetDlgItemText(m_hwnd, IDC_INFO1, GetDisplay(&w, TranslateT("Current condition for %n"))); SendDlgItemMessage(m_hwnd, IDC_INFOICON, STM_SETICON, (WPARAM)ppro->GetStatusIconBig(m_hContact), 0); // bold and enlarge the current condition LOGFONT lf; HFONT hNormalFont = (HFONT)SendDlgItemMessage(m_hwnd, IDC_INFO2, WM_GETFONT, 0, 0); GetObject(hNormalFont, sizeof(lf), &lf); lf.lfWeight = FW_BOLD; lf.lfWidth = 7; lf.lfHeight = 15; SendDlgItemMessage(m_hwnd, IDC_INFO2, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0); // set the text for displaying other current weather conditions data SetDlgItemText(m_hwnd, IDC_INFO2, GetDisplay(&w, L"%c %t")); SetDlgItemText(m_hwnd, IDC_INFO3, w.feel); SetDlgItemText(m_hwnd, IDC_INFO4, w.pressure); SetDlgItemText(m_hwnd, IDC_INFO5, GetDisplay(&w, L"%i %w")); SetDlgItemText(m_hwnd, IDC_INFO6, w.dewpoint); SetDlgItemText(m_hwnd, IDC_INFO7, w.sunrise); SetDlgItemText(m_hwnd, IDC_INFO8, w.sunset); SetDlgItemText(m_hwnd, IDC_INFO9, w.high); SetDlgItemText(m_hwnd, IDC_INFO10, w.low); SetDlgItemText(m_hwnd, IDC_INFO11, GetDisplay(&w, TranslateT("Last update on: %u"))); SetDlgItemText(m_hwnd, IDC_INFO12, w.humid); SetDlgItemText(m_hwnd, IDC_INFO13, w.vis); return true; } void OnDestroy() override { DestroyIcon((HICON)SendDlgItemMessage(m_hwnd, IDC_INFOICON, STM_SETICON, 0, 0)); DeleteObject((HFONT)SendDlgItemMessage(m_hwnd, IDC_INFO2, WM_GETFONT, 0, 0)); } void onClick_Detail(CCtrlButton *) { HWND hMoreDataDlg = WindowList_Find(hDataWindowList, m_hContact); if (hMoreDataDlg == nullptr) { auto *pDlg = new CBriefInfoDlg(ppro, m_hContact); pDlg->Create(); hMoreDataDlg = pDlg->GetHwnd(); } else { SetForegroundWindow(hMoreDataDlg); SetFocus(hMoreDataDlg); } ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 0); ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 1); } }; int CWeatherProto::UserInfoInit(WPARAM wParam, LPARAM hContact) { // check if it is a weather contact if (IsMyContact(hContact)) { USERINFOPAGE uip = {}; uip.szTitle.w = m_tszUserName; uip.position = 100000000; uip.flags = ODPF_ICON | ODPF_BOLDGROUPS | ODPF_UNICODE; uip.dwInitParam = LPARAM(g_plugin.getIconHandle(IDI_ICON)); uip.pDialog = new WeatherUserInfoDlg(); g_plugin.addUserInfo(wParam, &uip); } return 0; }