Hello, I have been improving the export to MyLifeOrganized.
Now I can export all my important information but cannot export the formatted text of the comments...
I can get the plain text comments with the following code:
LPCTSTR szComments = pSrcTaskFile->GetTaskComments(hTask);
But, how could I get the formatted version of it? Or, at least, to know if the text has been formatted or not?
Ideally, I would like to convert that formatted text to a markdown text or a html text, so MyLifeOrganized can display it...
Any ideas or help would be greatly appreciated!!!
In case you also are interested to export your tasks to MyLifeOrganized, here it is my improved version of the exporter. Now I export:
- Task colors
- Flag state
- Completion state
- Comments
- Link or multiple links
- Task dependency or multiple dependencies
- First level task exported in bold, like in ToDoList
- Folders and projects: These are not available in ToDoList, but I set a criteria for setting those in MyLifeOrganized
- Fixed importance scale
- Fixed dates
#include "stdafx.h"
#include "MLOImport.h"
#include "MLOExporter.h"
#include "..\shared\xmlfileex.h"
#include "..\shared\datehelper.h"
#include "..\shared\timehelper.h"
#include "..\shared\misc.h"
#include "..\3rdParty\T64Utils.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CMLOExporter::CMLOExporter()
{
m_icon.Load(IDI_MYLIFEORGANISED);
}
CMLOExporter::~CMLOExporter()
{
}
void CMLOExporter::SetLocalizer(ITransText* )
{
}
IIMPORTEXPORT_RESULT CMLOExporter::Export(const ITaskList* pSrcTaskFile, LPCTSTR szDestFilePath, DWORD , IPreferences* , LPCTSTR )
{
const ITASKLISTBASE* pTasks = GetITLInterface<ITASKLISTBASE>(pSrcTaskFile, IID_TASKLISTBASE);
if (pTasks == NULL)
{
ASSERT(0);
return IIER_BADINTERFACE;
}
CXmlFile fileDest(_T("MyLifeOrganized-xml"));
fileDest.SetXmlHeader(DEFAULT_UTF8_HEADER);
fileDest.AddItem(_T("ver"), _T("1.2"));
CXmlItem* pXITasks = fileDest.AddItem(_T("TaskTree"));
if (!ExportTask(pTasks, pSrcTaskFile->GetFirstTask(), pXITasks, TRUE))
return IIER_SOMEFAILED;
ExportPlaces(pTasks, fileDest.Root());
if (!fileDest.Save(szDestFilePath, SFEF_UTF8WITHOUTBOM))
return IIER_BADFILE;
return IIER_SUCCESS;
}
IIMPORTEXPORT_RESULT CMLOExporter::Export(const IMultiTaskList* pSrcTaskFile, LPCTSTR szDestFilePath, DWORD , IPreferences* , LPCTSTR )
{
CXmlFile fileDest(_T("MyLifeOrganized-xml"));
fileDest.SetXmlHeader(DEFAULT_UTF8_HEADER);
fileDest.AddItem(_T("ver"), _T("1.2"));
CXmlItem* pXITasks = fileDest.AddItem(_T("TaskTree"));
for (int nTaskList = 0; nTaskList < pSrcTaskFile->GetTaskListCount(); nTaskList++)
{
const ITASKLISTBASE* pTasks = GetITLInterface<ITASKLISTBASE>(pSrcTaskFile->GetTaskList(nTaskList), IID_TASKLISTBASE);
if (pTasks == NULL)
{
ASSERT(0);
return IIER_BADINTERFACE;
}
if (!ExportTask(pTasks, pTasks->GetFirstTask(), pXITasks, TRUE))
return IIER_SOMEFAILED;
ExportPlaces(pTasks, fileDest.Root());
}
if (!fileDest.Save(szDestFilePath, SFEF_UTF8WITHOUTBOM))
return IIER_BADFILE;
return IIER_SUCCESS;
}
bool CMLOExporter::ExportTask(const ITASKLISTBASE* pSrcTaskFile, HTASKITEM hTask,
CXmlItem* pXIDestParent, BOOL bAndSiblings)
{
if (!hTask)
return true;
CXmlItem* pXIDestItem = pXIDestParent->AddItem(_T("TaskNode"));
if (!pXIDestItem)
return false;
pXIDestItem->AddItem(_T("Caption"), pSrcTaskFile->GetTaskTitle(hTask));
int nPriority = pSrcTaskFile->GetTaskPriority(hTask, FALSE);
int nImportance = max(nPriority, 0) * 20;
pXIDestItem->AddItem(_T("Importance"), nImportance, XIT_ELEMENT);
CString strIDD;
unsigned long nIDD = pSrcTaskFile->GetTaskID(hTask);
strIDD.Format(_T("{00000000-0000-1111-0000-%012lu}"), nIDD);
pXIDestItem->AddItem(_T("IDD"), strIDD, XIT_ELEMENT);
CString strNote;
int nDependencies = pSrcTaskFile->GetTaskDependencyCount(hTask);
if (nDependencies > 0)
{
CXmlItem* pXIDestDependenciesItem = pXIDestItem->AddItem(_T("Dependency"), _T(""), XIT_ELEMENT);
if (!pXIDestDependenciesItem)
return false;
CString strUID;
CString strDependencyCount;
for (int nDependency = 0; nDependency < nDependencies; ++nDependency)
{
LPCWSTR pStrDependency = pSrcTaskFile->GetTaskDependency(hTask, nDependency);
strDependencyCount.Format(_T("%d"), nDependency + 1);
strNote += _T("ToDoList dependency (") + strDependencyCount + _T("): [ID " + CString(pStrDependency) + _T("] "));
unsigned long nID = _wtoi(pStrDependency);
HTASKITEM hTaskDependency = pSrcTaskFile->FindTask(nID);
if (hTaskDependency)
{
unsigned long nUID = pSrcTaskFile->GetTaskID(hTaskDependency);
strUID.Format(_T("{00000000-0000-1111-0000-%012lu}"), nUID);
pXIDestDependenciesItem->AddItem(_T("UID"), strUID, XIT_ELEMENT);
strNote += pSrcTaskFile->GetTaskTitle(hTaskDependency);
}
strNote += _T("\n");
}
}
time64_t tDate = T64Utils::T64_NULL;
if (pSrcTaskFile->GetTaskCreationDate64(hTask, tDate))
pXIDestItem->AddItem(_T("Created"), FormatDate(tDate), XIT_ELEMENT);
if (pSrcTaskFile->GetTaskDoneDate64(hTask, tDate))
pXIDestItem->AddItem(_T("CompletionDateTime"), FormatDate(tDate), XIT_ELEMENT);
if (pSrcTaskFile->GetTaskDueDate64(hTask, false, tDate))
pXIDestItem->AddItem(_T("DueDateTime"), FormatDate(tDate), XIT_ELEMENT);
TDC_UNITS nUnits;
double dTimeEst = pSrcTaskFile->GetTaskTimeEstimate(hTask, nUnits, FALSE);
if (dTimeEst > 0.0)
{
TH_UNITS nTHUnits = MapUnitsToTHUnits(nUnits);
pXIDestItem->AddItem(_T("EstimateMax"), CTimeHelper().Convert(dTimeEst, nTHUnits, THU_DAYS), XIT_ELEMENT);
}
CString strLink;
static const CString urlProtocol = _T("://");
static const CString fileProtocol = _T("file://");
int nLinks = pSrcTaskFile->GetTaskFileLinkCount(hTask);
if (nLinks > 1)
{
CString strLinkCount;
for (int nLinkCount = 0; nLinkCount < nLinks; ++nLinkCount)
{
strLink = pSrcTaskFile->GetTaskFileLink(hTask, nLinkCount);
strLinkCount.Format(_T("%d"), nLinkCount+1);
strNote += _T("ToDoList link (") + strLinkCount + _T("): <");
if (strLink.Find(urlProtocol) < 0)
strNote += fileProtocol;
strNote += CString(strLink) + _T(">\n");
}
}
else
{
strLink = pSrcTaskFile->GetTaskFileLinkPath(hTask);
if (!Misc::IsEmpty(strLink))
{
strNote += _T("ToDoList link: <");
if (strLink.Find(urlProtocol) < 0)
strNote += fileProtocol;
strNote += CString(strLink) + _T(">\n");
}
}
LPCTSTR szComments = pSrcTaskFile->GetTaskComments(hTask);
bool bHasFormattedComments = pSrcTaskFile->GetTaskComments(hTask);
if (bHasFormattedComments)
strNote += _T("ToDoList Comments: ***LOST THE FORMATTED TEXT!!!***\n");
if ((!Misc::IsEmpty(strNote)) && (!Misc::IsEmpty(szComments)))
strNote += _T("\n");
if (!Misc::IsEmpty(szComments))
strNote += szComments;
if (!strNote.IsEmpty())
pXIDestItem->AddItem(_T("Note"), strNote, XIT_ELEMENT);
if ((pSrcTaskFile->GetFirstTask(hTask) != nullptr)) {
if (strNote.IsEmpty())
pXIDestItem->AddItem(_T("HideInToDoThisTask"), -1, XIT_ELEMENT); else
pXIDestItem->AddItem(_T("IsProject"), -1, XIT_ELEMENT); }
bool bTaskFlagged = pSrcTaskFile->IsTaskFlagged(hTask, false);
if (bTaskFlagged)
pXIDestItem->AddItem(_T("Flag"), _T("Red Flag"), XIT_ELEMENT);
CXmlItem* pXIDestCustomFormatItem = pXIDestItem->AddItem(_T("CustomFormat"), _T(""), XIT_ELEMENT);
if (!pXIDestCustomFormatItem)
return false;
bool bIsParentTask = pSrcTaskFile->IsTaskParent(hTask);
if (bIsParentTask)
pXIDestCustomFormatItem->AddItem(_T("Bold"), _T("1"), XIT_ELEMENT);
unsigned long unTaskColor = pSrcTaskFile->GetTaskColor(hTask);
CString strColor;
strColor.Format(_T("%lu"), unTaskColor);
pXIDestCustomFormatItem->AddItem(_T("FontColor"), strColor, XIT_ELEMENT);
pXIDestCustomFormatItem->AddItem(_T("SideBarColor"), strColor, XIT_ELEMENT);
if (!ExportTask(pSrcTaskFile, pSrcTaskFile->GetFirstTask(hTask), pXIDestItem, TRUE))
return false;
if (bAndSiblings)
{
HTASKITEM hSibling = pSrcTaskFile->GetNextTask(hTask);
while (hSibling)
{
if (!ExportTask(pSrcTaskFile, hSibling, pXIDestParent, FALSE))
return false;
hSibling = pSrcTaskFile->GetNextTask(hSibling);
}
}
return true;
}
CString CMLOExporter::FormatDate(time64_t tDate)
{
COleDateTime date = CDateHelper::GetDate(tDate);
return CDateHelper::FormatDate(date, DHFD_ISO | DHFD_TIME, 'T');
}
void CMLOExporter::BuildPlacesMap(const ITASKLISTBASE* pSrcTaskFile, HTASKITEM hTask,
CMapStringToString& mapPlaces, BOOL bAndSiblings)
{
if (!hTask)
return;
int nCat = pSrcTaskFile->GetTaskCategoryCount(hTask);
while (nCat--)
{
CString sCat = pSrcTaskFile->GetTaskCategory(hTask, nCat);
CString sCatUpper(sCat);
sCat.MakeUpper();
mapPlaces[sCatUpper] = sCat;
}
BuildPlacesMap(pSrcTaskFile, pSrcTaskFile->GetFirstTask(hTask), mapPlaces, TRUE);
if (bAndSiblings)
{
HTASKITEM hSibling = pSrcTaskFile->GetNextTask(hTask);
while (hSibling)
{
BuildPlacesMap(pSrcTaskFile, hSibling, mapPlaces, FALSE);
hSibling = pSrcTaskFile->GetNextTask(hSibling);
}
}
}
void CMLOExporter::ExportPlaces(const ITASKLISTBASE* pSrcTaskFile, CXmlItem* pDestPrj)
{
CMapStringToString mapPlaces;
BuildPlacesMap(pSrcTaskFile, pSrcTaskFile->GetFirstTask(), mapPlaces, TRUE);
if (mapPlaces.GetCount())
{
CXmlItem* pXIResources = pDestPrj->AddItem(_T("PlacesList"));
CString sPlace, sPlaceUpper;
POSITION pos = mapPlaces.GetStartPosition();
while (pos)
{
mapPlaces.GetNextAssoc(pos, sPlaceUpper, sPlace);
CXmlItem* pXIRes = pXIResources->AddItem(_T("TaskPlace"));
if (pXIRes)
pXIRes->AddItem(_T("Caption"), sPlace);
}
}
}
TH_UNITS CMLOExporter::MapUnitsToTHUnits(TDC_UNITS nUnits)
{
switch (nUnits)
{
case TDCU_MINS: return THU_MINS;
case TDCU_HOURS: return THU_HOURS;
case TDCU_DAYS: return THU_DAYS;
case TDCU_WEEKDAYS: return THU_WEEKDAYS;
case TDCU_WEEKS: return THU_WEEKS;
case TDCU_MONTHS: return THU_MONTHS;
case TDCU_YEARS: return THU_YEARS;
}
ASSERT(0);
return THU_NULL;
}
Hope it is useful for someone!
|