source: trunk/src/HaliteWindow.cpp @ 380

Revision 380, 13.1 KB checked in by Eoin, 12 years ago (diff)

Added singaling, fixed UPnP bug.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2008.
3// Distributed under the Boost Software License, Version 1.0.
4//    (See accompanying file LICENSE_1_0.txt or copy at
5//          http://www.boost.org/LICENSE_1_0.txt)
6
7#include <string>
8#include <boost/format.hpp>
9#include <boost/bind.hpp>
10
11#include "stdAfx.hpp"
12#include "Halite.hpp"
13#include "HaliteWindow.hpp"
14
15#include "CSSFileDialog.hpp"
16#include "HaliteDialog.hpp"
17#include "AdvHaliteDialog.hpp"
18#include "AddTorrentDialog.hpp"
19#include "NewTorrentDialog.hpp"
20
21#include "ConfigOptions.hpp"
22#include "halConfig.hpp"
23
24HaliteWindow::HaliteWindow(unsigned areYouMe = 0) :
25        iniClass("HaliteWindow", "HaliteWindow"),
26        haliteList(*this),
27        WM_AreYouMe_(areYouMe),
28        splitterPos(100),
29        use_tray(true),
30        advancedUI(false),
31        closeToTray(false),
32        confirmClose(true),
33        activeTab(0)
34{
35        rect.top = 10;
36        rect.left = 10;
37        rect.bottom = 430;
38        rect.right = 620;
39       
40        load();
41}
42
43HaliteWindow::~HaliteWindow()
44{
45        save();
46        ATLASSERT(!::IsWindow(m_hWnd));
47}
48
49BOOL HaliteWindow::PreTranslateMessage(MSG* pMsg)
50{
51        if(CFrameWindowImpl<HaliteWindow>::PreTranslateMessage(pMsg))
52                return TRUE;
53
54        return mp_dlg->PreTranslateMessage(pMsg);
55}
56
57LRESULT HaliteWindow::OnCreate(LPCREATESTRUCT lpcs)
58{
59        try
60        {
61       
62        SetWindowText(L"Halite");
63        MoveWindow(rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, false);     
64
65
66        hal::event().post(shared_ptr<hal::EventDetail>(
67                new hal::EventMsg(L"Loading Halite config...")));
68        hal::config().load();
69       
70        hal::event().post(shared_ptr<hal::EventDetail>(
71                new hal::EventMsg(L"Applying setting...")));
72        if (!hal::config().settingsChanged())
73        {
74                hal::event().post(boost::shared_ptr<hal::EventDetail>(
75                        new hal::EventDebug(hal::Event::critical, hal::app().res_wstr(HAL_WINDOW_SOCKETS_FAILED))));
76                       
77                MessageBox(hal::app().res_wstr(HAL_WINDOW_SOCKETS_FAILED).c_str(), 0, 0);
78               
79                DestroyWindow();
80                return 0;
81        }
82       
83        hal::event().post(shared_ptr<hal::EventDetail>(
84                new hal::EventMsg(L"Starting GUI...")));
85       
86        RECT rc; GetClientRect(&rc);
87        SetMenu(0);
88       
89        //Init ToolBar
90        HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
91       
92        // Init ReBar
93        CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
94        AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
95       
96        // Init the StatusBar   
97        m_hWndStatusBar = m_StatusBar.Create(*this);
98        UIAddStatusBar(m_hWndStatusBar);
99       
100        int panes[] = {ID_DEFAULT_PANE, IDPANE_FILTER, IDPANE_DHT, IDPANE_STATUS};
101        m_StatusBar.SetPanes(panes, 4, false);
102       
103        // Create the Splitter Control
104        m_Split.Create(m_hWnd, rc, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
105        m_Split.SetSplitterExtendedStyle(!SPLIT_PROPORTIONAL, SPLIT_PROPORTIONAL);
106        m_Split.SetSplitterPos(splitterPos);
107       
108        m_hWndClient = m_Split.m_hWnd;
109
110        hal::event().post(shared_ptr<hal::EventDetail>(
111                new hal::EventMsg(L"Creating main listview...")));     
112        // Create ListView and Dialog
113        haliteList.Create(m_Split.m_hWnd, rc, NULL, 
114                LVS_REPORT|WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|LVS_SHOWSELALWAYS);
115        haliteList.manager().attach(bind(&HaliteWindow::issueUiUpdate, this));
116
117
118        hal::event().post(shared_ptr<hal::EventDetail>(
119                new hal::EventMsg(L"Creating classic dialog...")));             
120        mp_dlg.reset(new HaliteDialog(*this)),
121        mp_dlg->Create(m_Split.m_hWnd);
122//      mp_dlg->ShowWindow(true);
123       
124
125        hal::event().post(shared_ptr<hal::EventDetail>(
126                new hal::EventMsg(L"Creating advanced dialog...")));
127        mp_advDlg.reset(new AdvHaliteDialog(*this));
128        mp_advDlg->Create(m_Split.m_hWnd);
129//      mp_advDlg->ShowWindow(true);
130       
131//      m_Split.SetSplitterPanes(*mp_list, *mp_dlg);
132       
133        hal::event().post(shared_ptr<hal::EventDetail>(
134                new hal::EventMsg(L"Creating tray icon..."))); 
135        // Create the tray icon.
136        trayIcon_.Create(this, IDR_TRAY_MENU, L"Halite", 
137                CTrayNotifyIcon::LoadIconResource(IDR_APP_ICON), WM_TRAYNOTIFY, IDR_TRAY_MENU);
138        trayIcon_.Hide();
139       
140        // Add ToolBar and register it along with StatusBar for UIUpdates
141        UIAddToolBar(hWndToolBar);
142        UISetCheck(ID_VIEW_TOOLBAR, 1);
143        UISetCheck(ID_VIEW_STATUS_BAR, 1);
144        UISetCheck(IDR_TRAY_MENU, 1);
145       
146        // Register UIEvents and the timer for the monitoring interval
147        SetTimer(ID_UPDATE_TIMER, 500);
148        SetTimer(ID_SAVE_TIMER, 5000);
149        connectUiUpdate(bind(&HaliteWindow::updateWindow, this));
150       
151        hal::event().post(shared_ptr<hal::EventDetail>(
152                new hal::EventMsg(L"Registering drop target...")));     
153        RegisterDropTarget();
154       
155        // Register object for message filtering and idle updates
156        CMessageLoop* pLoop = _Module.GetMessageLoop();
157        assert(pLoop != NULL);
158        pLoop->AddMessageFilter(this);
159        pLoop->AddIdleHandler(this);
160       
161//      haliteList.manager().setSelected(0);
162        setCorrectDialog();
163       
164        hal::event().post(shared_ptr<hal::EventDetail>(
165                new hal::EventMsg(L"Starting event reciever...")));
166        hal::bittorrent().startEventReceiver();
167        hal::event().post(shared_ptr<hal::EventDetail>(
168                new hal::EventMsg(L"Initial setup complete!")));
169        issueUiUpdate();
170       
171        }
172        catch(const std::exception& e)
173        {
174                hal::event().post(boost::shared_ptr<hal::EventDetail>(
175                        new hal::EventStdException(hal::Event::critical, e, L"HaliteWindow::OnCreate"))); 
176
177                DestroyWindow();
178        }
179       
180        return 0;
181}
182
183LRESULT HaliteWindow::OnAdvanced(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
184{
185        advancedUI = !advancedUI;
186        setCorrectDialog();
187       
188        return 0;
189}
190
191LRESULT HaliteWindow::OnTrayNotification(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam)
192{
193    trayIcon_.OnTrayNotification(wParam, lParam);
194   
195    return 0;
196}
197
198void HaliteWindow::setCorrectDialog()
199{
200        if (!advancedUI)
201        {               
202                mp_dlg->ShowWindow(SW_SHOW);
203                mp_advDlg->ShowWindow(SW_HIDE);
204                m_Split.SetSplitterPanes(haliteList, *mp_dlg);
205        }
206        else
207        {               
208                mp_dlg->ShowWindow(SW_HIDE);
209                mp_advDlg->ShowWindow(SW_SHOW);
210                m_Split.SetSplitterPanes(haliteList, *mp_advDlg);
211        }
212        ui().update();
213}
214
215void HaliteWindow::updateWindow()
216{
217        try
218        {
219       
220        hal::SessionDetail details = hal::bittorrent().getSessionDetails();
221       
222        if (details.port > -1)
223                UISetText(0, 
224                        (wformat(hal::app().res_wstr(HAL_PORT_OPEN)) % details.port ).str().c_str());   
225        else
226                UISetText(0, hal::app().res_wstr(HAL_NOT_LISTENING).c_str());
227       
228        wstring downloadRates = (wformat(hal::app().res_wstr(HAL_DOWN_RATES)) 
229                        % (details.speed.first/1024) 
230                        % (details.speed.second/1024)).str();
231       
232        UISetText(3, downloadRates.c_str());   
233        trayIcon_.SetTooltipText(downloadRates.c_str());
234       
235        if (details.dht_on)
236        {
237                wstring dht = (wformat(hal::app().res_wstr(HAL_DHT_ON))
238                        % details.dht_nodes).str();
239                       
240                UISetText(2, dht.c_str());
241        }
242        else
243        {
244                UISetText(2, hal::app().res_wstr(HAL_DHT_OFF).c_str());
245        }
246       
247        if (details.ip_filter_on)
248        {
249                wstring filter = (wformat(hal::app().res_wstr(HAL_IPFILTER_ON))
250                        % details.ip_ranges_filtered).str();
251               
252                UISetText(1, filter.c_str());
253        }
254        else
255        {
256                UISetText(1, hal::app().res_wstr(HAL_IPFILTER_OFF).c_str());
257        }
258       
259        }
260        catch (std::exception& e)
261        {
262                hal::event().post(shared_ptr<hal::EventDetail>(\
263                        new hal::EventStdException(hal::Event::info, e, L"updateWindow")));
264        }
265}
266
267void HaliteWindow::OnTimer(UINT uTimerID)
268{               
269        if (uTimerID == ID_UPDATE_TIMER) 
270        {       
271                issueUiUpdate();
272        }
273        else if (uTimerID == ID_SAVE_TIMER) 
274        {
275                try
276                {
277               
278                halite().saveIniData();
279                hal::bittorrent().saveTorrentData();   
280       
281                }
282                catch (std::exception& e)
283                {
284                        hal::event().post(shared_ptr<hal::EventDetail>(\
285                                new hal::EventStdException(hal::Event::info, e, L"saveTimer")));
286                }
287        }
288        else 
289        {               
290                SetMsgHandled(false);
291        }       
292}       
293
294void HaliteWindow::issueUiUpdate()
295{       
296        try
297        {
298       
299        const hal::TorrentDetails& torrents = hal::bittorrent().updateTorrentDetails(
300                haliteList.manager().selected(), haliteList.manager().allSelected());
301
302        ui_update_signal_(torrents);
303
304        }
305        catch (std::exception& e)
306        {
307                hal::event().post(shared_ptr<hal::EventDetail>(
308                        new hal::EventStdException(hal::Event::info, e, L"updateTimer")));
309        }
310}
311
312LRESULT HaliteWindow::OnCopyData(HWND, PCOPYDATASTRUCT pCSD)
313{
314        hal::event().post(shared_ptr<hal::EventDetail>(
315                new hal::EventMsg(L"I recieved data.")));
316               
317        switch (pCSD->dwData)
318        {
319                case HALITE_SENDING_CMD:
320                {       
321                        wstring filename(static_cast<wchar_t*>(pCSD->lpData), pCSD->cbData/sizeof(wchar_t));
322                       
323                        hal::event().post(shared_ptr<hal::EventDetail>(
324                                new hal::EventMsg((wformat(L"Recieved data: %1%.") % filename), hal::Event::info)));
325               
326                        ProcessFile(filename.c_str());
327                        break;
328                }
329                default:
330                        break;
331        }
332        return 0;
333}
334
335void HaliteWindow::ProcessFile(LPCTSTR lpszPath)
336{
337        try
338        {
339       
340        wstring saveDirectory = wpath(hal::config().defaultSaveFolder).native_file_string();
341        bool startPaused = false;
342        bool compactStorage = false;
343       
344        if (!boost::filesystem::exists(saveDirectory))
345                boost::filesystem::create_directory(saveDirectory);
346       
347        if (hal::config().savePrompt)
348        {
349                AddTorrentDialog addTorrent(saveDirectory, startPaused, compactStorage);       
350               
351                if (IDOK != addTorrent.DoModal())
352                        return;
353        }
354       
355        wpath file(lpszPath, boost::filesystem::native);       
356        hal::bittorrent().addTorrent(file, wpath(saveDirectory), startPaused, compactStorage);
357
358        ui().update();
359
360        }
361        catch(const boost::filesystem::filesystem_error&)
362        {
363                hal::event().post(shared_ptr<hal::EventDetail>(
364                        new hal::EventDebug(hal::Event::warning, L"filesystem error")));
365        }
366}
367
368void HaliteWindow::OnClose()
369{
370        if (closeToTray && trayIcon_.IsHidden())
371        {               
372                ShowWindow(SW_MINIMIZE);
373        }
374        else
375        {
376                if (!confirmClose || (confirmClose && 
377                        MessageBox(hal::app().res_wstr(HAL_WINDOW_CLOSECONFRIM).c_str(), 
378                                hal::app().res_wstr(HAL_HALITE).c_str(), MB_YESNO) == IDYES))
379                {
380                        DestroyWindow();
381                }
382        }
383}
384 
385void HaliteWindow::OnDestroy()
386{
387        splitterPos = m_Split.GetSplitterPos();
388
389        hal::config().save();
390        save();
391        PostQuitMessage(0);
392}
393
394void HaliteWindow::OnSize(UINT type, CSize)
395{
396        if (type == SIZE_MINIMIZED)
397        {
398                if (use_tray)
399                {
400                        ShowWindow(SW_HIDE);
401                        trayIcon_.Show();
402                }
403        }
404        else
405        {
406                if (trayIcon_.IsShowing())
407                        trayIcon_.Hide();
408
409                GetWindowRect(rect);
410        }
411       
412        SetMsgHandled(false);
413}       
414
415void HaliteWindow::OnMove(CSize)
416{
417        WINDOWPLACEMENT wnd = { sizeof(WINDOWPLACEMENT ) };
418        GetWindowPlacement(&wnd);
419       
420        if (wnd.showCmd != SW_SHOWMINIMIZED)
421                GetWindowRect(rect);
422
423        SetMsgHandled(false);   
424}
425
426void HaliteWindow::OnShowWindow(BOOL bShow, UINT nStatus)
427{
428        SetMsgHandled(false);
429}
430
431LRESULT HaliteWindow::OnTrayOpenHalite(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
432{
433        trayIcon_.Hide();
434        ShowWindow(SW_RESTORE);
435       
436        return 0;
437}
438
439LRESULT HaliteWindow::OnTrayExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
440{
441        PostMessage(WM_CLOSE, 0, 0);
442       
443        return 0;
444}
445
446LRESULT HaliteWindow::OnFileOpen(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
447{
448        CSSFileDialog dlgOpen(TRUE, NULL, NULL, OFN_HIDEREADONLY, L"Torrents (*.torrent)|*.torrent|", m_hWnd);
449
450        if (dlgOpen.DoModal() == IDOK) 
451        {
452                ProcessFile(dlgOpen.m_ofn.lpstrFile);
453        }
454       
455        return 0;       
456}
457
458LRESULT HaliteWindow::OnFileNew(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
459{
460        NewTorrentDialog newTorrent;   
461    newTorrent.DoModal();
462
463        MessageBox(L"This feature is under development and currently disabled", 
464                L"Feature not availible", 0);
465        return 0;
466       
467        CSSFileDialog dlgOpen(TRUE, NULL, NULL, OFN_HIDEREADONLY, L"All Files|*.*|", m_hWnd);
468
469        if (dlgOpen.DoModal() != IDOK) 
470                return 0;
471       
472        wstring files = dlgOpen.m_ofn.lpstrFile;
473       
474        CSSFileDialog dlgSave(FALSE, NULL, NULL, OFN_HIDEREADONLY, L"Torrents (*.torrent)|*.torrent|", m_hWnd);
475       
476        if (dlgSave.DoModal() != IDOK) 
477                return 0;
478       
479        wstring torrent_filename = dlgSave.m_ofn.lpstrFile;
480       
481        hal::bittorrent().newTorrent(wpath(torrent_filename), wpath(files));
482       
483        ui().update();
484       
485        return 0;
486}
487
488LRESULT HaliteWindow::OnSettings(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
489{
490        ConfigOptionsProp sheet(this, L"Settings");     
491    sheet.DoModal();
492       
493        hal::config().settingsChanged();
494        setCorrectDialog();
495       
496        return 0;
497}
498
499LRESULT HaliteWindow::OnPauseAll(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
500{
501        hal::bittorrent().pauseAllTorrents();
502       
503        ui().update();
504        return 0;
505}
506
507LRESULT HaliteWindow::OnResumeAll(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
508{
509        hal::bittorrent().unpauseAllTorrents();
510       
511        ui().update();
512        return 0;
513}
514
515LRESULT HaliteWindow::OnHelp(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
516{
517        ConfigOptionsProp sheet(this, L"Settings", 4); 
518    sheet.DoModal();
519       
520        hal::config().settingsChanged();
521       
522        return 0;
523}
524
525LRESULT HaliteWindow::OnViewStatusBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
526{
527        BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
528        ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
529        UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
530       
531        UpdateLayout();
532       
533        return 0;
534}       
535
536LRESULT HaliteWindow::OnEraseBkgnd(HDC dc)
537{
538        return 1;
539}
540
541LRESULT HaliteWindow::OnPaint(HDC dc)
542{
543        return 1;
544}
545
546LRESULT HaliteWindow::OnAreYouMe(UINT, WPARAM, LPARAM, BOOL&) 
547{
548        hal::event().post(shared_ptr<hal::EventDetail>(
549                new hal::EventMsg(L"I tried to contact me.")));         
550
551        return WM_AreYouMe_; 
552}
Note: See TracBrowser for help on using the repository browser.