2018-09-25 22:55:14 +03:00
# include "task.h"
# include "storage.h"
2018-12-21 23:11:26 +02:00
# include "helper.h"
2018-09-25 22:55:14 +03:00
# include <QVariant>
# include <assert.h>
2018-12-21 23:11:26 +02:00
# if defined(TARGET_OSX) || defined(TARGET_LINUX)
# include <uuid / uuid.h>
# endif
2019-03-26 16:32:48 +02:00
using namespace helper ;
2018-09-25 22:55:14 +03:00
// -------- WorldId ------
WorldId : : WorldId ( )
{
}
WorldId : : WorldId ( const WorldId & src )
{
2018-12-21 23:11:26 +02:00
mId = src . mId ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
WorldId : : WorldId ( const std : : string & s )
: mId ( s )
2018-09-25 22:55:14 +03:00
{
}
WorldId : : ~ WorldId ( )
{
}
WorldId & WorldId : : operator = ( const WorldId & src )
{
2018-12-21 23:11:26 +02:00
mId = src . mId ;
return * this ;
2018-09-25 22:55:14 +03:00
}
bool WorldId : : operator = = ( const WorldId & src )
{
2018-12-21 23:11:26 +02:00
return mId = = src . mId ;
2018-09-25 22:55:14 +03:00
}
bool WorldId : : operator < ( const WorldId & src )
{
2018-12-21 23:11:26 +02:00
return mId < src . mId ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
std : : string WorldId : : asString ( ) const
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
return mId ;
2018-09-25 22:55:14 +03:00
}
WorldId WorldId : : create ( )
{
2018-12-21 23:11:26 +02:00
WorldId result ;
# if defined(TARGET_OSX) || defined(TARGET_LINUX)
uuid_t t ;
uuid_generate ( t ) ;
char buffer [ 128 ] ;
uuid_unparse ( t , buffer ) ;
result . mId = buffer ;
# endif
# if defined(TARGET_WIN)
# endif
return result ;
2018-09-25 22:55:14 +03:00
}
// -------- TimeRecord ----------
TimeRecord : : TimeRecord ( )
2018-12-21 23:11:26 +02:00
: mId ( 0 ) , mTaskId ( 0 ) , mSaved ( false )
2018-09-25 22:55:14 +03:00
{ }
2018-12-21 23:11:26 +02:00
TimeRecord : : TimeRecord ( const time_t & startTime , const time_t & endTime , Id taskId )
2019-03-26 16:32:48 +02:00
: mId ( 0 ) , mTaskId ( taskId ) , mStartTime ( startTime ) , mEndTime ( endTime ) , mSaved ( false )
2018-09-25 22:55:14 +03:00
{
}
TimeRecord : : ~ TimeRecord ( )
{ }
2018-12-21 23:11:26 +02:00
time_t TimeRecord : : endTime ( ) const
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
return mEndTime ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
void TimeRecord : : setEndTime ( const time_t & endTime )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
mEndTime = endTime ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
time_t TimeRecord : : startTime ( ) const
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
return mStartTime ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
void TimeRecord : : setStartTime ( const time_t & startTime )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
mStartTime = startTime ;
2018-09-25 22:55:14 +03:00
}
int TimeRecord : : length ( )
{
2019-01-13 14:11:00 +03:00
return static_cast < int > ( mEndTime - mStartTime ) ;
2018-09-25 22:55:14 +03:00
}
Id TimeRecord : : id ( ) const
{
2018-12-21 23:11:26 +02:00
return mId ;
2018-09-25 22:55:14 +03:00
}
void TimeRecord : : setId ( Id id )
{
2018-12-21 23:11:26 +02:00
mId = id ;
2018-09-25 22:55:14 +03:00
}
Id TimeRecord : : taskId ( ) const
{
2018-12-21 23:11:26 +02:00
return mTaskId ;
2018-09-25 22:55:14 +03:00
}
void TimeRecord : : setTaskId ( Id id )
{
2018-12-21 23:11:26 +02:00
mTaskId = id ;
2018-09-25 22:55:14 +03:00
}
WorldId TimeRecord : : worldId ( ) const
{
2018-12-21 23:11:26 +02:00
return mWorldId ;
2018-09-25 22:55:14 +03:00
}
void TimeRecord : : setWorldId ( const WorldId & id )
{
2018-12-21 23:11:26 +02:00
mWorldId = id ;
2018-09-25 22:55:14 +03:00
}
void TimeRecord : : save ( )
{
2018-12-21 23:11:26 +02:00
if ( ! mId )
{
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " insert into timeline(id, starttime, endtime, taskid, removed) values (NULL, :starttime, :endtime, :taskid, :removed) " ) ;
2019-01-13 14:11:00 +03:00
q . bind ( " :starttime " , helper : : chrono : : timeToStr ( mStartTime ) ) ;
q . bind ( " :endtime " , helper : : chrono : : timeToStr ( mEndTime ) ) ;
q . bind ( " :taskid " , static_cast < sqlite3_int64 > ( mTaskId ) ) ;
2018-12-21 23:11:26 +02:00
q . bind ( " :removed " , 0 ) ;
if ( q . exec ( ) )
mId = Storage : : instance ( ) . database ( ) . getLastInsertRowid ( ) ;
}
else
{
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) ,
" update timeline set starttime = :starttime, endtime = :endtime, taskid = :taskid, removed = 0 where id = :id " ) ;
2019-01-13 14:11:00 +03:00
q . bind ( " :starttime " , helper : : chrono : : timeToStr ( mStartTime ) ) ;
q . bind ( " :endtime " , helper : : chrono : : timeToStr ( mEndTime ) ) ;
q . bind ( " :taskid " , static_cast < sqlite3_int64 > ( mTaskId ) ) ;
q . bind ( " :id " , static_cast < sqlite3_int64 > ( mId ) ) ;
2018-12-21 23:11:26 +02:00
q . exec ( ) ;
}
2018-09-25 22:55:14 +03:00
}
void TimeRecord : : deleteRecord ( )
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " update timeline set removed = 1 where id = :id " ) ;
2019-01-13 14:11:00 +03:00
q . bind ( " :id " , static_cast < sqlite3_int64 > ( mId ) ) ;
2018-12-21 23:11:26 +02:00
q . exec ( ) ;
2018-09-25 22:55:14 +03:00
}
// -------------------- TimeLine --------------------
TimeLine : : TimeLine ( )
2019-03-26 16:32:48 +02:00
: mTaskId ( 0 ) , mActive ( false ) , mActiveTimeRecord ( nullptr ) , mTotalTime ( 0 )
2018-09-25 22:55:14 +03:00
{ }
TimeLine : : ~ TimeLine ( )
{ }
int TimeLine : : findTotalTime ( )
{
2018-12-21 23:11:26 +02:00
int result = 0 ;
2019-01-13 14:11:00 +03:00
for ( auto & t : mData )
2018-12-21 23:11:26 +02:00
{
2019-01-13 14:11:00 +03:00
int delta = static_cast < int > ( t . endTime ( ) - t . startTime ( ) ) ;
2018-12-21 23:11:26 +02:00
result + = delta + 1 ;
}
return result ;
2018-09-25 22:55:14 +03:00
}
int TimeLine : : totalTime ( )
{
2018-12-21 23:11:26 +02:00
return mTotalTime ;
2018-09-25 22:55:14 +03:00
}
bool TimeLine : : active ( )
{
2018-12-21 23:11:26 +02:00
return mActive ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : start ( )
{
2018-12-21 23:11:26 +02:00
if ( mActive )
return ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Mark timeline as active - it means it records time interval now
mActive = true ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Find current time in UTC format
time_t current = time ( nullptr ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Check if current time point does not belong to any existing time interval
if ( hasTimePoint ( current ) )
mActiveTimeRecord = nullptr ;
else
mActiveTimeRecord = makeNewRecord ( current , current ) ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
TimeRecord * TimeLine : : makeNewRecord ( time_t beginTime , time_t endTime )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
TimeRecord tr ;
tr . setStartTime ( beginTime ) ;
tr . setEndTime ( endTime ) ;
tr . setTaskId ( mTaskId ) ;
tr . save ( ) ;
mData . push_back ( tr ) ;
Id intervalId = tr . id ( ) ;
sortData ( ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
std : : reverse_iterator < TimeArray : : iterator > intervalIter = std : : find_if ( std : : reverse_iterator < TimeArray : : iterator > ( mData . end ( ) ) ,
std : : reverse_iterator < TimeArray : : iterator > ( mData . begin ( ) ) ,
[ = ] ( const TimeRecord & tr )
{
return tr . id ( ) = = intervalId ;
} ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( intervalIter ! = std : : reverse_iterator < TimeArray : : iterator > ( mData . begin ( ) ) )
return & ( * intervalIter ) ;
else
return nullptr ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
TimeRecord * TimeLine : : hasTimePoint ( time_t t )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
if ( mData . empty ( ) )
return nullptr ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
TimeRecord * tr = nullptr ;
TimeArray : : iterator result ;
result = std : : upper_bound ( mData . begin ( ) , mData . end ( ) , t ,
[ ] ( time_t t2 , const TimeRecord & tr )
{
return tr . startTime ( ) > t2 ;
} ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( result = = mData . end ( ) )
2019-01-13 14:11:00 +03:00
tr = & mData . back ( ) ;
2018-12-21 23:11:26 +02:00
else
if ( result ! = mData . begin ( ) )
tr = & ( * ( - - result ) ) ;
else
return nullptr ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
return ( tr - > startTime ( ) < = t & & tr - > endTime ( ) > = t ) ? tr : nullptr ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : sortData ( )
{
2018-12-21 23:11:26 +02:00
std : : sort ( mData . begin ( ) , mData . end ( ) , [ ] ( const TimeRecord & lhs , const TimeRecord & rhs ) { return lhs . startTime ( ) < rhs . startTime ( ) ; } ) ;
2018-09-25 22:55:14 +03:00
}
bool TimeLine : : hasIntersection ( const TimeRecord & interval )
{
2018-12-21 23:11:26 +02:00
if ( mData . empty ( ) )
return false ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
TimeArray : : iterator result ;
result = std : : upper_bound ( mData . begin ( ) , mData . end ( ) , interval . startTime ( ) ,
[ ] ( time_t t2 , const TimeRecord & tr )
{ return tr . startTime ( ) > t2 ; } ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( result = = mData . end ( ) )
{
// There is time record which start point is lesser than interval.startTime()
2019-01-13 14:11:00 +03:00
return ( mData . back ( ) . endTime ( ) > = interval . startTime ( ) ) ;
2018-12-21 23:11:26 +02:00
}
else
if ( result ! = mData . begin ( ) )
{
TimeRecord & prev = * ( result - 1 ) ;
TimeRecord & next = * result ;
if ( prev . endTime ( ) > = interval . startTime ( ) )
return true ;
if ( next . startTime ( ) < = interval . endTime ( ) )
return true ;
}
else
{
if ( mData . front ( ) . startTime ( ) < = interval . endTime ( ) )
return true ;
}
return false ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : insertInterval ( const TimeRecord & interval )
{
2018-12-21 23:11:26 +02:00
mData . push_back ( interval ) ;
2019-01-13 14:11:00 +03:00
mData . back ( ) . save ( ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
sortData ( ) ;
2018-09-25 22:55:14 +03:00
}
bool TimeLine : : removeInterval ( const TimeRecord & interval )
{
2018-12-21 23:11:26 +02:00
// Find interval by binary search
if ( mData . empty ( ) )
return false ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
TimeArray : : iterator result ;
result = std : : upper_bound ( mData . begin ( ) , mData . end ( ) , interval . startTime ( ) ,
[ ] ( time_t t2 , const TimeRecord & tr )
{ return tr . startTime ( ) > t2 ; } ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( result = = mData . end ( ) )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
// There is time record which start point is lesser than interval.startTime()
2019-01-13 14:11:00 +03:00
if ( mData . back ( ) . id ( ) = = interval . id ( ) )
2018-12-21 23:11:26 +02:00
{
// Remove from DB
mData . back ( ) . deleteRecord ( ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Remove from memory
mData . erase ( mData . begin ( ) + mData . size ( ) - 1 ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
return true ;
}
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
else
if ( result ! = mData . begin ( ) )
{
result - - ;
if ( result - > id ( ) = = interval . id ( ) )
{
// Remove from DB
result - > deleteRecord ( ) ;
// Remove from memory
mData . erase ( result ) ;
return true ;
}
}
return false ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : cutInterval ( const TimeRecord & interval )
{
2018-12-21 23:11:26 +02:00
// Find interval that startTime() time is greater than interval.endTime()
TimeArray : : iterator iter ;
iter = std : : upper_bound ( mData . begin ( ) , mData . end ( ) , interval . endTime ( ) ,
[ ] ( time_t t2 , const TimeRecord & tr )
{ return tr . startTime ( ) > t2 ; } ) ;
// If all intervals begins later() than requested interval - exit silently
if ( iter = = mData . begin ( ) )
return ;
// Go to previous interval - it is first interval to check
if ( iter = = mData . end ( ) )
iter = mData . begin ( ) + mData . size ( ) - 1 ;
2018-09-25 22:55:14 +03:00
else
2018-12-21 23:11:26 +02:00
iter - - ;
bool done = false ;
// Loop while current interval end time is greater than cut interval start time
while ( iter - > endTime ( ) > = interval . startTime ( ) )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
if ( iter - > endTime ( ) > interval . endTime ( ) )
{
if ( iter - > startTime ( ) > = interval . startTime ( ) )
{
iter - > setStartTime ( iter - > endTime ( ) + 1 ) ; // Current interval starts in [interval.startTime(), interval.endTime()], but finishes later
iter - > save ( ) ;
}
else
{
// Current interval starts before interval.startTime() and finishes later
// So cut interval will split it to 2 new intervals
// Also this operation will end loop
TimeRecord toInsert ( * iter ) ; // Backup current interval
iter - > setEndTime ( interval . startTime ( ) - 1 ) ;
iter - > save ( ) ;
toInsert . setStartTime ( interval . endTime ( ) + 1 ) ;
mData . insert ( + + iter , toInsert ) ;
toInsert . save ( ) ;
done = true ;
break ;
}
}
else
{
if ( iter - > startTime ( ) > = interval . startTime ( ) )
{
iter - > deleteRecord ( ) ;
iter = mData . erase ( iter ) ; // Current interval fits into cut interval
}
else
{
// Current interval starts before cut interval but finishes in cut interval
iter - > setEndTime ( interval . startTime ( ) - 1 ) ;
iter - > save ( ) ;
done = true ;
break ;
}
}
if ( iter = = mData . begin ( ) )
break ;
iter - - ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
// Look for exact the same interval as specified one
if ( ! done )
{
iter = std : : find_if ( mData . begin ( ) , mData . end ( ) ,
[ = ] ( const TimeRecord & tr )
{ return tr . id ( ) = = interval . id ( ) ; } ) ;
if ( iter ! = mData . end ( ) )
mData . erase ( iter ) ;
}
2018-09-25 22:55:14 +03:00
}
TimeRecord * TimeLine : : findIntervalById ( Id id )
{
2018-12-21 23:11:26 +02:00
TimeArray : : iterator iter = std : : find_if ( mData . begin ( ) , mData . end ( ) ,
[ = ] ( const TimeRecord & tr )
{ return tr . id ( ) = = id ; } ) ;
if ( iter = = mData . end ( ) )
return nullptr ;
return & ( * iter ) ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : stop ( bool updateTimeline )
{
2018-12-21 23:11:26 +02:00
if ( ! mActive )
return ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( updateTimeline )
flush ( true , time ( nullptr ) ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
mActive = false ;
mActiveTimeRecord = nullptr ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
void TimeLine : : flush ( bool saveToDb , time_t currentUtc )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
if ( ! mActive )
return ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( mActiveTimeRecord )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
long delta = currentUtc - mActiveTimeRecord - > endTime ( ) ;
2018-12-21 23:11:26 +02:00
mActiveTimeRecord - > setEndTime ( currentUtc ) ;
TimeRecord * tr = hasTimePoint ( currentUtc ) ;
if ( tr & & tr ! = mActiveTimeRecord )
{
mActiveTimeRecord - > setEndTime ( currentUtc ) ;
mActiveTimeRecord - > save ( ) ;
mActiveTimeRecord = nullptr ;
}
if ( saveToDb & & mActiveTimeRecord )
mActiveTimeRecord - > save ( ) ;
mTotalTime + = delta ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
else
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
if ( ! hasTimePoint ( currentUtc ) )
{
// Start new record here
mActiveTimeRecord = makeNewRecord ( currentUtc , currentUtc ) ;
}
2018-09-25 22:55:14 +03:00
}
}
void TimeLine : : load ( )
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " select id, starttime, endtime from timeline where (taskid = :taskid) and ((removed is null) or (removed != 1)) order by id asc " ) ;
2019-03-26 16:32:48 +02:00
q . bind ( " :taskid " , mTaskId ) ;
2018-12-21 23:11:26 +02:00
while ( q . executeStep ( ) )
{
2019-01-13 14:11:00 +03:00
time_t start = helper : : chrono : : strToTime ( q . getColumn ( 1 ) . getText ( ) ) ;
time_t stop = helper : : chrono : : strToTime ( q . getColumn ( 2 ) . getText ( ) ) ;
2018-12-21 23:11:26 +02:00
TimeRecord tr ;
tr . setId ( q . getColumn ( 0 ) . getInt64 ( ) ) ;
tr . setStartTime ( start ) ;
tr . setEndTime ( stop ) ;
tr . setTaskId ( mTaskId ) ;
mData . push_back ( tr ) ;
}
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Sort time intervals
sortData ( ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Find current total time length
mTotalTime = findTotalTime ( ) ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : save ( )
{
2018-12-21 23:11:26 +02:00
// No need to save anything here - everything is saved right on creation/update
2018-09-25 22:55:14 +03:00
}
Id TimeLine : : taskId ( )
{
2018-12-21 23:11:26 +02:00
return mTaskId ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : setTaskId ( Id id )
{
2018-12-21 23:11:26 +02:00
mTaskId = id ;
2018-09-25 22:55:14 +03:00
}
TimeArray & TimeLine : : data ( )
{
2018-12-21 23:11:26 +02:00
return mData ;
2018-09-25 22:55:14 +03:00
}
2019-03-26 16:32:48 +02:00
std : : set < int > TimeLine : : getYears ( )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
std : : set < int > r ;
2018-12-21 23:11:26 +02:00
if ( mData . empty ( ) )
2019-03-26 16:32:48 +02:00
return r ;
2018-09-25 22:55:14 +03:00
2019-03-26 16:32:48 +02:00
date t1 = date : : fromTimestamp ( mData . front ( ) . startTime ( ) , date : : To_LocalTime ) ,
t2 = date : : fromTimestamp ( mData . back ( ) . startTime ( ) , date : : To_LocalTime ) ;
2018-09-25 22:55:14 +03:00
2019-03-26 16:32:48 +02:00
r . insert ( t1 . mYear ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Find higher bound of years - it is last time record
2019-03-26 16:32:48 +02:00
if ( t1 . mYear = = t2 . mYear )
return r ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Try to find next year by binary search
2019-03-26 16:32:48 +02:00
for ( int year = t1 . mYear + 1 ; year < = t2 . mYear ; year + + )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
date yearStart ( year , 1 , 1 ) ;
2018-12-21 23:11:26 +02:00
TimeArray : : iterator iter = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , yearStart ,
2019-03-26 16:32:48 +02:00
[ & ] ( const TimeRecord & lhs , date rhs )
{
return date : : fromTimestamp ( lhs . endTime ( ) , date : : To_LocalTime ) < rhs ;
} ) ;
2018-12-21 23:11:26 +02:00
if ( iter ! = mData . end ( ) )
{
2019-03-26 16:32:48 +02:00
// Get found year
date found_date = date : : fromTimestamp ( iter - > startTime ( ) , date : : To_LocalTime ) ;
if ( found_date . mYear < = year )
r . insert ( year ) ;
2018-12-21 23:11:26 +02:00
}
2018-09-25 22:55:14 +03:00
}
2019-03-26 16:32:48 +02:00
return r ;
2018-09-25 22:55:14 +03:00
}
2019-03-26 16:32:48 +02:00
std : : set < int > TimeLine : : getMonthes ( int year )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
std : : set < int > r ;
2018-12-21 23:11:26 +02:00
for ( int month = 1 ; month < = 12 ; month + + )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
date monthBegin ( year , month , 1 ) ;
date monthEnd ( year , month , date : : daysInMonth ( year , month ) ) ;
2018-12-21 23:11:26 +02:00
// Find range for every month in year [lowest, higher)
2019-01-13 14:11:00 +03:00
TimeArray : : iterator lowest = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , monthBegin ,
2019-03-26 16:32:48 +02:00
[ ] ( const TimeRecord & tr , const date & d )
{
return date : : fromTimestamp ( tr . endTime ( ) , date : : To_LocalTime ) < d ;
} ) ;
2018-12-21 23:11:26 +02:00
//TimeArray::iterator higher = std::upper_bound(mData.begin(), mData.end(), monthEnd, [] (const TimeRecord& tr, const QDate& d) { return tr.startTime().toLocalTime().date() < d;});
if ( lowest ! = mData . end ( ) )
{
2019-01-13 14:11:00 +03:00
// Current date is local time!
2019-03-26 16:32:48 +02:00
helper : : date currentDate = helper : : date : : fromTimestamp ( lowest - > startTime ( ) , helper : : date : : To_LocalTime ) ;
2019-01-13 14:11:00 +03:00
if ( currentDate . mYear > year )
2018-12-21 23:11:26 +02:00
continue ;
2019-01-13 14:11:00 +03:00
if ( currentDate . mYear = = year & & currentDate . mMonth > month )
2018-12-21 23:11:26 +02:00
continue ;
2019-03-26 16:32:48 +02:00
r . insert ( month ) ;
2018-12-21 23:11:26 +02:00
}
2018-09-25 22:55:14 +03:00
}
2019-03-26 16:32:48 +02:00
return r ;
2018-09-25 22:55:14 +03:00
}
2019-03-26 16:32:48 +02:00
std : : set < int > TimeLine : : getDays ( int year , int month )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
std : : set < int > r ;
date monthBegin ( year , month , 1 ) ;
for ( int day = 1 ; day < = date : : daysInMonth ( year , month ) ; day + + )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
date currentDay ( year , month , day ) ;
2018-12-21 23:11:26 +02:00
2019-01-13 14:11:00 +03:00
TimeArray : : iterator lowest = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , currentDay ,
2019-03-26 16:32:48 +02:00
[ ] ( const TimeRecord & tr , const date & d )
2019-01-13 14:11:00 +03:00
{
2019-03-26 16:32:48 +02:00
return date : : fromTimestamp ( tr . endTime ( ) , date : : To_LocalTime ) < d ;
2019-01-13 14:11:00 +03:00
} ) ;
2018-12-21 23:11:26 +02:00
if ( lowest ! = mData . end ( ) )
{
2019-03-26 16:32:48 +02:00
helper : : date startDate = helper : : date : : fromTimestamp ( lowest - > startTime ( ) , helper : : date : : To_LocalTime ) ;
2019-01-13 14:11:00 +03:00
if ( startDate . mYear > year )
2018-12-21 23:11:26 +02:00
continue ;
2019-01-13 14:11:00 +03:00
if ( startDate . mYear = = year & & startDate . mMonth > month )
2018-12-21 23:11:26 +02:00
continue ;
2019-01-13 14:11:00 +03:00
if ( startDate . mYear = = year & & startDate . mMonth = = month & & startDate . mDay > day )
2018-12-21 23:11:26 +02:00
continue ;
2019-03-26 16:32:48 +02:00
r . insert ( day ) ;
2018-12-21 23:11:26 +02:00
}
2018-09-25 22:55:14 +03:00
}
2019-03-26 16:32:48 +02:00
return r ;
2018-09-25 22:55:14 +03:00
}
int TimeLine : : getTime ( int year , int month , int day , std : : vector < TimeRecord > * intervals )
{
2018-12-21 23:11:26 +02:00
int result = 0 ;
QDate d ( year , month , day ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Find range of related records [lowest, higher)
2019-01-13 14:11:00 +03:00
TimeArray : : iterator lowest = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , d , [ ] ( const TimeRecord & tr , const QDate & d )
{
return tr . endTime ( ) < QDateTime ( d ) . toTime_t ( ) ;
} ) ;
2018-12-21 23:11:26 +02:00
//TimeArray::iterator higher = std::upper_bound(mData.begin(), mData.end(), d, [] (const QDate& d, const TimeRecord& tr) { return tr.startTime().toLocalTime().date() < d;});
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
for ( ; lowest ! = mData . end ( ) ; /*&& lowest != higher;*/ lowest + + )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
TimeRecord & tr = * lowest ;
2019-01-13 14:11:00 +03:00
2019-03-26 16:32:48 +02:00
helper : : date startDate = helper : : date : : fromTimestamp ( tr . startTime ( ) , date : : To_LocalTime ) ;
2019-01-13 14:11:00 +03:00
if ( startDate . mYear > year )
2018-12-21 23:11:26 +02:00
break ;
2019-01-13 14:11:00 +03:00
if ( startDate . mYear = = year & & startDate . mMonth > month )
2018-12-21 23:11:26 +02:00
break ;
2019-01-13 14:11:00 +03:00
if ( startDate . mYear = = year & &
startDate . mMonth = = month & &
startDate . mDay > day )
2018-12-21 23:11:26 +02:00
break ;
2019-01-13 14:11:00 +03:00
time_t dayBegin = helper : : date { year , month , day } . toTimestamp ( ) ;
time_t dayEnd = dayBegin + 86399 ;
2018-12-21 23:11:26 +02:00
2019-01-13 14:11:00 +03:00
if ( tr . startTime ( ) > dayBegin )
dayBegin = tr . startTime ( ) ; // Time record begin is later than begin of the day
2018-12-21 23:11:26 +02:00
2019-01-13 14:11:00 +03:00
if ( tr . endTime ( ) < dayEnd )
dayEnd = tr . endTime ( ) ;
2018-12-21 23:11:26 +02:00
if ( intervals )
{
TimeRecord resultingRecord ;
resultingRecord . setStartTime ( dayBegin ) ;
resultingRecord . setEndTime ( dayEnd ) ;
resultingRecord . setId ( tr . id ( ) ) ;
resultingRecord . setTaskId ( tr . taskId ( ) ) ;
intervals - > push_back ( resultingRecord ) ;
}
result + + ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
return result ;
2018-09-25 22:55:14 +03:00
}
int TimeLine : : today ( )
{
2018-12-21 23:11:26 +02:00
int result = 0 ;
2018-09-25 22:55:14 +03:00
2019-03-26 16:32:48 +02:00
// Find starting record related to today
// Today is local time!
date today = date : : today ( ) ;
TimeArray : : iterator lowIter = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , today ,
[ ] ( const TimeRecord & lhs , const date & rhs )
2018-12-21 23:11:26 +02:00
{
2019-03-26 16:32:48 +02:00
return date : : fromTimestamp ( lhs . endTime ( ) , date : : To_LocalTime ) < rhs ;
2018-12-21 23:11:26 +02:00
} ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
for ( ; lowIter ! = mData . end ( ) ; lowIter + + )
2018-09-25 22:55:14 +03:00
{
2019-03-26 16:32:48 +02:00
if ( date : : fromTimestamp ( lowIter - > startTime ( ) , date : : To_LocalTime ) > today )
2018-12-21 23:11:26 +02:00
break ; // quit the loop
2019-03-26 16:32:48 +02:00
if ( date : : fromTimestamp ( lowIter - > endTime ( ) , date : : To_LocalTime ) > = today )
2018-12-21 23:11:26 +02:00
{
2019-03-26 16:32:48 +02:00
// Both are GMT time
time_t dayBegin = date : : today ( ) . toTimestamp ( ) ;
time_t dayEnd = dayBegin + 86359 ;
2018-09-25 22:55:14 +03:00
2019-03-26 16:32:48 +02:00
int64_t secondsTo = lowIter - > startTime ( ) - dayBegin ;
2018-12-21 23:11:26 +02:00
if ( secondsTo > 0 )
dayBegin = lowIter - > startTime ( ) ;
2018-09-25 22:55:14 +03:00
2019-03-26 16:32:48 +02:00
int64_t secondsFrom = lowIter - > endTime ( ) - dayEnd ;
2018-12-21 23:11:26 +02:00
if ( secondsFrom < 0 )
2019-03-26 16:32:48 +02:00
dayEnd = lowIter - > endTime ( ) ;
2018-09-25 22:55:14 +03:00
2019-03-26 16:32:48 +02:00
int secondsSpent = dayEnd - dayBegin ;
2018-12-21 23:11:26 +02:00
result + = secondsSpent ;
}
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
return result ;
2018-09-25 22:55:14 +03:00
}
int TimeLine : : month ( )
{
2018-12-21 23:11:26 +02:00
int result = 0 ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Find first day of month
2019-03-26 21:30:03 +02:00
date this_month = date : : today ( ) ;
this_month . mDay = 1 ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
// Find position in time record array close to month begin
2019-03-26 21:30:03 +02:00
TimeArray : : iterator lowIter = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , this_month ,
[ ] ( const TimeRecord & lhs , const date & rhs )
{
return date : : fromTimestamp ( lhs . endTime ( ) , date : : To_LocalTime ) < rhs ;
} ) ;
2018-09-25 22:55:14 +03:00
2019-03-26 21:30:03 +02:00
while ( lowIter ! = mData . end ( ) )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
// See if start of current time period is later than current month
2019-03-26 21:30:03 +02:00
if ( date : : fromTimestamp ( lowIter - > startTime ( ) , date : : To_LocalTime ) . mMonth > this_month . mMonth )
2018-12-21 23:11:26 +02:00
break ; // quit the loop
2019-03-26 21:30:03 +02:00
if ( date : : fromTimestamp ( lowIter - > endTime ( ) , date : : To_LocalTime ) . mMonth > = this_month . mMonth )
2018-12-21 23:11:26 +02:00
{
2019-03-26 21:30:03 +02:00
// GMT time!
time_t month_begin = this_month . toTimestamp ( ) ;
time_t month_end = month_begin + date : : daysInMonth ( this_month . mYear , this_month . mMonth ) * 86400 - 1 ;
2018-12-21 23:11:26 +02:00
2019-03-26 21:30:03 +02:00
int64_t secondsTo = lowIter - > startTime ( ) - month_begin ;
2018-12-21 23:11:26 +02:00
if ( secondsTo > 0 )
2019-03-26 21:30:03 +02:00
month_begin = lowIter - > startTime ( ) ;
2018-12-21 23:11:26 +02:00
2019-03-26 21:30:03 +02:00
int64_t secondsFrom = lowIter - > endTime ( ) - month_end ;
2018-12-21 23:11:26 +02:00
if ( secondsFrom < 0 )
2019-03-26 21:30:03 +02:00
month_end = lowIter - > endTime ( ) ;
2018-12-21 23:11:26 +02:00
2019-03-26 21:30:03 +02:00
int64_t secondsSpent = month_end - month_begin ;
2018-12-21 23:11:26 +02:00
result + = secondsSpent ;
}
2019-03-26 21:30:03 +02:00
lowIter + + ;
2018-09-25 22:55:14 +03:00
}
2018-12-21 23:11:26 +02:00
return result ;
2018-09-25 22:55:14 +03:00
}
2019-03-26 21:30:03 +02:00
int TimeLine : : getSum ( const date & start , const date & finish )
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
int result = 0 ;
2018-09-25 22:55:14 +03:00
2019-03-26 21:30:03 +02:00
TimeArray : : iterator lowest = std : : lower_bound ( mData . begin ( ) , mData . end ( ) , start ,
[ ] ( const TimeRecord & tr , const date & d )
{
return date : : fromTimestamp ( tr . endTime ( ) , date : : To_LocalTime ) < d ;
} ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
for ( ; lowest ! = mData . end ( ) ; lowest + + )
{
TimeRecord & tr = * lowest ;
2019-03-26 21:30:03 +02:00
if ( date : : fromTimestamp ( tr . startTime ( ) , date : : To_LocalTime ) > finish )
2018-12-21 23:11:26 +02:00
break ;
2018-09-25 22:55:14 +03:00
2019-03-26 21:30:03 +02:00
time_t day_begin = start . toTimestamp ( ) ;
time_t day_end = finish . toTimestamp ( ) + 86400 - 1 ;
2018-09-25 22:55:14 +03:00
2019-03-26 21:30:03 +02:00
if ( day_begin - tr . startTime ( ) < 0 )
day_begin = tr . startTime ( ) ; // Time record begin is later than begin of the interval
2018-09-25 22:55:14 +03:00
2019-03-26 21:30:03 +02:00
if ( day_end - tr . endTime ( ) > 0 )
day_end = tr . endTime ( ) ;
2018-09-25 22:55:14 +03:00
2019-03-26 21:30:03 +02:00
result + = day_end - day_begin ;
2018-12-21 23:11:26 +02:00
}
return result ;
2018-09-25 22:55:14 +03:00
}
bool TimeLine : : duplicateDetected ( ) const
{
2018-12-21 23:11:26 +02:00
return mActiveTimeRecord = = nullptr ;
2018-09-25 22:55:14 +03:00
}
void TimeLine : : putDebugRecord ( )
{
2019-03-26 21:30:03 +02:00
time_t current = time ( nullptr ) ;
time_t end = current + 600 ;
2018-12-21 23:11:26 +02:00
TimeRecord * r = makeNewRecord ( current , end ) ;
r - > save ( ) ;
2018-09-25 22:55:14 +03:00
}
// -------------------- Task --------------------------
static Task : : ModelId ModelIdGenerator = 0 ;
Task : : Task ( )
2018-12-21 23:11:26 +02:00
: mId ( 0 ) , mTitleModified ( false ) , mHtmlModified ( false ) , mHtmlLoaded ( false ) , mModelId ( + + ModelIdGenerator ) ,
mParentId ( - 1 ) , mIndex ( - 1 ) , mChecked ( false ) , mIndexModified ( false ) ,
mParentModified ( false ) , mReportedTime ( 0 ) , mChildrenReportedTime ( 0 ) , mAttachmentCount ( 0 ) ,
mDocument ( nullptr ) , mCursorPosition ( 0 )
2018-09-25 22:55:14 +03:00
{
}
Task : : ~ Task ( )
{
}
void Task : : load ( SQLite : : Statement & q )
{
2018-12-21 23:11:26 +02:00
mId = q . getColumn ( 0 ) . getInt64 ( ) ;
mTitle = q . getColumn ( 1 ) . getText ( ) ;
mIndex = q . getColumn ( 2 ) . getInt ( ) ;
mFlags = q . getColumn ( 3 ) . getInt ( ) ;
mAttachmentCount = q . getColumn ( 4 ) . getInt ( ) ;
2018-09-25 22:55:14 +03:00
}
Task : : Id Task : : id ( ) const
{
2018-12-21 23:11:26 +02:00
return mId ;
2018-09-25 22:55:14 +03:00
}
void Task : : setId ( Id id )
{
2018-12-21 23:11:26 +02:00
mId = id ;
2018-09-25 22:55:14 +03:00
}
Task : : Id Task : : parentId ( ) const
{
2018-12-21 23:11:26 +02:00
return mParentId ;
2018-09-25 22:55:14 +03:00
}
void Task : : setParentId ( Id id )
{
2018-12-21 23:11:26 +02:00
if ( mParentId ! = id )
{
mParentModified = true ;
mParentId = id ;
}
2018-09-25 22:55:14 +03:00
}
WorldId Task : : worldId ( ) const
{
2018-12-21 23:11:26 +02:00
return mWorldId ;
2018-09-25 22:55:14 +03:00
}
void Task : : setWorldId ( const WorldId & id )
{
2018-12-21 23:11:26 +02:00
mWorldId = id ;
2018-09-25 22:55:14 +03:00
}
Task : : ModelId Task : : modelId ( ) const
{
2018-12-21 23:11:26 +02:00
return mModelId ;
2018-09-25 22:55:14 +03:00
}
void Task : : setModelId ( ModelId id )
{
2018-12-21 23:11:26 +02:00
mModelId = id ;
2018-09-25 22:55:14 +03:00
}
int Task : : index ( ) const
{
2018-12-21 23:11:26 +02:00
return mIndex ;
2018-09-25 22:55:14 +03:00
}
void Task : : setIndex ( int index , bool modified )
{
2018-12-21 23:11:26 +02:00
if ( index ! = mIndex )
{
if ( modified )
mIndexModified = true ;
mIndex = index ;
}
2018-09-25 22:55:14 +03:00
}
QString Task : : html ( ) const
{
2018-12-21 23:11:26 +02:00
return mHtml ;
2018-09-25 22:55:14 +03:00
}
void Task : : setHtml ( const QString & html )
{
2018-12-21 23:11:26 +02:00
if ( mHtml ! = html )
{
mHtml = html ;
mHtmlModified = true ;
}
2018-09-25 22:55:14 +03:00
}
QString Task : : title ( ) const
{
2018-12-21 23:11:26 +02:00
return mTitle ;
2018-09-25 22:55:14 +03:00
}
void Task : : setTitle ( const QString & title , bool modified )
{
2018-12-21 23:11:26 +02:00
if ( mTitle ! = title )
{
mTitle = title ;
if ( modified )
mTitleModified = true ;
}
2018-09-25 22:55:14 +03:00
}
void Task : : save ( SaveOptions options )
{
2018-12-21 23:11:26 +02:00
if ( ! mTitleModified & & ! mHtmlModified & & ! mIndexModified & & ! mParentModified & & options = = Save_Automatic )
return ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
const char * queryText = NULL ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( mTitleModified & & mHtmlModified )
queryText = " update task set parentid = :parentid, flags = :flags, title = :title, html = :html, orderid = :orderid where id = :id " ;
else
if ( mTitleModified )
queryText = " update task set parentid = :parentid, flags = :flags, title = :title, orderid = :orderid where id = :id " ;
else
if ( mHtmlModified )
queryText = " update task set parentid = :parentid, flags = :flags, html = :html, orderid = :orderid where id = :id " ;
else
queryText = " update task set parentid = :parentid, flags = :flags, orderid = :orderid where id = :id " ;
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , queryText ) ;
if ( mParent )
q . bind ( " :parentid " , ( sqlite3_int64 ) mParent - > id ( ) ) ;
else
q . bind ( " :parentid " ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
q . bind ( " :flags " , mFlags ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( mTitleModified )
q . bind ( " :title " , mTitle . toStdString ( ) ) ;
if ( mHtmlModified )
q . bind ( " :html " , mHtml . toStdString ( ) ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
q . bind ( " :id " , ( sqlite3_int64 ) mId ) ;
q . bind ( " :orderid " , mIndex ) ;
q . exec ( ) ;
mIndexModified = mTitleModified = mHtmlModified = false ;
2018-09-25 22:55:14 +03:00
}
/*void Task::load()
{
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " select parentid, title, html, orderid from task where (id = :id) and (type = 0) " ) ;
q . bind ( " :id " , ( sqlite3_int64 ) mId ) ;
if ( q . executeStep ( ) )
{
mParentId = q . getColumn ( 0 ) . getInt64 ( ) ;
mTitle = q . getColumn ( 1 ) . getText ( ) ;
mHtml = q . getColumn ( 2 ) . getText ( ) ;
mIndex = q . getColumn ( 3 ) . getInt ( ) ;
}
mTitleModified = mHtmlModified = false ;
mHtmlLoaded = true ;
checkAttachments ( ) ;
} */
QString Task : : path ( ) const
{
2018-12-21 23:11:26 +02:00
QString result = this - > title ( ) ;
if ( parent ( ) )
result . insert ( 0 , parent ( ) - > path ( ) + " / " ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
return result ;
2018-09-25 22:55:14 +03:00
}
PTask Task : : parent ( ) const
{
2018-12-21 23:11:26 +02:00
return mParent ;
2018-09-25 22:55:14 +03:00
}
void Task : : setParent ( PTask task , bool modified )
{
2018-12-21 23:11:26 +02:00
if ( mParent ! = task )
{
mParent = task ;
if ( task )
mParentId = task - > id ( ) ;
else
mParentId = - 1 ;
if ( modified )
mTitleModified = true ; // To force save()
}
2018-09-25 22:55:14 +03:00
}
TaskArray & Task : : children ( )
{
2018-12-21 23:11:26 +02:00
return mChildren ;
2018-09-25 22:55:14 +03:00
}
void Task : : loadContent ( )
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement htmlQuery ( Storage : : instance ( ) . database ( ) , " select html from task where id = :id " ) ;
htmlQuery . bind ( " :id " , ( sqlite3_int64 ) mId ) ;
if ( htmlQuery . executeStep ( ) )
{
mHtml = htmlQuery . getColumn ( 0 ) . getText ( ) ;
mHtmlLoaded = true ;
mHtmlModified = false ;
}
if ( ! mTimeLine )
{
mTimeLine = PTimeLine ( new TimeLine ( ) ) ;
mTimeLine - > setTaskId ( mId ) ;
mTimeLine - > load ( ) ;
}
2018-09-25 22:55:14 +03:00
}
bool Task : : isContentLoaded ( ) const
{
2018-12-21 23:11:26 +02:00
return mHtmlLoaded ;
2018-09-25 22:55:14 +03:00
}
void Task : : unloadContent ( bool includeTimeline )
{
2018-12-21 23:11:26 +02:00
mHtml . clear ( ) ;
mHtmlModified = mHtmlLoaded = false ;
if ( includeTimeline )
mTimeLine . clear ( ) ;
2018-09-25 22:55:14 +03:00
}
PTimeLine Task : : timeline ( )
{
2018-12-21 23:11:26 +02:00
return mTimeLine ;
2018-09-25 22:55:14 +03:00
}
int Task : : getAttachmentCount ( )
{
2018-12-21 23:11:26 +02:00
return mAttachmentCount ;
2018-09-25 22:55:14 +03:00
}
void Task : : setAttachmentCount ( int count )
{
2018-12-21 23:11:26 +02:00
mAttachmentCount = count ;
2018-09-25 22:55:14 +03:00
}
int Task : : checkAttachments ( )
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " select count(*) from file where (taskid = :taskid) and ((removed = 0) or (removed is null)) " ) ;
q . bind ( " :taskid " , ( sqlite3_int64 ) mId ) ;
if ( q . executeStep ( ) )
mAttachmentCount = q . getColumn ( 0 ) . getInt ( ) ;
else
mAttachmentCount = 0 ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
return mAttachmentCount ;
2018-09-25 22:55:14 +03:00
}
bool Task : : isChecked ( ) const
{
2018-12-21 23:11:26 +02:00
return mChecked ;
2018-09-25 22:55:14 +03:00
}
void Task : : setChecked ( bool checked )
{
2018-12-21 23:11:26 +02:00
mChecked = checked ;
2018-09-25 22:55:14 +03:00
}
int Task : : getReportedTime ( ) const
{
2018-12-21 23:11:26 +02:00
return mReportedTime ;
2018-09-25 22:55:14 +03:00
}
void Task : : setReportedTime ( int t )
{
2018-12-21 23:11:26 +02:00
mReportedTime = t ;
2018-09-25 22:55:14 +03:00
}
int Task : : getChildrenReportedTime ( ) const
{
2018-12-21 23:11:26 +02:00
return mChildrenReportedTime ;
2018-09-25 22:55:14 +03:00
}
void Task : : setChildrenReportedTime ( int t )
{
2018-12-21 23:11:26 +02:00
mChildrenReportedTime = t ;
2018-09-25 22:55:14 +03:00
}
int Task : : flags ( ) const
{
2018-12-21 23:11:26 +02:00
return mFlags ;
2018-09-25 22:55:14 +03:00
}
void Task : : setFlags ( int value )
{
2018-12-21 23:11:26 +02:00
mFlags = value ;
save ( Save_Forced ) ;
2018-09-25 22:55:14 +03:00
}
int Task : : cursorPosition ( ) const
{
2018-12-21 23:11:26 +02:00
return mCursorPosition ;
2018-09-25 22:55:14 +03:00
}
void Task : : setCursorPosition ( int position )
{
2018-12-21 23:11:26 +02:00
mCursorPosition = position ;
2018-09-25 22:55:14 +03:00
}
/*
QTextDocument * Task : : getTextDocument ( ) const
{
return mDocument ;
}
void Task : : setTextDocument ( QTextDocument * doc )
{
mDocument = doc ;
if ( mDocument )
mDocument - > setParent ( this ) ;
}
*/
// ----------- Attachment -------------
Attachment : : Attachment ( )
2018-12-21 23:11:26 +02:00
: mId ( 0 ) , mTaskId ( 0 )
2018-09-25 22:55:14 +03:00
{
}
Attachment : : ~ Attachment ( )
{
}
Task : : Id Attachment : : id ( )
{
2018-12-21 23:11:26 +02:00
return mId ;
2018-09-25 22:55:14 +03:00
}
void Attachment : : setId ( Task : : Id id )
{
2018-12-21 23:11:26 +02:00
mId = id ;
2018-09-25 22:55:14 +03:00
}
Task : : Id Attachment : : taskId ( )
{
2018-12-21 23:11:26 +02:00
return mTaskId ;
2018-09-25 22:55:14 +03:00
}
void Attachment : : setTaskId ( Task : : Id id )
{
2018-12-21 23:11:26 +02:00
mTaskId = id ;
2018-09-25 22:55:14 +03:00
}
WorldId Attachment : : worldId ( ) const
{
2018-12-21 23:11:26 +02:00
return mWorldId ;
2018-09-25 22:55:14 +03:00
}
void Attachment : : setWorldId ( const WorldId & id )
{
2018-12-21 23:11:26 +02:00
mWorldId = id ;
2018-09-25 22:55:14 +03:00
}
int Attachment : : index ( )
{
2018-12-21 23:11:26 +02:00
return mIndex ;
2018-09-25 22:55:14 +03:00
}
void Attachment : : setIndex ( int index )
{
2018-12-21 23:11:26 +02:00
//TODO: introduce mIndexModified field and corresponding login in save()
mIndex = index ;
2018-09-25 22:55:14 +03:00
}
QByteArray Attachment : : loadContent ( )
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " select content from file where id = :id " ) ;
q . bind ( " :id " , ( sqlite3_int64 ) mId ) ;
if ( q . executeStep ( ) )
return QByteArray ( ( const char * ) q . getColumn ( 0 ) . getBlob ( ) , q . getColumn ( 0 ) . size ( ) ) ;
else
return QByteArray ( ) ;
2018-09-25 22:55:14 +03:00
}
void Attachment : : saveContent ( const QByteArray & content )
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " update file set content = :content where id = :id " ) ;
q . bind ( " :content " , content . data ( ) , content . size ( ) ) ;
q . bind ( " :id " , ( sqlite3_int64 ) mId ) ;
if ( q . exec ( ) )
;
2018-09-25 22:55:14 +03:00
}
void Attachment : : setFilename ( const QString & filename )
{
2018-12-21 23:11:26 +02:00
mFilename = filename ;
2018-09-25 22:55:14 +03:00
}
QString Attachment : : filename ( )
{
2018-12-21 23:11:26 +02:00
return mFilename ;
2018-09-25 22:55:14 +03:00
}
// mDatabase->exec("CREATE TABLE file (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, filename TEXT, content BLOB, orderid INTEGER, synctime TEXT)");
void Attachment : : save ( )
{
2018-12-21 23:11:26 +02:00
if ( mId )
{
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " update file set filename = :filename, orderid = :orderid where id = :id " ) ;
q . bind ( " :filename " , mFilename . toStdString ( ) . c_str ( ) ) ;
q . bind ( " :orderid " , mIndex ) ;
q . bind ( " :id " , ( sqlite3_int64 ) mId ) ;
2018-09-25 22:55:14 +03:00
2018-12-21 23:11:26 +02:00
if ( q . exec ( ) )
;
}
else
2018-09-25 22:55:14 +03:00
{
2018-12-21 23:11:26 +02:00
SQLite : : Statement q ( Storage : : instance ( ) . database ( ) , " insert into file (filename, taskid, orderid, removed) values(:filename, :taskid, :orderid, 0) " ) ;
q . bind ( " :filename " , mFilename . toStdString ( ) . c_str ( ) ) ;
q . bind ( " :taskid " , ( sqlite3_int64 ) mTaskId ) ;
q . bind ( " :orderid " , mIndex ) ;
if ( q . exec ( ) )
{
mId = Storage : : instance ( ) . database ( ) . getLastInsertRowid ( ) ;
}
2018-09-25 22:55:14 +03:00
}
}
void Attachment : : load ( )
{
}