/*
Copyright (C) 2012-24 Miranda NG team (https://miranda-ng.org)
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 .
*/
#include "stdafx.h"
class COptionsDlg : public CDlgBase
{
OBJLIST m_columns;
void AddColumn(int idx, ColumnItem *pCol)
{
LVITEM lvi = {};
lvi.mask = LVIF_PARAM;
lvi.iItem = idx;
lvi.lParam = LPARAM(pCol);
m_list.InsertItem(&lvi);
}
void CheckDirection(int iItem)
{
btnUp.Enable(iItem > 0);
btnDown.Enable(iItem < m_list.GetItemCount()-1);
}
void ClearScreen()
{
// setting
ShowWindow(GetDlgItem(m_hwnd, IDC_S_DATATYPE), SW_HIDE);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_DATATYPE), SW_HIDE);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_MODULE), SW_HIDE);
ShowWindow(GetDlgItem(m_hwnd, IDC_E_MODULE), SW_HIDE);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_SETTING), SW_HIDE);
ShowWindow(GetDlgItem(m_hwnd, IDC_E_SETTING), SW_HIDE);
// contact info
ShowWindow(GetDlgItem(m_hwnd, IDC_S_CNFTYPE), SW_HIDE);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_CNFTYPE), SW_HIDE);
// others
ShowWindow(GetDlgItem(m_hwnd, IDC_C_OTHER), SW_HIDE);
}
void DisplayCurInfo(const ColumnItem *pCol)
{
ClearScreen();
SetupScreen(pCol->setting_type);
editTitle.SetText(pCol->title);
cmbVarType.SelectData(pCol->setting_type);
switch (pCol->setting_type) {
case QST_SETTING:
cmbDataType.SelectData(pCol->datatype);
editModule.SetTextA(pCol->module);
editSetting.SetTextA(pCol->setting);
break;
case QST_SCRIPT:
SetDlgItemTextW(m_hwnd, IDC_E_SCRIPT, pCol->script);
break;
case QST_CONTACTINFO:
cmbCnfType.SelectData(pCol->cnftype);
break;
case QST_OTHER:
cmbOther.SelectData(pCol->other);
break;
}
}
void FillTableLine(int item, ColumnItem *pColumn)
{
m_list.SetItemText(item, 1, pColumn->title);
switch (pColumn->setting_type) {
case QST_SETTING:
m_list.SetItemText(item, 2, _A2T(pColumn->module));
m_list.SetItemText(item, 3, _A2T(pColumn->setting));
break;
case QST_SCRIPT:
m_list.SetItemText(item, 2, TranslateT("Script"));
break;
case QST_SERVICE:
m_list.SetItemText(item, 2, TranslateT("Service"));
m_list.SetItemText(item, 3, _A2T(pColumn->svc.service));
break;
case QST_CONTACTINFO:
m_list.SetItemText(item, 2, TranslateT("Contact info"));
m_list.SetItemText(item, 3, cnf2str(pColumn->cnftype));
break;
case QST_OTHER:
m_list.SetItemText(item, 2, TranslateT("Other"));
if (pColumn->other == QSTO_METACONTACT)
m_list.SetItemText(item, 3, TranslateT("Metacontact"));
break;
}
}
void InitScreen()
{
// setting
cmbDataType.SetCurSel(0);
editModule.SetText(L"");
editSetting.SetText(L"");
// contact info
cmbCnfType.SetCurSel(0);
// others
cmbOther.SetCurSel(0);
}
void ResizeControl(int id, int width)
{
HWND hwnd = GetDlgItem(m_hwnd, id);
RECT rc;
::GetWindowRect(hwnd, &rc);
::SetWindowPos(hwnd, 0, 0, 0, width, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
void SetupScreen(int type)
{
if (!IsWindowVisible(GetDlgItem(m_hwnd, IDC_E_TITLE)))
return;
// setting
int cmd = (type == QST_SETTING) ? SW_SHOW : SW_HIDE;
ShowWindow(GetDlgItem(m_hwnd, IDC_S_DATATYPE), cmd);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_DATATYPE), cmd);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_MODULE), cmd);
editModule.Show(cmd == SW_SHOW);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_SETTING), cmd);
editSetting.Show(cmd == SW_SHOW);
// contact info
cmd = (type == QST_CONTACTINFO) ? SW_SHOW : SW_HIDE;
ShowWindow(GetDlgItem(m_hwnd, IDC_S_CNFTYPE), cmd);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_CNFTYPE), cmd);
// script
cmd = (type == QST_SCRIPT) ? SW_SHOW : SW_HIDE;
ShowWindow(GetDlgItem(m_hwnd, IDC_E_SCRIPT), cmd);
// others
cmd = (type == QST_OTHER) ? SW_SHOW : SW_HIDE;
ShowWindow(GetDlgItem(m_hwnd, IDC_C_OTHER), cmd);
}
void UpdateList()
{
m_list.DeleteAllItems();
int cnt = 0;
for (auto &it : m_columns) {
AddColumn(cnt, it);
FillTableLine(cnt, it);
m_list.SetCheckState(cnt, it->bEnabled);
cnt++;
}
m_list.SetCurSel(0);
}
CCtrlEdit editTitle, editModule, editSetting;
CCtrlCheck chkSortStatus, chkAutoClose, chkUseToolstyle, chkDrawGrid, chkSavePattern, chkClientIcons;
CCtrlCombo cmbVarType, cmbDataType, cmbOther, cmbCnfType;
CCtrlListView m_list;
CCtrlButton btnSave, btnResize;
CCtrlMButton btnNew, btnUp, btnDown, btnDelete, btnDefault, btnReload;
public:
COptionsDlg() :
CDlgBase(g_plugin, IDD_OPTIONS),
m_columns(1),
m_list(this, IDC_LIST),
btnSave(this, IDC_SETITEM),
btnResize(this, IDC_B_RESIZE),
btnUp(this, IDC_UP, g_plugin.getIcon(IDI_UP), LPGEN("Up")),
btnNew(this, IDC_NEW, g_plugin.getIcon(IDI_NEW), LPGEN("New")),
btnDown(this, IDC_DN, g_plugin.getIcon(IDI_DOWN), LPGEN("Down")),
btnDelete(this, IDC_DELETE, g_plugin.getIcon(IDI_DELETE), LPGEN("Delete")),
btnReload(this, IDC_RELOAD, g_plugin.getIcon(IDI_RELOAD), LPGEN("Reload")),
btnDefault(this, IDC_DEFAULT, g_plugin.getIcon(IDI_DEFAULT), LPGEN("Default")),
editTitle(this, IDC_E_TITLE),
editModule(this, IDC_E_MODULE),
editSetting(this, IDC_E_SETTING),
cmbOther(this, IDC_C_OTHER),
cmbCnfType(this, IDC_C_CNFTYPE),
cmbVarType(this, IDC_C_VARTYPE),
cmbDataType(this, IDC_C_DATATYPE),
chkDrawGrid(this, IDC_CH_DRAWGRID),
chkAutoClose(this, IDC_CH_AUTOCLOSE),
chkSortStatus(this, IDC_CH_SORTSTATUS),
chkSavePattern(this, IDC_CH_SAVEPATTERN),
chkClientIcons(this, IDC_CH_CLIENTICONS),
chkUseToolstyle(this, IDC_CH_USETOOLSTYLE)
{
m_list.OnItemChanged = Callback(this, &COptionsDlg::onItemChanged_List);
btnUp.OnClick = Callback(this, &COptionsDlg::onClick_Up);
btnNew.OnClick = Callback(this, &COptionsDlg::onClick_New);
btnDown.OnClick = Callback(this, &COptionsDlg::onClick_Down);
btnSave.OnClick = Callback(this, &COptionsDlg::onClick_Save);
btnDelete.OnClick = Callback(this, &COptionsDlg::onClick_Delete);
btnReload.OnClick = Callback(this, &COptionsDlg::onClick_Reload);
btnResize.OnClick = Callback(this, &COptionsDlg::onClick_Resize);
btnDefault.OnClick = Callback(this, &COptionsDlg::onClick_Default);
cmbVarType.OnSelChanged = Callback(this, &COptionsDlg::onSelChanged_Var);
}
bool OnInitDialog() override
{
editTitle.SetSilent(); editModule.SetSilent(); editSetting.SetSilent();
cmbOther.SetSilent(); cmbCnfType.SetSilent(); cmbVarType.SetSilent(); cmbDataType.SetSilent();
m_list.SetExtendedListViewStyle(m_list.GetExtendedListViewStyle() | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
m_list.AddColumn(0, L"#", 20);
m_list.AddColumn(1, TranslateT("Title"), g_plugin.getWord("col1", 95));
m_list.AddColumn(2, TranslateT("Module/Info type"), g_plugin.getWord("col2", 105));
m_list.AddColumn(3, TranslateT("Setting"), g_plugin.getWord("col3", 85));
cmbVarType.AddString(TranslateT("Database setting"), QST_SETTING);
cmbVarType.AddString(TranslateT("Script"), QST_SCRIPT);
cmbVarType.AddString(TranslateT("Contact info"), QST_CONTACTINFO);
cmbVarType.AddString(TranslateT("Other"), QST_OTHER);
cmbVarType.SetCurSel(0);
cmbDataType.AddString(TranslateT("Byte"), QSTS_BYTE);
cmbDataType.AddString(TranslateT("Word"), QSTS_WORD);
cmbDataType.AddString(TranslateT("Dword"), QSTS_DWORD);
cmbDataType.AddString(TranslateT("Signed"), QSTS_SIGNED);
cmbDataType.AddString(TranslateT("Hexadecimal"), QSTS_HEXNUM);
cmbDataType.AddString(TranslateT("String"), QSTS_STRING);
cmbDataType.AddString(TranslateT("Timestamp"), QSTS_TIMESTAMP);
cmbDataType.SetCurSel(0);
cmbOther.AddString(TranslateT("Last seen"), QSTO_LASTSEEN);
cmbOther.AddString(TranslateT("Last event"), QSTO_LASTEVENT);
cmbOther.AddString(TranslateT("Metacontact"), QSTO_METACONTACT);
cmbOther.AddString(TranslateT("Event count"), QSTO_EVENTCOUNT);
cmbOther.AddString(TranslateT("Display name"), QSTO_DISPLAYNAME);
cmbOther.AddString(TranslateT("Account name"), QSTO_ACCOUNT);
cmbOther.SetCurSel(0);
for (int i = CNF_FIRSTNAME; i < CNF_MAX; i++)
if (auto *pwszText = cnf2str(i))
cmbCnfType.AddString(pwszText, i);
cmbCnfType.SetCurSel(0);
chkDrawGrid.SetState((g_plugin.m_flags & QSO_DRAWGRID) != 0);
chkAutoClose.SetState((g_plugin.m_flags & QSO_AUTOCLOSE) != 0);
chkSortStatus.SetState((g_plugin.m_flags & QSO_SORTBYSTATUS) != 0);
chkClientIcons.SetState((g_plugin.m_flags & QSO_CLIENTICONS) != 0);
chkSavePattern.SetState((g_plugin.m_flags & QSO_SAVEPATTERN) != 0);
chkUseToolstyle.SetState((g_plugin.m_flags & QSO_TOOLSTYLE) != 0);
// make local copy of column descriptions
for (auto &it : g_plugin.m_columns)
m_columns.insert(new ColumnItem(*it));
UpdateList();
onClick_Resize(0);
if (m_columns.getCount())
DisplayCurInfo(&m_columns[0]);
return true;
}
bool OnApply() override
{
// checkboxes
g_plugin.m_flags &= ~QSO_MAINOPTIONS;
if (chkDrawGrid.IsChecked()) g_plugin.m_flags |= QSO_DRAWGRID;
if (chkAutoClose.IsChecked()) g_plugin.m_flags |= QSO_AUTOCLOSE;
if (chkSortStatus.IsChecked()) g_plugin.m_flags |= QSO_SORTBYSTATUS;
if (chkClientIcons.IsChecked()) g_plugin.m_flags |= QSO_CLIENTICONS;
if (chkSavePattern.IsChecked()) g_plugin.m_flags |= QSO_SAVEPATTERN;
if (chkUseToolstyle.IsChecked()) g_plugin.m_flags |= QSO_TOOLSTYLE;
int tmpbool = CloseSrWindow(false);
g_plugin.m_columns.destroy();
int nCount = m_list.GetItemCount();
for (int i = 0; i < nCount; i++) {
auto *pCol = (ColumnItem *)m_list.GetItemData(i);
pCol->bEnabled = m_list.GetCheckState(i) != 0;
g_plugin.m_columns.insert(new ColumnItem(*pCol));
}
g_plugin.SaveOptions();
if (tmpbool)
OpenSrWindow(0);
return true;
}
void OnDestroy() override
{
m_columns.destroy();
g_plugin.setWord("col1", m_list.GetColumnWidth(1));
g_plugin.setWord("col2", m_list.GetColumnWidth(2));
g_plugin.setWord("col3", m_list.GetColumnWidth(3));
}
void onClick_New(CCtrlButton *)
{
int idx = m_list.GetSelectionMark()+1;
auto *pNew = new ColumnItem(TranslateT("New column"));
m_columns.insert(pNew);
AddColumn(idx, pNew);
m_list.EnsureVisible(idx, FALSE);
m_list.SetCurSel(idx);
InitScreen();
CheckDirection(idx);
btnDelete.Enable();
NotifyChange();
}
void onClick_Delete(CCtrlButton *)
{
int idx = m_list.GetSelectionMark();
auto *pCol = (ColumnItem *)m_list.GetItemData(idx);
m_list.DeleteItem(idx);
m_columns.remove(pCol);
int nCount = m_list.GetItemCount();
if (nCount == 0) {
m_list.Disable();
InitScreen();
}
else {
if (nCount == idx)
idx--;
m_list.SetCurSel(idx);
}
CheckDirection(idx);
NotifyChange();
}
void onClick_Up(CCtrlButton *)
{
int idx = m_list.GetSelectionMark();
if (idx > 0) {
CheckDirection(m_list.MoveItem(idx, -1));
NotifyChange();
}
}
void onClick_Down(CCtrlButton *)
{
int idx = m_list.GetSelectionMark();
if (idx < m_list.GetItemCount() - 1) {
CheckDirection(m_list.MoveItem(idx, 1));
NotifyChange();
}
}
void onClick_Reload(CCtrlButton *)
{
g_plugin.LoadColumns(m_columns);
UpdateList();
}
void onClick_Default(CCtrlButton *)
{
LoadDefaultColumns(m_columns);
UpdateList();
NotifyChange();
}
void onClick_Save(CCtrlButton *)
{
if (m_list.GetItemCount() == 0) {
AddColumn(0, new ColumnItem(TranslateT("New column")));
m_list.SetCurSel(0);
btnDelete.Enable();
}
int idx = m_list.GetSelectionMark();
auto *pCol = (ColumnItem *)m_list.GetItemData(idx);
pCol->dwFlags = 0;
if (m_list.GetCheckState(idx))
pCol->bEnabled = pCol->bFilter = true;
pCol->setting_type = cmbVarType.GetItemData(cmbVarType.GetCurSel());
replaceStrW(pCol->title, editTitle.GetText());
switch (pCol->setting_type) {
case QST_SETTING:
pCol->datatype = cmbDataType.GetItemData(cmbDataType.GetCurSel());
pCol->module = mir_u2a(ptrW(editModule.GetText()));
pCol->setting = mir_u2a(ptrW(editSetting.GetText()));
break;
case QST_CONTACTINFO:
pCol->cnftype = cmbCnfType.GetItemData(cmbCnfType.GetCurSel());
break;
case QST_OTHER:
pCol->other = cmbCnfType.GetItemData(cmbCnfType.GetCurSel());
break;
}
FillTableLine(idx, pCol);
NotifyChange();
}
void onClick_Resize(CCtrlButton *)
{
wchar_t *pcw;
int dx, rside;
RECT rc, rc1;
GetClientRect(m_hwnd, &rc);
GetWindowRect(btnResize.GetHwnd(), &rc1);
POINT pt = { rc1.left, 0 };
ScreenToClient(m_hwnd, &pt);
if (pt.x < (rc.right - 50)) {
rside = SW_HIDE;
dx = rc.right - (rc1.right - rc1.left) - 4;
pcw = L"<";
}
else {
rside = SW_SHOW;
GetWindowRect(GetDlgItem(m_hwnd, IDC_S_COLSETTING), &rc);
pt.x = rc.left;
pt.y = 0;
ScreenToClient(m_hwnd, &pt);
dx = pt.x - (rc1.right - rc1.left) - 4;
pcw = L">";
}
btnResize.SetText(pcw);
// move separator button
SetWindowPos(btnResize.GetHwnd(), 0, dx + 2, 2, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
// resize left side controls
ResizeControl(IDC_LIST, dx);
ResizeControl(IDC_CH_GROUP, dx);
ResizeControl(IDC_CH_USETOOLSTYLE, dx - 8);
ResizeControl(IDC_CH_DRAWGRID, dx - 8);
ResizeControl(IDC_CH_SAVEPATTERN, dx - 8);
ResizeControl(IDC_CH_AUTOCLOSE, dx - 8);
ResizeControl(IDC_CH_SORTSTATUS, dx - 8);
ResizeControl(IDC_CH_CLIENTICONS, dx - 8);
// show/hide setting block (ugly, i know!)
ShowWindow(GetDlgItem(m_hwnd, IDC_S_COLSETTING), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_LINE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_TITLE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_E_TITLE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_E_SCRIPT), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_E_MODULE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_E_SETTING), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_S_VARTYPE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_VARTYPE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_OTHER), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_CNFTYPE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_C_DATATYPE), rside);
ShowWindow(GetDlgItem(m_hwnd, IDC_SETITEM), rside);
ClearScreen();
if (rside == SW_SHOW)
SetupScreen(cmbVarType.GetItemData(cmbVarType.GetCurSel()));
}
void onItemChanged_List(CCtrlListView::TEventInfo *ev)
{
auto *nmlv = ev->nmlv;
// we got new focus
if ((nmlv->uOldState & LVNI_FOCUSED) < (nmlv->uNewState & LVNI_FOCUSED)) {
CheckDirection(nmlv->iItem);
InitScreen();
DisplayCurInfo((ColumnItem*)nmlv->lParam);
}
}
void onSelChanged_Var(CCtrlCombo *pCombo)
{
SetupScreen(pCombo->GetItemData(pCombo->GetCurSel()));
}
};
int OnOptInit(WPARAM wParam, LPARAM)
{
OPTIONSDIALOGPAGE odp = {};
odp.flags = ODPF_BOLDGROUPS;
odp.szGroup.a = LPGEN("Contacts");
odp.szTitle.a = LPGEN("Quick Search");
odp.position = 900003000;
odp.pDialog = new COptionsDlg();
g_plugin.addOptions(wParam, &odp);
return 0;
}