source: src/advtabs/Files.hpp @ 345

Revision 345, 10.1 KB checked in by Eoin, 12 years ago (diff)

Minor renaming and attempts to decouple GUI from Torrents.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2007.
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#pragma once
8
9#include "../stdAfx.hpp"
10#include "../global/string_conv.hpp"
11
12#include "../DdxEx.hpp"
13#include "../Halite.hpp"
14
15#include "../HaliteTabPage.hpp"
16#include "../HaliteListManager.hpp"
17#include "../HaliteDialogBase.hpp"
18#include "../HaliteIni.hpp"
19#include "../HaliteListViewCtrl.hpp"
20
21#include "../HaliteUpdateLock.hpp"
22
23struct FileLink
24{
25        FileLink(const boost::filesystem::wpath& b, size_t o=0) :
26                branch(b),
27                filename(L""),
28                order_(o)
29        {}
30
31        FileLink(const wstring& f, size_t o=0) :
32                branch(L""),
33                filename(f),
34                order_(o)
35        {}
36
37        FileLink(const hal::FileDetail& f) :
38                branch(f.branch),
39                filename(f.filename),
40                order_(f.order())
41        {
42//              hal::event().post(shared_ptr<hal::EventDetail>(
43//                      new hal::EventMsg(wformat(L"Con -> %1% - %2%.") % filename % order())));       
44        }
45       
46        bool operator==(const FileLink& f) const
47        {
48                return (branch == f.branch);
49        }
50       
51        bool operator<(const FileLink& f) const
52        {
53                return (branch < f.branch);
54        }
55       
56        enum FileType
57        {
58                folder,
59                file
60        };
61       
62        size_t order() { return order_; }
63       
64        boost::filesystem::wpath branch;
65        wstring filename;
66        unsigned type;
67       
68private:
69        size_t order_;
70};
71
72
73inline bool FileLinkNamesEqual(const FileLink& l, const FileLink& r)
74{
75        return l.filename == r.filename;
76}
77
78inline bool FileLinkNamesLess(const FileLink& l, const FileLink& r)
79{
80        return l.filename < r.filename;
81}
82
83class FileListView :
84        public CHaliteSortListViewCtrl<FileListView, const hal::FileDetail>,
85        public hal::IniBase<FileListView>,
86        private boost::noncopyable
87{
88public:
89        typedef FileListView thisClass;
90        typedef const hal::FileDetail dataClass;
91        typedef CHaliteSortListViewCtrl<thisClass, dataClass> listClass;
92        typedef hal::IniBase<thisClass> iniClass;
93
94        friend class listClass;
95       
96        struct ColumnAdapters
97        {       
98        typedef listClass::ColumnAdapter ColAdapter_t; 
99       
100        struct Size : public ColAdapter_t
101        {
102                virtual int compare(dataClass& l, dataClass& r) { return hal::compare(l.size, r.size); }               
103                virtual std::wstring print(dataClass& dc) 
104                {
105                        return (wformat(L"%1$.2fMB") % 
106                                (static_cast<float>(dc.size)/(1024*1024))).str(); 
107                }               
108        };
109       
110        struct Progress : public ColAdapter_t
111        {
112                virtual int compare(dataClass& l, dataClass& r) { return hal::compare(l.progress, r.progress); }               
113                virtual std::wstring print(dataClass& t) 
114                {
115                        return (wformat(L"%1$.2f%%") % (t.progress*100)).str(); 
116                }               
117        };
118       
119        struct Priority : public ColAdapter_t
120        {
121                virtual int compare(dataClass& l, dataClass& r) { return hal::compare(l.priority, r.priority); }               
122                virtual std::wstring print(dataClass& dc) 
123                {
124                        switch (dc.priority)
125                        {
126                        case 0:
127                                return hal::app().res_wstr(HAL_FILE_PRIORITY_0);
128                        case 1:
129                                return hal::app().res_wstr(HAL_FILE_PRIORITY_1);
130                        case 2:
131                                return hal::app().res_wstr(HAL_FILE_PRIORITY_2);
132                        case 3:
133                                return hal::app().res_wstr(HAL_FILE_PRIORITY_3);
134                        case 4:
135                                return hal::app().res_wstr(HAL_FILE_PRIORITY_4);
136                        case 5:
137                                return hal::app().res_wstr(HAL_FILE_PRIORITY_5);
138                        case 6:
139                                return hal::app().res_wstr(HAL_FILE_PRIORITY_6);
140                        case 7:
141                                return hal::app().res_wstr(HAL_FILE_PRIORITY_7);
142                        default:
143                                return hal::app().res_wstr(HAL_FILE_PRIORITY_0);
144                        }       
145                }               
146        };
147       
148        };
149
150public: 
151        enum { 
152                LISTVIEW_ID_MENU = IDR_FILESLISTVIEW_MENU,
153                LISTVIEW_ID_COLUMNNAMES = HAL_DIALOGFILE_LISTVIEW_ADV,
154                LISTVIEW_ID_COLUMNWIDTHS = 0
155        };
156       
157        BEGIN_MSG_MAP_EX(thisClass)
158                MSG_WM_DESTROY(OnDestroy)
159                COMMAND_RANGE_HANDLER_EX(ID_HAL_FILE_PRIORITY_0, ID_HAL_FILE_PRIORITY_7, OnMenuPriority)
160
161                CHAIN_MSG_MAP(listClass)
162                DEFAULT_REFLECTION_HANDLER()
163        END_MSG_MAP()
164
165        FileListView();
166       
167        void saveSettings()
168        {
169                GetListViewDetails();
170                Save();
171        }
172       
173        HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
174                DWORD dwStyle = 0, DWORD dwExStyle = 0,
175                ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL);
176       
177        bool SubclassWindow(HWND hwnd)
178        {
179                if(!listClass::SubclassWindow(hwnd))
180                        return false;
181               
182                ApplyDetails();         
183                return true;
184        }
185       
186        void OnDestroy()
187        {
188                saveSettings();
189        }
190       
191        void OnMenuPriority(UINT, int, HWND);
192       
193        friend class boost::serialization::access;
194        template<class Archive>
195        void serialize(Archive& ar, const unsigned int version)
196        {
197                ar & boost::serialization::make_nvp("listview", 
198                        boost::serialization::base_object<listClass>(*this));
199        }
200       
201        dataClass CustomItemConversion(LVCompareParam* param, int iSortCol)
202        {                       
203                return focused_->fileDetails()[param->dwItemData];
204        }               
205       
206        void setFocused(const hal::TorrentDetail_ptr& f) { focused_ = f; }
207        const hal::TorrentDetail_ptr focused() { return focused_; }
208
209private:
210        hal::TorrentDetail_ptr focused_;
211};
212
213class FileTreeView :
214        public CWindowImpl<FileTreeView, CTreeViewCtrlEx>,
215        public hal::IniBase<FileTreeView>,
216        private boost::noncopyable
217{
218protected:
219        typedef FileTreeView thisClass;
220        typedef CWindowImpl<thisClass, CTreeViewCtrlEx> treeClass;
221        typedef hal::IniBase<thisClass> iniClass;
222
223        friend class treeClass;
224       
225public: 
226        thisClass() :
227                iniClass("treeviews/advFiles", "FileTreeView"),
228                updateLock_(0)
229        {}
230       
231        BEGIN_MSG_MAP_EX(thisClass)
232                MSG_WM_DESTROY(OnDestroy)
233
234                REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
235                REFLECTED_NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnSelChanged)
236               
237                COMMAND_RANGE_HANDLER_EX(ID_HAL_FILE_PRIORITY_0, ID_HAL_FILE_PRIORITY_7, OnMenuPriority)
238                DEFAULT_REFLECTION_HANDLER()
239        END_MSG_MAP()
240       
241        HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
242                DWORD dwStyle = 0, DWORD dwExStyle = 0,
243                ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL);
244       
245        LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&);
246        void OnMenuPriority(UINT, int, HWND);
247       
248        wpath focused() { return focused_; }
249       
250        void attach(boost::function<void ()> fn) const { selection_.connect(fn); }
251       
252        void signal() { selection_(); }
253       
254        void determineFocused();
255       
256protected:
257        void OnDestroy()
258        {
259        //      saveSettings();
260        }
261       
262        LRESULT OnSelChanged(int, LPNMHDR pnmh, BOOL&);
263       
264        int updateLock_;
265        friend class UpdateLock<thisClass>;     
266        friend class TryUpdateLock<thisClass>; 
267       
268        mutable boost::signal<void ()> selection_;
269        wpath focused_;
270
271private:
272        WTL::CMenu menu_;
273};
274
275template<typename T>
276class TreeViewManager
277{
278public:
279        TreeViewManager(T& t) :
280                tree_(t)
281        {}
282       
283        struct ValidTreeItem
284        {
285                ValidTreeItem() 
286                {}
287
288                ValidTreeItem(CTreeItem& t) :
289                        valid(true),
290                        treeItem(t)
291                {}
292               
293                bool valid;
294                CTreeItem treeItem;
295        };
296       
297        typedef std::map<wpath, ValidTreeItem> MapType;
298       
299        void EnsureValid(wpath p)
300        {               
301                wpath branchPath = p;
302               
303                MapType::iterator i = map_.find(branchPath);           
304                if (i == map_.end())
305                {
306                        CTreeItem ti = tree_.GetRootItem();
307                       
308                        wpath branch;
309                        foreach (wstring b, branchPath)
310                        {
311                                branch /= b;                           
312                                MapType::iterator j = map_.find(branch);
313                               
314                                if (j == map_.end())
315                                {
316                                        CTreeItem tmp = ti.AddTail(b.c_str(), -1);
317                                        ti.Expand();
318                                        ti = tmp;
319                                        map_[branch] = ValidTreeItem(ti);
320                                }
321                                else
322                                {
323                                        (*j).second.valid = true;
324                                        ti = (*j).second.treeItem;
325                                }                               
326                        }
327                }
328                else
329                {
330                        if (!(*i).second.valid)
331                        {
332                                (*i).second.valid = true;
333                                EnsureValid(branchPath.branch_path());
334                        }
335                }
336        }
337       
338        void InvalidateAll()
339        {
340                for(MapType::iterator i=map_.begin(), e=map_.end(); i!=e; ++i)
341                {
342                        (*i).second.valid = false;
343                }
344        }
345       
346        void ClearInvalid()
347        {
348                for(MapType::iterator i=map_.begin(), e=map_.end(); i!=e; /**/)
349                {
350                        if ((*i).second.valid)
351                        {
352                                ++i;
353                        }
354                        else
355                        {
356                                (*i).second.treeItem.Delete();
357                                map_.erase(i++);
358                        }
359                }       
360        }
361       
362private:
363        T& tree_;
364        MapType map_;
365};
366
367class FileStatic :
368        public CWindowImpl<FileStatic, CStatic>
369{       
370public:
371        BEGIN_MSG_MAP_EX(FileStatic)
372                REFLECT_NOTIFICATIONS()
373        END_MSG_MAP()
374};
375
376class AdvFilesDialog :
377        public CHalTabPageImpl<AdvFilesDialog>,
378        public CDialogResize<AdvFilesDialog>,
379        public CHaliteDialogBase<AdvFilesDialog>,
380        public CWinDataExchangeEx<AdvFilesDialog>,
381        public hal::IniBase<AdvFilesDialog>,
382        private boost::noncopyable
383{
384protected:
385        typedef AdvFilesDialog thisClass;
386        typedef CHalTabPageImpl<thisClass> baseClass;
387        typedef CDialogResize<thisClass> resizeClass;
388        typedef CHaliteDialogBase<thisClass> dialogBaseClass;
389        typedef hal::IniBase<thisClass> iniClass;
390
391public:
392        enum { IDD = IDD_ADVFILES };
393
394        AdvFilesDialog(HaliteWindow& halWindow) :
395                dialogBaseClass(halWindow),
396                treeManager_(tree_),
397                iniClass("AdvFiles", "AdvFiles"),
398                splitterPos(150)
399        {
400                Load();
401        }
402       
403        ~AdvFilesDialog() { Save(); }
404       
405        BOOL PreTranslateMessage(MSG* pMsg)
406        {
407                return this->IsDialogMessage(pMsg);
408        }
409
410        BEGIN_MSG_MAP_EX(thisClass)
411                MSG_WM_INITDIALOG(onInitDialog)
412                MSG_WM_CLOSE(onClose)
413               
414                if (uMsg == WM_FORWARDMSG)
415                        if (PreTranslateMessage((LPMSG)lParam)) return TRUE;
416               
417                CHAIN_MSG_MAP(dialogBaseClass)
418                CHAIN_MSG_MAP(resizeClass)
419                CHAIN_MSG_MAP(baseClass)
420                REFLECT_NOTIFICATIONS()
421        END_MSG_MAP()
422
423        BEGIN_DLGRESIZE_MAP(thisClass)
424                DLGRESIZE_CONTROL(IDC_CONTAINER, DLSZ_SIZE_X|DLSZ_SIZE_Y|DLSZ_REPAINT)
425        END_DLGRESIZE_MAP()
426
427    friend class boost::serialization::access;
428    template<class Archive>
429    void serialize(Archive& ar, const unsigned int version)
430        {
431                ar & BOOST_SERIALIZATION_NVP(splitterPos);
432        }
433
434        LRESULT onInitDialog(HWND, LPARAM);
435        void onClose();
436       
437        void DlgResize_UpdateLayout(int cxWidth, int cyHeight);
438        void doUiUpdate();
439        void uiUpdate(const hal::TorrentDetails& tD);
440        void focusChanged(const hal::TorrentDetail_ptr pT);
441
442protected:
443        CSplitterWindow splitter_;
444        unsigned int splitterPos;
445       
446        FileStatic static_;
447        FileTreeView tree_;
448        FileListView list_;
449       
450        std::map<wpath, CTreeItem> fileTreeMap_;
451        TreeViewManager<FileTreeView> treeManager_;
452       
453        std::vector<FileLink> fileLinks_;
454       
455        hal::FileDetails fileDetails_;
456        std::pair<std::vector<FileLink>::iterator, std::vector<FileLink>::iterator> range_;
457};
Note: See TracBrowser for help on using the repository browser.