From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/modules/srfile/ftmanager.cpp | 592 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 592 insertions(+) create mode 100644 src/modules/srfile/ftmanager.cpp (limited to 'src/modules/srfile/ftmanager.cpp') diff --git a/src/modules/srfile/ftmanager.cpp b/src/modules/srfile/ftmanager.cpp new file mode 100644 index 0000000000..a219d2188a --- /dev/null +++ b/src/modules/srfile/ftmanager.cpp @@ -0,0 +1,592 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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; either version 2 +of the License, or (at your option) any later version. + +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, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" +#include "file.h" + +static HWND hwndFtMgr = NULL; + +struct TFtMgrData +{ + HWND hwndIncoming; + HWND hwndOutgoing; + + HANDLE hhkPreshutdown; + TBPFLAG errorState; +}; + + +#define M_CALCPROGRESS (WM_USER + 200) +struct TFtProgressData +{ + unsigned int init, run, scan; + unsigned __int64 totalBytes, totalProgress; +}; + +struct TLayoutWindowInfo +{ + HWND hwnd; + RECT rc; +}; + +struct TLayoutWindowList +{ + struct TLayoutWindowInfo **items; + int realCount, limit, increment; + FSortFunc sortFunc; +}; + +struct TFtPageData +{ + struct TLayoutWindowList *wnds; + int runningCount; + int height, dataHeight, scrollPos; +}; + +static void LayoutTransfers(HWND hwnd, struct TFtPageData *dat) +{ + int top = 0; + RECT rc; + GetClientRect(hwnd, &rc); + + dat->scrollPos = GetScrollPos(hwnd, SB_VERT); + dat->height = rc.bottom - rc.top; + + if (dat->wnds->realCount) + { + int i; + HDWP hdwp; + + hdwp = BeginDeferWindowPos(dat->wnds->realCount); + top -= dat->scrollPos; + for (i = 0; i < dat->wnds->realCount; ++i) + { + int height = dat->wnds->items[i]->rc.bottom - dat->wnds->items[i]->rc.top; + hdwp = DeferWindowPos(hdwp, dat->wnds->items[i]->hwnd, NULL, 0, top, rc.right, height, SWP_NOZORDER); + top += height; + } + top += dat->scrollPos; + EndDeferWindowPos(hdwp); + } + + dat->dataHeight = top; + + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_DISABLENOSCROLL|SIF_PAGE|SIF_RANGE; + si.nPage = dat->height; + si.nMin = 0; + si.nMax = dat->dataHeight; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + } +} + +static INT_PTR CALLBACK FtMgrPageDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct TFtPageData *dat = (struct TFtPageData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (msg) + { + case WM_INITDIALOG: + { + // Force scrollbar visibility + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_DISABLENOSCROLL; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + + dat = (struct TFtPageData *)mir_alloc(sizeof(struct TFtPageData)); + dat->wnds = (struct TLayoutWindowList *)List_Create(0, 1); + dat->scrollPos = 0; + dat->runningCount = 0; + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); + break; + } + + case WM_FT_ADD: + { + struct TLayoutWindowInfo *wnd = (struct TLayoutWindowInfo *)mir_alloc(sizeof(struct TLayoutWindowInfo)); + wnd->hwnd = (HWND)lParam; + GetWindowRect(wnd->hwnd, &wnd->rc); + List_Insert((SortedList *)dat->wnds, wnd, dat->wnds->realCount); + LayoutTransfers(hwnd, dat); + dat->runningCount++; + PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL); + break; + } + + case WM_FT_RESIZE: + { + int i; + for (i = 0; i < dat->wnds->realCount; ++i) + if (dat->wnds->items[i]->hwnd == (HWND)lParam) + { + GetWindowRect(dat->wnds->items[i]->hwnd, &dat->wnds->items[i]->rc); + break; + } + LayoutTransfers(hwnd, dat); + break; + } + + case WM_FT_REMOVE: + { + int i; + for (i = 0; i < dat->wnds->realCount; ++i) + if (dat->wnds->items[i]->hwnd == (HWND)lParam) + { + mir_free(dat->wnds->items[i]); + List_Remove((SortedList *)dat->wnds, i); + break; + } + LayoutTransfers(hwnd, dat); + break; + } + + case WM_FT_COMPLETED: + { //wParam: { ACKRESULT_SUCCESS | ACKRESULT_FAILED | ACKRESULT_DENIED } + dat->runningCount--; + int i = 0; + while (i < dat->wnds->realCount) + { + // no error when canceling (WM_FT_REMOVE is send first, check if hwnd is still registered) + if (dat->wnds->items[i]->hwnd == (HWND)lParam) + { + SendMessage(GetParent(hwnd), WM_TIMER, 1, (LPARAM)wParam); + break; + } + ++i; + } + if (i == dat->wnds->realCount) + PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL); + + if(dat->runningCount == 0 && (int)wParam == ACKRESULT_SUCCESS && DBGetContactSettingByte(NULL,"SRFile","AutoClose",0)) + ShowWindow(hwndFtMgr, SW_HIDE); + break; + } + + case WM_FT_CLEANUP: + { + int i; + for (i = 0; i < dat->wnds->realCount; ++i) + SendMessage(dat->wnds->items[i]->hwnd, WM_FT_CLEANUP, wParam, lParam); + break; + } + + case WM_SIZE: + { + LayoutTransfers(hwnd, dat); + break; + } + + case WM_MOUSEWHEEL: + { + int zDelta = GET_WHEEL_DELTA_WPARAM(wParam); + if (zDelta) + { + int i, nScrollLines = 0; + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, (void*)&nScrollLines, 0); + for (i = 0; i < (nScrollLines + 1) / 2; i++ ) + SendMessage(hwnd, WM_VSCROLL, (zDelta < 0) ? SB_LINEDOWN : SB_LINEUP, 0); + } + + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 0); + return TRUE; + } + + case WM_VSCROLL: + { + int pos = dat->scrollPos; + switch (LOWORD(wParam)) + { + case SB_LINEDOWN: + pos += 15; + break; + case SB_LINEUP: + pos -= 15; + break; + case SB_PAGEDOWN: + pos += dat->height - 10; + break; + case SB_PAGEUP: + pos -= dat->height - 10; + break; + case SB_THUMBTRACK: + pos = HIWORD(wParam); + break; + } + + if (pos > dat->dataHeight - dat->height) pos = dat->dataHeight - dat->height; + if (pos < 0) pos = 0; + + if (dat->scrollPos != pos) + { + ScrollWindow(hwnd, 0, dat->scrollPos - pos, NULL, NULL); + SetScrollPos(hwnd, SB_VERT, pos, TRUE); + dat->scrollPos = pos; + } + break; + } + + case M_PRESHUTDOWN: + { + int i; + for (i = 0; i < dat->wnds->realCount; ++i) + PostMessage(dat->wnds->items[i]->hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 0); + break; + } + + case WM_DESTROY: + { + int i; + for (i = 0; i < dat->wnds->realCount; ++i) + mir_free(dat->wnds->items[i]); + List_Destroy((SortedList *)dat->wnds); + mir_free(dat->wnds); + mir_free(dat); + break; + } + + case M_CALCPROGRESS: + { + int i; + TFtProgressData * prg = (TFtProgressData *)wParam; + for (i = 0; i < dat->wnds->realCount; ++i) + { + struct FileDlgData *trdat = (struct FileDlgData *)GetWindowLongPtr(dat->wnds->items[i]->hwnd, GWLP_USERDATA); + if (trdat->transferStatus.totalBytes && trdat->fs && !trdat->send && (trdat->transferStatus.totalBytes == trdat->transferStatus.totalProgress)) + { + prg->scan++; + } else if (trdat->transferStatus.totalBytes && trdat->fs) + { // in progress + prg->run++; + prg->totalBytes += trdat->transferStatus.totalBytes; + prg->totalProgress += trdat->transferStatus.totalProgress; + } else if (trdat->fs) + { // starting + prg->init++; + } + + } + } + } + + return FALSE; +} + +static INT_PTR CALLBACK FtMgrDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct TFtMgrData *dat = (struct TFtMgrData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (msg) + { + case WM_INITDIALOG: + { + TCITEM tci = {0}; + HWND hwndTab = GetDlgItem(hwnd, IDC_TABS); + + TranslateDialogDefault(hwnd); + Window_SetIcon_IcoLib(hwnd, SKINICON_EVENT_FILE); + + dat = (struct TFtMgrData *)mir_calloc(sizeof(struct TFtMgrData)); + + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); + + dat->hhkPreshutdown = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwnd, M_PRESHUTDOWN); + + dat->hwndIncoming = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc); + dat->hwndOutgoing = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc); + ShowWindow(dat->hwndIncoming, SW_SHOW); + + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.pszText = TranslateT("Incoming"); + tci.lParam = (LPARAM)dat->hwndIncoming; + TabCtrl_InsertItem(hwndTab, 0, &tci); + tci.pszText = TranslateT("Outgoing"); + tci.lParam = (LPARAM)dat->hwndOutgoing; + TabCtrl_InsertItem(hwndTab, 1, &tci); + + // Utils_RestoreWindowPosition(hwnd, NULL, "SRFile", "FtMgrDlg_"); + SAVEWINDOWPOS swp; + swp.hwnd=hwnd; swp.hContact=NULL; swp.szModule="SRFile"; swp.szNamePrefix="FtMgrDlg_"; + CallService(MS_UTILS_RESTOREWINDOWPOSITION, RWPF_NOACTIVATE, (LPARAM)&swp); + + // Fall through to setup initial placement + } + case WM_SIZE: + { + RECT rc, rcButton; + HDWP hdwp; + HWND hwndTab = GetDlgItem(hwnd, IDC_TABS); + + GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rcButton); + OffsetRect(&rcButton, -rcButton.left, -rcButton.top); + + GetClientRect(hwnd, &rc); + InflateRect(&rc, -6, -6); + + hdwp = BeginDeferWindowPos(3); + + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_CLEAR), NULL, rc.left, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwnd, IDCANCEL), NULL, rc.right-rcButton.right, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE); + + rc.bottom -= rcButton.bottom + 5; + + hdwp = DeferWindowPos(hdwp, hwndTab, NULL, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER); + + EndDeferWindowPos(hdwp); + + GetWindowRect(hwndTab, &rc); + MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2); + TabCtrl_AdjustRect(hwndTab, FALSE, &rc); + InflateRect(&rc, -5, -5); + + hdwp = BeginDeferWindowPos(2); + + hdwp = DeferWindowPos(hdwp, dat->hwndIncoming, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0); + hdwp = DeferWindowPos(hdwp, dat->hwndOutgoing, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0); + + EndDeferWindowPos(hdwp); + + break; + } + + case WM_MOUSEWHEEL: + { + if (IsWindowVisible(dat->hwndIncoming)) SendMessage(dat->hwndIncoming, msg, wParam, lParam); + if (IsWindowVisible(dat->hwndOutgoing)) SendMessage(dat->hwndOutgoing, msg, wParam, lParam); + break; + } + + case WM_FT_SELECTPAGE: + { + TCITEM tci = {0}; + HWND hwndTab = GetDlgItem(hwnd, IDC_TABS); + + if (TabCtrl_GetCurSel(hwndTab) == (int)wParam) break; + + tci.mask = TCIF_PARAM; + + TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci); + ShowWindow((HWND)tci.lParam, SW_HIDE); + + TabCtrl_SetCurSel(hwndTab, wParam); + + TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci); + ShowWindow((HWND)tci.lParam, SW_SHOW); + + break; + } + + case WM_GETMINMAXINFO: + { + LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam; + lpmmi->ptMinTrackSize.x = 300; + lpmmi->ptMinTrackSize.y = 400; + return 0; + } + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDCANCEL: + PostMessage(hwnd, WM_CLOSE , 0, 0); + break; + + case IDC_CLEAR: + PostMessage(dat->hwndIncoming, WM_FT_CLEANUP, 0, 0); + PostMessage(dat->hwndOutgoing, WM_FT_CLEANUP, 0, 0); + break; + } + break; + + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->idFrom) + { + case IDC_TABS: + { + HWND hwndTab = GetDlgItem(hwnd, IDC_TABS); + switch (((LPNMHDR)lParam)->code) + { + case TCN_SELCHANGING: + { + TCITEM tci = {0}; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci); + ShowWindow((HWND)tci.lParam, SW_HIDE); + break; + } + + case TCN_SELCHANGE: + { + TCITEM tci = {0}; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci); + ShowWindow((HWND)tci.lParam, SW_SHOW); + break; + } + } + break; + } + } + break; + } + + case M_PRESHUTDOWN: + SendMessage(dat->hwndIncoming, M_PRESHUTDOWN, 0, 0); + SendMessage(dat->hwndOutgoing, M_PRESHUTDOWN, 0, 0); + DestroyWindow(hwnd); + break; + + case WM_CLOSE: + ShowWindow(hwnd, SW_HIDE); + if (DBGetContactSettingByte(NULL, "SRFile", "AutoClear", 1)) { + PostMessage(dat->hwndIncoming, WM_FT_CLEANUP, 0, 0); + PostMessage(dat->hwndOutgoing, WM_FT_CLEANUP, 0, 0); + } + return TRUE; /* Disable default IDCANCEL notification */ + + case WM_DESTROY: + UnhookEvent(dat->hhkPreshutdown); + Window_FreeIcon_IcoLib(hwnd); + DestroyWindow(dat->hwndIncoming); + DestroyWindow(dat->hwndOutgoing); + mir_free(dat); + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + Utils_SaveWindowPosition(hwnd, NULL, "SRFile", "FtMgrDlg_"); + break; + + case WM_ACTIVATE: + { + dat->errorState = TBPF_NOPROGRESS; + wParam = 1; + } break; + case WM_SHOWWINDOW: + { + if (!wParam) // hiding + { + KillTimer(hwnd, 1); + break; + } + lParam = 0; + } + case WM_TIMER: + { + if (pTaskbarInterface) + { + SetTimer(hwnd, 1, 400, NULL); + if ((lParam == ACKRESULT_FAILED) || (lParam == ACKRESULT_DENIED)) + dat->errorState = TBPF_ERROR; + + TFtProgressData prg = {0}; + SendMessage(dat->hwndIncoming, M_CALCPROGRESS, (WPARAM)&prg, 0); + SendMessage(dat->hwndOutgoing, M_CALCPROGRESS, (WPARAM)&prg, 0); + if (dat->errorState) + { + pTaskbarInterface->SetProgressState(hwnd, dat->errorState); + if (!prg.run) + pTaskbarInterface->SetProgressValue(hwnd, 1, 1); + } else if (prg.run) + { + pTaskbarInterface->SetProgressState(hwnd, TBPF_NORMAL); + } else if (prg.init || prg.scan) + { + pTaskbarInterface->SetProgressState(hwnd, TBPF_INDETERMINATE); + } else { + pTaskbarInterface->SetProgressState(hwnd, TBPF_NOPROGRESS); + KillTimer(hwnd, 1); + } + + if (prg.run) + { + pTaskbarInterface->SetProgressValue(hwnd, prg.totalProgress, prg.totalBytes); + } + + } + } break; + + } + + return FALSE; +} + +HWND FtMgr_Show(bool bForceActivate, bool bFromMenu) +{ + bool bAutoMin = DBGetContactSettingByte(NULL,"SRFile","AutoMin",0) != 0; /* lqbe */ + + bool bJustCreated = (hwndFtMgr == NULL); + if (bJustCreated) + { + hwndFtMgr = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTMGR), NULL, FtMgrDlgProc); + } + if (bFromMenu) /* lqbe */ + { + ShowWindow(hwndFtMgr, SW_RESTORE); + ShowWindow(hwndFtMgr, SW_SHOW); + SetForegroundWindow(hwndFtMgr); + return hwndFtMgr; + } + else if (bAutoMin && bJustCreated) /* lqbe */ + { + ShowWindow(hwndFtMgr, SW_HIDE); + ShowWindow(hwndFtMgr, SW_MINIMIZE); + return hwndFtMgr; + } + else if (bForceActivate) /* lqbe */ + { + ShowWindow(hwndFtMgr, SW_RESTORE); + ShowWindow(hwndFtMgr, SW_SHOWNOACTIVATE); + SetForegroundWindow(hwndFtMgr); + return hwndFtMgr; + } + if (!bJustCreated && IsWindowVisible(hwndFtMgr)) + return hwndFtMgr; + + ShowWindow(hwndFtMgr, bAutoMin ? SW_SHOWMINNOACTIVE : SW_SHOWNOACTIVATE); + return hwndFtMgr; + } + +void FtMgr_Destroy() +{ + if (hwndFtMgr) + DestroyWindow(hwndFtMgr); +} + +void FtMgr_ShowPage(int page) +{ + if (hwndFtMgr) + SendMessage(hwndFtMgr, WM_FT_SELECTPAGE, page, 0); +} + +HWND FtMgr_AddTransfer(FileDlgData *fdd) +{ + bool bForceActivate = fdd->send || !DBGetContactSettingByte(NULL, "SRFile", "AutoAccept", 0); + TFtMgrData *dat = (TFtMgrData*)GetWindowLongPtr(FtMgr_Show(bForceActivate, false), GWLP_USERDATA); + if (dat == NULL) return NULL; + HWND hwndBox = fdd->send ? dat->hwndOutgoing : dat->hwndIncoming; + HWND hwndFt = CreateDialogParam(hMirandaInst, MAKEINTRESOURCE(IDD_FILETRANSFERINFO), hwndBox, DlgProcFileTransfer, (LPARAM)fdd); + ShowWindow(hwndFt, SW_SHOWNA); + SendMessage(hwndBox, WM_FT_ADD, 0, (LPARAM)hwndFt); + FtMgr_ShowPage(fdd->send ? 1 : 0); + return hwndFt; +} \ No newline at end of file -- cgit v1.2.3