source: filezilla/trunk/fuentes/src/interface/filter_conditions_dialog.cpp @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 2 years ago

Update new version: 3.15.02

File size: 22.1 KB
Line 
1#include <filezilla.h>
2#include "filter_conditions_dialog.h"
3#include "customheightlistctrl.h"
4#include "textctrlex.h"
5
6static wxArrayString stringConditionTypes;
7static wxArrayString sizeConditionTypes;
8static wxArrayString attributeConditionTypes;
9static wxArrayString permissionConditionTypes;
10static wxArrayString attributeSetTypes;
11static wxArrayString dateConditionTypes;
12
13static wxChoice* CreateChoice(wxWindow* parent, wxPoint pos, const wxArrayString& items, wxSize const& size = wxDefaultSize)
14{
15#ifdef __WXGTK__
16        // Really obscure bug in wxGTK: If creating in a single step,
17        // first item in the choice sometimes looks disabled
18        // even though it can still be selected and returns to looking
19        // normal after hovering mouse over it.
20        // This works around it nicely.
21        wxChoice *ret( new wxChoice );
22        ret->Create(parent, wxID_ANY, pos, size);
23        ret->Append(items);
24        ret->InvalidateBestSize();
25        ret->SetInitialSize();
26        return ret;
27#else
28        return new wxChoice(parent, wxID_ANY, pos, size, items);
29#endif
30}
31
32CFilterControls::CFilterControls()
33{
34        pType = 0;
35        pCondition = 0;
36        pValue = 0;
37        pSet = 0;
38        pLabel = 0;
39        pRemove = 0;
40}
41
42void CFilterControls::Reset()
43{
44        delete pType;
45        delete pCondition;
46        delete pValue;
47        delete pSet;
48        delete pLabel;
49        delete pRemove;
50
51        pType = 0;
52        pCondition = 0;
53        pValue = 0;
54        pSet = 0;
55        pLabel = 0;
56        pRemove = 0;
57}
58
59BEGIN_EVENT_TABLE(CFilterConditionsDialog, wxDialogEx)
60EVT_BUTTON(wxID_ANY, CFilterConditionsDialog::OnButton)
61EVT_CHOICE(wxID_ANY, CFilterConditionsDialog::OnFilterTypeChange)
62EVT_LISTBOX(wxID_ANY, CFilterConditionsDialog::OnConditionSelectionChange)
63EVT_NAVIGATION_KEY(CFilterConditionsDialog::OnNavigationKeyEvent)
64END_EVENT_TABLE()
65
66CFilterConditionsDialog::CFilterConditionsDialog()
67{
68        m_choiceBoxHeight = 0;
69        m_pListCtrl = 0;
70        m_has_foreign_type = false;
71        m_pAdd = 0;
72        m_button_size = wxSize(-1, -1);
73}
74
75bool CFilterConditionsDialog::CreateListControl(int conditions /*=common*/)
76{
77        wxScrolledWindow* wnd = XRCCTRL(*this, "ID_CONDITIONS", wxScrolledWindow);
78        if (!wnd)
79                return false;
80
81        m_pListCtrl = new wxCustomHeightListCtrl(this, wxID_ANY, wxDefaultPosition, wnd->GetSize(), wxVSCROLL|wxSUNKEN_BORDER|wxTAB_TRAVERSAL);
82        if (!m_pListCtrl)
83                return false;
84        m_pListCtrl->AllowSelection(false);
85        ReplaceControl(wnd, m_pListCtrl);
86        CalcMinListWidth();
87
88        if (stringConditionTypes.empty())
89        {
90                stringConditionTypes.Add(_("contains"));
91                stringConditionTypes.Add(_("is equal to"));
92                stringConditionTypes.Add(_("begins with"));
93                stringConditionTypes.Add(_("ends with"));
94                stringConditionTypes.Add(_("matches regex"));
95                stringConditionTypes.Add(_("does not contain"));
96
97                sizeConditionTypes.Add(_("greater than"));
98                sizeConditionTypes.Add(_("equals"));
99                sizeConditionTypes.Add(_("does not equal"));
100                sizeConditionTypes.Add(_("less than"));
101
102                attributeSetTypes.Add(_("is set"));
103                attributeSetTypes.Add(_("is unset"));
104
105                attributeConditionTypes.Add(_("Archive"));
106                attributeConditionTypes.Add(_("Compressed"));
107                attributeConditionTypes.Add(_("Encrypted"));
108                attributeConditionTypes.Add(_("Hidden"));
109                attributeConditionTypes.Add(_("Read-only"));
110                attributeConditionTypes.Add(_("System"));
111
112                permissionConditionTypes.Add(_("owner readable"));
113                permissionConditionTypes.Add(_("owner writeable"));
114                permissionConditionTypes.Add(_("owner executable"));
115                permissionConditionTypes.Add(_("group readable"));
116                permissionConditionTypes.Add(_("group writeable"));
117                permissionConditionTypes.Add(_("group executable"));
118                permissionConditionTypes.Add(_("world readable"));
119                permissionConditionTypes.Add(_("world writeable"));
120                permissionConditionTypes.Add(_("world executable"));
121
122                dateConditionTypes.Add(_("before"));
123                dateConditionTypes.Add(_("equals"));
124                dateConditionTypes.Add(_("does not equal"));
125                dateConditionTypes.Add(_("after"));
126        }
127
128        if (conditions & filter_name)
129        {
130                filterTypes.Add(_("Filename"));
131                filter_type_map.push_back(filter_name);
132        }
133        if (conditions & filter_size)
134        {
135                filterTypes.Add(_("Filesize"));
136                filter_type_map.push_back(filter_size);
137        }
138        if (conditions & filter_attributes)
139        {
140                filterTypes.Add(_("Attribute"));
141                filter_type_map.push_back(filter_attributes);
142        }
143        if (conditions & filter_permissions)
144        {
145                filterTypes.Add(_("Permission"));
146                filter_type_map.push_back(filter_permissions);
147        }
148        if (conditions & filter_path)
149        {
150                filterTypes.Add(_("Path"));
151                filter_type_map.push_back(filter_path);
152        }
153        if (conditions & filter_date)
154        {
155                filterTypes.Add(_("Date"));
156                filter_type_map.push_back(filter_date);
157        }
158
159        SetFilterCtrlState(true);
160
161        m_pListCtrl->Connect(wxEVT_SIZE, wxSizeEventHandler(CFilterConditionsDialog::OnListSize), 0, this);
162
163        m_pListCtrl->MoveAfterInTabOrder(XRCCTRL(*this, "ID_MATCHTYPE", wxChoice));
164
165        return true;
166}
167
168void CFilterConditionsDialog::CalcMinListWidth()
169{
170        wxChoice *pType = new wxChoice(m_pListCtrl, wxID_ANY, wxDefaultPosition, wxDefaultSize, filterTypes);
171        int requiredWidth = pType->GetBestSize().GetWidth();
172        pType->Destroy();
173
174        wxChoice *pStringCondition = new wxChoice(m_pListCtrl, wxID_ANY, wxDefaultPosition, wxDefaultSize, stringConditionTypes);
175        wxChoice *pSizeCondition = new wxChoice(m_pListCtrl, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizeConditionTypes);
176        wxStaticText *pSizeLabel = new wxStaticText(m_pListCtrl, wxID_ANY, _("bytes"));
177        wxChoice *pDateCondition = new wxChoice(m_pListCtrl, wxID_ANY, wxDefaultPosition, wxDefaultSize, dateConditionTypes);
178
179        int w = wxMax(pStringCondition->GetBestSize().GetWidth(), pSizeCondition->GetBestSize().GetWidth() + 5 + pSizeLabel->GetBestSize().GetWidth());
180        w = wxMax(w, pDateCondition->GetBestSize().GetWidth());
181        requiredWidth += w;
182
183        m_size_label_size = pSizeLabel->GetBestSize();
184
185        pStringCondition->Destroy();
186        pSizeCondition->Destroy();
187        pSizeLabel->Destroy();
188        pDateCondition->Destroy();
189
190        requiredWidth += m_pListCtrl->GetWindowBorderSize().x;
191        requiredWidth += 40;
192        requiredWidth += 120;
193        wxSize minSize = m_pListCtrl->GetMinSize();
194        minSize.IncTo(wxSize(requiredWidth, -1));
195        m_pListCtrl->SetMinSize(minSize);
196
197        m_lastListSize = m_pListCtrl->GetClientSize();
198}
199
200t_filterType CFilterConditionsDialog::GetTypeFromTypeSelection(int selection)
201{
202        if (selection < 0 || selection > (int)filter_type_map.size())
203                selection = 0;
204
205        return filter_type_map[selection];
206}
207
208void CFilterConditionsDialog::SetSelectionFromType(wxChoice* pChoice, t_filterType type)
209{
210        for (unsigned int i = 0; i < filter_type_map.size(); ++i) {
211                if (filter_type_map[i] == type) {
212                        pChoice->SetSelection(i);
213                        return;
214                }
215        }
216
217         pChoice->SetSelection(0);
218}
219
220void CFilterConditionsDialog::OnMore()
221{
222        wxPoint pos = m_pAdd->GetPosition();
223        pos.y += m_choiceBoxHeight + 6;
224        m_pAdd->SetPosition(pos);
225
226        CFilterCondition cond;
227        m_currentFilter.filters.push_back(cond);
228
229        MakeControls(cond);
230
231        CFilterControls& controls = m_filterControls.back();
232        m_pAdd->MoveAfterInTabOrder(controls.pSet ? (wxWindow*)controls.pSet : (wxWindow*)controls.pValue);
233
234        m_pListCtrl->SetLineCount(m_filterControls.size() + 1);
235        UpdateConditionsClientSize();
236}
237
238void CFilterConditionsDialog::OnRemove(int item)
239{
240        std::set<int> selected;
241        selected.insert(item);
242        OnRemove(selected);
243        if (m_filterControls.empty())
244                OnMore();
245}
246
247void CFilterConditionsDialog::OnRemove(const std::set<int> &selected)
248{
249        int delta_y = 0;
250
251        m_pListCtrl->SetLineCount(m_filterControls.size() - selected.size() + 1);
252
253        std::vector<CFilterControls> filterControls = m_filterControls;
254        m_filterControls.clear();
255
256        std::vector<CFilterCondition> filters = m_currentFilter.filters;
257        m_currentFilter.filters.clear();
258
259        for (unsigned int i = 0; i < filterControls.size(); ++i) {
260                CFilterControls& controls = filterControls[i];
261                if (selected.find(i) == selected.end()) {
262                        m_filterControls.push_back(controls);
263                        m_currentFilter.filters.push_back(filters[i]);
264
265                        // Reposition controls
266                        wxPoint pos;
267
268                        pos = controls.pType->GetPosition();
269                        pos.y -= delta_y;
270                        controls.pType->SetPosition(pos);
271
272                        pos = controls.pCondition->GetPosition();
273                        pos.y -= delta_y;
274                        controls.pCondition->SetPosition(pos);
275
276                        if (controls.pValue) {
277                                pos = controls.pValue->GetPosition();
278                                pos.y -= delta_y;
279                                controls.pValue->SetPosition(pos);
280                        }
281                        if (controls.pSet) {
282                                pos = controls.pSet->GetPosition();
283                                pos.y -= delta_y;
284                                controls.pSet->SetPosition(pos);
285                        }
286                        if (controls.pLabel) {
287                                pos = controls.pLabel->GetPosition();
288                                pos.y -= delta_y;
289                                controls.pLabel->SetPosition(pos);
290                        }
291
292                        pos = controls.pRemove->GetPosition();
293                        pos.y -= delta_y;
294                        controls.pRemove->SetPosition(pos);
295                }
296                else {
297                        controls.Reset();
298                        delta_y += m_choiceBoxHeight + 6;
299                }
300        }
301
302        wxPoint pos = m_pAdd->GetPosition();
303        pos.y -= delta_y;
304        m_pAdd->SetPosition(pos);
305
306        m_pListCtrl->ClearSelection();
307        UpdateConditionsClientSize();
308
309        SetFilterCtrlState(false);
310}
311
312void CFilterConditionsDialog::OnFilterTypeChange(wxCommandEvent& event)
313{
314        int item;
315        for (item = 0; item < (int)m_filterControls.size(); ++item) {
316                if (!m_filterControls[item].pType || m_filterControls[item].pType->GetId() != event.GetId())
317                        continue;
318
319                break;
320        }
321        if (item == (int)m_filterControls.size())
322                return;
323
324        CFilterCondition& filter = m_currentFilter.filters[item];
325
326        t_filterType type = GetTypeFromTypeSelection(event.GetSelection());
327        if (type == filter.type)
328                return;
329        filter.type = type;
330
331        if (filter.type == filter_size && filter.condition > 3)
332                filter.condition = 0;
333        else if (filter.type == filter_date && filter.condition > 3)
334                filter.condition = 0;
335        delete m_filterControls[item].pCondition;
336        m_filterControls[item].pCondition = 0;
337
338        MakeControls(filter, item);
339}
340
341void CFilterConditionsDialog::MakeControls(const CFilterCondition& condition, int i /*=-1*/)
342{
343        wxRect client_size = m_pListCtrl->GetClientSize();
344
345        if (i == -1) {
346                i = m_filterControls.size();
347                CFilterControls controls;
348                m_filterControls.push_back(controls);
349        }
350        CFilterControls& controls = m_filterControls[i];
351
352        // Get correct coordinates
353        int posy = i * (m_choiceBoxHeight + 6) + 3;
354        int posx = 0, x, y;
355        m_pListCtrl->CalcScrolledPosition(posx, posy, &x, &y);
356        posy = y;
357
358        wxPoint pos = wxPoint(5, posy);
359        if (!controls.pType)
360                controls.pType = CreateChoice(m_pListCtrl, pos, filterTypes);
361        else
362                controls.pType->SetPosition(pos);
363        SetSelectionFromType(controls.pType, condition.type);
364        wxRect typeRect = controls.pType->GetSize();
365
366        if (!m_choiceBoxHeight) {
367                wxSize size = controls.pType->GetSize();
368                m_choiceBoxHeight = size.GetHeight();
369                m_pListCtrl->SetLineHeight(m_choiceBoxHeight + 6);
370        }
371
372        pos = wxPoint(10 + typeRect.GetWidth(), posy);
373        if (!controls.pCondition) {
374                switch (condition.type)
375                {
376                case filter_name:
377                case filter_path:
378                        controls.pCondition = CreateChoice(m_pListCtrl, pos, stringConditionTypes);
379                        break;
380                case filter_size:
381                        controls.pCondition = CreateChoice(m_pListCtrl, pos, sizeConditionTypes);
382                        break;
383                case filter_attributes:
384                        controls.pCondition = CreateChoice(m_pListCtrl, pos, attributeConditionTypes);
385                        break;
386                case filter_permissions:
387                        controls.pCondition = CreateChoice(m_pListCtrl, pos, permissionConditionTypes);
388                        break;
389                case filter_date:
390                        controls.pCondition = CreateChoice(m_pListCtrl, pos, dateConditionTypes);
391                        break;
392                default:
393                        wxFAIL_MSG(_T("Unhandled condition"));
394                        return;
395                }
396                if (controls.pCondition && controls.pType) {
397                        controls.pCondition->MoveAfterInTabOrder(controls.pType);
398                }
399        }
400        else
401                controls.pCondition->SetPosition(pos);
402
403        controls.pCondition->Select(condition.condition);
404        wxRect conditionsRect = controls.pCondition->GetSize();
405
406        if (!controls.pRemove) {
407                controls.pRemove = new wxButton(m_pListCtrl, wxID_ANY, _T("-"), wxPoint(client_size.GetWidth() - 5 - m_button_size.x, posy), m_button_size, wxBU_EXACTFIT);
408                if (m_button_size.x <= 0) {
409                        m_button_size.x = wxMax(m_choiceBoxHeight, controls.pRemove->GetSize().x);
410                        m_button_size.y = m_choiceBoxHeight;
411                        controls.pRemove->SetSize(m_button_size);
412                        controls.pRemove->SetPosition(wxPoint(client_size.GetWidth() - 5 - m_button_size.x, posy));
413                }
414                controls.pRemove->MoveAfterInTabOrder(controls.pCondition);
415        }
416        else
417                controls.pRemove->SetPosition(wxPoint(client_size.GetWidth() - 5 - m_button_size.x, posy));
418
419        posx = 15 + typeRect.GetWidth() + conditionsRect.GetWidth();
420        int maxwidth = client_size.GetWidth() - posx - 10 - m_button_size.x;
421        if (condition.type == filter_name || condition.type == filter_size || condition.type == filter_path || condition.type == filter_date) {
422                delete controls.pSet;
423                controls.pSet = 0;
424
425                if (condition.type == filter_size) {
426                        // Label needs to be aligned
427                        int size_posy = posy;
428                        if (conditionsRect.GetHeight() > m_size_label_size.GetHeight())
429                                size_posy += (conditionsRect.GetHeight() - m_size_label_size.GetHeight()) / 2;
430                        maxwidth -= m_size_label_size.GetWidth() + 5;
431                        if (!controls.pLabel)
432                                controls.pLabel = new wxStaticText(m_pListCtrl, wxID_ANY, _("bytes"), wxPoint(posx + maxwidth + 5, size_posy), m_size_label_size);
433                        else {
434                                controls.pLabel->SetPosition(wxPoint(posx + maxwidth + 5, size_posy));
435                                controls.pLabel->SetSize(m_size_label_size);
436                        }
437                }
438                else {
439                        delete controls.pLabel;
440                        controls.pLabel = 0;
441                }
442
443                pos = wxPoint(posx, posy);
444                wxSize size(maxwidth, -1);
445
446                if (!controls.pValue) {
447                        controls.pValue = new wxTextCtrlEx();
448                        controls.pValue->Create(m_pListCtrl, wxID_ANY, _T(""), pos, size);
449                }
450                else {
451                        controls.pValue->SetPosition(pos);
452                        controls.pValue->SetSize(size);
453                }
454                controls.pValue->SetValue(condition.strValue);
455
456                // Need to explicitely set min size, otherwise initial size becomes min size
457                controls.pValue->SetMinSize(wxSize(20, -1));
458                controls.pValue->MoveBeforeInTabOrder(controls.pRemove);
459        }
460        else {
461                delete controls.pValue;
462                controls.pValue = 0;
463                delete controls.pLabel;
464                controls.pLabel = 0;
465
466                pos = wxPoint(posx, posy);
467                wxSize size(maxwidth, -1);
468                if (!controls.pSet)
469                        controls.pSet = CreateChoice(m_pListCtrl, pos, attributeSetTypes, size);
470                else {
471                        controls.pSet->SetPosition(pos);
472                        controls.pSet->SetSize(size);
473                }
474                controls.pSet->Select(condition.strValue != _T("0") ? 0 : 1);
475
476                // Need to explicitely set min size, otherwise initial size becomes min size
477                controls.pSet->SetMinSize(wxSize(20, -1));
478                controls.pSet->MoveBeforeInTabOrder(controls.pRemove);
479        }
480}
481
482void CFilterConditionsDialog::DestroyControls()
483{
484        for (unsigned int i = 0; i < m_filterControls.size(); ++i) {
485                CFilterControls& controls = m_filterControls[i];
486                controls.Reset();
487        }
488        m_filterControls.clear();
489}
490
491void CFilterConditionsDialog::UpdateConditionsClientSize()
492{
493        wxSize newSize = m_pListCtrl->GetClientSize();
494
495        if (m_lastListSize.GetWidth() == newSize.GetWidth())
496                return;
497
498        int deltaX = newSize.GetWidth() - m_lastListSize.GetWidth();
499        m_lastListSize = newSize;
500
501        // Resize text fields
502        for (unsigned int i = 0; i < m_filterControls.size(); ++i) {
503                CFilterControls& controls = m_filterControls[i];
504                if (!controls.pValue)
505                        continue;
506
507                wxSize size = controls.pValue->GetSize();
508                size.SetWidth(size.GetWidth() + deltaX);
509                controls.pValue->SetSize(size);
510
511                wxPoint pos = controls.pRemove->GetPosition();
512                pos.x += deltaX;
513                controls.pRemove->SetPosition(pos);
514
515                if (controls.pLabel) {
516                        wxPoint labelPos = controls.pLabel->GetPosition();
517                        labelPos.x += deltaX;
518                        controls.pLabel->SetPosition(labelPos);
519                }
520        }
521
522        // Move add button
523        if (m_pAdd) {
524                wxPoint pos = m_pAdd->GetPosition();
525                pos.x += deltaX;
526                m_pAdd->SetPosition(pos);
527        }
528}
529
530void CFilterConditionsDialog::EditFilter(const CFilter& filter)
531{
532        DestroyControls();
533
534        // Create new controls
535        m_currentFilter = filter;
536
537        if (m_currentFilter.filters.empty())
538                m_currentFilter.filters.push_back(CFilterCondition());
539
540        for (unsigned int i = 0; i < m_currentFilter.filters.size(); ++i) {
541                const CFilterCondition& cond = m_currentFilter.filters[i];
542
543                MakeControls(cond);
544        }
545
546        // Get correct coordinates
547        wxSize client_size = m_pListCtrl->GetClientSize();
548        wxPoint pos;
549        m_pListCtrl->CalcScrolledPosition(client_size.GetWidth() - 5 - m_button_size.x, (m_choiceBoxHeight + 6) * m_filterControls.size() + 3, &pos.x, &pos.y);
550
551        if (!m_pAdd)
552                m_pAdd = new wxButton(m_pListCtrl, wxID_ANY, _T("+"), pos, m_button_size);
553        else
554                m_pAdd->SetPosition(pos);
555
556        m_pListCtrl->SetLineCount(m_filterControls.size() + 1);
557        UpdateConditionsClientSize();
558
559        XRCCTRL(*this, "ID_MATCHTYPE", wxChoice)->SetSelection(filter.matchType);
560
561        SetFilterCtrlState(false);
562}
563
564CFilter CFilterConditionsDialog::GetFilter()
565{
566        wxASSERT(m_filterControls.size() == m_currentFilter.filters.size());
567
568        CFilter filter;
569        for (unsigned int i = 0; i < m_currentFilter.filters.size(); ++i) {
570                CFilterControls const& controls = m_filterControls[i];
571                if (!controls.pType || !controls.pCondition || !controls.pValue) {
572                        continue;
573                }
574                CFilterCondition condition = m_currentFilter.filters[i];
575
576                condition.type = GetTypeFromTypeSelection(controls.pType->GetSelection());
577                condition.condition = controls.pCondition->GetSelection();
578
579                switch (condition.type)
580                {
581                case filter_name:
582                case filter_path:
583                        if (controls.pValue->GetValue().empty())
584                                continue;
585                        condition.strValue = controls.pValue->GetValue();
586                        break;
587                case filter_size:
588                        {
589                                if (controls.pValue->GetValue().empty())
590                                        continue;
591                                condition.strValue = controls.pValue->GetValue();
592                                unsigned long long tmp;
593                                condition.strValue.ToULongLong(&tmp);
594                                condition.value = tmp;
595                        }
596                        break;
597                case filter_attributes:
598                case filter_permissions:
599                        if (controls.pSet->GetSelection()) {
600                                condition.strValue = _T("0");
601                                condition.value = 0;
602                        }
603                        else {
604                                condition.strValue = _T("1");
605                                condition.value = 1;
606                        }
607                        break;
608                case filter_date:
609                        if (controls.pValue->GetValue().empty())
610                                continue;
611                        else {
612                                condition.strValue = controls.pValue->GetValue();
613                                condition.date = fz::datetime(condition.strValue.ToStdWstring(), fz::datetime::local);
614                                if (!condition.date.empty()) {
615                                        continue;
616                                }
617                        }
618                        break;
619                default:
620                        wxFAIL_MSG(_T("Unhandled condition"));
621                        break;
622                }
623
624                condition.matchCase = filter.matchCase;
625
626                filter.filters.push_back(condition);
627        }
628
629        switch (XRCCTRL(*this, "ID_MATCHTYPE", wxChoice)->GetSelection())
630        {
631        case 1:
632                filter.matchType = CFilter::any;
633                break;
634        case 2:
635                filter.matchType = CFilter::none;
636                break;
637        default:
638                filter.matchType = CFilter::all;
639                break;
640        }
641
642        return filter;
643}
644
645void CFilterConditionsDialog::ClearFilter(bool disable)
646{
647        DestroyControls();
648        m_pListCtrl->SetLineCount(0);
649
650        SetFilterCtrlState(disable);
651}
652
653void CFilterConditionsDialog::SetFilterCtrlState(bool disable)
654{
655        m_pListCtrl->Enable(!disable);
656
657        XRCCTRL(*this, "ID_MATCHTYPE", wxChoice)->Enable(!disable);
658}
659
660bool CFilterConditionsDialog::ValidateFilter(wxString& error, bool allow_empty /*=false*/)
661{
662        const unsigned int size = m_currentFilter.filters.size();
663        if (!size) {
664                if (allow_empty)
665                        return true;
666
667                error = _("Each filter needs at least one condition.");
668                return false;
669        }
670
671        wxASSERT(m_filterControls.size() == m_currentFilter.filters.size());
672
673        for (unsigned int i = 0; i < size; ++i) {
674                const CFilterControls& controls = m_filterControls[i];
675                enum t_filterType type = GetTypeFromTypeSelection(controls.pType->GetSelection());
676                if (!controls.pValue) {
677                        continue;
678                }
679
680                if ((type == filter_name || type == filter_path) && (!controls.pValue || controls.pValue->GetValue().empty())) {
681                        if (allow_empty)
682                                continue;
683
684                        m_pListCtrl->SelectLine(i);
685                        controls.pValue->SetFocus();
686                        error = _("At least one filter condition is incomplete");
687                        SetFilterCtrlState(false);
688                        return false;
689                }
690                else if (type == filter_size) {
691                        const wxString v = controls.pValue->GetValue();
692                        if (v.empty() && allow_empty)
693                                continue;
694
695                        long long number;
696                        if (!v.ToLongLong(&number) || number < 0) {
697                                m_pListCtrl->SelectLine(i);
698                                controls.pValue->SetFocus();
699                                error = _("Invalid size in condition");
700                                SetFilterCtrlState(false);
701                                return false;
702                        }
703                }
704                else if (type == filter_date) {
705                        const wxString d = controls.pValue->GetValue();
706                        if (d.empty() && allow_empty)
707                                continue;
708
709                        wxDateTime date;
710                        if (!date.ParseFormat(d, _T("%Y-%m-%d")) || !date.IsValid()) {
711                                m_pListCtrl->SelectLine(i);
712                                controls.pValue->SetFocus();
713                                error = _("Please enter a date of the form YYYY-MM-DD such as for example 2010-07-18.");
714                                SetFilterCtrlState(false);
715                                return false;
716                        }
717                }
718        }
719
720        return true;
721}
722
723void CFilterConditionsDialog::OnConditionSelectionChange(wxCommandEvent& event)
724{
725        if (event.GetId() != m_pListCtrl->GetId())
726                return;
727
728        SetFilterCtrlState(false);
729}
730
731void CFilterConditionsDialog::OnButton(wxCommandEvent& event)
732{
733        if (event.GetId() == m_pAdd->GetId()) {
734                OnMore();
735                return;
736        }
737
738        for (int i = 0; i < (int)m_filterControls.size(); ++i) {
739                if (m_filterControls[i].pRemove->GetId() == event.GetId()) {
740                        OnRemove(i);
741                        return;
742                }
743        }
744        event.Skip();
745}
746
747void CFilterConditionsDialog::OnListSize(wxSizeEvent& event)
748{
749        UpdateConditionsClientSize();
750        event.Skip();
751}
752
753void CFilterConditionsDialog::OnNavigationKeyEvent(wxNavigationKeyEvent& event)
754{
755        wxWindow* source = FindFocus();
756        if (!source)
757        {
758                event.Skip();
759                return;
760        }
761
762        wxWindow* target = 0;
763
764        if (event.GetDirection()) {
765                for (int i = 0; i < (int)m_filterControls.size(); ++i) {
766                        if (m_filterControls[i].pType == source) {
767                                target = m_filterControls[i].pCondition;
768                                break;
769                        }
770                        if (m_filterControls[i].pCondition == source) {
771                                target = m_filterControls[i].pValue;
772                                if (!target)
773                                        target = m_filterControls[i].pSet;
774                                break;
775                        }
776                        if (m_filterControls[i].pSet == source || m_filterControls[i].pValue == source) {
777                                target = m_filterControls[i].pRemove;
778                                break;
779                        }
780                        if (m_filterControls[i].pRemove == source) {
781                                int j = i + 1;
782                                if (j == (int)m_filterControls.size())
783                                        target = m_pAdd;
784                                else
785                                        target = m_filterControls[j].pType;
786                                break;
787                        }
788                }
789        }
790        else {
791                if (source == m_pAdd) {
792                        if (!m_filterControls.empty())
793                                target = m_filterControls[m_filterControls.size() - 1].pRemove;
794                }
795                else {
796                        for (int i = 0; i < (int)m_filterControls.size(); ++i) {
797                                if (m_filterControls[i].pType == source) {
798                                        if (i > 0)
799                                                target = m_filterControls[i - 1].pRemove;
800                                        break;
801                                }
802                                if (m_filterControls[i].pCondition == source) {
803                                        target = m_filterControls[i].pType;
804                                        break;
805                                }
806                                if (m_filterControls[i].pSet == source || m_filterControls[i].pValue == source) {
807                                        target = m_filterControls[i].pCondition;
808                                        break;
809                                }
810                                if (m_filterControls[i].pRemove == source) {
811                                        target = m_filterControls[i].pValue;
812                                        if (!target)
813                                                target = m_filterControls[i].pSet;
814                                        break;
815                                }
816                        }
817                }
818        }
819
820        if (target)
821                target->SetFocus();
822        else
823                event.Skip();
824}
Note: See TracBrowser for help on using the repository browser.