home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UGroupTreeDoc.cp < prev    next >
Encoding:
Text File  |  1994-02-20  |  12.2 KB  |  498 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UGroupTreeDoc.cp
  3.  
  4. #include "UGroupTreeDoc.h"
  5. #include "UGroupTreeView.h"
  6. #include "UGroupTree.h"
  7. #include "UGroupListDoc.h"
  8. #include "UGroupList.h"
  9. #include "UNewsAppl.h"
  10. #include "UNntp.h"
  11. #include "UProgress.h"
  12. #include "UPrefsFileMgr.h"
  13. #include "FileTools.h"
  14. #include "Tools.h"
  15. #include "StreamTools.h"
  16. #include "NetAsciiTools.h"
  17. #include "UBufferedFileStream.h"
  18.  
  19. #include <RsrcGlobals.h>
  20. #include <ErrorGlobals.h>
  21.  
  22. #include <UPrinting.h>
  23.  
  24. #pragma segment MyGroupList
  25.  
  26. const long kCurrentGroupTreeDocVersion = 6;
  27. const long kMinGroupTreeDocVersion = 6;
  28.  
  29. TGroupTreeDoc::TGroupTreeDoc()
  30. {
  31. }
  32.  
  33. pascal void TGroupTreeDoc::Initialize()
  34. {
  35.     inherited::Initialize();
  36.     fGroupTree = nil;
  37.     fGroupTreeViewList = nil;
  38.     fLastUpdateDate = 0;
  39.     fIdentifier = kGroupTreeDocFileType;
  40. }
  41.  
  42. void TGroupTreeDoc::IGroupTreeDoc(TFile *itsFile)
  43. {
  44.     inherited::IFileBasedDocument(itsFile, kGroupTreeDocFileType);
  45.     FailInfo fi;
  46.     if (fi.Try())
  47.     {
  48.         TGroupTree *gt = new TGroupTree();
  49.         gt->IGroupTree();
  50.         fGroupTree = gt;
  51.         fGroupTree->DoInitialState();
  52.         
  53.         fGroupTreeViewList = NewList();
  54.         
  55. //    TStdPrintHandler *aHandler = new TStdPrintHandler;
  56. //        aHandler->IStdPrintHandler(this, nil, !kSquareDots, kFixedSize, !kFixedSize);
  57.         fSavePrintInfo = false;
  58.         
  59.         fi.Success();
  60.     }
  61.     else // fail
  62.     {
  63.         Free();
  64.         fi.ReSignal();
  65.     }
  66. }
  67.  
  68. pascal void TGroupTreeDoc::Free()
  69. {
  70.     FreeIfObject(fGroupTree); fGroupTree = nil;
  71. #if qDebug
  72.     if (fGroupTreeViewList->GetSize())
  73.         ProgramBreak("fGroupTreeViewList is not empty when free'ing TGroupTreeDoc");
  74. #endif
  75.     FreeIfObject(fGroupTreeViewList); fGroupTreeViewList = nil;
  76.     inherited::Free();
  77. }
  78.  
  79. pascal void TGroupTreeDoc::Close()
  80. {
  81.     SaveTheTree();
  82.     inherited::Close();
  83. }
  84.  
  85. void TGroupTreeDoc::SaveTheTree()
  86. {
  87.     if (!GetChangeCount())
  88.         return;
  89.     if (fFileHandler->FileExists())
  90.         SaveDocument(cSave); // if it has not been saved, SaveDocument asks for a filename
  91.     else
  92.     {
  93.         // so just save it without checks first time!
  94.         fFileHandler->SaveFile(cSave, false, true, false);
  95.     }
  96. }
  97.  
  98. pascal void TGroupTreeDoc::DoPostMakeViews(Boolean forPrinting)
  99. {
  100.     gNewsAppl->SetGroupTreeDoc(this);
  101.     inherited::DoPostMakeViews(forPrinting);
  102. }
  103.  
  104. void TGroupTreeDoc::ForgetGroupTreeView(TGroupTreeView *view)
  105. {
  106.     fGroupTreeViewList->Delete(view);
  107. }
  108.  
  109. pascal void TGroupTreeDoc::DoInitialState()
  110. {
  111.     CloseAllWindows();
  112.     fGroupTree->DoInitialState();
  113.     inherited::DoInitialState();
  114.     SetChangeCount(0);
  115. }
  116.  
  117. pascal void TGroupTreeDoc::DoRead(TFile *aFile, Boolean forPrinting)
  118. {
  119.     FailOSErr(aFile->SetDataMark(0, fsFromStart)); 
  120.     TStream *aStream = NewBufferedFileStream(aFile, 150 * 1024, 0);
  121.     VOLATILE(aStream);
  122.     FailInfo fi;
  123.     if (fi.Try())
  124.     {
  125.         DoReadFile(aStream);
  126.         aStream->Free(); aStream = nil;
  127.         inherited::DoRead(aFile, forPrinting);
  128.         fi.Success();
  129.     }
  130.     else // fail
  131.     {
  132.         FreeIfObject(aStream); aStream = nil;
  133.         fi.ReSignal();
  134.     }
  135. }
  136.  
  137. void TGroupTreeDoc::DoReadFile(TStream *aStream)
  138. {
  139.     long version = aStream->ReadLong();
  140.     if (!MyCheckVersion(version, kMinGroupTreeDocVersion, kCurrentGroupTreeDocVersion, "TGroupTreeDoc"))
  141.         return;
  142.     fLastUpdateDate = aStream->ReadLong();
  143.     fGroupTree->DoRead(aStream);
  144. }
  145.  
  146. pascal void TGroupTreeDoc::DoWrite(TFile *aFile, Boolean forPrinting)
  147. {
  148.     FailOSErr(aFile->SetDataMark(0, fsFromStart)); 
  149.     TStream *aStream = NewBufferedFileStream(aFile, 0, 150 * 1024);
  150.     VOLATILE(aStream);
  151.     FailInfo fi;
  152.     if (fi.Try())
  153.     {
  154.         DoWriteFile(aStream);
  155.         aStream->Free(); aStream = nil;
  156.         inherited::DoWrite(aFile, forPrinting);
  157.         fi.Success();
  158.     }
  159.     else // fail
  160.     {
  161.         FreeIfObject(aStream); aStream = nil;
  162.         aFile->SetDataLength(0);
  163.         FailNewMessage(fi.error, fi.message, 0); //@@
  164.     }
  165. }
  166.  
  167. void TGroupTreeDoc::DoWriteFile(TStream *aStream)
  168. {
  169. #if qDebug
  170.     fprintf(stderr, "TGroupTreeDoc is saved with fLastUpdateDate = %ld\n", fLastUpdateDate);
  171. #endif
  172.     aStream->WriteLong(kCurrentGroupTreeDocVersion);
  173.     aStream->WriteLong(fLastUpdateDate);
  174.     fGroupTree->DoWrite(aStream);
  175. }
  176.  
  177. pascal void TGroupTreeDoc::DoNeedDiskSpace(TFile *itsFile, long &dataForkBytes, long &rsrcForkBytes)
  178. {
  179.     dataForkBytes += sizeof(long); // version
  180.     dataForkBytes += sizeof(long); // fLastUpdateDate
  181.     fGroupTree->DoNeedDiskSpace(dataForkBytes);
  182.     inherited::DoNeedDiskSpace(itsFile, dataForkBytes, rsrcForkBytes);
  183. }
  184.  
  185. void TGroupTreeDoc::WriteTreeInfo(TStream *aStream)
  186. {
  187. #if qDebug
  188.         fprintf(stderr, "Saved fLastUpdateDate == $%lx\n", fLastUpdateDate);
  189. #endif
  190.     aStream->WriteLong(fLastUpdateDate);
  191.     fGroupTree->WriteTreeInfo(aStream);
  192. }
  193.  
  194. void TGroupTreeDoc::ReadTreeInfo(TStream *aStream)
  195. {
  196.     unsigned long modDate = (unsigned long)aStream->ReadLong();
  197.     if (modDate != fLastUpdateDate)
  198.     {
  199. #if qDebug
  200.         fprintf(stderr, "TGroupTreeDoc::ReadTreeInfo, does not read info as mod-date is different:\n");
  201.         fprintf(stderr, "-   DiskTree == $%lx   !=   Prefs == $%lx\n", fLastUpdateDate, modDate);
  202. #endif
  203.         Failure(0, 0); // tree have been modified, can't read saved info
  204.     }
  205.     fGroupTree->ReadTreeInfo(aStream);
  206. }
  207.  
  208. void TGroupTreeDoc::WriteWindowInfo(TStream *aStream, TWindow *window)
  209. {
  210.     TGroupTreeView *gtv = (TGroupTreeView *)window->FindSubView(kGroupTreeViewID);
  211. #if qDebug
  212.     if (!IsObject(gtv))
  213.         ProgramBreak("Is missing TGroupTreeView");
  214. #endif
  215.     gtv->WriteWindowInfo(aStream);
  216. }
  217.  
  218. void TGroupTreeDoc::ReadWindowInfo(TStream *aStream)
  219. {
  220.     TWindow *window = gViewServer->NewTemplateWindow(kGroupTreeView, this);
  221.     TGroupTreeView *gtv = (TGroupTreeView*) window->FindSubView(kGroupTreeViewID);
  222. #if qDebug
  223.     if (!IsObject(window) || !IsObject(gtv))
  224.         ProgramBreak("Missing GroupTreeWindow or -view");
  225. #endif
  226.     gtv->ReadWindowInfo(aStream);
  227.     fGroupTreeViewList->Insert(gtv);
  228.     TStdPrintHandler *aHandler = new TStdPrintHandler;
  229.     aHandler->IStdPrintHandler(this, gtv, !kSquareDots, kFixedSize, !kFixedSize);
  230.  
  231.     CRect maxResize(window->fResizeLimits);
  232.     maxResize.right = 300; //@@ hack
  233.     window->SetResizeLimits(maxResize[topLeft], maxResize[botRight]);
  234.  
  235.     gtv->UpdateList();
  236.     window->Open();
  237. }
  238.  
  239. pascal void TGroupTreeDoc::UntitledName(CStr255& noName)
  240. {
  241.     GetPrefsLocationFileUntitledName(noName, kGroupTreeFileName);
  242. }
  243.  
  244. pascal void TGroupTreeDoc::DoMakeViews(Boolean /* forPrinting */)
  245. {
  246. }
  247.  
  248. pascal void TGroupTreeDoc::OpenAgain(CommandNumber itsCommandNumber, TDocument *openingDoc)
  249. {
  250.     inherited::OpenAgain(itsCommandNumber, openingDoc);
  251. }
  252.  
  253. pascal TFile *TGroupTreeDoc::DoMakeFile(CommandNumber /* itsCommandNumber */)
  254. {
  255.     return gNewsAppl->DoMakeFile(cNewGroupTreeDoc);
  256. }
  257.  
  258. void TGroupTreeDoc::CreateGroupTreeWindow(ArrayIndex windowFolderIndex, TGroupTreeView *openFromView)
  259. {
  260.     if (!windowFolderIndex)
  261.         windowFolderIndex = kFirstIndex;
  262. #if qDebug
  263.     if (!IsObject(this))
  264.         ProgramBreak("this is not object");
  265.     if (!IsObject(fGroupTreeViewList))
  266.         ProgramBreak("fGroupTreeViewList is not object");
  267. #endif
  268. // test if already open
  269.     {
  270.         CObjectIterator iter(fGroupTreeViewList);
  271.         for (TObject *obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
  272.         {
  273.             TGroupTreeView *gtv = (TGroupTreeView*) obj;
  274.             if (gtv->GetWindowFolderIndex() == windowFolderIndex)
  275.             {
  276.                 gtv->GetWindow()->Select();
  277.                 gtv->GetWindow()->Open();
  278.                 return;
  279.             }
  280.         }
  281.     }
  282.     
  283. // not open, create new
  284.     TWindow *window = gViewServer->NewTemplateWindow(kGroupTreeView, this);
  285.     TGroupTreeView *gtv = (TGroupTreeView*) window->FindSubView(kGroupTreeViewID);
  286. #if qDebug
  287.     if (!IsObject(window) || !IsObject(gtv))
  288.         ProgramBreak("Missing GroupTreeWindow or -view");
  289. #endif
  290.     fGroupTreeViewList->Insert(gtv);
  291.     gtv->SetWindowFolder(windowFolderIndex, openFromView);
  292.     TStdPrintHandler *aHandler = new TStdPrintHandler;
  293.     aHandler->IStdPrintHandler(this, gtv, !kSquareDots, kFixedSize, !kFixedSize);
  294.  
  295.     CRect maxResize(window->fResizeLimits);
  296.     maxResize.right = 300; //@@ hack
  297.     window->SetResizeLimits(maxResize[topLeft], maxResize[botRight]);
  298.  
  299.     gtv->UpdateList();
  300.     window->Open();
  301. }
  302.  
  303. pascal void TGroupTreeDoc::CloseWindow(TWindow* aWindow)
  304. {
  305.     if (aWindow && (aWindow->fDocument == this))
  306.         aWindow->CloseAndFree();
  307.         // don't close document even if no windows is left open
  308.         // so TDocument::Close can't be used
  309. }
  310.  
  311. void TGroupTreeDoc::CloseAllWindows()
  312. {
  313.     while (fGroupTreeViewList->GetSize())
  314.     {
  315.         TGroupTreeView *gtv = (TGroupTreeView*) fGroupTreeViewList->Last();
  316.         gtv->GetWindow()->CloseByUser();
  317.     }
  318. }
  319.  
  320. TGroupTree *TGroupTreeDoc::GetGroupTree()
  321. {
  322.     return fGroupTree;
  323. }
  324.  
  325. void TGroupTreeDoc::RebuildGroupTree()
  326. {    
  327.     PNntp *nntp = nil;
  328.     VOLATILE(nntp);
  329.     Handle groupData = nil;
  330.     VOLATILE(groupData);
  331.     TGroupTree *tree = nil;
  332.     VOLATILE(tree);
  333.     FailInfo fi;
  334.     if (fi.Try())
  335.     {
  336.         TGroupTree *gt = new TGroupTree();
  337.         gt->IGroupTree();
  338.         tree = gt;
  339.         tree->DoInitialState();
  340.  
  341.         unsigned long curDate;
  342.         GetDateTime(curDate);
  343.         fLastUpdateDate = curDate;
  344.         
  345.         gCurProgress->SetWorkToDo(kCandyStribes);
  346.         if (!gCurProgress->IsWorking())
  347.             gCurProgress->ClearTexts();
  348.         gCurProgress->StartProgress(true);
  349.         nntp = gNntpCache->GetNntp();
  350.  
  351.         gCurProgress->SetText(kUpdGTFetchesGroupList);
  352.         groupData = nntp->GetListOfAllGroups();
  353.         gCurProgress->SetText(kUpdGTBuildsTree);
  354.         Changed(cUpdateGroupTree, this);
  355.         tree->UpdateGroupTree(groupData, nil);
  356.         groupData = DisposeIfHandle(groupData);
  357.  
  358.         FailInfo innerFI;
  359.         if (innerFI.Try())
  360.         {
  361.             gCurProgress->SetText(kUpdGTFetchesGroupDescriptions);
  362.             gCurProgress->SetWorkToDo(kCandyStribes);
  363.             groupData = nntp->GetListOfGroupDesciptions();
  364.             if (GetHandleSize(groupData))
  365.             {
  366.                 gCurProgress->SetText(kUpdGTProcessGroupsDescriptions);
  367.                 TranslateViaTable(gNetAscii2Mac, *groupData, GetHandleSize(groupData));
  368.                 Changed(cUpdateGroupTree, this);
  369.                 tree->UpdateDescriptions(groupData);
  370.             }
  371.             innerFI.Success();
  372.         }
  373.         else // fail
  374.         {
  375.             // show show alert???
  376.         }
  377.         groupData = DisposeIfHandle(groupData);
  378.         
  379.         gNntpCache->ReturnNntp(nntp); nntp = nil;
  380.         gCurProgress->SetText(kUpdGTSavesTree);
  381.  
  382.         CloseAllWindows();
  383.         fGroupTree->Free(); fGroupTree = tree; tree = nil; // replace with new tree
  384.         SaveTheTree();
  385.         fi.Success();
  386.     }
  387.     else // fail
  388.     {
  389.         FreeIfObject(tree); tree = nil;
  390.         gNntpCache->DiscardNntp(nntp); nntp = nil;
  391.         groupData = DisposeIfHandle(groupData);
  392.         FailNewMessage(fi.error, fi.message, messageUpdateGroupListFailed);
  393.     }    
  394. }
  395.  
  396. void TGroupTreeDoc::UpdateGroupTree()
  397. {    
  398.     unsigned long curDate;
  399.     GetDateTime(curDate);
  400.     PNntp *nntp = nil;
  401.     VOLATILE(nntp);
  402.     Handle groupData = nil;
  403.     VOLATILE(groupData);
  404.     TGroupList *groupList = nil;
  405.     VOLATILE(groupList);
  406.     FailInfo fi;
  407.     if (fi.Try())
  408.     {
  409.         unsigned long oldDate = fLastUpdateDate - 2 * 24 * 60 * 60;
  410.         gCurProgress->SetWorkToDo(kCandyStribes);
  411.         gCurProgress->StartProgress(true);
  412.         nntp = gNntpCache->GetNntp();
  413.  
  414.         gCurProgress->SetText(kUpdGTFetchesListOfNewGroups);
  415.         groupData = nntp->GetListOfNewGroups(oldDate);
  416.  
  417.         TGroupList *gl = new TGroupList();
  418.         gl->IGroupList(nil);
  419.         groupList = gl;
  420.                 
  421.         if (GetHandleSize(groupData) > 1)
  422.         {
  423.             gCurProgress->SetText(kUpdGTUpdatesTree);
  424.             CloseAllWindows();
  425.  
  426.             fGroupTree->UpdateGroupTree(groupData, groupList);
  427.         }
  428.         groupData = DisposeIfHandle(groupData);
  429.         
  430.         gNntpCache->ReturnNntp(nntp); nntp = nil;
  431.         fi.Success();
  432.     }
  433.     else // fail
  434.     {
  435.         gNntpCache->DiscardNntp(nntp); nntp = nil;
  436.         groupData = DisposeIfHandle(groupData);
  437.         FreeIfObject(groupList); groupList = nil;
  438.         FailNewMessage(fi.error, fi.message, messageUpdateGroupListFailed);
  439.     }
  440. #if qDebug
  441.     fprintf(stderr, "Found %ld new groups\n", groupList->GetSize());
  442. #endif
  443.     if (!groupList->GetSize())
  444.     {
  445.         groupList->Free();
  446.         gCurProgress->WorkDone();
  447.         return;
  448.     }
  449.     fLastUpdateDate = curDate;
  450. #if qDebug
  451.     fprintf(stderr, "New fLastUpdateDate == $%lx\n", fLastUpdateDate);
  452. #endif
  453.     TGroupListDoc *doc = nil;
  454.     VOLATILE(doc);
  455.     if (fi.Try())
  456.     {
  457.         Changed(cUpdateGroupTree, this);
  458.         gCurProgress->SetText(kUpdGTSavesTree);
  459.         SaveTheTree();
  460.         gCurProgress->WorkDone();
  461.  
  462.         TGroupListDoc *gld = new TGroupListDoc();
  463.         gld->IGroupListDoc(nil);
  464.         doc = gld;
  465.         doc->DoInitialState();
  466.         doc->SpecifyList(groupList);
  467.  
  468.         doc->DoMakeViews(kForDisplay);
  469.         CStr255 title;
  470.         MyGetIndString(title, kUpdGTNewGroupsDocName);
  471.         doc->SetTitle(title);
  472.  
  473.         FailSpaceIsLow();                        // Fail if document leaves us with no room 
  474.  
  475.         // Don't attempt to show the windows until we're sure we won't fail 
  476.         doc->DoPostMakeViews(kForDisplay);
  477.  
  478.         groupList->Free(); groupList = nil;
  479.         fi.Success();
  480.     }
  481.     else // fail
  482.     {
  483.         FreeIfObject(doc); doc = nil;
  484.         FreeIfObject(groupList); groupList = nil;
  485.         FailNewMessage(fi.error, fi.message, messageUpdateGroupListFailed);
  486.     }
  487. }
  488.  
  489. pascal void TGroupTreeDoc::DoMenuCommand(CommandNumber aCommandNumber)
  490. {
  491.     inherited::DoMenuCommand(aCommandNumber);
  492. }
  493.  
  494. pascal void TGroupTreeDoc::DoSetupMenus()
  495. {
  496.     inherited::DoSetupMenus();
  497. }
  498.