|
That's great. Thanks for the update Hugo.
|
|
|
|
|
Hello! After exporting my ToDoList projects to MyLifeOrganized... I imported them into MLO and found that a lot of information was totally missing, for example all the notes/comments on the tasks... Although the notes/comments were exported into the .ML/.XML file from TDL, that information was missing in MLO. I contacted the MLO support and they told me that the format should exactly match what they are currently exporting. It seems they broke the compatibility with older versions of their own files! So MLO import is broken and can no longer properly import the older MLO format. So TDL export is no longer working fine for MLO...
It seems they changed the attribute
<TaskNode Note="..."> for another format:
<TaskNode><Note>...</Note></TaskNode>
Another thing I found as a very serious issue for me was loosing the TDL links. MLO has no similar field for the TDL links... And I have a lot of those links in my TDL projects, so: I was not accepting loosing the links nor the notes/comments of my tasks... and decided to fix the source code (thanks Dan for opensourcing!) myself! I decided to get the link information and put it at the beginning of the notes/comments. It would be nice if this can be improved also exporting the text format, the text markdown that MLO supports, task colors, flags, completion, and other info... maybe I will update the fix, but, in case you are interested, here it is my customization to the CMLOExporter::ExportTask funtion:
Instead of:
LPCTSTR szComments = pSrcTaskFile->GetTaskComments(hTask);
if (!Misc::IsEmpty(szComments))
pXIDestItem->AddItem(_T("Note"), szComments);
I wrote the following, in case you are interested:
LPCTSTR szLink = pSrcTaskFile->GetTaskFileLinkPath(hTask);
LPCTSTR szComments = pSrcTaskFile->GetTaskComments(hTask);
CString strNote;
if (!Misc::IsEmpty(szLink))
strNote += _T("ToDoList link: ") + CString(szLink);
if ((!Misc::IsEmpty(szLink)) && (!Misc::IsEmpty(szComments)))
strNote += _T("\n\n");
if (!Misc::IsEmpty(szComments))
strNote += szComments;
if (!strNote.IsEmpty())
pXIDestItem->AddItem(_T("Note"), strNote, XIT_ELEMENT);
Ideally, I would like to keep using both software, so it would be really nice to keep this exporting up to date, and also the other way around, importing from MLO into TDL...
Also, recorded a quick video about this issue: My experience migrating from ToDoList to MyLifeOrganized - YouTube[^]
Thank you for your interest!
EDIT: Check my own reply below for a very improved version of the code, exporting a lot more data...
modified 9-Aug-22 19:22pm.
|
|
|
|
|
I have improved the export to MyLifeOrganized, now I export:
- Task colors
- Flag state
- Completion state
- Comments in plain text and in HTML format! RTF / rich text comments are also exported in HTML
- 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
Here it is the final code (that might apply to ToDoList 8.1 only, later versions might include Dan's improvements):
bool SupportsHtmlComments() const { return true; }
#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);
CString strTitle = pSrcTaskFile->GetTaskTitle(hTask);
unsigned long nTaskNameCode = strTitle.GetLength();
if (nTaskNameCode > 1)
nTaskNameCode *= int(strTitle[1]);
strIDD.Format(_T("{%08lu-0000-1111-0000-%012lu}"), nIDD, nTaskNameCode);
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);
CString strDependencyTitle = pSrcTaskFile->GetTaskTitle(hTaskDependency);
unsigned long nTaskDependencyNameCode = strDependencyTitle.GetLength();
if (nTaskDependencyNameCode > 1)
nTaskDependencyNameCode *= int(strDependencyTitle[1]);
strUID.Format(_T("{%08lu-0000-1111-0000-%012lu}"), nUID, nTaskDependencyNameCode);
pXIDestDependenciesItem->AddItem(_T("UID"), strUID, XIT_ELEMENT);
strNote += strDependencyTitle;
}
strNote += _T("\r\n\r\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(">\r\n\r\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(">\r\n\r\n");
}
}
LPCTSTR szComments = pSrcTaskFile->GetTaskComments(hTask);
CString strHtmlComments = pSrcTaskFile->GetTaskAttribute(hTask, TDCA_HTMLCOMMENTS);
CString strCommentsType;
strHtmlComments.Trim();
bool bHasFormattedComments = !strHtmlComments.IsEmpty();
if (bHasFormattedComments)
{
bool bIsRTFContent = (strHtmlComments.Find(_T("<div class=WordSection1>")) >= 0);
if (bIsRTFContent)
{
strHtmlComments.Replace(_T("<div class=WordSection1>"), _T(""));
strHtmlComments.Replace(_T("</div>"), _T(""));
strHtmlComments.Replace(_T(" style='font-size:8.0pt;font-family:"), _T(""));
strHtmlComments.Replace(_T("\"Arial\",\"sans-serif\"'"), _T(""));
strHtmlComments.Replace(_T(" lang=EN-GB"), _T(""));
strHtmlComments.Replace(_T(" class=MsoNormal style='margin-top:0cm;margin-bottom:.0001pt;line-height:"), _T(""));
strHtmlComments.Replace(_T("normal;text-autospace:none'"), _T(""));
strHtmlComments.Replace(_T("<p\r\n>"), _T("<p>"));
strHtmlComments.Replace(_T("<p\n>"), _T("<p>"));
strHtmlComments.Replace(_T("<span\r\n>"), _T("<span>"));
strHtmlComments.Replace(_T("<span\n>"), _T("<span>"));
strCommentsType = _T("RTF"); }
else
strCommentsType = _T("HTML");
strNote += _T("ToDoList Comments (from ") + strCommentsType + _T("): *** To see format in notes, activate \"Use Markdown format in notes\" in the MyLifeOrganized options ***\r\n\r\n");
}
if ((!Misc::IsEmpty(strNote)) && (!Misc::IsEmpty(szComments)))
strNote += _T("\r\n\r\n");
if (!Misc::IsEmpty(szComments))
{
if (!strHtmlComments.IsEmpty())
strNote += _T("----- *** ToDoList Plain Text (HTML below) *** -----\r\n\r\n");
strNote += szComments;
}
if (!strHtmlComments.IsEmpty())
strNote += _T("\r\n\r\n\r\n----- *** ToDoList HTML (from ") + strCommentsType + _T(") *** (MyLifeOrganized supports only basic HTML formatting and Markdown) -----\r\n\r\n") + strHtmlComments;
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!
modified 10-Aug-22 17:41pm.
|
|
|
|
|
I'm very sorry for not having responded to this earlier Hugo.
If you can add this information to the bug report requested in my other comment, I'll be happy to get it fixed in the next update of 8.3.
|
|
|
|
|
Can MyLifeOrganized (MLO) Android app be used to display ToDoList TDL files exporting ML files to Dropbox or similar?
I have seen ToDoList can export and import in MLO format, so... it seems possible to export TDL into ML files and then use the MLO app to display them (better than the current Android app).
Is there a way to automatically export and open the ML files?
It would be really interesting to explore that possibility to have a better app been able to display the taks...
Thank you!
|
|
|
|
|
Hi Hugo
You can definitely auto-export your TDL file to MLO via the following preference:
Tools > Preferences > File Actions (more) > Saving > Automatically export after saving > Other format: My Life Organised
But then, after DropBox had synced the file to your Android device, you would need some code to detect the change and load the exported file into the MLO Android app. Which I unfortunately cannot help you with.
[Update] I've installed DropBox and MLO on my Android tablet but I can't understand how to import a .ml file. Have you figured that part out?
modified 28-Jul-22 22:20pm.
|
|
|
|
|
Hi Dan, thank you very much for your reply! The automatic export is very useful indeed. I think it is not possible to import a ML file on Android, I asked the MLO team in case they can implement that... it would be extremelly useful. The only way I found was to import it on the Windows MLO app, and them sync it with the Android app. But... I still have to search for the ML file on Android, because maybe there is a possibility to *replace* it with the one in Dropbox...
If that part were possible in the future, the issue would be re-integrating the changes in the Android's ML file, into the TDL file on Windows. As ToDoList can import from ML, it seems feasible... Although the newest ML file seems to be a binary file, not sure if TDL can read from it. Maybe it would require to export an XML from MLO or something...
I will be doing some testings, but it would be great if the MLO team could help with the integration or could help giving us access to their API...
|
|
|
|
|
Hello Dan, I have been making some tests... exporting to MLO generates a <mylifeorganized-xml> that seems to be somehow incompatible with the current MLO, as a lot of information is not properly imported into MLO. The information is in the <mylifeorganized-xml>, but MLO is not currently reading it... For example, the text of the Notes field is completely gone! This makes the export useles, as the notes field has key information...
It seems MLO now uses <mylifeorganized-xml ver="1.2">, which may be the reason for the loose of information... Is it possible to fix this format, so the notes and other info is not lost when importing it from MLO?
Thank you very much for all the help!
EDIT: it seems they changed the attribute
<TaskNode Note="..."> for another format:
<TaskNode><Note>...</Note></TaskNode>
modified 2-Aug-22 16:44pm.
|
|
|
|
|
Hello Dan,
I have been researching this a little further. The MLO for Android cannot import files at all, the XML export works only for MLO for Windows. But the MLO Android ans iPhone apps can sync with the Windows app through a "WiFi Sync" bidirectional process they implemented for the Pro versions. The WiFi Sync is done with a separate library called "MLOWiFiSync.dll" in Windows, which is dynamically loaded from the main executable "mlo.exe". That libary implements some functions that could be called from a different utility, which names are:
GetActiveSessionCount
GetLastSynchronizationError
GetLastSynchronizationErrorCode
SetLogFileName
SetOnDataNeeded
SetOnDataReceived
SetOnPairRequested
SetOnServerError
StartListening
StopListening
The problem is the library is not specifying the arguments to those functions, which is a problem without the source headers nor API documentation, which is unavailable. But, it is possible to create a fake library to replace it and debug the process, having a possibility to get the arguments when the fake library is called by the MLO executable. Once that is done, then it would be possible to directly call the "MLOWiFiSync.dll" library from a different app or utility. For example, it would be possible to create a WiFi Sync of the AbstractSpoon ToDoList with the MLO for Android/iPhone app, which would be really cool.
That would mean TDL calling directly to "MLOWiFiSync.dll". The user would still need to buy the MLO for Android/iPhone Pro version to be able to use that feature, but not the Windows version, they could keep using TDL for Windows. Of course that would be a kind of reverse engineering that would require a lot of work, but seems feasible... and ToDoList would have a perfect sync with Android and iPhone apps from MLO!
Regards!
|
|
|
|
|
Hi Hugo
Could you do me two huge favours please:
1. Create a bug report[^] regarding the format changes that have broken the MLO Export so I can get that fixed.
2. Create a suggestion[^] containing the recent information regarding MLOWiFiSync.dll so we can have a detailed discussion.
ps. I'm very grateful that you have persisted with your involvement.
modified 4-Aug-24 23:03pm.
|
|
|
|
|
How about a crowdfounding campaing to create a good mobile app for ToDoList? I would really pay money for that. No problem to pay $200 or more for a good app if available, it would solve my life!
These days mobile apps are key. For desktop to-do-lists, this one is the absolute best for me! And it is free!!!
Sorry, but the app from "ajiget", Tdl Todo List, is not enough for the user's needs...
There are a lot of worse apps that are actually getting much money because they have a mobile app and sync with the PC.
If this one would have a good mobile app, that could sync via Dropbox or FTP, it would be an absolute winner competing with the others!
Even with a paid app! You could get a lot of money. Keeping the free desktop version, but charging for a good mobile app.
The others want a monthly fee, that a lot of people don't want to pay... This could be a great solution. One-time payment app...
And you could get their market!
Thank you for your time! Hope someday this could be possible!
|
|
|
|
|
Hi Hugo
Perhaps in a parallel universe this would be possible
Unfortunately, I don't have the skills, energy or time to take on such a challenge.
|
|
|
|
|
Hi Dan, I totally understand that... but I was not thinking about you doing all the stuff, it is too much work... I don't know how many people are currently using ToDoList, how many downloads? Not sure, but more than 2300 five-start votes, means so many more downloads... imagine just $10 per vote or more for the super-fans like me... that would be at least $23000 but could be more, because there are lot of people tired of paying that much each month for a worse app in the market... Maybe a crowdfounding can take all that money to pay a mobile developer to port your code into a mobile app! It would make such a difference! I understand the campaing itself would require time, but would be great if someone else could do something like that!
|
|
|
|
|
Yes, but I would have to organise it and I'm really not very good with people
|
|
|
|
|
Link to 8.1 and add a link to phpBB forum?
TY
|
|
|
|
|
|
To get TodoList working on Linux Debian 11.2:
- Emphasis on winetricks dlls mfc42
sudo dpkg --add-architecture i386
sudo apt-get update && sudo apt install wine32 wine64 -y
sudo wget -qO- https:
sudo apt install software-properties-common && sudo add-apt-repository 'deb https://dl.winehq.org/wine-builds/debian/ bullseye main'
sudo apt update
sudo apt install --install-recommends winehq-stable
winecfg
sudo apt install -y winetricks
winetricks dlls mfc42
...download ToDoList from codeproject, then:
wine ./ToDoList.exe
modified 24-Feb-22 17:51pm.
|
|
|
|
|
Many thx fabio.
BTW, do you have a GitHub account?
|
|
|
|
|
|
Yes.
Reason I asked is that I'm hoping you might have time to integrate your suggestions with the existing Linux instructions, submitting a suitable PR as required...
|
|
|
|
|
Hi! Quick one - in the task tree, I have a child (eg highlighted red due to passed due date). The parent looks normal - is there a way to have a visual cue that it has a child requiring attention?
I see if I use the due date filter, the parent appears in the list (still looking normal) so you know there must be a due child in there. But a little red corner on the priority indicator similar to due tasks would draw your attention even with no filters.
Thanks
|
|
|
|
|
Hi Markus
Try:
Preferences > Tasks > Attribute Calculations > Display a task's 'Due Date' as: > The earliest of its due date and all its subtasks' due dates
|
|
|
|
|
That's perfect Dan, thanks!
You know software is mature when so many questions on the forum point to an existing feature rather than having to implement it
|
|
|
|
|
|
Hello.
When visually checking spelling in the task comments, I noticed I have a incorrect spelling of a word with a number embedded in it (i.e. 'u8nits' it should be 'units'). I right click, select 'spell check' and there is no indication that this word has an incorrect spelling in the "Spell Checking" popup window. If I change it from 'u8nits' to 'uYints' then it indicates it as a misspelling. I get the same results with Microsoft Word spell checking and also this message inline spell check. Is this some sort of bug? Or is this something that all spell checking engines do? If so, do you know why?
|
|
|
|
|