bool CFilterConditionsDialog::ValidateFilter(wxString& error, bool allow_empty /*=false*/)
{
	const unsigned int size = m_currentFilter.filters.size();
	if (!size)
	{
		if (allow_empty)
			return true;

		error = _("Each filter needs at least one condition.");
		return false;
	}

	wxASSERT(m_filterControls.size() == m_currentFilter.filters.size());

	for (unsigned int i = 0; i < size; i++)
	{
		const CFilterControls& controls = m_filterControls[i];
		enum t_filterType type = GetTypeFromTypeSelection(controls.pType->GetSelection());

		if ((type == filter_name || type == filter_path) && controls.pValue->GetValue() == _T(""))
		{
			if (allow_empty)
				continue;

			m_pListCtrl->SelectLine(i);
			controls.pValue->SetFocus();
			error = _("At least one filter condition is incomplete");
			SetFilterCtrlState(false);
			return false;
		}
		else if (type == filter_size)
		{
			const wxString v = controls.pValue->GetValue();
			if (v == _T("") && allow_empty)
				continue;

			long number;
			if (!v.ToLong(&number) || number < 0)
			{
				m_pListCtrl->SelectLine(i);
				controls.pValue->SetFocus();
				error = _("Invalid size in condition");
				SetFilterCtrlState(false);
				return false;
			}
		}
	}

	return true;
}
void CFilterConditionsDialog::OnConditionSelectionChange(wxCommandEvent& event)
{
	if (event.GetId() != m_pListCtrl->GetId())
		return;

	SetFilterCtrlState(false);
}
void CFilterConditionsDialog::ClearFilter(bool disable)
{
	DestroyControls();
	m_pListCtrl->SetLineCount(0);

	SetFilterCtrlState(disable);
}
void CFilterConditionsDialog::EditFilter(const CFilter& filter)
{
	DestroyControls();

	// Create new controls
	m_currentFilter = filter;

	if (m_currentFilter.filters.empty())
		m_currentFilter.filters.push_back(CFilterCondition());

	for (unsigned int i = 0; i < m_currentFilter.filters.size(); i++)
	{
		const CFilterCondition& cond = m_currentFilter.filters[i];

		MakeControls(cond);
	}

	// Get correct coordinates
	wxSize client_size = m_pListCtrl->GetClientSize();
	wxPoint pos;
	m_pListCtrl->CalcScrolledPosition(client_size.GetWidth() - 5 - m_button_size.x, (m_choiceBoxHeight + 6) * m_filterControls.size() + 3, &pos.x, &pos.y);

	if (!m_pAdd)
		m_pAdd = new wxButton(m_pListCtrl, wxID_ANY, _T("+"), pos, m_button_size);
	else
		m_pAdd->SetPosition(pos);

	m_pListCtrl->SetLineCount(m_filterControls.size() + 1);
	UpdateConditionsClientSize();

	XRCCTRL(*this, "ID_MATCHTYPE", wxChoice)->SetSelection(filter.matchType);

	SetFilterCtrlState(false);
}
bool CFilterConditionsDialog::CreateListControl(int conditions /*=common*/)
{
	wxScrolledWindow* wnd = XRCCTRL(*this, "ID_CONDITIONS", wxScrolledWindow);
	if (!wnd)
		return false;

	m_pListCtrl = new wxCustomHeightListCtrl(this, wxID_ANY, wxDefaultPosition, wnd->GetSize(), wxVSCROLL|wxSUNKEN_BORDER|wxTAB_TRAVERSAL);
	if (!m_pListCtrl)
		return false;
	m_pListCtrl->AllowSelection(false);
	ReplaceControl(wnd, m_pListCtrl);
	CalcMinListWidth();

	if (stringConditionTypes.IsEmpty())
	{
		stringConditionTypes.Add(_("contains"));
		stringConditionTypes.Add(_("is equal to"));
		stringConditionTypes.Add(_("begins with"));
		stringConditionTypes.Add(_("ends with"));
		stringConditionTypes.Add(_("matches regex"));
		stringConditionTypes.Add(_("does not contain"));

		sizeConditionTypes.Add(_("greater than"));
		sizeConditionTypes.Add(_("equals"));
		sizeConditionTypes.Add(_("does not equal"));
		sizeConditionTypes.Add(_("less than"));

		attributeSetTypes.Add(_("is set"));
		attributeSetTypes.Add(_("is unset"));

		attributeConditionTypes.Add(_("Archive"));
		attributeConditionTypes.Add(_("Compressed"));
		attributeConditionTypes.Add(_("Encrypted"));
		attributeConditionTypes.Add(_("Hidden"));
		attributeConditionTypes.Add(_("Read-only"));
		attributeConditionTypes.Add(_("System"));

		permissionConditionTypes.Add(_("owner readable"));
		permissionConditionTypes.Add(_("owner writeable"));
		permissionConditionTypes.Add(_("owner executable"));
		permissionConditionTypes.Add(_("group readable"));
		permissionConditionTypes.Add(_("group writeable"));
		permissionConditionTypes.Add(_("group executable"));
		permissionConditionTypes.Add(_("world readable"));
		permissionConditionTypes.Add(_("world writeable"));
		permissionConditionTypes.Add(_("world executable"));

		dateConditionTypes.Add(_("before"));
		dateConditionTypes.Add(_("equals"));
		dateConditionTypes.Add(_("does not equal"));
		dateConditionTypes.Add(_("after"));
	}

	if (conditions & filter_name)
	{
		filterTypes.Add(_("Filename"));
		filter_type_map.push_back(filter_name);
	}
	if (conditions & filter_size)
	{
		filterTypes.Add(_("Filesize"));
		filter_type_map.push_back(filter_size);
	}
	if (conditions & filter_attributes)
	{
		filterTypes.Add(_("Attribute"));
		filter_type_map.push_back(filter_attributes);
	}
	if (conditions & filter_permissions)
	{
		filterTypes.Add(_("Permission"));
		filter_type_map.push_back(filter_permissions);
	}
	if (conditions & filter_path)
	{
		filterTypes.Add(_("Path"));
		filter_type_map.push_back(filter_path);
	}
	if (conditions & filter_date)
	{
		filterTypes.Add(_("Date"));
		filter_type_map.push_back(filter_date);
	}

	SetFilterCtrlState(true);

	m_pListCtrl->Connect(wxEVT_SIZE, wxSizeEventHandler(CFilterConditionsDialog::OnListSize), 0, this);

	m_pListCtrl->MoveAfterInTabOrder(XRCCTRL(*this, "ID_MATCHTYPE", wxChoice));

	return true;
}
void CFilterConditionsDialog::OnRemove(const std::set<int> &selected)
{
	int delta_y = 0;

	m_pListCtrl->SetLineCount(m_filterControls.size() - selected.size() + 1);

	std::vector<CFilterControls> filterControls = m_filterControls;
	m_filterControls.clear();

	std::vector<CFilterCondition> filters = m_currentFilter.filters;
	m_currentFilter.filters.clear();

	for (unsigned int i = 0; i < filterControls.size(); i++)
	{
		CFilterControls& controls = filterControls[i];
		if (selected.find(i) == selected.end())
		{
			m_filterControls.push_back(controls);
			m_currentFilter.filters.push_back(filters[i]);

			// Reposition controls
			wxPoint pos;

			pos = controls.pType->GetPosition();
			pos.y -= delta_y;
			controls.pType->SetPosition(pos);

			pos = controls.pCondition->GetPosition();
			pos.y -= delta_y;
			controls.pCondition->SetPosition(pos);

			if (controls.pValue)
			{
				pos = controls.pValue->GetPosition();
				pos.y -= delta_y;
				controls.pValue->SetPosition(pos);
			}
			if (controls.pSet)
			{
				pos = controls.pSet->GetPosition();
				pos.y -= delta_y;
				controls.pSet->SetPosition(pos);
			}
			if (controls.pLabel)
			{
				pos = controls.pLabel->GetPosition();
				pos.y -= delta_y;
				controls.pLabel->SetPosition(pos);
			}

			pos = controls.pRemove->GetPosition();
			pos.y -= delta_y;
			controls.pRemove->SetPosition(pos);
		}
		else
		{
			controls.Reset();
			delta_y += m_choiceBoxHeight + 6;
		}
	}

	wxPoint pos = m_pAdd->GetPosition();
	pos.y -= delta_y;
	m_pAdd->SetPosition(pos);

	m_pListCtrl->ClearSelection();
	UpdateConditionsClientSize();

	SetFilterCtrlState(false);
}