winix/plugins/ticket/templates.cpp

836 lines
17 KiB
C++
Executable File

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
#include "ezc.h"
#include "ticketinfo.h"
#include "editticket.h"
#include "createticket.h"
#include "core/request.h"
#include "core/misc.h"
#include "core/plugin.h"
#include "functions/functions.h"
#include "templates/templates.h"
#include "sessiondata.h"
#include "plugins/thread/pluginmsg.h"
#include "templates/miscspace.h"
#include "space/space.h"
namespace Ticket
{
using namespace TemplatesFunctions;
using TemplatesFunctions::system;
extern TicketInfo ticket_info;
extern CreateTicket fun_create_ticket;
extern EditTicket fun_edit_ticket;
struct TicketValue
{
bool is_param; // true if there is a paremeter (in config Space)
PT::Space * config_par; // current space param (from current config) if is_param is true
// when is_param is true then this pointer is never null
long param_id; // param id (the same as config_par->Long(L"id"))
bool is_value; // true if value for such a param was defined
bool is_in_ticket_par; // true if the value is defined in ticket.par_tab
// else the value is defined in meta
Ticket::TicketParam * ticket_par; // if is_in_ticket_par is true:
PT::Space * value_meta; // if is_in_ticket_par is false:
TicketValue()
{
Clear();
}
void Clear()
{
is_param = false;
config_par = 0;
param_id = 0;
is_value = false;
is_in_ticket_par = false;
value_meta = 0;
}
};
int ticket_calc_progress_image_number(int percent)
{
percent = int( double(percent) / 10.0 + 0.5 ) * 10;
if( percent < 0 )
percent = 0;
if( percent > 100 )
percent = 100;
return percent;
}
/*
binary search for param in par_tab
(par_tab must be sorted by 'param')
*/
bool find_ticket_param(long param, const Ticket::ParTab & par_tab, size_t & ticket_par_index)
{
if( par_tab.empty() )
return false;
size_t o1 = 0;
size_t o2 = par_tab.size() - 1;
if( par_tab[o1].param == param )
{
ticket_par_index = o1;
return true;
}
if( param < par_tab[o1].param )
return false;
if( par_tab[o2].param == param )
{
ticket_par_index = o2;
return true;
}
if( param > par_tab[o2].param )
return false;
while( o1 + 1 < o2 )
{
ticket_par_index = (o1 + o2) / 2;
if( par_tab[ticket_par_index].param == param )
return true;
if( par_tab[ticket_par_index].param < param )
o1 = ticket_par_index;
else
o2 = ticket_par_index;
}
return false;
}
/*
looking for a subspace in meta which has id equal to param_id
can return a null pointer
*/
PT::Space * find_ticket_param(long param_id, PT::Space & meta)
{
wchar_t param_id_str[50];
// for performane
// should be a little faster in each loop comparing only just text
Toa(param_id, param_id_str, sizeof(param_id_str)/sizeof(wchar_t));
for(size_t i=0 ; i<meta.spaces.size() ; ++i)
{
PT::Space & sp = *meta.spaces[i];
if( sp.name == L"param" && sp.Text(L"id") == param_id_str )
return &sp;
}
return 0;
}
/*
first par_tab is searched for the specified value.param_id
if it is found then value.is_in_ticket_par is set to true and value.ticket_par is pointing
to the par_tab item
if not then meta is searched and if found then value.is_in_ticket_par is false and
value.value_meta is set to the specified item in meta
input:
value.is_param
value.config_par
value.param_id
par_tab
meta
output:
value.is_value
value.is_in_ticket_par
value.ticket_par
value.value_meta
*/
void find_ticket_value(TicketValue & value, Ticket::ParTab & par_tab, PT::Space & item_meta)
{
size_t par_index;
if( !value.is_param )
return;
value.is_value = false;
if( find_ticket_param(value.param_id, par_tab, par_index) )
{
value.is_value = true;
value.is_in_ticket_par = true;
value.ticket_par = &par_tab[par_index];
value.value_meta = 0;
}
else
{
PT::Space * meta = item_meta.FindSpace(L"ticket");
if( meta )
{
PT::Space * sp = find_ticket_param(value.param_id, *meta);
if( sp )
{
value.is_value = true;
value.is_in_ticket_par = false;
value.ticket_par = 0;
value.value_meta = sp;
}
}
}
}
void ticket_print_value_select(Info & i, TicketValue & value)
{
if( value.is_param && value.is_value )
{
for(size_t a=0 ; a<value.config_par->spaces.size() ; ++a)
{
PT::Space & sp = *value.config_par->spaces[a];
if( sp.name == L"option" && sp.Long(L"id") == value.ticket_par->intv )
{
i.out << sp.Text(L"value");
break;
}
}
}
}
void ticket_print_value(Info & i, TicketValue & value)
{
if( !value.is_param || !value.is_value )
return;
std::wstring & type = value.config_par->Text(L"type");
if( value.is_in_ticket_par )
{
if( type == L"decimal" )
i.out << value.ticket_par->decv;
else
if( type == L"select" )
ticket_print_value_select(i, value);
else
i.out << value.ticket_par->intv;
}
else
{
i.out << value.value_meta->Text(L"value");
}
}
void ticket_can_create(Info & i)
{
i.res = fun_create_ticket.HasAccess();
}
void ticket_can_edit(Info & i)
{
i.res = fun_edit_ticket.HasAccess();
}
void ticket_is_creating_new(Info & i)
{
i.res = ticket_info.create_new_ticket;
}
namespace ns_tickets_tab
{
struct TicketsTabValue
{
bool is_item; // true if there is an item (item pointer is valid)
bool is_ticket; // true if there is a ticket (ticket pointer is valid)
Item * item; // an item for that ticket (if is_item is true)
Ticket * ticket; // pointer to the ticket (if is_ticket is true)
/*
there can be two situations:
- is_item is false and is_ticket is false
- is_item is true and is_ticket is false
- is_item is true and is_ticket is true
so when is_ticket is true then is_item is true as well so you don't have to check it
*/
TicketsTabValue()
{
Clear();
}
void Clear()
{
is_item = false;
is_ticket = false;
ticket = 0;
item = 0;
}
};
// binary search for file_id in ticket_tab (ticket_tab must be sorted by 'file_id')
bool find_ticket(long file_id, const std::vector<Ticket> & ticket_tab, size_t & ticket_index)
{
if( ticket_tab.empty() )
return false;
size_t o1 = 0;
size_t o2 = ticket_tab.size() - 1;
if( ticket_tab[o1].file_id == file_id )
{
ticket_index = o1;
return true;
}
if( file_id < ticket_tab[o1].file_id )
return false;
if( ticket_tab[o2].file_id == file_id )
{
ticket_index = o2;
return true;
}
if( file_id > ticket_tab[o2].file_id )
return false;
while( o1 + 1 < o2 )
{
ticket_index = (o1 + o2) / 2;
if( ticket_tab[ticket_index].file_id == file_id )
return true;
if( ticket_tab[ticket_index].file_id < file_id )
o1 = ticket_index;
else
o2 = ticket_index;
}
return false;
}
static size_t tickets_tab_reqid = 0;
static TicketsTabValue tickets_value;
static TicketValue value;
static size_t item_sort_index; // index for: ticket_info.item_sort_tab
static size_t conf_index; // index for: ticket_info.cur_conf->spaces
void tickets_tab_check_reqid()
{
if( tickets_tab_reqid != cur->request->id )
{
tickets_tab_reqid = cur->request->id;
tickets_value.Clear();
value.Clear();
}
}
void tickets_tab(Info & i)
{
tickets_tab_check_reqid();
tickets_value.Clear();
value.Clear();
item_sort_index = i.iter;
i.res = (item_sort_index < ticket_info.item_sort_tab.size());
if( i.res )
{
tickets_value.is_item = true;
tickets_value.item = ticket_info.item_sort_tab[item_sort_index];
long file_id = ticket_info.item_sort_tab[item_sort_index]->id;
size_t ticket_index;
if( find_ticket(file_id, ticket_info.ticket_tab, ticket_index) )
{
tickets_value.is_ticket = true;
tickets_value.ticket = &ticket_info.ticket_tab[ticket_index];
}
plugin.Call(WINIX_PL_THREAD_SET_SORTTAB_INDEX, item_sort_index);
}
}
void tickets_tab_url(Info & i)
{
tickets_tab_check_reqid();
if( tickets_value.is_item )
i.out << tickets_value.item->url;
}
void tickets_tab_subject_empty(Info & i)
{
tickets_tab_check_reqid();
if( tickets_value.is_item )
i.res = tickets_value.item->subject.empty();
}
void tickets_tab_subject(Info & i)
{
tickets_tab_check_reqid();
if( tickets_value.is_item )
i.out << tickets_value.item->subject;
}
void tickets_tab_conf_tab(Info & i)
{
tickets_tab_check_reqid();
value.Clear();
if( tickets_value.is_ticket )
{
conf_index = i.iter;
PT::Space & space = *ticket_info.cur_conf;
while( conf_index < space.spaces.size() && space.spaces[conf_index]->name != L"param" )
conf_index += 1;
i.res = conf_index < space.spaces.size();
if( i.res )
{
value.is_param = true;
value.config_par = space.spaces[conf_index];
value.param_id = value.config_par->Long(L"id");
find_ticket_value(value, tickets_value.ticket->par_tab, tickets_value.item->meta);
}
}
}
void tickets_tab_conf_tab_has_value(Info & i)
{
tickets_tab_check_reqid();
i.res = value.is_value;
}
void tickets_tab_conf_tab_value(Info & i)
{
tickets_tab_check_reqid();
if( value.is_value )
ticket_print_value(i, value);
}
void tickets_tab_conf_tab_type_is(Info & i)
{
tickets_tab_check_reqid();
if( value.is_param )
i.res = (value.config_par->Text(L"type") == i.par);
}
void tickets_tab_conf_tab_progress_image_number(Info & i)
{
tickets_tab_check_reqid();
if( value.is_value && value.is_in_ticket_par )
{
int progress = value.ticket_par->intv;
i.out << ticket_calc_progress_image_number(progress);
}
}
} // namespace ns_tickets_tab
namespace ns_ticket_tab
{
static size_t conf_index; // index for: ticket_info.cur_conf->spaces
static TicketValue value; // current ticket value
static size_t ticket_req_id = 0;
static size_t select_index;
static size_t ticket_file_index;
static size_t ticket_file_number;
void ticket_tab_check_reqid()
{
if( ticket_req_id != cur->request->id )
{
ticket_req_id = cur->request->id;
value.Clear();
}
}
void ticket_tab(Info & i)
{
ticket_tab_check_reqid();
value.Clear();
conf_index = i.iter;
PT::Space & space = *ticket_info.cur_conf;
while( conf_index < space.spaces.size() && space.spaces[conf_index]->name != L"param" )
conf_index += 1;
i.res = conf_index < space.spaces.size();
if( i.res )
{
value.is_param = true;
value.config_par = space.spaces[conf_index];
value.param_id = value.config_par->Long(L"id");
find_ticket_value(value, ticket_info.ticket->par_tab, ticket_info.item->meta);
}
}
void ticket_tab_param_id(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
i.out << value.param_id;
}
void ticket_tab_param_name(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
i.out << value.config_par->Text(L"name");
}
void ticket_tab_has_value(Info & i)
{
ticket_tab_check_reqid();
i.res = value.is_value;
}
void ticket_tab_value(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value )
ticket_print_value(i, value);
}
void ticket_tab_value_int(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && value.is_in_ticket_par )
i.out << value.ticket_par->intv;
}
void ticket_tab_value_dec(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && value.is_in_ticket_par )
i.out << value.ticket_par->decv;
}
void ticket_tab_value_meta(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && !value.is_in_ticket_par )
space(i, *value.value_meta);
}
void ticket_tab_type_is(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
i.res = (value.config_par->Text(L"type") == i.par);
}
void ticket_tab_select_tab(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
{
select_index = i.iter;
PT::Space & sp = *value.config_par;
while( select_index < sp.spaces.size() && sp.spaces[select_index]->name != L"option" )
select_index += 1;
i.res = (select_index < sp.spaces.size());
}
}
void ticket_tab_select_tab_is_selected(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
{
PT::Space & sp = *value.config_par;
if( select_index < sp.spaces.size() )
{
long id = sp.spaces[select_index]->Long(L"id");
if( value.is_value )
{
if( value.is_in_ticket_par )
i.res = (id == value.ticket_par->intv);
}
else
{
i.res = (id == sp.Long(L"default"));
}
}
}
}
void ticket_tab_select_tab_name(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
{
PT::Space & sp = *value.config_par;
if( select_index < sp.spaces.size() )
i.out << sp.spaces[select_index]->Text(L"value");
}
}
void ticket_tab_select_tab_id(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
{
PT::Space & sp = *value.config_par;
if( select_index < sp.spaces.size() )
i.out << sp.spaces[select_index]->Text(L"id");
}
}
void ticket_tab_select_tab_meta(Info & i)
{
ticket_tab_check_reqid();
if( value.is_param )
{
PT::Space & sp = *value.config_par;
if( select_index < sp.spaces.size() )
space(i, *sp.spaces[select_index]);
}
}
void ticket_tab_file_tab(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && !value.is_in_ticket_par )
{
ticket_file_index = i.iter;
if( i.iter == 0 )
ticket_file_number = 0;
PT::Space & mt = *value.value_meta;
while( ticket_file_index < mt.spaces.size() && mt.spaces[ticket_file_index]->name != L"file" )
ticket_file_index += 1;
i.res = (ticket_file_index < mt.spaces.size());
if( i.res && i.iter > 0 )
ticket_file_number += 1;
}
}
void ticket_tab_file_tab_index(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && !value.is_in_ticket_par )
{
PT::Space & mt = *value.value_meta;
if( ticket_file_index < mt.spaces.size() )
i.out << ticket_file_number;
}
}
void ticket_tab_file_tab_path(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && !value.is_in_ticket_par )
{
PT::Space & mt = *value.value_meta;
if( ticket_file_index < mt.spaces.size() )
i.out << mt.spaces[ticket_file_index]->Text(L"path");
}
}
void ticket_tab_file_tab_itemid(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && !value.is_in_ticket_par )
{
PT::Space & mt = *value.value_meta;
if( ticket_file_index < mt.spaces.size() )
i.out << mt.spaces[ticket_file_index]->Text(L"itemid");
}
}
void ticket_tab_file_tab_meta(Info & i)
{
ticket_tab_check_reqid();
if( value.is_value && !value.is_in_ticket_par )
{
PT::Space & mt = *value.value_meta;
if( ticket_file_index < mt.spaces.size() )
space(i, *mt.spaces[ticket_file_index]);
}
}
} // namespace ns_ticket_tab
void AddEzcFunctions(PluginInfo & info)
{
using namespace ns_tickets_tab;
using namespace ns_ticket_tab;
using TemplatesFunctions::EzcFun;
EzcFun * fun = reinterpret_cast<EzcFun*>(info.p1);
fun->Insert("ticket_can_create", ticket_can_create);
fun->Insert("ticket_can_edit", ticket_can_edit);
fun->Insert("ticket_is_creating_new", ticket_is_creating_new);
fun->Insert("tickets_tab", tickets_tab);
fun->Insert("tickets_tab_url", tickets_tab_url);
fun->Insert("tickets_tab_subject_empty", tickets_tab_subject_empty);
fun->Insert("tickets_tab_subject", tickets_tab_subject);
fun->Insert("tickets_tab_conf_tab", tickets_tab_conf_tab);
fun->Insert("tickets_tab_conf_tab_has_value", tickets_tab_conf_tab_has_value);
fun->Insert("tickets_tab_conf_tab_value", tickets_tab_conf_tab_value);
fun->Insert("tickets_tab_conf_tab_type_is", tickets_tab_conf_tab_type_is);
fun->Insert("tickets_tab_conf_tab_progress_image_number", tickets_tab_conf_tab_progress_image_number);
fun->Insert("ticket_tab", ticket_tab);
fun->Insert("ticket_tab_param_id", ticket_tab_param_id);
fun->Insert("ticket_tab_param_name", ticket_tab_param_name);
fun->Insert("ticket_tab_has_value", ticket_tab_has_value);
fun->Insert("ticket_tab_value", ticket_tab_value);
fun->Insert("ticket_tab_value_int", ticket_tab_value_int);
fun->Insert("ticket_tab_value_dec", ticket_tab_value_dec);
fun->Insert("ticket_tab_value_meta", ticket_tab_value_meta);
fun->Insert("ticket_tab_type_is", ticket_tab_type_is);
fun->Insert("ticket_tab_select_tab", ticket_tab_select_tab);
fun->Insert("ticket_tab_select_tab_is_selected", ticket_tab_select_tab_is_selected);
fun->Insert("ticket_tab_select_tab_name", ticket_tab_select_tab_name);
fun->Insert("ticket_tab_select_tab_id", ticket_tab_select_tab_id);
fun->Insert("ticket_tab_select_tab_meta", ticket_tab_select_tab_meta);
fun->Insert("ticket_tab_file_tab", ticket_tab_file_tab);
fun->Insert("ticket_tab_file_tab_index", ticket_tab_file_tab_index);
fun->Insert("ticket_tab_file_tab_path", ticket_tab_file_tab_path);
fun->Insert("ticket_tab_file_tab_itemid", ticket_tab_file_tab_itemid);
fun->Insert("ticket_tab_file_tab_meta", ticket_tab_file_tab_meta);
}
} // namespace Ticket