Advertisement
Guest User

Untitled

a guest
Mar 24th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 18.96 KB | None | 0 0
  1. unit package;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  9.   StdCtrls, Buttons, ButtonPanel, ExtCtrls, fpjson, types;
  10.  
  11. type
  12.   TPackageRelease = record
  13.     Version: String;
  14.     Download: String;
  15.     Notes: String;
  16.     Time: String;
  17.   end;
  18.  
  19.   TPackageReleases = array of TPackageRelease;
  20.  
  21.   TPackageData = class
  22.   protected
  23.     FReleases: TPackageReleases;
  24.     FName: String;
  25.     FOwner: String;
  26.     FVersion: String;
  27.     FPath: String;
  28.     FAutoUpdate: Boolean;
  29.     FURL: String;
  30.   public
  31.     property Releases: TPackageReleases read FReleases write FReleases;
  32.     property Name: String read FName write FName;
  33.     property Owner: String read FOwner write FOwner;
  34.     property Version: String read FVersion write FVersion;
  35.     property Path: String read FPath write FPath;
  36.     property AutoUpdate: Boolean read FAutoUpdate write FAutoUpdate;
  37.     property URL: String read FURL write FURL;
  38.  
  39.     procedure SaveToSettings;
  40.     procedure Delete;
  41.  
  42.     function LoadFromSettings(Key: String): Boolean;
  43.     function LoadFromURL(Force: Boolean = False): Boolean;
  44.  
  45.     function Install(Release: Int32): Boolean;
  46.   end;
  47.  
  48.   TPackageForm = class(TForm)
  49.     btnInstall: TButton;
  50.     btnPanel: TButtonPanel;
  51.     cbAutoUpdate: TCheckBox;
  52.     comboVersions: TComboBox;
  53.     editPath: TEdit;
  54.     lblStatus: TLabel;
  55.     lblSelectVersion: TLabel;
  56.     lblVersion: TLabel;
  57.     lblPath: TLabel;
  58.     lbPackages: TListBox;
  59.     memoReleaseNotes: TMemo;
  60.     pnlTop: TPanel;
  61.     pnlBottom: TPanel;
  62.     btnAdd: TSpeedButton;
  63.     btnRefresh: TSpeedButton;
  64.     btnRemove: TSpeedButton;
  65.  
  66.     procedure packagedChanged(Sender: TObject; User: boolean);
  67.     procedure comboVersionsChange(Sender: TObject);
  68.     procedure comboVersionsDrawItem(Control: TWinControl; Index: Integer; R: TRect; State: TOwnerDrawState);
  69.     procedure btnInstallClick(Sender: TObject);
  70.     procedure btnRemoveClick(Sender: TObject);
  71.     procedure btnAddClick(Sender: TObject);
  72.     procedure btnRefreshClick(Sender: TObject);
  73.   protected
  74.     FStatus: String;
  75.  
  76.     procedure __UpdateStatus;
  77.  
  78.     procedure Clear;
  79.     procedure SetState(Enable: Boolean; Skip: array of TControl);
  80.  
  81.     function GetPackage(var Package: TPackageData): Boolean;
  82.   public
  83.     procedure UpdateStatus(Status: String);
  84.     procedure UpdateDownloadStatus(Sender: TObject; const Size, Progress: Int64);
  85.     procedure UpdateExtractStatus(Sender: TObject; const FilePath: String);
  86.  
  87.     constructor Create(TheOwner: TComponent); override;
  88.   end;
  89.  
  90. var
  91.   PackageForm: TPackageForm;
  92.  
  93. implementation
  94.  
  95. uses
  96.   LCLType, newsimbasettings, dateutils, MufasaTypes, httpd, zipper,
  97.   {$IFDEF VER3_0} fphttpclient {$warn we can delete the package internet files now!} {$ELSE} package_fphttpclient {$ENDIF};
  98.  
  99. type
  100.   TDownloader = class(TThread)
  101.   protected
  102.     FURL: String;
  103.     FData: TMemoryStream;
  104.     FExtract: String;
  105.     FResponseCode: Int32;
  106.  
  107.     procedure GetZipperStream(Sender: TObject; var Stream: TStream);
  108.  
  109.     function GetData: String;
  110.     function GetResponseCode: Int32;
  111.  
  112.     procedure Execute; override;
  113.   public
  114.     property Data: String read GetData;
  115.     property ResponseCode: Int32 read GetResponseCode;
  116.  
  117.     constructor Create(URL: String; Extract: String = '');
  118.     destructor Destroy; override;
  119.   end;
  120.  
  121. function TDownloader.GetData: String;
  122. begin
  123.   SetString(Result, PAnsiChar(FData.Memory), FData.Size);
  124. end;
  125.  
  126. procedure TDownloader.Execute;
  127. var
  128.   Zipper: TUnZipper;
  129.   Client: TFPHTTPClient;
  130.   Archive, Disk: String;
  131. begin
  132.   Client := TFPHTTPClient.Create(nil);
  133.   Client.AllowRedirect := True;
  134.   Client.AddHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36');
  135.   Client.OnDataReceived := @PackageForm.UpdateDownloadStatus;
  136.   Client.OnDataReceived(nil, 0, 0);
  137.  
  138.   try
  139.     Client.Get(FURL, FData);
  140.  
  141.     FResponseCode := Client.ResponseStatusCode;
  142.  
  143.     if (FResponseCode = HTTP_OK) and (FExtract <> '') then
  144.     begin
  145.       Zipper := TUnZipper.Create();
  146.  
  147.       try
  148.         Zipper.OnOpenInputStream := @Self.GetZipperStream;
  149.         Zipper.OnStartFile := @PackageForm.UpdateExtractStatus;
  150.         Zipper.OutputPath := IncludeTrailingPathDelimiter(ExtractFilePath(FExtract));
  151.         Zipper.Examine();
  152.  
  153.         Archive := ExtractFilePath(FExtract) + Zipper.Entries[0].ArchiveFileName;
  154.         Disk := ExtractFilePath(FExtract) + ExtractFileName(FExtract);
  155.  
  156.         if DirectoryExists(Archive) and (not DeleteDirectory(Archive, False)) then
  157.           WriteLn('TDownloader.Execute: Couldn''t delete archive');
  158.  
  159.         Zipper.Clear();
  160.         Zipper.UnZipAllFiles();
  161.  
  162.         if (not RenameFileUTF8(Archive, Disk)) then
  163.           WriteLn('TDownloader.Execute: Didn''t rename "', Archive, '" to "', Disk, '" - [', FileExistsUTF8(Archive), ', ', FileExistsUTF8(Disk), ']');
  164.       finally
  165.         Zipper.Free();
  166.       end;
  167.     end;
  168.   except
  169.     on e: Exception do
  170.     begin
  171.       WriteLn('TDownloader.Execute: ', e.ClassName, '::', e.Message);
  172.  
  173.       if (e is EHTTPClient) then
  174.         FResponseCode := EHTTPClient(e).StatusCode;
  175.     end;
  176.   end;
  177.  
  178.   Client.Free();
  179.  
  180.   Terminate();
  181. end;
  182.  
  183. function TDownloader.GetResponseCode: Int32;
  184. begin
  185.   while (not Terminated) do
  186.   begin
  187.     if (GetCurrentThreadID() = MainThreadID) then
  188.       Application.ProcessMessages();
  189.  
  190.     Sleep(1);
  191.   end;
  192.  
  193.   Result := FResponseCode;
  194. end;
  195.  
  196. procedure TDownloader.GetZipperStream(Sender: TObject; var Stream: TStream);
  197. begin
  198.   FData.Position := 0;
  199.  
  200.   // The zipper will free this.
  201.   Stream := TMemoryStream.Create();
  202.   Stream.CopyFrom(FData, FData.Size);
  203. end;
  204.  
  205. constructor TDownloader.Create(URL: String; Extract: String);
  206. begin
  207.   inherited Create(False);
  208.  
  209.   FResponseCode := -1;
  210.   FURL := URL;
  211.   FExtract := Extract;
  212.   FData := TMemoryStream.Create();
  213. end;
  214.  
  215. destructor TDownloader.Destroy;
  216. begin
  217.   FData.Free();
  218.  
  219.   inherited Destroy();
  220. end;
  221.  
  222. procedure TPackageData.SaveToSettings;
  223. begin
  224.   SimbaSettings.MMLSettings.SetKeyValue('Packages/' + FName + '/Version', FVersion);
  225.   SimbaSettings.MMLSettings.SetKeyValue('Packages/' + FName + '/URL', FURL);
  226.   SimbaSettings.MMLSettings.SetKeyValue('Packages/' + FName + '/Path', FPath);
  227.   SimbaSettings.MMLSettings.SetKeyValue('Packages/' + FName + '/AutoUpdate', BoolToStr(FAutoUpdate, True));
  228.   SimbaSettings.MMLSettings.SetKeyValue('Packages/' + FName + '/Owner', FOwner);
  229.   SimbaSettings.Save(SimbaSettingsFile);
  230. end;
  231.  
  232. procedure TPackageData.Delete;
  233. begin
  234.   SimbaSettings.MMLSettings.DeleteKey('Packages/' + FName);
  235.   SimbaSettings.Save(SimbaSettingsFile);
  236. end;
  237.  
  238. function TPackageData.LoadFromSettings(Key: String): Boolean;
  239. begin
  240.   FName := Key;
  241.   FVersion := SimbaSettings.MMLSettings.GetKeyValueDef('Packages/' + FName + '/Version', 'N/A');
  242.   FURL := SimbaSettings.MMLSettings.GetKeyValue('Packages/' + FName + '/URL');
  243.   FPath := SimbaSettings.MMLSettings.GetKeyValue('Packages/' + FName + '/Path');
  244.   FOwner := SimbaSettings.MMLSettings.GetKeyValue('Packages/' + FName + '/Owner');
  245.   FAutoUpdate := StrToBoolDef(SimbaSettings.MMLSettings.GetKeyValue('Packages/' + FName + '/AutoUpdate'), False);
  246.  
  247.   Exit(True);
  248. end;
  249.  
  250. function TPackageData.LoadFromURL(Force: Boolean): Boolean;
  251.  
  252.    // if (assets <> nil) and (assets is TJSONArray) and (TJSONArray(assets).Count = 1) then
  253.    //   custom := TJSONObject(TJSONArray(assets)[0]).Elements['browser_download_url']
  254.  
  255.   procedure AddRelease(JSON: TJSONObject);
  256.   var
  257.     Release: TPackageRelease;
  258.   begin
  259.     FillByte(Release, SizeOf(TPackageRelease), 0);
  260.  
  261.     try
  262.       if (JSON.Elements['body'] <> nil) then
  263.         Release.Notes := JSON.Elements['body'].AsString;
  264.       if (JSON.Elements['tag_name'] <> nil) then
  265.         Release.Version := JSON.Elements['tag_name'].AsString;
  266.       if (JSON.Elements['zipball_url'] <> nil) then
  267.         Release.Download := JSON.Elements['zipball_url'].AsString;
  268.       if (JSON.Elements['created_at'] <> nil) then
  269.       begin
  270.         Release.Time := JSON.Elements['created_at'].AsString;
  271.  
  272.         System.Delete(Release.Time, Pos('T', Release.Time), 1);
  273.         System.Delete(Release.Time, Pos('Z', Release.Time), 1);
  274.       end;
  275.  
  276.       if (Release.Version <> '') and (Release.Download <> '') then
  277.       begin
  278.         SetLength(FReleases, Length(FReleases) + 1);
  279.         Self.Releases[High(FReleases)] := Release;
  280.       end;
  281.     except
  282.       on e: Exception do
  283.         WriteLn('TPackageData.LoadFromURL: ', e.ClassName, '::', e.Message);
  284.     end;
  285.  end;
  286.  
  287. var
  288.   Downloader: TDownloader;
  289.   JSON: TJSONData;
  290.   i: Int32;
  291. begin
  292.   if (Length(Self.Releases) = 0) or Force then
  293.   begin
  294.     Downloader := TDownloader.Create(Self.URL);
  295.  
  296.     if (Downloader.ResponseCode = HTTP_OK) then
  297.     begin
  298.       JSON := GetJSON(Downloader.Data);
  299.  
  300.       if (JSON <> nil) and (JSON is TJSONArray) then
  301.       begin
  302.         SetLength(FReleases, 0);
  303.  
  304.         with TJSONArray(JSON) do
  305.           for i := 0 to Count - 1 do
  306.             AddRelease(Objects[i]);
  307.  
  308.         if (Length(FReleases) = 0) then
  309.           PackageForm.UpdateStatus('ERROR: No releases found');
  310.       end else
  311.         PackageForm.UpdateStatus('ERROR: Invalid JSON');
  312.  
  313.       if (JSON <> nil) then
  314.         JSON.Free();
  315.     end else
  316.       PackageForm.UpdateStatus('ERROR: Could not access API: ' + IntToStr(Downloader.ResponseCode));
  317.  
  318.     Downloader.Free();
  319.   end;
  320.  
  321.   Result := Length(FReleases) > 0;
  322. end;
  323.  
  324. function TPackageData.Install(Release: Int32): Boolean;
  325. var
  326.   Downloader: TDownloader;
  327. begin
  328.   if (Release < Length(FReleases)) then
  329.   begin
  330.     if DirectoryExistsUTF8(FPath + FName + '.old') and (not DeleteDirectory(FPath + FName + '.old', False)) then
  331.       PackageForm.UpdateStatus('ERROR: Couldn''t delete old package');
  332.     if DirectoryExistsUTF8(FPath + FName) and (not RenameFileUTF8(FPath + FName, FPath + FName + '.old')) then
  333.       PackageForm.UpdateStatus('ERROR: Couldn''t rename package to old');
  334.  
  335.     if (not FileExistsUTF8(FPath + FName)) then
  336.     begin
  337.       Downloader := TDownloader.Create(FReleases[Release].Download, FPath + FName);
  338.  
  339.       try
  340.         if (Downloader.GetResponseCode() = HTTP_OK) then
  341.         begin
  342.           if DirectoryExistsUTF8(FPath + FName) then
  343.           begin
  344.             FVersion := FReleases[Release].Version;
  345.  
  346.             SaveToSettings();
  347.  
  348.             PackageForm.UpdateStatus('Succesfully installed package "' + FName + '"');
  349.  
  350.             Exit(True);
  351.           end else
  352.             PackageForm.UpdateStatus('ERROR: Failed to extract package');
  353.         end;
  354.       finally
  355.         Downloader.Free();
  356.       end;
  357.     end;
  358.   end;
  359.  
  360.   Exit(False);
  361. end;
  362.  
  363. procedure TPackageForm.comboVersionsChange(Sender: TObject);
  364. var
  365.   Package: TPackageData;
  366.   i: Int32;
  367. begin
  368.   memoReleaseNotes.Clear();
  369.   memoReleaseNotes.Font.Italic := True;
  370.   memoReleaseNotes.Text := '(no release notes)';
  371.  
  372.   if GetPackage(Package) then
  373.   begin
  374.     for i := 0 to high(Package.Releases) do
  375.       if (Package.Releases[i].Version = comboVersions.Text) and (Package.Releases[i].Notes <> '') then
  376.       begin
  377.         memoReleaseNotes.Font.Italic := False;
  378.         memoReleaseNotes.Text := package.releases[i].Notes;
  379.       end;
  380.   end;
  381. end;
  382.  
  383. procedure TPackageForm.comboVersionsDrawItem(Control: TWinControl; Index: Integer; R: TRect; State: TOwnerDrawState);
  384. var
  385.   TimeSpan: String;
  386. begin
  387.   with Control as TComboBox do
  388.   begin
  389.     if (odSelected in State) then
  390.     begin
  391.       Canvas.Pen.Color := clHighlight;
  392.       Canvas.Brush.Color := clHighlight;
  393.       Canvas.Font.Color := clHighlightText;
  394.     end else
  395.     begin
  396.       Canvas.Pen.Color := clWindow;
  397.       Canvas.Brush.Color := clWindow;
  398.       Canvas.Font.Color := clWindowText;
  399.  
  400.       if (not Control.Enabled) then
  401.         Canvas.Font.Color := clGrayText;
  402.     end;
  403.  
  404.     Canvas.Rectangle(R);
  405.     Canvas.Font.Italic := False;
  406.     Canvas.TextOut(R.Left + 2, R.Top, Items[Index]);
  407.  
  408.     if (Items.Objects[Index] <> nil) then
  409.     begin
  410.       TimeSpan := '(' + IntToStr(Int32(Items.Objects[Index])) + ' days ago)';
  411.  
  412.       case Int32(Items.Objects[Index]) of
  413.         0: TimeSpan := '(today)';
  414.         1: TimeSpan := '(yesterday)';
  415.       end;
  416.  
  417.       Canvas.Font.Italic := True;
  418.       Canvas.TextOut(R.Left + Canvas.TextWidth(Items[Index] + ' ') + 2, R.Top, TimeSpan);
  419.     end;
  420.   end;
  421. end;
  422.  
  423. procedure TPackageForm.btnInstallClick(Sender: TObject);
  424. var
  425.   Package: TPackageData;
  426. begin
  427.   if GetPackage(Package) then
  428.   begin
  429.     SetState(False, []);
  430.  
  431.     try
  432.       if (comboVersions.Items.IndexOf(comboVersions.Text) >= 0) then
  433.       begin
  434.         Package.Path := IncludeTrailingPathDelimiter(editPath.Text);
  435.         Package.Install(comboVersions.Items.IndexOf(comboVersions.Text));
  436.  
  437.         lbPackages.OnSelectionChange(Self, False);
  438.       end;
  439.     finally
  440.       SetState(True, []);
  441.     end;
  442.   end;
  443. end;
  444.  
  445. procedure TPackageForm.btnRemoveClick(Sender: TObject);
  446. var
  447.   Package: TPackageData;
  448. begin
  449.   if GetPackage(Package) then
  450.   begin
  451.     Package.Delete();
  452.  
  453.     lbPackages.Items.Delete(lbPackages.ItemIndex);
  454.     lbPackages.OnSelectionChange(Self, False);
  455.   end;
  456. end;
  457.  
  458. procedure TPackageForm.packagedChanged(Sender: TObject; User: boolean);
  459. var
  460.   Package: TPackageData;
  461.   i: Int32;
  462. begin
  463.   if GetPackage(Package) then
  464.   begin
  465.     if (Length(Package.Releases) = 0) then
  466.     begin
  467.        SetState(False, []);
  468.  
  469.        try
  470.          if Package.LoadFromURL() then
  471.            PackageForm.UpdateStatus('');
  472.        finally
  473.          SetState(True, []);
  474.        end;
  475.     end;
  476.  
  477.     if (Length(Package.Releases) > 0) then
  478.     begin
  479.       comboVersions.Clear();
  480.       comboVersions.Items.BeginUpdate();
  481.  
  482.       for i := 0 to High(Package.Releases) do
  483.       try
  484.         comboVersions.Items.AddObject(Package.Releases[i].Version, TObject(DaysBetween(Now(),  ScanDateTime('yyyy-mm-ddhh:nn:ss', Package.Releases[i].Time))));
  485.       except
  486.         comboVersions.Items.Add(Package.Releases[i].Version);
  487.       end;
  488.  
  489.       comboVersions.Text := comboVersions.Items[0];
  490.       comboVersions.OnChange(nil);
  491.       comboVersions.Items.EndUpdate();
  492.  
  493.       lblVersion.Caption := 'Installed Version: ' + Package.Version;
  494.  
  495.       editPath.Text := Package.Path;
  496.  
  497.       SetState(True, []);
  498.     end else
  499.     begin
  500.       memoReleaseNotes.Font.Italic := True;
  501.       memoReleaseNotes.Text := '(unknown)';
  502.  
  503.       comboVersions.Items.Add('(unknown)');
  504.       comboVersions.Text := comboVersions.Items[0];
  505.  
  506.       SetState(True, []);
  507.       SetState(False, [btnRefresh, lbPackages]);
  508.     end;
  509.   end else
  510.   begin
  511.     SetState(False, [lbPackages]);
  512.  
  513.     Clear();
  514.   end;
  515. end;
  516.  
  517. procedure TPackageForm.btnAddClick(Sender: TObject);
  518. var
  519.   URL: String;
  520.   Path: TStringList;
  521.   Package: TPackageData;
  522. begin
  523.   URL := 'https://github.com/';
  524.  
  525.   if InputQuery('New Package', 'Git Repository URL:', URL) then
  526.   begin
  527.     Path := TStringList.Create();
  528.     Path.Delimiter := '/';
  529.     Path.DelimitedText := URL;
  530.     while (Path.Count > 2) do
  531.       Path.Delete(0);
  532.  
  533.     if (Path.Count = 2) then
  534.     begin
  535.       Package := TPackageData.Create();
  536.       Package.Owner := Path[0];
  537.       Package.Name := Path[1];
  538.       Package.URL := Format('https://api.github.com/repos/%s/%s/releases', [Package.Owner, Package.Name]);
  539.       Package.Version := 'N/A';
  540.       Package.Path := IncludeTrailingPathDelimiter(CreateRelativePath(SimbaSettings.Includes.Path.Value, GetCurrentDirUTF8()));
  541.  
  542.       try
  543.         SetState(False, []);
  544.  
  545.         if Package.LoadFromURL() then
  546.         begin
  547.           lbPackages.AddItem(Package.Name, Package);
  548.           lbPackages.ItemIndex := lbPackages.Count - 1;
  549.  
  550.           UpdateStatus('Added package "' + Package.Name + '"');
  551.         end else
  552.           Package.Free();
  553.       finally
  554.         SetState(True, []);
  555.       end;
  556.     end else
  557.       UpdateStatus('ERROR: Invalid URL entered');
  558.  
  559.     Path.Free();
  560.   end;
  561. end;
  562.  
  563. procedure TPackageForm.btnRefreshClick(Sender: TObject);
  564. var
  565.   Package: TPackageData;
  566. begin
  567.   if GetPackage(Package) then
  568.   try
  569.     SetState(False, []);
  570.  
  571.     Package.LoadFromURL(True);
  572.   finally
  573.     SetState(True, []);
  574.   end;
  575. end;
  576.  
  577. procedure TPackageForm.__UpdateStatus;
  578. begin
  579.   lblStatus.Caption := FStatus;
  580. end;
  581.  
  582. procedure TPackageForm.Clear;
  583. begin
  584.   memoReleaseNotes.Text := '';
  585.   comboVersions.Text := '';;
  586.   editPath.Text := '';
  587.   lblVersion.Caption:= 'Installed Version:';
  588.   cbAutoUpdate.Checked := False;
  589. end;
  590.  
  591. procedure TPackageForm.SetState(Enable: Boolean; Skip: array of TControl);
  592.  
  593.   function isSkip(Control: TControl): Boolean;
  594.   var
  595.     i: Int32;
  596.   begin
  597.     for i := 0 to High(Skip) do
  598.       if Control.Equals(Skip[i]) then
  599.         Exit(True);
  600.  
  601.     Exit(False);
  602.   end;
  603.  
  604.   procedure StateSetting(Control: TWinControl);
  605.   var
  606.     i: Int32;
  607.   begin
  608.     if (Control.Tag = 0) and (not isSkip(Control)) then
  609.       Control.Enabled := Enable;
  610.  
  611.     for i := 0 to Control.ControlCount - 1 do
  612.       if (Control.Controls[i] is TWinControl) and (Control.Controls[i].Tag = 0) then
  613.         StateSetting(Control.Controls[i] as TWinControl);
  614.   end;
  615.  
  616. begin
  617.   StateSetting(Self);
  618. end;
  619.  
  620. function TPackageForm.GetPackage(var Package: TPackageData): Boolean;
  621. begin
  622.   if (lbPackages.ItemIndex >= 0) then
  623.   begin
  624.     Package := lbPackages.Items.Objects[lbPackages.ItemIndex] as TPackageData;
  625.  
  626.     Exit(True);
  627.   end;
  628.  
  629.   Exit(False);
  630. end;
  631.  
  632. procedure TPackageForm.UpdateStatus(Status: String);
  633. begin
  634.   if Visible then
  635.   begin
  636.     FStatus := Status;
  637.  
  638.     TThread.Synchronize(nil, @__UpdateStatus);
  639.   end;
  640. end;
  641.  
  642. procedure TPackageForm.UpdateDownloadStatus(Sender: TObject; const Size, Progress: Int64);
  643. begin
  644.   if (Size = 0) then
  645.     UpdateStatus('Connecting...')
  646.   else
  647.     UpdateStatus('Downloading... ' + IntToStr(Round((Progress / Size) * 100)) + '%');
  648. end;
  649.  
  650. procedure TPackageForm.UpdateExtractStatus(Sender: TObject; const FilePath: String);
  651. var
  652.   i, Current, Total: Int32;
  653. begin
  654.   Current := 0;
  655.   Total := 0;
  656.  
  657.   with Sender as TUnZipper do
  658.   begin
  659.     for i := 0 to Entries.Count - 1 do
  660.     begin
  661.       if (not Entries[i].IsLink) and (not Entries[i].IsDirectory) then
  662.       begin
  663.         Inc(Total);
  664.         if (Entries[i].ArchiveFileName = Copy(FilePath, Length(OutputPath) + 1, $FFFFFF)) then
  665.           Current := Total;
  666.       end;
  667.     end;
  668.  
  669.     UpdateStatus('Extracting... ' + IntToStr(Current) + '/' + IntToStr(Total));
  670.   end;
  671. end;
  672.  
  673. constructor TPackageForm.Create(TheOwner: TComponent);
  674. var
  675.   i: Int32;
  676.   Packages: TStringArray;
  677.   Package: TPackageData;
  678. begin
  679.   inherited Create(TheOwner);
  680.  
  681.   with lbPackages do
  682.   begin
  683.     Font.Size := 10;
  684.  
  685.     ItemHeight := lbPackages.Canvas.TextHeight('TaylorSwift') + 4;
  686.  
  687.     TStringList(Items).OwnsObjects := True;
  688.   end;
  689.  
  690.   SimbaSettings.MMLSettings.ListKeys('Packages', Packages);
  691.  
  692.   for i := 0 to High(Packages) do
  693.   begin
  694.     Package := TPackageData.Create();
  695.     Package.LoadFromSettings(Packages[i]);
  696.  
  697.     lbPackages.AddItem(Package.Name, Package);
  698.   end;
  699.  
  700.   SetState(False, [lbPackages]);
  701. end;
  702.  
  703. initialization
  704.   {$I package.lrs}
  705.  
  706. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement