Google APIs on component palette

git-svn-id: trunk@48961 -
This commit is contained in:
michael 2015-05-07 20:41:16 +00:00
parent 63cc6a0188
commit 6fc243643c
114 changed files with 6046 additions and 0 deletions

113
.gitattributes vendored
View File

@ -1633,6 +1633,119 @@ components/fpweb/lazwebextra.lpk svneol=native#text/plain
components/fpweb/weblaz.lpk svneol=native#text/plain
components/fpweb/weblaz.pas svneol=native#text/plain
components/fpweb/weblazideintf.pp svneol=native#text/plain
components/googleapis/README.txt svneol=native#text/plain
components/googleapis/demo/calendar/calendardemo.lpi svneol=native#text/plain
components/googleapis/demo/calendar/calendardemo.lpr svneol=native#text/plain
components/googleapis/demo/calendar/calendardemo.res -text
components/googleapis/demo/calendar/frmmain.lfm svneol=native#text/plain
components/googleapis/demo/calendar/frmmain.pp svneol=native#text/plain
components/googleapis/demo/calendar/google.ini svneol=native#text/plain
components/googleapis/demo/discovery/discoverydemo.ico -text
components/googleapis/demo/discovery/discoverydemo.lpi svneol=native#text/plain
components/googleapis/demo/discovery/discoverydemo.lpr svneol=native#text/plain
components/googleapis/demo/discovery/discoverydemo.res -text
components/googleapis/demo/discovery/frmgenoptions.lfm svneol=native#text/plain
components/googleapis/demo/discovery/frmgenoptions.pp svneol=native#text/plain
components/googleapis/demo/discovery/frmmain.lfm svneol=native#text/plain
components/googleapis/demo/discovery/frmmain.pp svneol=native#text/plain
components/googleapis/demo/discovery/frmview.lfm svneol=native#text/plain
components/googleapis/demo/discovery/frmview.pp svneol=native#text/plain
components/googleapis/demo/drive/drivedemo.ico -text
components/googleapis/demo/drive/drivedemo.lpi svneol=native#text/plain
components/googleapis/demo/drive/drivedemo.lpr svneol=native#text/plain
components/googleapis/demo/drive/drivedemo.res -text
components/googleapis/demo/drive/frmmain.lfm svneol=native#text/plain
components/googleapis/demo/drive/frmmain.pp svneol=native#text/plain
components/googleapis/demo/drive/frmselectdownload.lfm svneol=native#text/plain
components/googleapis/demo/drive/frmselectdownload.pp svneol=native#text/plain
components/googleapis/demo/drive/google.ini svneol=native#text/plain
components/googleapis/demo/tasks/frmmain.lfm svneol=native#text/plain
components/googleapis/demo/tasks/frmmain.pp svneol=native#text/plain
components/googleapis/demo/tasks/google.ini svneol=native#text/plain
components/googleapis/demo/tasks/tasksdemo.ico -text
components/googleapis/demo/tasks/tasksdemo.lpi svneol=native#text/plain
components/googleapis/demo/tasks/tasksdemo.lpr svneol=native#text/plain
components/googleapis/demo/tasks/tasksdemo.res -text
components/googleapis/images/TAdexchangebuyerAPI.png -text svneol=unset#image/png
components/googleapis/images/TAdexchangesellerAPI.png -text svneol=unset#image/png
components/googleapis/images/TAdminAPI.png -text svneol=unset#image/png
components/googleapis/images/TAdsenseAPI.png -text svneol=unset#image/png
components/googleapis/images/TAdsensehostAPI.png -text svneol=unset#image/png
components/googleapis/images/TAnalyticsAPI.png -text svneol=unset#image/png
components/googleapis/images/TAndroidenterpriseAPI.png -text svneol=unset#image/png
components/googleapis/images/TAndroidpublisherAPI.png -text svneol=unset#image/png
components/googleapis/images/TAppsactivityAPI.png -text svneol=unset#image/png
components/googleapis/images/TAppstateAPI.png -text svneol=unset#image/png
components/googleapis/images/TAuditAPI.png -text svneol=unset#image/png
components/googleapis/images/TAutoscalerAPI.png -text svneol=unset#image/png
components/googleapis/images/TBigqueryAPI.png -text svneol=unset#image/png
components/googleapis/images/TBloggerAPI.png -text svneol=unset#image/png
components/googleapis/images/TBooksAPI.png -text svneol=unset#image/png
components/googleapis/images/TCalendarAPI.png -text svneol=unset#image/png
components/googleapis/images/TCivicinfoAPI.png -text svneol=unset#image/png
components/googleapis/images/TCloudlatencytestAPI.png -text svneol=unset#image/png
components/googleapis/images/TCloudmonitoringAPI.png -text svneol=unset#image/png
components/googleapis/images/TCloudsearchAPI.png -text svneol=unset#image/png
components/googleapis/images/TComputeAPI.png -text svneol=unset#image/png
components/googleapis/images/TComputeaccountsAPI.png -text svneol=unset#image/png
components/googleapis/images/TContainerAPI.png -text svneol=unset#image/png
components/googleapis/images/TContentAPI.png -text svneol=unset#image/png
components/googleapis/images/TCoordinateAPI.png -text svneol=unset#image/png
components/googleapis/images/TCustomsearchAPI.png -text svneol=unset#image/png
components/googleapis/images/TDataflowAPI.png -text svneol=unset#image/png
components/googleapis/images/TDatastoreAPI.png -text svneol=unset#image/png
components/googleapis/images/TDeploymentmanagerAPI.png -text svneol=unset#image/png
components/googleapis/images/TDfareportingAPI.png -text svneol=unset#image/png
components/googleapis/images/TDiscoveryAPI.png -text svneol=unset#image/png
components/googleapis/images/TDnsAPI.png -text svneol=unset#image/png
components/googleapis/images/TDoubleclickbidmanagerAPI.png -text svneol=unset#image/png
components/googleapis/images/TDoubleclicksearchAPI.png -text svneol=unset#image/png
components/googleapis/images/TDriveAPI.png -text svneol=unset#image/png
components/googleapis/images/TFitnessAPI.png -text svneol=unset#image/png
components/googleapis/images/TFreebaseAPI.png -text svneol=unset#image/png
components/googleapis/images/TFusiontablesAPI.png -text svneol=unset#image/png
components/googleapis/images/TGamesAPI.png -text svneol=unset#image/png
components/googleapis/images/TGamesConfigurationAPI.png -text svneol=unset#image/png
components/googleapis/images/TGamesManagementAPI.png -text svneol=unset#image/png
components/googleapis/images/TGanAPI.png -text svneol=unset#image/png
components/googleapis/images/TGenomicsAPI.png -text svneol=unset#image/png
components/googleapis/images/TGmailAPI.png -text svneol=unset#image/png
components/googleapis/images/TGroupsmigrationAPI.png -text svneol=unset#image/png
components/googleapis/images/TGroupssettingsAPI.png -text svneol=unset#image/png
components/googleapis/images/TIdentitytoolkitAPI.png -text svneol=unset#image/png
components/googleapis/images/TLicensingAPI.png -text svneol=unset#image/png
components/googleapis/images/TLoggingAPI.png -text svneol=unset#image/png
components/googleapis/images/TManagerAPI.png -text svneol=unset#image/png
components/googleapis/images/TMapsengineAPI.png -text svneol=unset#image/png
components/googleapis/images/TMirrorAPI.png -text svneol=unset#image/png
components/googleapis/images/TOauth2API.png -text svneol=unset#image/png
components/googleapis/images/TPagespeedonlineAPI.png -text svneol=unset#image/png
components/googleapis/images/TPlusAPI.png -text svneol=unset#image/png
components/googleapis/images/TPlusDomainsAPI.png -text svneol=unset#image/png
components/googleapis/images/TPredictionAPI.png -text svneol=unset#image/png
components/googleapis/images/TPubsubAPI.png -text svneol=unset#image/png
components/googleapis/images/TQpxExpressAPI.png -text svneol=unset#image/png
components/googleapis/images/TReplicapoolAPI.png -text svneol=unset#image/png
components/googleapis/images/TReplicapoolupdaterAPI.png -text svneol=unset#image/png
components/googleapis/images/TResellerAPI.png -text svneol=unset#image/png
components/googleapis/images/TResourceviewsAPI.png -text svneol=unset#image/png
components/googleapis/images/TSiteVerificationAPI.png -text svneol=unset#image/png
components/googleapis/images/TSpectrumAPI.png -text svneol=unset#image/png
components/googleapis/images/TSqladminAPI.png -text svneol=unset#image/png
components/googleapis/images/TStorageAPI.png -text svneol=unset#image/png
components/googleapis/images/TTagmanagerAPI.png -text svneol=unset#image/png
components/googleapis/images/TTaskqueueAPI.png -text svneol=unset#image/png
components/googleapis/images/TTasksAPI.png -text svneol=unset#image/png
components/googleapis/images/TTranslateAPI.png -text svneol=unset#image/png
components/googleapis/images/TUrlshortenerAPI.png -text svneol=unset#image/png
components/googleapis/images/TWebfontsAPI.png -text svneol=unset#image/png
components/googleapis/images/TWebmastersAPI.png -text svneol=unset#image/png
components/googleapis/images/TYoutubeAPI.png -text svneol=unset#image/png
components/googleapis/images/TYoutubeAnalyticsAPI.png -text svneol=unset#image/png
components/googleapis/lazgoogleapis.lpk svneol=native#text/plain
components/googleapis/lazgoogleapis.pas svneol=native#text/plain
components/googleapis/reggoogleapi.inc svneol=native#text/plain
components/googleapis/reggoogleapi.pp svneol=native#text/plain
components/h2pas/h2pasconfig.pas svneol=native#text/plain
components/h2pas/h2pasconvert.pas svneol=native#text/plain
components/h2pas/h2pasdlg.lfm svneol=native#text/plain

View File

@ -0,0 +1,99 @@
This package installs the Google APIs in Free Pascal 3.1 in the lazarus
component palette.
Each Google Service API is a REST API that offers multiple resources.
==================
Component overview
==================
A Google API breaks down in 4 parts, all of which have a base class in the
following units:
TGoogleClient - unit googleclient
---------------------------------
This is a simple component that handles the transport and authorization,
it needs a TFPWebClient descendent (such as TFPHTTPWebClient, available in
the weblaz package) and a TFPOauth2Handler descendent to communicate with
Google servers (the component creates a default one).
These 2 classes are part of fcl-web, a synapse-based TFPWebclient descendant
is available separately.
TGoogleAPI - unit googleservice
-------------------------------
There is a descendent of this component for each Google service API, which
handles all calls to the service. It uses a TGoogleClient component to
handle actual communication.
This class contains a method called ServiceCall which is used by all
resources in the API to execute service requests. It will use the client to
do the actual HTTP request.
Each unit google*.pp in this package contains a single component that
descends from the TGoogleAPI component.
TGoogleResource - unit googleservice
------------------------------------
For each resource exposed by the service, a descendent of this class is generated
that has all the methods for that resource, as described in the REST service
description.
TGoogleResource uses an instance of the TGoogleAPI class to handle all calls to
the service.
Each API unit google*.pp in this package contains one or more
TGoogleResource
descendents, used in the API of that unit.
TGoogleBaseObject - unit googlebase
-----------------------------------
For each data type used in the API, a descendent of this class is used: it is a
descendent of TBaseObject (unit restbase, part of fcl-web) and handles
loading from and saving to JSON.
====================
Demo programs setup.
====================
The demo programs create the necessary API components in code, it is
therefor not necessary to install the lazgoogleapis package in the IDE,
it just has to be opened and compiled.
There are 4 demo programs. Before they can be used, they must be defined in Google.
The following procedure is not needed for the discovery demo, it does not
need authentication.
You will need to:
1. Have a google account
2. Be registered as a google Developer. Just go to the google developer console at:
https://console.developers.google.com/
3. Register a new project in the console.
4. Create a new client ID and Secret key under Credentials (APIs & Auth)
As a redirect URI, enter: urn:ietf:wg:oauth:2.0:oob
The Client ID and secret key must be saved in the google.ini file in the example directory:
[Credentials]
ClientID=Your client ID
ClientSecret=Your secret key
Scope=https://www.googleapis.com/auth/calendar
The scope must match the API that is used. (the example files contain the
correct scope)
5. Under credentials, request credentials (under APIs) for
Calendar API
Drive API
Tasks API
You can re-use the same Client ID and secret for all examples, or you
can create different client IDs and keys, or even create different projects.

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<Flags>
<SaveOnlyProjectUnits Value="True"/>
<SaveJumpHistory Value="False"/>
<SaveFoldState Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="calendardemo"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="2">
<Item1 Name="Default" Default="True"/>
<Item2 Name="Debug">
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="calendardemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="..\..;..\..\..\base"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<CodeGeneration>
<Optimizations>
<OptimizationLevel Value="0"/>
</Optimizations>
</CodeGeneration>
<Linking>
<Debugging>
<UseHeaptrc Value="True"/>
</Debugging>
</Linking>
</CompilerOptions>
</Item2>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="googleapiclient"/>
</Item1>
<Item2>
<PackageName Value="laz_synapse"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="calendardemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="frmmain.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="MainForm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmmain"/>
</Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="calendardemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="C:\Documents and Settings\Ludo\Mes documents\Borland Studio Projects\ODBCHTTP\synapse\source\libsvn;.."/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<CodeGeneration>
<SmartLinkUnit Value="True"/>
<Optimizations>
<OptimizationLevel Value="2"/>
</Optimizations>
</CodeGeneration>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2Set"/>
<UseHeaptrc Value="True"/>
<UseExternalDbgSyms Value="True"/>
</Debugging>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,20 @@
program calendardemo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, frmmain;
{$R *.res}
begin
RequireDerivedFormResource := True;
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

Binary file not shown.

View File

@ -0,0 +1,113 @@
object MainForm: TMainForm
Left = 456
Height = 388
Top = 191
Width = 666
Caption = 'Calendar Demo'
ClientHeight = 388
ClientWidth = 666
OnCreate = FormCreate
OnDestroy = FormDestroy
LCLVersion = '1.5'
object BFetchCalendars: TButton
Left = 8
Height = 25
Top = 8
Width = 128
Caption = 'Fetch calendars'
OnClick = BFetchCalendarsClick
TabOrder = 0
end
object GBAccess: TGroupBox
Left = 0
Height = 80
Top = 308
Width = 666
Align = alBottom
Caption = 'Please provide Google API access code'
ClientHeight = 52
ClientWidth = 662
TabOrder = 1
Visible = False
object LEAccess: TLabel
Left = 16
Height = 12
Top = 8
Width = 56
Caption = 'Access code'
ParentColor = False
end
object BSetAccess: TButton
Left = 490
Height = 25
Top = 9
Width = 75
Anchors = [akTop, akRight]
Caption = 'OK'
OnClick = BSetAccessClick
TabOrder = 0
end
object BCancel: TButton
Left = 570
Height = 25
Top = 8
Width = 75
Anchors = [akTop, akRight]
Caption = 'Cancel'
OnClick = BCancelClick
TabOrder = 1
end
object EAccessCode: TEdit
Left = 112
Height = 18
Top = 8
Width = 362
Anchors = [akTop, akLeft, akRight]
TabOrder = 2
end
end
object BFetchEvents: TButton
Left = 548
Height = 25
Top = 8
Width = 96
Anchors = [akTop, akRight]
Caption = 'Fetch Events'
Enabled = False
OnClick = BFetchEventsClick
TabOrder = 2
end
object LBCalendars: TListBox
Left = 8
Height = 248
Top = 40
Width = 312
Anchors = [akTop, akLeft, akBottom]
ItemHeight = 0
OnSelectionChange = LBCalendarsSelectionChange
ScrollWidth = 308
TabOrder = 3
TopIndex = -1
end
object LBEvents: TListBox
Left = 328
Height = 249
Top = 40
Width = 324
Anchors = [akTop, akLeft, akRight, akBottom]
ItemHeight = 0
ScrollWidth = 320
TabOrder = 4
TopIndex = -1
end
object LEvents: TLabel
Left = 328
Height = 12
Top = 16
Width = 207
Anchors = [akTop, akLeft, akRight]
AutoSize = False
Caption = 'Events for calendar : <select a calendar>'
ParentColor = False
end
end

View File

@ -0,0 +1,265 @@
unit frmmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
synautil, IniFiles, googlebase, googleservice, googleclient, googlecalendar;
type
{ TMainForm }
TAccessTokenState = (acsWaiting,acsOK,acsCancel);
TMainForm = class(TForm)
BCancel: TButton;
BSetAccess: TButton;
BFetchCalendars: TButton;
BFetchEvents: TButton;
EAccessCode: TEdit;
GBAccess: TGroupBox;
LEvents: TLabel;
LEAccess: TLabel;
LBCalendars: TListBox;
LBEvents: TListBox;
procedure BCancelClick(Sender: TObject);
procedure BFetchEventsClick(Sender: TObject);
procedure BSetAccessClick(Sender: TObject);
procedure BFetchCalendarsClick(Sender: TObject);
Procedure DoUserConsent(Const AURL : String; Out AAuthCode : String) ;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LBCalendarsSelectionChange(Sender: TObject; User: boolean);
private
{ private declarations }
FAccessState : TAccessTokenState;
FClient : TGoogleClient;
FCalendarAPI: TCalendarAPI;
calendarList: TCalendarList;
FCurrentCalendar : TCalendarListEntry;
events : TEvents;
procedure LoadAuthConfig;
procedure SaveRefreshToken;
public
{ public declarations }
end;
var
MainForm: TMainForm;
implementation
uses
{$ifdef windows}windows,{$endif}
jsonparser, // needed
fpoauth2,
lclintf,
{$IFDEF NATIVEWEBCLIENT}
fphttpwebclient
{$ELSE}
ssl_openssl,
synapsewebclient
{$ENDIF}
;
{$R *.lfm}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
// Register calendar resources.
TCalendarAPI.RegisterAPIResources;
// Set up google client.
FClient:=TGoogleClient.Create(Self);
FClient.WebClient:=TSynapseWebClient.Create(Self);
FClient.WebClient.RequestSigner:=FClient.AuthHandler;
FClient.AuthHandler.WebClient:=FClient.WebClient;
FClient.AuthHandler.Config.AccessType:=atOffLine;
// We want to enter a code.
FClient.OnUserConsent:=@DoUserConsent;
// Create a calendar API and connect it to the client.
FCalendarAPI:=TCalendarAPI.Create(Self);
FCalendarAPI.GoogleClient:=FClient;
// Load configuration
LoadAuthConfig;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FreeAndNil(CalendarList);
FreeAndNil(Events);
end;
procedure TMainForm.LBCalendarsSelectionChange(Sender: TObject; User: boolean);
begin
BFetchEvents.Enabled:=User and (LBCalendars.ItemIndex<>-1);
if BFetchEvents.Enabled then
begin
FCurrentCalendar:=LBCalendars.Items.Objects[LBCalendars.ItemIndex] as TCalendarListEntry;
if (FCurrentCalendar.Summary<>'') then
LEvents.Caption:='Events for calendar : '+FCurrentCalendar.Summary
else
LEvents.Caption:='Events for calendar : '+FCurrentCalendar.ID;
end
else
begin
LEvents.Caption:='Events for calendar : <select a calendar>';
LBEvents.Items.Clear;
FCurrentCalendar:=Nil;
end;
end;
procedure TMainForm.LoadAuthConfig;
Var
ini:TIniFile;
begin
ini:=TIniFile.Create('google.ini');
try
With FClient.AuthHandler.Config,Ini do
begin
// Registered application needs calendar scope
ClientID:=ReadString('Credentials','ClientID','');
ClientSecret:=ReadString('Credentials','ClientSecret','');
AuthScope:=ReadString('Credentials','Scope',
'https://www.googleapis.com/auth/calendar');
// We are offline.
RedirectUri:='urn:ietf:wg:oauth:2.0:oob';
end;
With FClient.AuthHandler.Session,Ini do
begin
// Session data
RefreshToken:=ReadString('Session','RefreshToken','');
AccessToken:=ReadString('Session','AccesToken','');
AuthTokenType:=ReadString('Session','TokenType','');
AuthExpires:=ReadDateTime('Session','AuthExpires',0);
AuthExpiryPeriod:=ReadInteger('Session','AuthPeriod',0);
end;
finally
Ini.Free;
end;
end;
procedure TMainForm.SaveRefreshToken;
Var
ini:TIniFile;
begin
// We save the refresh token for later use.
With FClient.AuthHandler.Session do
if RefreshToken<>'' then
begin
ini:=TIniFile.Create('google.ini');
try
With ini do
begin
WriteString('Session','RefreshToken',RefreshToken);
WriteString('Session','AccessToken',AccessToken);
WriteString('Session','TokenType',AuthTokenType);
WriteDateTime('Session','AuthExpires',AuthExpires);
WriteInteger('Session','AuthPeriod',AuthExpiryPeriod);
end;
finally
Ini.Free;
end;
end;
end;
procedure TMainForm.BFetchCalendarsClick(Sender: TObject);
var
Entry: TCalendarListEntry;
Resource : TCalendarListResource;
EN : String;
i:integer;
begin
LBCalendars.Items.Clear;
FreeAndNil(CalendarList);
Resource:=Nil;
try
Resource:=FCalendarAPI.CreateCalendarListResource;
CalendarList:=Resource.list('');
SaveRefreshToken;
if assigned(calendarList) then
for i:= 0 to Length(calendarList.items)-1 do
begin
Entry:=calendarList.items[i];
EN:=Entry.Summary;
if EN='' then
EN:=Entry.id+' ('+Entry.description+')';
LBCalendars.Items.AddObject(IntToStr(i)+': '+EN,Entry);
end;
BFetchEvents.Enabled:=LBCalendars.Items.Count>0;
finally
FreeAndNil(Resource);
end;
end;
procedure TMainForm.BSetAccessClick(Sender: TObject);
begin
FAccessState:=acsOK;
GBAccess.Visible:=False;
end;
procedure TMainForm.BCancelClick(Sender: TObject);
begin
FAccessState:=acsCancel;
GBAccess.Visible:=False;
end;
procedure TMainForm.BFetchEventsClick(Sender: TObject);
var
Entry: TEvent;
EN : String;
i:integer;
begin
if LBCalendars.ItemIndex<0 then
Exit;
LBEvents.Items.Clear;
FreeAndNil(Events);
Events:=FCalendarAPI.EventsResource.list(FCurrentCalendar.id,'');
SaveRefreshToken;
if assigned(Events) then
for i:= 0 to Length(Events.items)-1 do
begin
Entry:=Events.items[i];
EN:=Entry.Summary;
if EN='' then
EN:=Entry.id+' ('+Entry.description+')';
if Assigned(Entry.Start) then
if Entry.start.date<>0 then
EN:=DateToStr(Entry.start.date)+' : '+EN
else if Entry.start.dateTime<>0 then
EN:=DateTimeToStr(Entry.start.datetime)+' : '+EN
else
EN:='(unspecified time) '+EN;
LBEvents.Items.AddObject(IntToStr(i)+': '+EN,Entry);
end;
end;
Procedure TMainForm.DoUserConsent(Const AURL: String; Out AAuthCode: String);
begin
GBAccess.Visible:=True;
EAccessCode.Text:='<enter code here>';
FAccessState:=acsWaiting;
OpenUrl(AURL);
While (FAccessState=acsWaiting) do
Application.ProcessMessages;
if FAccessState=acsOK then
AAuthCode:=EAccessCode.Text;
GBAccess.Visible:=False;
end;
end.

View File

@ -0,0 +1,12 @@
[Credentials]
ClientID=Your client id
ClientSecret=Your secret key
Scope=https://www.googleapis.com/auth/calendar
[Session]
;RefreshToken=
;AccessToken=
;TokenType=
;AuthExpires=
;AuthPeriod=
;AccessToken=

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="discoverydemo"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="4">
<Item1>
<PackageName Value="LazControls"/>
</Item1>
<Item2>
<PackageName Value="SynEdit"/>
</Item2>
<Item3>
<PackageName Value="laz_synapse"/>
</Item3>
<Item4>
<PackageName Value="LCL"/>
</Item4>
</RequiredPackages>
<Units Count="4">
<Unit0>
<Filename Value="discoverydemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="frmmain.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="MainForm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmmain"/>
</Unit1>
<Unit2>
<Filename Value="frmgenoptions.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="GenCodeFormOptions"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmgenoptions"/>
</Unit2>
<Unit3>
<Filename Value="frmview.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="ViewForm"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmview"/>
</Unit3>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="discoverydemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="../..;../../../base"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,22 @@
program discoverydemo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, lazcontrols, frmmain, frmgenoptions, frmview;
{$R *.res}
begin
RequireDerivedFormResource := True;
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TGenCodeFormOptions, GenCodeFormOptions);
Application.CreateForm(TViewForm, ViewForm);
Application.Run;
end.

Binary file not shown.

View File

@ -0,0 +1,125 @@
object GenCodeFormOptions: TGenCodeFormOptions
Left = 644
Height = 205
Top = 319
Width = 374
Caption = 'Generate pascal code'
ClientHeight = 205
ClientWidth = 374
Position = poMainFormCenter
LCLVersion = '1.5'
object EBaseClass: TEdit
Left = 160
Height = 18
Top = 64
Width = 200
TabOrder = 0
end
object EExtraUnits: TEdit
Left = 160
Height = 18
Top = 88
Width = 200
TabOrder = 1
end
object EPrefix: TEdit
Left = 160
Height = 18
Top = 112
Width = 80
TabOrder = 2
end
object Label1: TLabel
Left = 62
Height = 12
Top = 64
Width = 87
Alignment = taRightJustify
Caption = 'Parent Class name'
ParentColor = False
end
object Label2: TLabel
Left = 27
Height = 12
Top = 88
Width = 122
Alignment = taRightJustify
Caption = 'Extra units for uses clause'
ParentColor = False
end
object ButtonPanel1: TButtonPanel
Left = 6
Height = 33
Top = 166
Width = 362
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
HelpButton.Name = 'HelpButton'
HelpButton.DefaultCaption = True
CloseButton.Name = 'CloseButton'
CloseButton.DefaultCaption = True
CancelButton.Name = 'CancelButton'
CancelButton.DefaultCaption = True
TabOrder = 3
ShowButtons = [pbOK, pbCancel]
end
object Label3: TLabel
Left = 48
Height = 12
Top = 112
Width = 101
Alignment = taRightJustify
Caption = 'Prefix for class names'
ParentColor = False
end
object EUnitName: TEdit
Left = 160
Height = 18
Top = 11
Width = 104
OnEditingDone = EUnitNameEditingDone
TabOrder = 4
end
object Label4: TLabel
Left = 99
Height = 12
Top = 11
Width = 50
Alignment = taRightJustify
Caption = 'Unit name'
ParentColor = False
end
object EFileName: TFileNameEdit
Left = 160
Height = 20
Top = 37
Width = 200
DialogKind = dkSave
DialogOptions = [ofPathMustExist, ofEnableSizing, ofViewDetail]
Filter = 'All pascal files|*.pp;*.pas|Delphi files|*.pas|FPC files|*.pp|All files|*.*'
FilterIndex = 0
DefaultExt = '.pp'
HideDirectories = False
ButtonWidth = 23
NumGlyphs = 1
MaxLength = 0
TabOrder = 5
end
object LFileName: TLabel
Left = 99
Height = 12
Top = 40
Width = 51
Alignment = taRightJustify
Caption = 'Save in file'
ParentColor = False
end
object CBView: TCheckBox
Left = 160
Height = 26
Top = 136
Width = 131
Caption = 'View generated code'
TabOrder = 6
end
end

View File

@ -0,0 +1,106 @@
unit frmgenoptions;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ButtonPanel, EditBtn;
type
{ TGenCodeFormOptions }
TGenCodeFormOptions = class(TForm)
ButtonPanel1: TButtonPanel;
CBView: TCheckBox;
EBaseClass: TEdit;
EUnitName: TEdit;
EExtraUnits: TEdit;
EPrefix: TEdit;
EFileName: TFileNameEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
LFileName: TLabel;
procedure EUnitNameEditingDone(Sender: TObject);
private
function GetB: Boolean;
function GetS(AIndex: Integer): String;
procedure SetB(AValue: Boolean);
procedure SetS(AIndex: Integer; AValue: String);
{ private declarations }
public
{ public declarations }
Property FileName : String index 0 read GetS Write SetS;
Property UnitName : String index 1 read GetS Write SetS;
Property ExtraUnits : String index 2 read GetS Write SetS;
Property Prefix : String index 3 read GetS Write SetS;
Property BaseClass : String index 4 read GetS Write SetS;
Property DoPreview : Boolean Read GetB Write SetB;
end;
var
GenCodeFormOptions: TGenCodeFormOptions;
implementation
{$R *.lfm}
{ TGenCodeFormOptions }
procedure TGenCodeFormOptions.EUnitNameEditingDone(Sender: TObject);
Var
E,FN : String;
begin
E:=ExtractFileExt(EFileName.FileName);
if E='' then
E:=EFileName.DefaultExt;
FN:=ExtractFilePath(EFileName.FileName);
if FN='' then
FN:=IncludeTrailingPathDelimiter(Application.Location);
FN:=FN+EUnitName.Text+E;
EFileName.FileName:=FN;
end;
function TGenCodeFormOptions.GetB: Boolean;
begin
Result:=CBView.Checked;
end;
function TGenCodeFormOptions.GetS(AIndex: Integer): String;
begin
Case AIndex of
0 : Result:=EFileName.Text;
1 : Result:=EUnitName.Text;
2 : Result:=EExtraUnits.Text;
3 : Result:=EPRefix.Text;
4 : Result:=EBaseClass.Text;
end;
end;
procedure TGenCodeFormOptions.SetB(AValue: Boolean);
begin
CBView.Checked:=AValue
end;
procedure TGenCodeFormOptions.SetS(AIndex: Integer; AValue: String);
begin
Case AIndex of
0 : EFileName.Text:=Avalue;
1 : begin
EUnitName.Text:=AValue;
EUnitNameEditingDone(EUnitName);
end;
2 : EExtraUnits.Text:=AValue;
3 : EPRefix.Text:=AValue;
4 : EBaseClass.Text:=AValue;
end;
end;
end.

View File

@ -0,0 +1,659 @@
object MainForm: TMainForm
Left = 533
Height = 444
Top = 225
Width = 707
Caption = 'Google Discovery Service Demo'
ClientHeight = 428
ClientWidth = 707
Menu = MainMenu1
OnCreate = FormCreate
ShowHint = True
LCLVersion = '1.5'
object LVServices: TListView
Left = 0
Height = 386
Top = 26
Width = 707
Align = alClient
Columns = <
item
Caption = 'Name'
Width = 120
end
item
Caption = 'Preferred'
end
item
Caption = 'ID'
Width = 120
end
item
Caption = 'Title'
Width = 200
end
item
Caption = 'Version'
end
item
Caption = 'Description'
Width = 300
end
item
Caption = 'DiscoveryLink'
Width = 300
end
item
Caption = 'DiscoveryRestURL'
Width = 300
end
item
Caption = 'DocumentationLink'
Width = 300
end
item
Caption = '16x16 Icon'
Width = 300
end
item
Caption = '32x32 Icon'
Width = 300
end
item
Caption = 'Labels'
Width = 300
end>
SortColumn = 0
SortType = stText
TabOrder = 0
ViewStyle = vsReport
end
object ToolBar1: TToolBar
Left = 0
Height = 26
Top = 0
Width = 707
Caption = 'ToolBar1'
Images = ILDiscovery
ParentShowHint = False
ShowHint = True
TabOrder = 1
object ToolButton1: TToolButton
Left = 1
Top = 2
Action = AFetch
end
object ToolButton2: TToolButton
Left = 24
Height = 22
Top = 2
Width = 10
Caption = 'ToolButton2'
Style = tbsSeparator
end
object ToolButton3: TToolButton
Left = 34
Top = 2
Action = ASaveREST
end
object ToolButton4: TToolButton
Left = 57
Top = 2
Action = AViewHelp
end
object ToolButton5: TToolButton
Left = 80
Top = 2
Action = AGenCode
end
object ToolButton6: TToolButton
Left = 103
Top = 2
Action = APreViewRest
end
object EFilter: TEdit
Left = 627
Height = 24
Top = 2
Width = 80
Align = alRight
OnChange = EFilterChange
TabOrder = 0
end
object Label1: TLabel
Left = 591
Height = 24
Top = 2
Width = 28
Align = alRight
BorderSpacing.Right = 8
Caption = 'Filter:'
Layout = tlCenter
ParentColor = False
end
end
object SBDiscovery: TStatusBar
Left = 0
Height = 16
Top = 412
Width = 707
Panels = <
item
Text = '0 items'
Width = 50
end
item
Width = 50
end>
SimplePanel = False
end
object ActionList1: TActionList
Images = ILDiscovery
left = 40
top = 96
object AFetch: TAction
Caption = 'List services/APIs'
ImageIndex = 0
OnExecute = BFetchClick
end
object AQuit: TAction
Caption = '&Quit'
ImageIndex = 2
OnExecute = AQuitExecute
ShortCut = 16465
end
object APreferredOnly: TAction
Caption = 'Show preferred only'
OnExecute = CBPreferredOnlyChange
end
object ASaveREST: TAction
Category = 'API'
Caption = 'Save REST description'
ImageIndex = 1
OnExecute = ASaveRESTExecute
OnUpdate = ASaveRESTUpdate
ShortCut = 16466
end
object AViewHelp: TAction
Category = 'API'
Caption = 'View API Help'
ImageIndex = 4
OnExecute = AViewHelpExecute
OnUpdate = AViewHelpUpdate
end
object AGenCode: TAction
Category = 'API'
Caption = 'Generate code'
ImageIndex = 3
OnExecute = AGenCodeExecute
OnUpdate = AGenCodeUpdate
end
object APreViewRest: TAction
Category = 'API'
Caption = 'View Rest JSON'
ImageIndex = 5
OnExecute = APreViewRestExecute
OnUpdate = APreViewRestUpdate
end
end
object MainMenu1: TMainMenu
Images = ILDiscovery
left = 176
top = 88
object MServices: TMenuItem
Caption = 'Services'
object MenuItem1: TMenuItem
Action = AFetch
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF00A465
34A2A4653401FFFFFF00FFFFFF00A4653405A4653453A76A3ABEA66938E9A466
35FAA76A3AE4A76B3BAAA4653424FFFFFF00FFFFFF00FFFFFF00FFFFFF00A465
34FFA5673693FFFFFF00A4653454A66737EEB58055F3CEA684FFD8B697FFDBB9
99FFD3AC8AFFC2946DFCA66838F6A466355BFFFFFF00FFFFFF00FFFFFF00A567
37FEB7845BF7A56736D4B17A4EF4E3CAB4FFECDAC9FFE7D1BCFFE3C9B0FFDEBE
A0FFD2AB88FFCEA582FFD3AE8EFFA66838F5A465342AFFFFFF00FFFFFF00A668
38FDF1E4D8FFD4B295FEF4E9E0FFF3E8DDFFEDDCCCFFD2AD8FFEB0784CF5A566
35FBA66939FFA66939FEA96D3DFFB0784CFFA76A3AA8FFFFFF00FFFFFF00A567
37FDF6EEE6FFF5ECE3FFF5EDE4FFE6D2C1FFB0794DF5A66938CAA4653436FFFF
FF00A465346AA96B3CEDB67C4FFFA76A3AFEA56837FAFFFFFF00FFFFFF00A466
35FCF6EEE6FFEBD7C4FFEAD9C9FFA46534FEA465346AFFFFFF00FFFFFF00FFFF
FF00A465340BA56635E9C9956C8DB77F53C2A46534FFA4653405FFFFFF00A465
34FCF5EDE5FFF6EDE5FFF5ECE4FFD7B79CFDA66837E0A4653410FFFFFF00FFFF
FF00FFFFFF00FFFFFF00D5A47E1ACD997239A46534FCA465340CFFFFFF00A465
34F9A46534FEA46534FEA46534FDA46534FCA46534FBA46534B9A465341DA465
3418A4653418A4653418A4653418A4653418A465341CFFFFFF00FFFFFF00A465
340DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A46534A0A465
34FFAD7447F8AF774CF7AF774CF7AF784CF7A46534FFA4653408FFFFFF00A465
34FCB3794C7ECF9D762BBB835713A4653402FFFFFF00FFFFFF00A4653404A668
38C4D0AC8FFAF6EEE7FFF2E6DBFFF6EEE6FFA66A3AFBA4653409FFFFFF00A465
35FEA76A3AFBC791689DA56737E6A4653423FFFFFF00FFFFFF00FFFFFF00A465
3460A46635FFE9D7C7FFEBD8C6FFF5ECE3FFA66A3AFAA465340AFFFFFF00A668
38F3AB7041FFA96C3CFEA76A3AF5A4653475A4653419A4653445A66938CDB988
61F5EBDBCDFFF5EBE2FFF6EEE6FFF6EEE6FFA76A3AFAA465340BFFFFFF00A769
399BC09069FDC59872FFA86B3CFFA46635FFA76A3AFCB7855DF3D9BBA1FEF1E4
D8FFF2E6DBFFF3E8DDFFCEA788FDEAD8C8FFA76A3AF9A465340DFFFFFF00A465
3429A66939F5D3AD8CFFDCBD9DFFDDBEA1FFE5CBB4FFE9D3BFFFEEDDCCFFF0E2
D5FFE7D2BFFFAF774BF5A56736C0AB7143F7A46635FCA465340EFFFFFF00FFFF
FF00A4653550A66838F6C09068FAD3B08FFFDFC2A8FFDEC1A8FFD4B193FFB987
5FF4A56737F0A4653458FFFFFF00A4663566A46534FFA465340FFFFFFF00FFFF
FF00FFFFFF00A465341DA7693A9FA76A3ADEA56736F6A76939E5A76A3ABCA465
3453A4653405FFFFFF00FFFFFF00FFFFFF00A4653479A4653410
}
end
object MIPreferredOnly: TMenuItem
Action = APreferredOnly
AutoCheck = True
ShortCut = 16464
ShowAlwaysCheckable = True
end
object MenuItem2: TMenuItem
Caption = '-'
end
object MIQuit: TMenuItem
Action = AQuit
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D63
9B1619609839145D9562105A92880D5890A4135C92FC0C578FED999999FF7171
71FF545454FF515151FF4F4F4FFF4C4C4CFF4A4A4AFF474747FF454545FF2567
9DFF3274A8FF3D7CAFFF4784B5FF4E8ABAFF3E7EADFF0C578FEAFFFFFF00FFFF
FF00585858FFA2A2A2FFA2A2A2FFA3A3A3FFA4A4A4FFA4A4A4FFA5A5A5FF2F6F
A5FF78ABD2FF78ABD3FF73A7D1FF69A0CDFF407FAEFF0F5991EAFFFFFF00FFFF
FF005C5C5CFFA1A1A1FF3C7340FFA0A1A1FFA3A3A3FFA3A3A3FFA4A4A4FF3674
AAFF7DAFD4FF5B9AC9FF5495C7FF5896C8FF4180AEFF135C94EAFFFFFF00FFFF
FF00606060FFA0A0A0FF3D7641FF367139FFA2A2A2FFA2A2A2FFA3A3A3FF3D79
B0FF82B3D7FF629FCCFF5A9AC9FF5E9BCAFF4381AFFF196098EA37823EFF347E
3BFF317937FF2E7534FF499150FF468F4CFF39733DFFA1A1A1FFA2A2A2FF457E
B4FF88B7D9FF67A3CFFF619ECCFF639FCCFF4583B1FF1F649CEA3B8742FF89CB
92FF84C88DFF80C688FF7BC383FF77C17FFF478F4DFF3B743FFFA1A1A1FF4C84
BAFF8DBBDBFF6EA8D1FF66A6D1FF5FB4DFFF4785B1FF2569A1EA3E8B46FF8FCE
99FF7DC687FF78C381FF73C07CFF74C07CFF79C281FF49904FFF547F57FF5489
BFFF94BFDDFF75ADD4FF63B8E1FF4BD4FFFF428BB8FF2C6EA6EA41904AFF94D2
9FFF91D09AFF8DCD96FF89CB92FF84C88DFF519858FF417C46FF9F9F9FFF5A8E
C4FF98C3E0FF7CB3D7FF74AFD6FF5EC4EDFF4B88B3FF3473ABEA44944DFF4291
4BFF3F8D48FF3D8945FF5DA465FF5AA061FF45834BFF9E9E9EFF9E9E9EFF6092
C9FF9EC7E2FF83B8DAFF7DB4D7FF7EB3D7FF4F89B4FF3B79B1EAFFFFFF00FFFF
FF00777777FF9A9A9AFF3D8A45FF498A4FFF9C9C9CFF9D9D9DFF9D9D9DFF6696
CCFFA2CBE3FF89BDDCFF83B9DAFF84B9DAFF518BB5FF437EB6EAFFFFFF00FFFF
FF007A7A7AFF999999FF529159FF999A99FF9B9B9BFF9C9C9CFF9C9C9CFF6C9A
D0FFA7CEE5FF8FC1DFFF89BDDCFF8BBDDCFF538DB6FF4B84BCEAFFFFFF00FFFF
FF007D7D7DFF999999FF999999FF9A9A9AFF9A9A9AFF9B9B9BFF9B9B9BFF6F9D
D3FFAAD1E7FFABD1E7FF98C7E1FF91C2DEFF568FB7FF5289C1EAFFFFFF00FFFF
FF00808080FF7E7E7EFF7C7C7CFF7A7A7AFF777777FF757575FF727272FF719E
D4FF6F9ED6FF87B2DCFFABD3E8FFA9D0E6FF5890B8FF598EC6EAFFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00709ED6DB6D9CD4FF85B1DAFF5A91B9FF6093CBEAFFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF006D9CD4896A9AD2FB6697CFEE
}
end
end
object MAPI: TMenuItem
Caption = 'API'
object MenuItem6: TMenuItem
Action = APreViewRest
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000545655FF5456
55FF545655FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C4C4C4FF8484
84FF848484FF848484FF848484FF848484FF848484FFFFFFFF00545655FF0EB2
5FFF7ECAA3FF545655FFFFFFFF00848484FF848484FF848484FF848484FFE5E5
E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FF848484FFFFFFFF00545655FF0EB2
5FFF0EB25FFF7ECAA3FF545655FF848484FFFFFFFF00FFFFFF00848484FF8484
84FF848484FF848484FF848484FF848484FFC4C4C4FFFFFFFF00FFFFFF005456
55FF0EB25FFF0EB25FFF7ECAA3FF545655FFFFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00545655FF0EB25FFF0EB25FFF7ECAA3FF545655FF545655FF545655FF5456
55FF545655FF848484FF848484FF848484FF848484FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00545655FF0EB25FFF545655FF545655FFE4B881FFB97F5FFFE2B6
8EFF545655FF545655FFE5E5E5FFE5E5E5FF848484FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00545655FF545655FFE4B881FFE4B881FFB97F5FFFB67A
58FFBD7C4FFF545655FF545655FF848484FFC4C4C4FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00545655FF947868FFE4B881FFDCBAA0FFD9BFA9FFD7C1
B4FFDFB896FFE3BB7EFF545655FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00545655FFAD795DFFDFBB94FFD4C3C0FFD8C0AEFFAD85
6BFFC1824DFFA87F66FF545655FF848484FF848484FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00545655FF8F746BFFC67B3CFF9D8B86FF9C8D8AFFD8C0
AEFFE3BB7EFFE4B881FF545655FFE5E5E5FF848484FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00545655FF545655FFD4B2A4FFD4C3C0FFF9E9D8FFD4C3
C0FFBA774FFF545655FF545655FF848484FFC4C4C4FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00545655FF545655FFD4C3C0FFF9E9D8FFD4C3
C0FF545655FF545655FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00C4C4C4FF8484
84FF848484FF848484FFFFFFFF00848484FF545655FF545655FF545655FF5456
55FF545655FF848484FF848484FF848484FF848484FFFFFFFF00848484FFE5E5
E5FFE5E5E5FF848484FF848484FF848484FF848484FF848484FF848484FFE5E5
E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FF848484FFFFFFFF00848484FF8484
84FF848484FFC4C4C4FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00848484FF8484
84FF848484FF848484FF848484FF848484FFC4C4C4FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
}
end
object MenuItem3: TMenuItem
Action = ASaveREST
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00995B1EC496581AC9FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF009F6327CFAF7841FFAD753DFF9759
1BD1FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00AB723A06A86E35D9B5804BFFCCA37AFFCCA37AFFAE76
3FFF97591BDB95571906FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00AF7841B8AC743CF7C19263FFCEA67EFFCDA47CFFB17A
44FF9A5D20F7985A1DBBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00B0794238B5804BFFD0A983FFCFA881FFA266
2BFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B17A44FFD2AC87FFD1AB85FFA66C
32FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B7834FFFD3AE8AFFD3AE8AFFAB72
3AFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00BA8755FFD5B18EFFD5B18EFFAF78
41FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00BF8F5FFFD8B695FFD7B593FFB580
4BFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C39567FFD9B898FFD8B695FFB884
51FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C6996DFFDBBC9DFFDABA9AFFBD8C
5BFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CAA076FFDDBFA2FFDCBD9FFFC293
65FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CCA37AFFDEC1A4FFDDBFA2FFC598
6BFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CDA47CFFCDA47CFFCAA076FFC99E
73FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
}
end
object MenuItem4: TMenuItem
Action = AViewHelp
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00AD744423AC72417DAA703FDBA86D3CF3A76B3AF3A569
37DBA468357DA3663323FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00B57E5153B37C4EE6D7BBA3FFE9DACAFFECE0D1FFECE0D1FFE8D8
C8FFD3B59CFFA76C3AE6A66A3853FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00BD895F53BB875BF4E7D5C4FFE5D2BFFFC9A685FFB88E67FFB68A65FFC5A1
80FFE0CCBAFFE3D0BEFFAB7040F4A96E3D53FFFFFF00FFFFFF00FFFFFF00C695
6D22C3926AE5EAD8C9FFE3CDBAFFC0946BFFBA8C62FFCFB094FFCFB094FFB789
5FFFB28761FFDAC0AAFFE4D1C0FFAE7546E5AD734322FFFFFF00FFFFFF00CC9E
787EE4CCB9FFEAD6C5FFC79971FFBF9066FFBF9066FFF7F1ECFFF6F0EAFFB789
5FFFB7895FFFB58963FFE2CEBBFFD9BDA6FFB27B4D7EFFFFFF00FFFFFF00D3A7
84DBEFE1D3FFD9B595FFC7986CFFC39569FFC19367FFBF9066FFBF9066FFBB8B
63FFB98A63FFB88A62FFCBA786FFEADCCCFFB88357DBFFFFFF00FFFFFF00D9B0
8FF6F2E4D9FFD1A57AFFC5996BFFC4976AFFC49669FFFAF6F2FFF3EAE1FFC295
6DFFBE8F65FFBE8F64FFC0956DFFEFE3D5FFBF8C61F6FFFFFF00FFFFFF00E0B9
99F6F2E5DAFFD1A67EFFCC9D71FFC79A6CFFC5986BFFE2CCB6FFF8F3EEFFF6EE
E8FFD9BDA1FFC29468FFC59B71FFF0E2D6FFC5956CF6FFFFFF00FFFFFF00E6C1
A3DBF3E5D9FFDFBB9EFFCFA075FFCD9E72FFF5EBE3FFE4CBB4FFE7D3BFFFFBF8
F6FFE5D3BFFFC4986BFFD6B491FFEEE0D2FFCC9E78DBFFFFFF00FFFFFF00EBC9
AD7EF4E3D4FFEFDCCDFFD5A87EFFD0A077FFFBF8F5FFFCF8F5FFFCF8F5FFFBF8
F5FFD1A881FFCFA47BFFEAD5C3FFEAD4C2FFD2A7837EFFFFFF00FFFFFF00F1D0
B522EFCEB3E5F6E9DDFFECD8C6FFD7AC81FFDCBB9AFFF6ECE3FFF5ECE2FFE4C8
AEFFD2A77BFFE6CEBAFFF1E2D5FFDBB391E5D9B08E22FFFFFF00FFFFFF00FFFF
FF00F4D4BB53F2D2B8F4F7EADFFFEEDED0FFE3C1A7FFD8AE89FFD7AC86FFDDBB
9CFFEBD6C7FFF3E6D9FFE3BE9FF4E1BB9C53FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00F6D8BF53F5D6BDE6F9E9DCFFF6E8DDFFF3E5DAFFF3E5DAFFF5E7
DCFFF5E4D6FFEBC8ACE6E9C6A953FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00F9DBC423F8DAC27DF7D8C0DBF6D7BEF3F4D5BCF3F3D3
B9DBF1D1B77DF0CFB423FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
}
end
object MenuItem5: TMenuItem
Action = AGenCode
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF008C8E
8DFF888D8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D
8BFF888D8BFF888D8BFF888D8BFF888D8BFF8C8E8DFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFE
FEFFFEFEFEFFFEFEFEFFFEFEFEFFFFFFFFFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF3F4F4FF858A88FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5
F5FFF4F5F5FFECECECFFEBECECFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF4F5F5FFF4F5F5FF000000FF36576BFF02598FFFF4F5F5FFF4F5
F5FFF4F5F5FFEEEEEEFFEDEDEDFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF6F7F7FF858A88FF325061FF8AABC2FF5585A3FF02598FFF858A
88FF858A88FF858A88FFEEEFEFFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FFF6F7F7FF02598FFFC4E5EDFF649FC8FF5787A4FF0259
8FFFF1F2F2FFF0F1F1FFF0F0F0FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FF858A88FF858A88FF02598FFFC5E6EDFF68A6CEFF5784
A0FF02598FFFF7F8F8FFF1F2F2FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FFF4F5F5FFF4F5F5FFF4F5F5FF02598FFFC6EAEEFF69AA
CFFF5683A0FF02598FFFF3F3F3FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FFA36936FFA36936FFA36936FFA36936FF02598FFFC7EB
EFFF6AACD2FF5787A4FF02598FFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FF0259
8FFFC7EBEFFF02598FFF02598FFF02598FFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FF858A88FF858A88FF858A88FF858A88FF858A88FF858A
88FF02598FFF02598FFFC7EBEFFF02598FFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8
F8FFF7F8F8FF02598FFF02598FFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FF0E0ED8FF0E0ED8FF0E0ED8FF858A88FF858A88FFF7F8
F8FFF7F8F8FFF7F8F8FFF7F8F8FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A
88FFFFFFFFFFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8
F8FFF7F8F8FFF7F8F8FFF7F8F8FF858A88FFFFFFFF00FFFFFF00FFFFFF00858A
88FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFF858A88FFFFFFFF00FFFFFF00FFFFFF00FFFFFF008C8E
8DFF858A88FF858A88FF858A88FF858A88FF858A88FF858A88FF858A88FF858A
88FF858A88FF858A88FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00
}
end
end
end
object ILDiscovery: TImageList
left = 113
top = 96
Bitmap = {
4C69060000001000000010000000FFFFFF00FFFFFF00FFFFFF00A465341DA769
3A9FA76A3ADEA56736F6A76939E5A76A3ABCA4653453A4653405FFFFFF00FFFF
FF00FFFFFF00A4653479A4653410FFFFFF00FFFFFF00A4653550A66838F6C090
68FAD3B08FFFDFC2A8FFDEC1A8FFD4B193FFB9875FF4A56737F0A4653458FFFF
FF00A4663566A46534FFA465340FFFFFFF00A4653429A66939F5D3AD8CFFDCBD
9DFFDDBEA1FFE5CBB4FFE9D3BFFFEEDDCCFFF0E2D5FFE7D2BFFFAF774BF5A567
36C0AB7143F7A46635FCA465340EFFFFFF00A769399BC09069FDC59872FFA86B
3CFFA46635FFA76A3AFCB7855DF3D9BBA1FEF1E4D8FFF2E6DBFFF3E8DDFFCEA7
88FDEAD8C8FFA76A3AF9A465340DFFFFFF00A66838F3AB7041FFA96C3CFEA76A
3AF5A4653475A4653419A4653445A66938CDB98861F5EBDBCDFFF5EBE2FFF6EE
E6FFF6EEE6FFA76A3AFAA465340BFFFFFF00A46535FEA76A3AFBC791689DA567
37E6A4653423FFFFFF00FFFFFF00FFFFFF00A4653460A46635FFE9D7C7FFEBD8
C6FFF5ECE3FFA66A3AFAA465340AFFFFFF00A46534FCB3794C7ECF9D762BBB83
5713A4653402FFFFFF00FFFFFF00A4653404A66838C4D0AC8FFAF6EEE7FFF2E6
DBFFF6EEE6FFA66A3AFBA4653409FFFFFF00A465340DFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00A46534A0A46534FFAD7447F8AF774CF7AF77
4CF7AF784CF7A46534FFA4653408FFFFFF00A46534F9A46534FEA46534FEA465
34FDA46534FCA46534FBA46534B9A465341DA4653418A4653418A4653418A465
3418A4653418A465341CFFFFFF00FFFFFF00A46534FCF5EDE5FFF6EDE5FFF5EC
E4FFD7B79CFDA66837E0A4653410FFFFFF00FFFFFF00FFFFFF00FFFFFF00D5A4
7E1ACD997239A46534FCA465340CFFFFFF00A46635FCF6EEE6FFEBD7C4FFEAD9
C9FFA46534FEA465346AFFFFFF00FFFFFF00FFFFFF00A465340BA56635E9C995
6C8DB77F53C2A46534FFA4653405FFFFFF00A56737FDF6EEE6FFF5ECE3FFF5ED
E4FFE6D2C1FFB0794DF5A66938CAA4653436FFFFFF00A465346AA96B3CEDB67C
4FFFA76A3AFEA56837FAFFFFFF00FFFFFF00A66838FDF1E4D8FFD4B295FEF4E9
E0FFF3E8DDFFEDDCCCFFD2AD8FFEB0784CF5A56635FBA66939FFA66939FEA96D
3DFFB0784CFFA76A3AA8FFFFFF00FFFFFF00A56737FEB7845BF7A56736D4B17A
4EF4E3CAB4FFECDAC9FFE7D1BCFFE3C9B0FFDEBEA0FFD2AB88FFCEA582FFD3AE
8EFFA66838F5A465342AFFFFFF00FFFFFF00A46534FFA5673693FFFFFF00A465
3454A66737EEB58055F3CEA684FFD8B697FFDBB999FFD3AC8AFFC2946DFCA668
38F6A466355BFFFFFF00FFFFFF00FFFFFF00A46534A2A4653401FFFFFF00FFFF
FF00A4653405A4653453A76A3ABEA66938E9A46635FAA76A3AE4A76B3BAAA465
3424FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00CDA47CFFCDA47CFFCAA076FFC99E73FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00CCA37AFFDEC1A4FFDDBFA2FFC5986BFFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00CAA076FFDDBFA2FFDCBD9FFFC29365FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00C6996DFFDBBC9DFFDABA9AFFBD8C5BFFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00C39567FFD9B898FFD8B695FFB88451FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00BF8F5FFFD8B695FFD7B593FFB5804BFFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00BA8755FFD5B18EFFD5B18EFFAF7841FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00B7834FFFD3AE8AFFD3AE8AFFAB723AFFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00B17A44FFD2AC87FFD1AB85FFA66C32FFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00B0794238B5804BFFD0A983FFCFA881FFA2662BFFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AF78
41B8AC743CF7C19263FFCEA67EFFCDA47CFFB17A44FF9A5D20F7985A1DBBFFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AB72
3A06A86E35D9B5804BFFCCA37AFFCCA37AFFAE763FFF97591BDB95571906FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF009F6327CFAF7841FFAD753DFF97591BD1FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00995B1EC496581AC9FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF006D9CD4896A9AD2FB6697CFEEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00709ED6DB6D9C
D4FF85B1DAFF5A91B9FF6093CBEAFFFFFF00FFFFFF00808080FF7E7E7EFF7C7C
7CFF7A7A7AFF777777FF757575FF727272FF719ED4FF6F9ED6FF87B2DCFFABD3
E8FFA9D0E6FF5890B8FF598EC6EAFFFFFF00FFFFFF007D7D7DFF999999FF9999
99FF9A9A9AFF9A9A9AFF9B9B9BFF9B9B9BFF6F9DD3FFAAD1E7FFABD1E7FF98C7
E1FF91C2DEFF568FB7FF5289C1EAFFFFFF00FFFFFF007A7A7AFF999999FF5291
59FF999A99FF9B9B9BFF9C9C9CFF9C9C9CFF6C9AD0FFA7CEE5FF8FC1DFFF89BD
DCFF8BBDDCFF538DB6FF4B84BCEAFFFFFF00FFFFFF00777777FF9A9A9AFF3D8A
45FF498A4FFF9C9C9CFF9D9D9DFF9D9D9DFF6696CCFFA2CBE3FF89BDDCFF83B9
DAFF84B9DAFF518BB5FF437EB6EA44944DFF42914BFF3F8D48FF3D8945FF5DA4
65FF5AA061FF45834BFF9E9E9EFF9E9E9EFF6092C9FF9EC7E2FF83B8DAFF7DB4
D7FF7EB3D7FF4F89B4FF3B79B1EA41904AFF94D29FFF91D09AFF8DCD96FF89CB
92FF84C88DFF519858FF417C46FF9F9F9FFF5A8EC4FF98C3E0FF7CB3D7FF74AF
D6FF5EC4EDFF4B88B3FF3473ABEA3E8B46FF8FCE99FF7DC687FF78C381FF73C0
7CFF74C07CFF79C281FF49904FFF547F57FF5489BFFF94BFDDFF75ADD4FF63B8
E1FF4BD4FFFF428BB8FF2C6EA6EA3B8742FF89CB92FF84C88DFF80C688FF7BC3
83FF77C17FFF478F4DFF3B743FFFA1A1A1FF4C84BAFF8DBBDBFF6EA8D1FF66A6
D1FF5FB4DFFF4785B1FF2569A1EA37823EFF347E3BFF317937FF2E7534FF4991
50FF468F4CFF39733DFFA1A1A1FFA2A2A2FF457EB4FF88B7D9FF67A3CFFF619E
CCFF639FCCFF4583B1FF1F649CEAFFFFFF00FFFFFF00606060FFA0A0A0FF3D76
41FF367139FFA2A2A2FFA2A2A2FFA3A3A3FF3D79B0FF82B3D7FF629FCCFF5A9A
C9FF5E9BCAFF4381AFFF196098EAFFFFFF00FFFFFF005C5C5CFFA1A1A1FF3C73
40FFA0A1A1FFA3A3A3FFA3A3A3FFA4A4A4FF3674AAFF7DAFD4FF5B9AC9FF5495
C7FF5896C8FF4180AEFF135C94EAFFFFFF00FFFFFF00585858FFA2A2A2FFA2A2
A2FFA3A3A3FFA4A4A4FFA4A4A4FFA5A5A5FF2F6FA5FF78ABD2FF78ABD3FF73A7
D1FF69A0CDFF407FAEFF0F5991EA999999FF717171FF545454FF515151FF4F4F
4FFF4C4C4CFF4A4A4AFF474747FF454545FF25679DFF3274A8FF3D7CAFFF4784
B5FF4E8ABAFF3E7EADFF0C578FEAFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D639B1619609839145D9562105A
92880D5890A4135C92FC0C578FEDFFFFFF008C8E8DFF858A88FF858A88FF858A
88FF858A88FF858A88FF858A88FF858A88FF858A88FF858A88FF858A88FFFFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00858A88FFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF858A
88FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FFF7F8
F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8
F8FF858A88FFFFFFFF00FFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FF0E0E
D8FF0E0ED8FF0E0ED8FF858A88FF858A88FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8
F8FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FFF7F8
F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FFF7F8F8FF02598FFF0259
8FFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FF858A
88FF858A88FF858A88FF858A88FF858A88FF858A88FF02598FFF02598FFFC7EB
EFFF02598FFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FFF4F5
F5FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FF02598FFFC7EBEFFF02598FFF0259
8FFF02598FFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FFA369
36FFA36936FFA36936FFA36936FF02598FFFC7EBEFFF6AACD2FF5787A4FF0259
8FFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FFF4F5
F5FFF4F5F5FFF4F5F5FF02598FFFC6EAEEFF69AACFFF5683A0FF02598FFFF3F3
F3FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FF858A
88FF858A88FF02598FFFC5E6EDFF68A6CEFF5784A0FF02598FFFF7F8F8FFF1F2
F2FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF7F8F8FFF6F7
F7FF02598FFFC4E5EDFF649FC8FF5787A4FF02598FFFF1F2F2FFF0F1F1FFF0F0
F0FFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF6F7F7FF858A
88FF325061FF8AABC2FF5585A3FF02598FFF858A88FF858A88FF858A88FFEEEF
EFFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF4F5F5FFF4F5
F5FF000000FF36576BFF02598FFFF4F5F5FFF4F5F5FFF4F5F5FFEEEEEEFFEDED
EDFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFF3F4F4FF858A
88FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FFF4F5F5FFECECECFFEBEC
ECFFFEFEFEFF888D8BFFFFFFFF00FFFFFF00858A88FFFFFFFFFFFEFEFEFFFEFE
FEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFE
FEFFFFFFFFFF888D8BFFFFFFFF00FFFFFF008C8E8DFF888D8BFF888D8BFF888D
8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D8BFF888D
8BFF888D8BFF8C8E8DFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F9DB
C423F8DAC27DF7D8C0DBF6D7BEF3F4D5BCF3F3D3B9DBF1D1B77DF0CFB423FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F6D8BF53F5D6
BDE6F9E9DCFFF6E8DDFFF3E5DAFFF3E5DAFFF5E7DCFFF5E4D6FFEBC8ACE6E9C6
A953FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F4D4BB53F2D2B8F4F7EA
DFFFEEDED0FFE3C1A7FFD8AE89FFD7AC86FFDDBB9CFFEBD6C7FFF3E6D9FFE3BE
9FF4E1BB9C53FFFFFF00FFFFFF00FFFFFF00F1D0B522EFCEB3E5F6E9DDFFECD8
C6FFD7AC81FFDCBB9AFFF6ECE3FFF5ECE2FFE4C8AEFFD2A77BFFE6CEBAFFF1E2
D5FFDBB391E5D9B08E22FFFFFF00FFFFFF00EBC9AD7EF4E3D4FFEFDCCDFFD5A8
7EFFD0A077FFFBF8F5FFFCF8F5FFFCF8F5FFFBF8F5FFD1A881FFCFA47BFFEAD5
C3FFEAD4C2FFD2A7837EFFFFFF00FFFFFF00E6C1A3DBF3E5D9FFDFBB9EFFCFA0
75FFCD9E72FFF5EBE3FFE4CBB4FFE7D3BFFFFBF8F6FFE5D3BFFFC4986BFFD6B4
91FFEEE0D2FFCC9E78DBFFFFFF00FFFFFF00E0B999F6F2E5DAFFD1A67EFFCC9D
71FFC79A6CFFC5986BFFE2CCB6FFF8F3EEFFF6EEE8FFD9BDA1FFC29468FFC59B
71FFF0E2D6FFC5956CF6FFFFFF00FFFFFF00D9B08FF6F2E4D9FFD1A57AFFC599
6BFFC4976AFFC49669FFFAF6F2FFF3EAE1FFC2956DFFBE8F65FFBE8F64FFC095
6DFFEFE3D5FFBF8C61F6FFFFFF00FFFFFF00D3A784DBEFE1D3FFD9B595FFC798
6CFFC39569FFC19367FFBF9066FFBF9066FFBB8B63FFB98A63FFB88A62FFCBA7
86FFEADCCCFFB88357DBFFFFFF00FFFFFF00CC9E787EE4CCB9FFEAD6C5FFC799
71FFBF9066FFBF9066FFF7F1ECFFF6F0EAFFB7895FFFB7895FFFB58963FFE2CE
BBFFD9BDA6FFB27B4D7EFFFFFF00FFFFFF00C6956D22C3926AE5EAD8C9FFE3CD
BAFFC0946BFFBA8C62FFCFB094FFCFB094FFB7895FFFB28761FFDAC0AAFFE4D1
C0FFAE7546E5AD734322FFFFFF00FFFFFF00FFFFFF00BD895F53BB875BF4E7D5
C4FFE5D2BFFFC9A685FFB88E67FFB68A65FFC5A180FFE0CCBAFFE3D0BEFFAB70
40F4A96E3D53FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B57E5153B37C
4EE6D7BBA3FFE9DACAFFECE0D1FFECE0D1FFE8D8C8FFD3B59CFFA76C3AE6A66A
3853FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AD74
4423AC72417DAA703FDBA86D3CF3A76B3AF3A56937DBA468357DA3663323FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00848484FF848484FF848484FFC4C4C4FFFFFF
FF00FFFFFF00FFFFFF00FFFFFF00848484FF848484FF848484FF848484FF8484
84FF848484FFC4C4C4FFFFFFFF00848484FFE5E5E5FFE5E5E5FF848484FF8484
84FF848484FF848484FF848484FF848484FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5
E5FFE5E5E5FF848484FFFFFFFF00C4C4C4FF848484FF848484FF848484FFFFFF
FF00848484FF545655FF545655FF545655FF545655FF545655FF848484FF8484
84FF848484FF848484FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00545655FF545655FFD4C3C0FFF9E9D8FFD4C3C0FF545655FF545655FFFFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005456
55FF545655FFD4B2A4FFD4C3C0FFF9E9D8FFD4C3C0FFBA774FFF545655FF5456
55FF848484FFC4C4C4FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005456
55FF8F746BFFC67B3CFF9D8B86FF9C8D8AFFD8C0AEFFE3BB7EFFE4B881FF5456
55FFE5E5E5FF848484FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005456
55FFAD795DFFDFBB94FFD4C3C0FFD8C0AEFFAD856BFFC1824DFFA87F66FF5456
55FF848484FF848484FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005456
55FF947868FFE4B881FFDCBAA0FFD9BFA9FFD7C1B4FFDFB896FFE3BB7EFF5456
55FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005456
55FF545655FFE4B881FFE4B881FFB97F5FFFB67A58FFBD7C4FFF545655FF5456
55FF848484FFC4C4C4FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00545655FF0EB2
5FFF545655FF545655FFE4B881FFB97F5FFFE2B68EFF545655FF545655FFE5E5
E5FFE5E5E5FF848484FFFFFFFF00FFFFFF00FFFFFF00545655FF0EB25FFF0EB2
5FFF7ECAA3FF545655FF545655FF545655FF545655FF545655FF848484FF8484
84FF848484FF848484FFFFFFFF00FFFFFF00545655FF0EB25FFF0EB25FFF7ECA
A3FF545655FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00545655FF0EB25FFF0EB25FFF7ECAA3FF5456
55FF848484FFFFFFFF00FFFFFF00848484FF848484FF848484FF848484FF8484
84FF848484FFC4C4C4FFFFFFFF00545655FF0EB25FFF7ECAA3FF545655FFFFFF
FF00848484FF848484FF848484FF848484FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5
E5FFE5E5E5FF848484FFFFFFFF00545655FF545655FF545655FFFFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00C4C4C4FF848484FF848484FF848484FF8484
84FF848484FF848484FFFFFFFF00
}
end
object SDJSON: TSaveDialog
DefaultExt = '.json'
Filter = 'JSON Files|*.json|All files|*.*'
Options = [ofPathMustExist, ofEnableSizing, ofViewDetail]
left = 104
top = 157
end
end

View File

@ -0,0 +1,394 @@
unit frmmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ComCtrls, ActnList, Menus, ListViewFilterEdit, restbase, googleclient,
googlediscovery, frmgenoptions, frmview;
type
{ TMainForm }
TMainForm = class(TForm)
APreViewRest: TAction;
AGenCode: TAction;
AViewHelp: TAction;
ASaveREST: TAction;
APreferredOnly: TAction;
AQuit: TAction;
AFetch: TAction;
ActionList1: TActionList;
EFilter: TEdit;
ILDiscovery: TImageList;
Label1: TLabel;
LVServices: TListView;
MainMenu1: TMainMenu;
MenuItem1: TMenuItem;
MenuItem2: TMenuItem;
MAPI: TMenuItem;
MenuItem3: TMenuItem;
MenuItem4: TMenuItem;
MenuItem5: TMenuItem;
MenuItem6: TMenuItem;
MIQuit: TMenuItem;
MIPreferredOnly: TMenuItem;
MServices: TMenuItem;
SDJSON: TSaveDialog;
SBDiscovery: TStatusBar;
ToolBar1: TToolBar;
ToolButton1: TToolButton;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
ToolButton5: TToolButton;
ToolButton6: TToolButton;
procedure APreViewRestExecute(Sender: TObject);
procedure APreViewRestUpdate(Sender: TObject);
procedure ASaveRESTExecute(Sender: TObject);
procedure ASaveRESTUpdate(Sender: TObject);
procedure AGenCodeExecute(Sender: TObject);
procedure AGenCodeUpdate(Sender: TObject);
procedure AQuitExecute(Sender: TObject);
procedure AViewHelpExecute(Sender: TObject);
procedure AViewHelpUpdate(Sender: TObject);
procedure BFetchClick(Sender: TObject);
procedure CBPreferredOnlyChange(Sender: TObject);
procedure EFilterChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
FClient : TGoogleClient;
FDiscoveryAPI : TDiscoveryAPI;
FDirectory : TDirectoryList;
Function CurrentAPI : TDirectoryListitems;
procedure DoFetch;
procedure DownLoadRestAPI(Const AName,AURL: String);
procedure GenerateCode(const AName, AURL: String);
procedure ShowDiscovery(PreferredOnly: Boolean; FilterOn: String);
procedure UpdateCaption;
procedure ViewFile(AFileName: String);
procedure ViewFile(AStream: TStream; ASyntax: TSyntax; ACaption: String);
procedure ViewRestAPI(const AName, AURL: String);
public
{ public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.lfm}
uses
ssl_openssl,
jsonparser, // needed
fpoauth2, lclintf,
synapsewebclient,
googlediscoverytopas,
httpsend;
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
// set up communication.
FClient:=TGoogleClient.Create(Self);
FClient.WebClient:=TSynapseWebClient.Create(Self);
// Register all classes so they can be streamed.
TDiscoveryAPI.RegisterAPIResources;
// create the API and hook it up to the google client.
FDiscoveryAPI:=TDiscoveryAPI.Create(Self);
FDiscoveryAPI.GoogleClient:=FClient;
// The code generator uses it's own objects.
TDiscoveryJSONToPas.RegisterAllObjects;
UpdateCaption;
end;
procedure TMainForm.BFetchClick(Sender: TObject);
begin
DoFetch;
end;
procedure TMainForm.AQuitExecute(Sender: TObject);
begin
Close;
end;
procedure TMainForm.AViewHelpExecute(Sender: TObject);
begin
OpenURL(CurrentAPI.DocumentationLink);
end;
procedure TMainForm.AViewHelpUpdate(Sender: TObject);
begin
(Sender as TAction).Enabled:=Assigned(CurrentAPI) and (CurrentAPI.documentationLink<>'');
end;
procedure TMainForm.ASaveRESTUpdate(Sender: TObject);
begin
(Sender as TAction).Enabled:=Assigned(CurrentAPI) and (CurrentAPI.discoveryRestUrl<>'');
end;
procedure TMainForm.AGenCodeExecute(Sender: TObject);
Var
DLI : TDirectoryListitems;
begin
DLI:=CurrentAPI;
GenerateCode(DLI.Name,DLI.DiscoveryRestUrl);
end;
procedure TMainForm.AGenCodeUpdate(Sender: TObject);
begin
(Sender as TAction).Enabled:=Assigned(CurrentAPI) and (CurrentAPI.discoveryRestUrl<>'')
end;
procedure TMainForm.ViewFile(AFileName : String);
begin
With TViewForm.Create(Nil) do
begin
Caption:='Viewing file: '+AFileName;
FileName:=AFileName;
Show;
end;
end;
procedure TMainForm.ViewFile(AStream : TStream; ASyntax : TSyntax; ACaption : String);
begin
With TViewForm.Create(Nil) do
begin
AStream.POsition:=0;
Caption:='Viewing: '+ACaption;
Stream:=AStream;
Syntax:=ASyntax;
FreeStream:=True;
Show;
end;
end;
procedure TMainForm.GenerateCode(const AName, AURL: String);
Var
S : TMemoryStream;
FO : TGenCodeFormOptions;
DP : TDiscoveryJSONToPas;
begin
FO:=Nil;
DP:=Nil;
S:=TMemoryStream.Create;
try
if HttpGetBinary(AURL,S) then
begin
S.Position:=0;
FO:=TGenCodeFormOptions.Create(Self);
FO.UnitName:=AName;
If FO.ShowModal=mrOK then
begin
DP:=TDiscoveryJSONToPas.Create(Self);
DP.LoadFromStream(S);
DP.BaseClassName:=FO.BaseClass;
DP.OutputUnitName:=FO.UnitName;
DP.ExtraUnits:=FO.ExtraUnits;
DP.ClassPrefix:=FO.Prefix;
DP.SaveToFile(FO.FileName);
if FO.DoPreview then
ViewFile(FO.FileName);
end;
end;
Finally
FO.Free;
DP.Free;
S.Free;
end;
end;
procedure TMainForm.DownLoadRestAPI(const AName, AURL: String);
Var
S : TMemoryStream;
begin
S:=TMemoryStream.Create;
try
if HttpGetBinary(AURL,S) then
begin
SDJSON.FileName:='google'+aname+'.json';
If SDJSON.Execute then
With TFileStream.Create(SDJSON.FileName,fmCreate) do
try
CopyFrom(S,0);
finally
Free;
end;
end;
finally
S.Free;
end;
end;
procedure TMainForm.ViewRestAPI(const AName, AURL: String);
Var
S : TMemoryStream;
begin
S:=TMemoryStream.Create;
try
if HttpGetBinary(AURL,S) then
begin
ViewFile(S,sJSON,'REST discovery for '+AName);
S:=Nil;
end;
finally
S.Free;
end;
end;
procedure TMainForm.ASaveRESTExecute(Sender: TObject);
Var
DLI : TDirectoryListitems;
begin
DLI:=CurrentAPI;
DownLoadRestAPI(DLI.Name,DLI.DiscoveryRestUrl);
end;
procedure TMainForm.APreViewRestUpdate(Sender: TObject);
begin
(Sender as TAction).Enabled:=Assigned(CurrentAPI) and (CurrentAPI.discoveryRestUrl<>'');
end;
procedure TMainForm.APreViewRestExecute(Sender: TObject);
Var
DLI : TDirectoryListitems;
begin
DLI:=CurrentAPI;
ViewRestAPI(DLI.Name,DLI.DiscoveryRestUrl);
end;
procedure TMainForm.CBPreferredOnlyChange(Sender: TObject);
begin
if (LVServices.Items.Count>0) then
ShowDiscovery(MIPreferredOnly.Checked,EFilter.Text);
end;
procedure TMainForm.EFilterChange(Sender: TObject);
begin
if (LVServices.Items.Count>0) then
ShowDiscovery(MIPreferredOnly.Checked,EFilter.Text);
end;
procedure TMainForm.UpdateCaption;
Var
C : Integer;
begin
C:=LVServices.Items.Count;
if (C=0) then
Caption:='Google Discovery Service Demo'
else
Caption:=Format('Google Discovery Service Demo (%d services)',[C]);
SBDiscovery.Panels[0].Text:=Format('%d items',[C]);
end;
function TMainForm.CurrentAPI: TDirectoryListitems;
begin
If Assigned(LVServices.Selected) and Assigned(LVServices.Selected.Data) then
Result:=TDirectoryListitems(LVServices.Selected.Data)
else
Result:=Nil;
end;
procedure TMainForm.ShowDiscovery(PreferredOnly : Boolean; FilterOn : String);
Function DoComma(S : TStringArray) : String;
Var
I : String;
begin
Result:='';
For I in S do
begin
if Result<>'' then
Result:=Result+',';
Result:=Result+I;
end;
end;
Function Contains(S: String) : Boolean; inline;
begin
Result:=Pos(FilterOn,LowerCase(S))<>0;
end;
Function ShowItem (DLI : TDirectoryListitems) : Boolean;
begin
Result:=DLI.Preferred or (Not PreferredOnly);
if Result and (FilterOn<>'') then
begin
Result:=Contains(DLI.Name)
or Contains(DLI.Title)
or Contains(DLI.kind)
or Contains(DLI.description)
or Contains(DoComma(DLI.Labels));
end;
end;
Var
DLI : TDirectoryListitems;
LI : TListItem;
begin
FilterOn:=LowerCase(Filteron);
LVServices.Items.BeginUpdate;
try
LVServices.Items.Clear;
LVServices.Column[1].Visible:=Not PreferredOnly;
For DLI in FDirectory.Items do
if ShowItem(DLI) then
begin
LI:=LVServices.Items.Add;
LI.Caption:=DLI.name;
LI.Data:=DLI;
With LI.SubItems,DLI do
begin
Add(BoolToStr(preferred,'True','False'));
Add(id);
Add(title);
Add(version);
Add(description);
Add(discoveryLink);
Add(discoveryRestUrl);
Add(documentationLink);
Add(icons.x16);
Add(icons.x32);
Add(DoComma(labels));
end;
end;
UpdateCaption;
finally
LVServices.Items.EndUpdate;
end;
end;
procedure TMainForm.DoFetch;
begin
// Free any previous list.
FreeAndNil(FDirectory);
// Get the new list using a default ApisResource.
FDirectory:=FDiscoveryAPI.ApisResource.List();
ShowDiscovery(MIPreferredOnly.Checked,EFilter.Text);
end;
end.

View File

@ -0,0 +1,539 @@
object ViewForm: TViewForm
Left = 453
Height = 507
Top = 289
Width = 754
Caption = 'Preview'
ClientHeight = 507
ClientWidth = 754
OnDestroy = FormDestroy
Position = poMainFormCenter
LCLVersion = '1.5'
inline SEFile: TSynEdit
Left = 0
Height = 462
Top = 0
Width = 754
Align = alClient
Font.Height = -13
Font.Name = 'Courier New'
Font.Pitch = fpFixed
Font.Quality = fqNonAntialiased
ParentColor = False
ParentFont = False
TabOrder = 0
Gutter.Width = 57
Gutter.MouseActions = <>
RightGutter.Width = 0
RightGutter.MouseActions = <>
Keystrokes = <
item
Command = ecUp
ShortCut = 38
end
item
Command = ecSelUp
ShortCut = 8230
end
item
Command = ecScrollUp
ShortCut = 16422
end
item
Command = ecDown
ShortCut = 40
end
item
Command = ecSelDown
ShortCut = 8232
end
item
Command = ecScrollDown
ShortCut = 16424
end
item
Command = ecLeft
ShortCut = 37
end
item
Command = ecSelLeft
ShortCut = 8229
end
item
Command = ecWordLeft
ShortCut = 16421
end
item
Command = ecSelWordLeft
ShortCut = 24613
end
item
Command = ecRight
ShortCut = 39
end
item
Command = ecSelRight
ShortCut = 8231
end
item
Command = ecWordRight
ShortCut = 16423
end
item
Command = ecSelWordRight
ShortCut = 24615
end
item
Command = ecPageDown
ShortCut = 34
end
item
Command = ecSelPageDown
ShortCut = 8226
end
item
Command = ecPageBottom
ShortCut = 16418
end
item
Command = ecSelPageBottom
ShortCut = 24610
end
item
Command = ecPageUp
ShortCut = 33
end
item
Command = ecSelPageUp
ShortCut = 8225
end
item
Command = ecPageTop
ShortCut = 16417
end
item
Command = ecSelPageTop
ShortCut = 24609
end
item
Command = ecLineStart
ShortCut = 36
end
item
Command = ecSelLineStart
ShortCut = 8228
end
item
Command = ecEditorTop
ShortCut = 16420
end
item
Command = ecSelEditorTop
ShortCut = 24612
end
item
Command = ecLineEnd
ShortCut = 35
end
item
Command = ecSelLineEnd
ShortCut = 8227
end
item
Command = ecEditorBottom
ShortCut = 16419
end
item
Command = ecSelEditorBottom
ShortCut = 24611
end
item
Command = ecToggleMode
ShortCut = 45
end
item
Command = ecCopy
ShortCut = 16429
end
item
Command = ecPaste
ShortCut = 8237
end
item
Command = ecDeleteChar
ShortCut = 46
end
item
Command = ecCut
ShortCut = 8238
end
item
Command = ecDeleteLastChar
ShortCut = 8
end
item
Command = ecDeleteLastChar
ShortCut = 8200
end
item
Command = ecDeleteLastWord
ShortCut = 16392
end
item
Command = ecUndo
ShortCut = 32776
end
item
Command = ecRedo
ShortCut = 40968
end
item
Command = ecLineBreak
ShortCut = 13
end
item
Command = ecSelectAll
ShortCut = 16449
end
item
Command = ecCopy
ShortCut = 16451
end
item
Command = ecBlockIndent
ShortCut = 24649
end
item
Command = ecLineBreak
ShortCut = 16461
end
item
Command = ecInsertLine
ShortCut = 16462
end
item
Command = ecDeleteWord
ShortCut = 16468
end
item
Command = ecBlockUnindent
ShortCut = 24661
end
item
Command = ecPaste
ShortCut = 16470
end
item
Command = ecCut
ShortCut = 16472
end
item
Command = ecDeleteLine
ShortCut = 16473
end
item
Command = ecDeleteEOL
ShortCut = 24665
end
item
Command = ecUndo
ShortCut = 16474
end
item
Command = ecRedo
ShortCut = 24666
end
item
Command = ecGotoMarker0
ShortCut = 16432
end
item
Command = ecGotoMarker1
ShortCut = 16433
end
item
Command = ecGotoMarker2
ShortCut = 16434
end
item
Command = ecGotoMarker3
ShortCut = 16435
end
item
Command = ecGotoMarker4
ShortCut = 16436
end
item
Command = ecGotoMarker5
ShortCut = 16437
end
item
Command = ecGotoMarker6
ShortCut = 16438
end
item
Command = ecGotoMarker7
ShortCut = 16439
end
item
Command = ecGotoMarker8
ShortCut = 16440
end
item
Command = ecGotoMarker9
ShortCut = 16441
end
item
Command = ecSetMarker0
ShortCut = 24624
end
item
Command = ecSetMarker1
ShortCut = 24625
end
item
Command = ecSetMarker2
ShortCut = 24626
end
item
Command = ecSetMarker3
ShortCut = 24627
end
item
Command = ecSetMarker4
ShortCut = 24628
end
item
Command = ecSetMarker5
ShortCut = 24629
end
item
Command = ecSetMarker6
ShortCut = 24630
end
item
Command = ecSetMarker7
ShortCut = 24631
end
item
Command = ecSetMarker8
ShortCut = 24632
end
item
Command = ecSetMarker9
ShortCut = 24633
end
item
Command = EcFoldLevel1
ShortCut = 41009
end
item
Command = EcFoldLevel2
ShortCut = 41010
end
item
Command = EcFoldLevel3
ShortCut = 41011
end
item
Command = EcFoldLevel4
ShortCut = 41012
end
item
Command = EcFoldLevel5
ShortCut = 41013
end
item
Command = EcFoldLevel6
ShortCut = 41014
end
item
Command = EcFoldLevel7
ShortCut = 41015
end
item
Command = EcFoldLevel8
ShortCut = 41016
end
item
Command = EcFoldLevel9
ShortCut = 41017
end
item
Command = EcFoldLevel0
ShortCut = 41008
end
item
Command = EcFoldCurrent
ShortCut = 41005
end
item
Command = EcUnFoldCurrent
ShortCut = 41003
end
item
Command = EcToggleMarkupWord
ShortCut = 32845
end
item
Command = ecNormalSelect
ShortCut = 24654
end
item
Command = ecColumnSelect
ShortCut = 24643
end
item
Command = ecLineSelect
ShortCut = 24652
end
item
Command = ecTab
ShortCut = 9
end
item
Command = ecShiftTab
ShortCut = 8201
end
item
Command = ecMatchBracket
ShortCut = 24642
end
item
Command = ecColSelUp
ShortCut = 40998
end
item
Command = ecColSelDown
ShortCut = 41000
end
item
Command = ecColSelLeft
ShortCut = 40997
end
item
Command = ecColSelRight
ShortCut = 40999
end
item
Command = ecColSelPageDown
ShortCut = 40994
end
item
Command = ecColSelPageBottom
ShortCut = 57378
end
item
Command = ecColSelPageUp
ShortCut = 40993
end
item
Command = ecColSelPageTop
ShortCut = 57377
end
item
Command = ecColSelLineStart
ShortCut = 40996
end
item
Command = ecColSelLineEnd
ShortCut = 40995
end
item
Command = ecColSelEditorTop
ShortCut = 57380
end
item
Command = ecColSelEditorBottom
ShortCut = 57379
end>
MouseActions = <>
MouseTextActions = <>
MouseSelActions = <>
Lines.Strings = (
'SEFile'
)
VisibleSpecialChars = [vscSpace, vscTabAtLast]
ReadOnly = True
SelectedColor.BackPriority = 50
SelectedColor.ForePriority = 50
SelectedColor.FramePriority = 50
SelectedColor.BoldPriority = 50
SelectedColor.ItalicPriority = 50
SelectedColor.UnderlinePriority = 50
SelectedColor.StrikeOutPriority = 50
BracketHighlightStyle = sbhsBoth
BracketMatchColor.Background = clNone
BracketMatchColor.Foreground = clNone
BracketMatchColor.Style = [fsBold]
FoldedCodeColor.Background = clNone
FoldedCodeColor.Foreground = clGray
FoldedCodeColor.FrameColor = clGray
MouseLinkColor.Background = clNone
MouseLinkColor.Foreground = clBlue
LineHighlightColor.Background = clNone
LineHighlightColor.Foreground = clNone
inline SynLeftGutterPartList1: TSynGutterPartList
object SynGutterMarks1: TSynGutterMarks
Width = 24
MouseActions = <>
end
object SynGutterLineNumber1: TSynGutterLineNumber
Width = 17
MouseActions = <>
MarkupInfo.Background = clBtnFace
MarkupInfo.Foreground = clNone
DigitCount = 2
ShowOnlyLineNumbersMultiplesOf = 1
ZeroStart = False
LeadingZeros = False
end
object SynGutterChanges1: TSynGutterChanges
Width = 4
MouseActions = <>
ModifiedColor = 59900
SavedColor = clGreen
end
object SynGutterSeparator1: TSynGutterSeparator
Width = 2
MouseActions = <>
MarkupInfo.Background = clWhite
MarkupInfo.Foreground = clGray
end
object SynGutterCodeFolding1: TSynGutterCodeFolding
MouseActions = <>
MarkupInfo.Background = clNone
MarkupInfo.Foreground = clGray
MouseActionsExpanded = <>
MouseActionsCollapsed = <>
end
end
end
object ButtonPanel1: TButtonPanel
Left = 6
Height = 33
Top = 468
Width = 742
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
HelpButton.Name = 'HelpButton'
HelpButton.DefaultCaption = True
CloseButton.Name = 'CloseButton'
CloseButton.DefaultCaption = True
CancelButton.Name = 'CancelButton'
CancelButton.DefaultCaption = True
TabOrder = 1
ShowButtons = [pbClose]
end
object SynJS: TSynJScriptSyn
left = 46
top = 19
end
object SynFPC: TSynFreePascalSyn
StringAttri.Style = [fsBold]
CompilerMode = pcmObjFPC
NestedComments = True
left = 136
top = 16
end
end

View File

@ -0,0 +1,85 @@
unit frmview;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ButtonPanel,
SynEdit, SynHighlighterMulti, SynHighlighterJScript, SynHighlighterPas;
type
{ TViewForm }
TSyntax = (sPascal,sJSON);
TViewForm = class(TForm)
ButtonPanel1: TButtonPanel;
SEFile: TSynEdit;
SynFPC: TSynFreePascalSyn;
SynJS: TSynJScriptSyn;
procedure FormDestroy(Sender: TObject);
private
FFileName: String;
FFreeStream: Boolean;
FStream: TStream;
FSyntax: TSyntax;
procedure SetFileName(AValue: String);
procedure SetStream(AValue: TStream);
procedure SetSyntax(AValue: TSyntax);
{ private declarations }
public
{ public declarations }
Property FileName : String Read FFileName Write SetFileName;
Property Syntax : TSyntax Read FSyntax Write SetSyntax;
Property Stream : TStream Read FStream Write SetStream;
Property FreeStream : Boolean Read FFreeStream Write FFreeStream;
end;
var
ViewForm: TViewForm;
implementation
{$R *.lfm}
{ TViewForm }
procedure TViewForm.FormDestroy(Sender: TObject);
begin
If Assigned(FStream) and FFreeStream then
FreeAndNil(FStream);
end;
procedure TViewForm.SetFileName(AValue: String);
begin
if FFileName=AValue then Exit;
FFileName:=AValue;
Case lowercase(ExtractFileExt(FFilename)) of
'.pas','.pp','.inc','.lpr','.dpr' :
Syntax:=sPascal;
'.json','.js':
Syntax:=sJSON;
end;
SEFIle.Lines.LoadFromFile(AValue);
end;
procedure TViewForm.SetStream(AValue: TStream);
begin
if FStream=AValue then Exit;
FStream:=AValue;
SEFIle.Lines.LoadFromStream(AValue);
end;
procedure TViewForm.SetSyntax(AValue: TSyntax);
begin
if FSyntax=AValue then Exit;
FSyntax:=AValue;
Case FSyntax of
sPascal: SEFile.Highlighter:=SynFPC;
sJSON : SEFile.Highlighter:=SynJS;
end;
SEFile.Highlighter.Enabled:=True;
end;
end.

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="drivedemo"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="laz_synapse"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="3">
<Unit0>
<Filename Value="drivedemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="frmmain.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="MainForm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmmain"/>
</Unit1>
<Unit2>
<Filename Value="frmselectdownload.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="SelectDownloadForm"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmselectdownload"/>
</Unit2>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="drivedemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="../..;../../../base"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,22 @@
program drivedemo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, frmmain, frmselectdownload
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource := True;
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TSelectDownloadForm, SelectDownloadForm);
Application.Run;
end.

Binary file not shown.

View File

@ -0,0 +1,154 @@
object MainForm: TMainForm
Left = 506
Height = 396
Top = 173
Width = 756
Caption = 'Google drive demo'
ClientHeight = 396
ClientWidth = 756
OnCreate = FormCreate
OnDestroy = FormDestroy
LCLVersion = '1.5'
object BRefreshFolders: TButton
Left = 72
Height = 25
Top = 8
Width = 64
Caption = 'Refresh'
OnClick = BRefreshFoldersClick
TabOrder = 0
end
object GBAccess: TGroupBox
Left = 0
Height = 73
Top = 323
Width = 756
Align = alBottom
Caption = 'Please provide Google API access code'
ClientHeight = 45
ClientWidth = 752
TabOrder = 1
Visible = False
object LEAccess: TLabel
Left = 16
Height = 12
Top = 8
Width = 56
Caption = 'Access code'
ParentColor = False
end
object BSetAccess: TButton
Left = 582
Height = 25
Top = 1
Width = 75
Anchors = [akTop, akRight]
Caption = 'OK'
OnClick = BSetAccessClick
TabOrder = 0
end
object BCancel: TButton
Left = 662
Height = 25
Top = 0
Width = 75
Anchors = [akTop, akRight]
Caption = 'Cancel'
OnClick = BCancelClick
TabOrder = 1
end
object EAccessCode: TEdit
Left = 112
Height = 18
Top = 8
Width = 400
TabOrder = 2
end
end
object BRefreshFiles: TButton
Left = 614
Height = 25
Top = 8
Width = 112
Anchors = [akTop, akRight]
Caption = 'Refresh'
Enabled = False
OnClick = BRefreshFilesClick
TabOrder = 2
end
object LTasks: TLabel
Left = 392
Height = 12
Top = 16
Width = 215
Anchors = [akTop, akLeft, akRight]
Caption = 'Files in folder'
ParentColor = False
end
object Label1: TLabel
Left = 22
Height = 12
Top = 16
Width = 34
Caption = 'Folders'
ParentColor = False
end
object TVFolders: TTreeView
Left = 16
Height = 272
Top = 35
Width = 344
Anchors = [akTop, akLeft, akBottom]
DefaultItemHeight = 14
ReadOnly = True
TabOrder = 3
OnSelectionChanged = TVFoldersSelectionChanged
Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
end
object LVFiles: TListView
Left = 384
Height = 272
Top = 35
Width = 360
Anchors = [akTop, akLeft, akRight, akBottom]
Columns = <
item
Caption = 'Title'
end
item
Caption = 'Date Created'
Width = 100
end
item
Caption = 'Description'
Width = 200
end
item
Caption = 'Editable'
end
item
Caption = 'Size'
end
item
Caption = 'Last modified by'
end
item
Caption = 'DownloadURL'
Width = 300
end
item
Caption = 'Version'
end
item
Caption = 'Mime Type'
Width = 200
end>
TabOrder = 4
ViewStyle = vsReport
OnDblClick = LVFilesDblClick
end
object SDDownload: TSaveDialog
left = 415
top = 163
end
end

View File

@ -0,0 +1,390 @@
unit frmmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ComCtrls, synautil, IniFiles, googlebase, googleservice, googleclient,
googledrive;
Const
ILeaf = 0;
ILeafEmpty = 1;
type
{ TMainForm }
TAccessTokenState = (acsWaiting,acsOK,acsCancel);
TMainForm = class(TForm)
BCancel: TButton;
BSetAccess: TButton;
BRefreshFolders: TButton;
BRefreshFiles: TButton;
EAccessCode: TEdit;
GBAccess: TGroupBox;
Label1: TLabel;
LVFiles: TListView;
LTasks: TLabel;
LEAccess: TLabel;
SDDownload: TSaveDialog;
TVFolders: TTreeView;
procedure BCancelClick(Sender: TObject);
procedure BRefreshFilesClick(Sender: TObject);
procedure BSetAccessClick(Sender: TObject);
procedure BRefreshFoldersClick(Sender: TObject);
Procedure DoUserConsent(Const AURL : String; Out AAuthCode : String) ;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LVFilesDblClick(Sender: TObject);
procedure TVFoldersSelectionChanged(Sender: TObject);
private
{ private declarations }
FAccessState : TAccessTokenState;
FClient : TGoogleClient;
FDriveAPI: TDriveAPI;
procedure AddFolders(AParent: TTreeNode; AFolderID: String);
procedure ClearFileListView;
procedure ClearTreeView;
procedure LoadAuthConfig;
procedure SaveRefreshToken;
procedure ShowFolder(AFolderID: String);
public
{ public declarations }
end;
var
MainForm: TMainForm;
implementation
uses {$ifdef windows}windows,{$endif}
ssl_openssl,
jsonparser, // needed
fpjson,
fpoauth2,
lclintf,
fpwebclient,
frmselectdownload,
synapsewebclient;
{$R *.lfm}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
// Register Tasks resources.
TDriveAPI.RegisterAPIResources;
// Set up google client.
FClient:=TGoogleClient.Create(Self);
FClient.WebClient:=TSynapseWebClient.Create(Self);
FClient.WebClient.RequestSigner:=FClient.AuthHandler;
FClient.WebClient.LogFile:='requests.log';
FClient.AuthHandler.WebClient:=FClient.WebClient;
FClient.AuthHandler.Config.AccessType:=atOffLine;
// We want to enter a code.
FClient.OnUserConsent:=@DoUserConsent;
// Create a Tasks API and connect it to the client.
FDriveAPI:=TDriveAPI.Create(Self);
FDriveAPI.GoogleClient:=FClient;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
end;
procedure TMainForm.LVFilesDblClick(Sender: TObject);
Var
Entry : TFile;
Request : TWebClientRequest;
Response: TWebClientResponse;
S,URL,LFN: String;
D : TJSONEnum;
begin
If Not (Assigned(LVFiles.Selected) and Assigned(LVFiles.Selected.Data)) then
Exit;
Entry:=TFile(LVFiles.Selected.Data);
if (Entry.DownloadUrl='')
and ((Entry.exportLinks=Nil) or (Entry.exportLinks.additionalProperties=Nil) or ((Entry.exportLinks.additionalProperties.Count)=0)) then
Exit;
if Entry.DownloadUrl<>'' then
URL:=TDriveAPI.APIBaseURL+'files/'+Entry.ID+'?alt=media'
else
begin
With TSelectDownloadForm.Create(Self) do
try
Formats.BeginUpdate;
For D in Entry.exportLinks.additionalProperties do
Formats.Add(D.Key);
if (ShowModal=mrOK) then
S:=Selected;
finally
Free;
end;
URL:=Entry.exportLinks.additionalProperties.Strings[S];
end;
SDDownload.FileName:=Application.Location+Entry.Title+'.'+Entry.fileExtension;
If Not SDDownload.Execute then
Exit;
Response:=Nil;
Request:=FClient.WebClient.CreateRequest;
try
Response:=FClient.WebClient.ExecuteSignedRequest('GET',URL,Request);
With TFileStream.Create(SDDownLoad.FileName,fmCreate) do
try
CopyFrom(Response.Content,0);
finally
Free;
end;
finally
Response.Free;
Request.Free;
end;
end;
procedure TMainForm.TVFoldersSelectionChanged(Sender: TObject);
begin
BRefreshFilesClick(Sender)
end;
procedure TMainForm.LoadAuthConfig;
Var
ini:TIniFile;
begin
ini:=TIniFile.Create('google.ini');
try
// Registered application needs tasks scope
FClient.AuthHandler.Config.ClientID:=ini.ReadString('Credentials','ClientID','');;
FClient.AuthHandler.Config.ClientSecret:=ini.ReadString('Credentials','ClientSecret','');
FClient.AuthHandler.Config.AuthScope:=ini.ReadString('Credentials','Scope','https://www.googleapis.com/auth/drive');
// We are offline.
FClient.AuthHandler.Config.RedirectUri:='urn:ietf:wg:oauth:2.0:oob';
// Session data
FClient.AuthHandler.Session.RefreshToken:=ini.ReadString('Session','RefreshToken','');
FClient.AuthHandler.Session.AccessToken:=ini.ReadString('Session','AccesToken','');
FClient.AuthHandler.Session.AuthTokenType:=ini.ReadString('Session','TokenType','');
FClient.AuthHandler.Session.AuthExpires:=ini.ReadDateTime('Session','AuthExpires',0);
FClient.AuthHandler.Session.AuthExpiryPeriod:=Ini.ReadInteger('Session','AuthPeriod',0);
finally
Ini.Free;
end;
end;
procedure TMainForm.SaveRefreshToken;
Var
ini:TIniFile;
begin
// We save the refresh token for later use.
if FClient.AuthHandler.Session.RefreshToken<>'' then
begin
ini:=TIniFile.Create('google.ini');
try
ini.WriteString('Session','RefreshToken',FClient.AuthHandler.Session.RefreshToken);
ini.WriteString('Session','AccessToken',FClient.AuthHandler.Session.AccessToken);
ini.WriteString('Session','TokenType',FClient.AuthHandler.Session.AuthTokenType);
ini.WriteDateTime('Session','AuthExpires',FClient.AuthHandler.Session.AuthExpires);
ini.WriteInteger('Session','AuthPeriod',FClient.AuthHandler.Session.AuthExpiryPeriod);
finally
Ini.Free;
end;
end;
end;
procedure TMainForm.ClearTreeView;
Var
I : Integer;
begin
With TVFolders.Items do
begin
BeginUpdate;
try
For I:=0 to Count-1 do
TObject(Item[i].Data).Free;
Clear;
finally
EndUpdate;
end;
end;
end;
procedure TMainForm.AddFolders(AParent : TTreeNode; AFolderID : String);
var
Entry: TFile;
Resource : TFilesResource;
EN : String;
Q : TFilesListOptions;
List : TFileList;
i : integer;
N : TTreeNode;
begin
Resource:=Nil;
try
Resource:=FDriveAPI.CreateFilesResource(Self);
// Search for folders of indicated folder only.
Q.q:='mimeType = ''application/vnd.google-apps.folder'' and '''+AFolderId+''' in parents';
Q.corpus:='';
q.maxResults:=0;
Q.pageToken:='';
Q.projection:='';
List:=Resource.list(Q);
SaveRefreshToken;
With TVFolders.Items do
begin
BeginUpdate;
try
if Assigned(List) then
for i:= 0 to Length(List.items)-1 do
begin
Entry:=List.items[i];
List.Items[i]:=Nil;
N:=AddChild(AParent,Entry.title);
N.Data:=Entry;
end;
finally
EndUpdate;
end;
end;
Application.ProcessMessages;
if Assigned(AParent) then
for I:=AParent.Count-1 downto 0 do
AddFolders(AParent.Items[i],TFile(AParent.Items[i].Data).id)
else if (TVFolders.Items.Count>0) then
for I:=TVFolders.Items.Count-1 downto 0 do
AddFolders(TVFolders.Items[i],TFile(TVFolders.Items[i].Data).id)
finally
FreeAndNil(Resource);
end;
end;
procedure TMainForm.BRefreshFoldersClick(Sender: TObject);
begin
LoadAuthConfig;
ClearTreeView;
AddFolders(Nil,'root');
end;
procedure TMainForm.BSetAccessClick(Sender: TObject);
begin
FAccessState:=acsOK;
GBAccess.Visible:=False;
end;
procedure TMainForm.BCancelClick(Sender: TObject);
begin
FAccessState:=acsCancel;
GBAccess.Visible:=False;
end;
procedure TMainForm.ClearFileListView;
Var
I : Integer;
begin
With LVFiles.Items do
begin
BeginUpdate;
try
For I:=0 to Count-1 do
TObject(Item[i].Data).Free;
Clear;
finally
EndUpdate;
end;
end;
end;
procedure TMainForm.BRefreshFilesClick(Sender: TObject);
begin
if (TVFolders.Selected=Nil) or (TVFolders.Selected.Data=Nil) then
ShowFolder('root')
else
ShowFolder(TFile(TVFolders.Selected.Data).ID);
end;
procedure TMainForm.ShowFolder(AFolderID : String);
var
Entry: TFile;
EN : String;
i:integer;
Q : TFilesListOptions;
List : TFileList;
Resource : TFilesResource;
LI : TListItem;
begin
ClearFileListView;
Resource:=Nil;
try
Resource:=FDriveAPI.CreateFilesResource(Self);
// Search for files of indicated folder only.
Q.q:='mimeType != ''application/vnd.google-apps.folder'' and '''+AFolderId+''' in parents';
List:=Resource.list(Q);
SaveRefreshToken;
With LVFiles.Items do
begin
BeginUpdate;
try
Clear;
if Assigned(List) then
for i:= 0 to Length(List.items)-1 do
begin
Entry:=List.items[i];
List.Items[i]:=Nil;
LI:=Add;
LI.Caption:=Entry.Title;
With LI.SubItems do
begin
Add(DateTimeToStr(Entry.createdDate));
Add(Entry.Description);
Add(BoolToStr(Entry.Editable,'Yes','No'));
Add(Entry.fileSize);
Add(Entry.lastModifyingUserName);
Add(Entry.downloadUrl);
Add(Entry.version);
Add(Entry.mimeType);
end;
Li.Data:=Entry;
end;
finally
EndUpdate;
end;
end;
Finally
Resource.Free;
end;
end;
Procedure TMainForm.DoUserConsent(Const AURL: String; Out AAuthCode: String);
begin
GBAccess.Visible:=True;
EAccessCode.Text:='<enter code here>';
FAccessState:=acsWaiting;
OpenUrl(AURL);
While (FAccessState=acsWaiting) do
Application.ProcessMessages;
if FAccessState=acsOK then
AAuthCode:=EAccessCode.Text;
GBAccess.Visible:=False;
end;
end.

View File

@ -0,0 +1,44 @@
object SelectDownloadForm: TSelectDownloadForm
Left = 612
Height = 226
Top = 344
Width = 354
Caption = 'Select download format for file'
ClientHeight = 226
ClientWidth = 354
Position = poOwnerFormCenter
LCLVersion = '1.5'
object ButtonPanel1: TButtonPanel
Left = 6
Height = 33
Top = 187
Width = 342
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
HelpButton.Name = 'HelpButton'
HelpButton.DefaultCaption = True
CloseButton.Name = 'CloseButton'
CloseButton.DefaultCaption = True
CancelButton.Name = 'CancelButton'
CancelButton.DefaultCaption = True
TabOrder = 0
ShowButtons = [pbOK, pbCancel]
end
object RGFormat: TRadioGroup
Left = 0
Height = 181
Top = 0
Width = 354
Align = alClient
AutoFill = True
Caption = 'Available download formats'
ChildSizing.LeftRightSpacing = 6
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
ChildSizing.EnlargeVertical = crsHomogenousChildResize
ChildSizing.ShrinkHorizontal = crsScaleChilds
ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
TabOrder = 1
end
end

View File

@ -0,0 +1,48 @@
unit frmselectdownload;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ButtonPanel,
ExtCtrls;
type
{ TSelectDownloadForm }
TSelectDownloadForm = class(TForm)
ButtonPanel1: TButtonPanel;
RGFormat: TRadioGroup;
private
function GetFormats: TStrings;
function GetSelected: String;
{ private declarations }
public
{ public declarations }
Property Formats : TStrings Read GetFormats;
Property Selected : String Read GetSelected;
end;
var
SelectDownloadForm: TSelectDownloadForm;
implementation
{$R *.lfm}
{ TSelectDownloadForm }
function TSelectDownloadForm.GetFormats: TStrings;
begin
Result:=RGFormat.Items;
end;
function TSelectDownloadForm.GetSelected: String;
begin
Result:=RGFormat.Items[RGFormat.ItemIndex];
end;
end.

View File

@ -0,0 +1,11 @@
[Credentials]
ClientID=Your client ID
ClientSecret=Your secret key
Scope=https://www.googleapis.com/auth/drive
[Session]
;RefreshToken=
;AccessToken=
;TokenType=
;AuthExpires=
;AuthPeriod=

View File

@ -0,0 +1,111 @@
object MainForm: TMainForm
Left = 456
Height = 345
Top = 191
Width = 702
Caption = 'Google Tasks demo'
ClientHeight = 345
ClientWidth = 702
OnCreate = FormCreate
OnDestroy = FormDestroy
LCLVersion = '1.3'
object BFetchTaskLists: TButton
Left = 8
Height = 25
Top = 8
Width = 112
Caption = 'Fetch task lists'
OnClick = BFetchTaskListsClick
TabOrder = 0
end
object GBAccess: TGroupBox
Left = 0
Height = 73
Top = 272
Width = 702
Align = alBottom
Caption = 'Please provide Google API access code'
ClientHeight = 45
ClientWidth = 698
TabOrder = 1
Visible = False
object LEAccess: TLabel
Left = 16
Height = 12
Top = 8
Width = 56
Caption = 'Access code'
ParentColor = False
end
object BSetAccess: TButton
Left = 528
Height = 25
Top = 1
Width = 75
Anchors = [akTop, akRight]
Caption = 'OK'
OnClick = BSetAccessClick
TabOrder = 0
end
object BCancel: TButton
Left = 608
Height = 25
Top = 0
Width = 75
Anchors = [akTop, akRight]
Caption = 'Cancel'
OnClick = BCancelClick
TabOrder = 1
end
object EAccessCode: TEdit
Left = 112
Height = 18
Top = 8
Width = 400
TabOrder = 2
end
end
object BFetchTasks: TButton
Left = 560
Height = 25
Top = 8
Width = 112
Anchors = [akTop, akRight]
Caption = 'Fetch tasks'
Enabled = False
OnClick = BFetchTasksClick
TabOrder = 2
end
object LBTaskLists: TListBox
Left = 8
Height = 210
Top = 40
Width = 360
Anchors = [akTop, akLeft, akBottom]
ItemHeight = 0
OnSelectionChange = LBTaskListsSelectionChange
ScrollWidth = 356
TabOrder = 3
TopIndex = -1
end
object LBTasks: TListBox
Left = 384
Height = 218
Top = 40
Width = 304
Anchors = [akTop, akLeft, akRight, akBottom]
ItemHeight = 0
ScrollWidth = 300
TabOrder = 4
TopIndex = -1
end
object LTasks: TLabel
Left = 392
Height = 12
Top = 16
Width = 161
Anchors = [akTop, akLeft, akRight]
Caption = 'Tasks for list : <select a tasklist>'
ParentColor = False
end
end

View File

@ -0,0 +1,236 @@
unit frmmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
synautil, IniFiles, googlebase, googleservice, googleclient, googletasks;
type
{ TMainForm }
TAccessTokenState = (acsWaiting,acsOK,acsCancel);
TMainForm = class(TForm)
BCancel: TButton;
BSetAccess: TButton;
BFetchTaskLists: TButton;
BFetchTasks: TButton;
EAccessCode: TEdit;
GBAccess: TGroupBox;
LTasks: TLabel;
LEAccess: TLabel;
LBTaskLists: TListBox;
LBTasks: TListBox;
procedure BCancelClick(Sender: TObject);
procedure BFetchTasksClick(Sender: TObject);
procedure BSetAccessClick(Sender: TObject);
procedure BFetchTaskListsClick(Sender: TObject);
Procedure DoUserConsent(Const AURL : String; Out AAuthCode : String) ;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LBTaskListsSelectionChange(Sender: TObject; User: boolean);
private
{ private declarations }
FAccessState : TAccessTokenState;
FClient : TGoogleClient;
FTasksAPI: TTasksAPI;
FTaskLists: TTaskLists;
FCurrentList: TTaskList;
FTasks : TTasks;
procedure LoadAuthConfig;
procedure SaveRefreshToken;
public
{ public declarations }
end;
var
MainForm: TMainForm;
implementation
uses {$ifdef windows}windows,{$endif}
ssl_openssl,
jsonparser, // needed
fpoauth2,
lclintf,
synapsewebclient;
{$R *.lfm}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
// Register Tasks resources.
TTasksAPI.RegisterAPIResources;
// Set up google client.
FClient:=TGoogleClient.Create(Self);
FClient.WebClient:=TSynapseWebClient.Create(Self);
FClient.WebClient.RequestSigner:=FClient.AuthHandler;
FClient.WebClient.LogFile:='requests.log';
FClient.AuthHandler.WebClient:=FClient.WebClient;
FClient.AuthHandler.Config.AccessType:=atOffLine;
// We want to enter a code.
FClient.OnUserConsent:=@DoUserConsent;
// Create a Tasks API and connect it to the client.
FTasksAPI:=TTasksAPI.Create(Self);
FTasksAPI.GoogleClient:=FClient;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FreeAndNil(FTaskLists);
FreeAndNil(FTasks);
end;
procedure TMainForm.LBTaskListsSelectionChange(Sender: TObject; User: boolean);
begin
BFetchTasks.Enabled:=User and (LBTaskLists.ItemIndex<>-1);
if BFetchTasks.Enabled then
begin
FCurrentList:=LBTaskLists.Items.Objects[LBTaskLists.ItemIndex] as TTaskList;
LTasks.Caption:='Tasks for list : '+FCurrentList.Title;
end
else
begin
LTasks.Caption:='Tasks for list : <select as tasklist>';
LBTasks.Items.Clear;
FCurrentList:=Nil;
end;
end;
procedure TMainForm.LoadAuthConfig;
Var
ini:TIniFile;
begin
ini:=TIniFile.Create('google.ini');
try
// Registered application needs tasks scope
FClient.AuthHandler.Config.ClientID:=ini.ReadString('Credentials','ClientID','');;
FClient.AuthHandler.Config.ClientSecret:=ini.ReadString('Credentials','ClientSecret','');
FClient.AuthHandler.Config.AuthScope:=ini.ReadString('Credentials','Scope','https://www.googleapis.com/auth/tasks');
// We are offline.
FClient.AuthHandler.Config.RedirectUri:='urn:ietf:wg:oauth:2.0:oob';
// Session data
FClient.AuthHandler.Session.RefreshToken:=ini.ReadString('Session','RefreshToken','');
FClient.AuthHandler.Session.AccessToken:=ini.ReadString('Session','AccesToken','');
FClient.AuthHandler.Session.AuthTokenType:=ini.ReadString('Session','TokenType','');
FClient.AuthHandler.Session.AuthExpires:=ini.ReadDateTime('Session','AuthExpires',0);
FClient.AuthHandler.Session.AuthExpiryPeriod:=Ini.ReadInteger('Session','AuthPeriod',0);
finally
Ini.Free;
end;
end;
procedure TMainForm.SaveRefreshToken;
Var
ini:TIniFile;
begin
// We save the refresh token for later use.
if FClient.AuthHandler.Session.RefreshToken<>'' then
begin
ini:=TIniFile.Create('google.ini');
try
ini.WriteString('Session','RefreshToken',FClient.AuthHandler.Session.RefreshToken);
ini.WriteString('Session','AccessToken',FClient.AuthHandler.Session.AccessToken);
ini.WriteString('Session','TokenType',FClient.AuthHandler.Session.AuthTokenType);
ini.WriteDateTime('Session','AuthExpires',FClient.AuthHandler.Session.AuthExpires);
ini.WriteInteger('Session','AuthPeriod',FClient.AuthHandler.Session.AuthExpiryPeriod);
finally
Ini.Free;
end;
end;
end;
procedure TMainForm.BFetchTaskListsClick(Sender: TObject);
var
Entry: TTaskList;
Resource : TTaskListsResource;
EN : String;
i:integer;
begin
LBTaskLists.Items.Clear;
FreeAndNil(FTaskLists);
Resource:=Nil;
try
LoadAuthConfig;
Resource:=FTasksAPI.CreateTaskListsResource;
FTaskLists:=Resource.list('');
SaveRefreshToken;
if assigned(FTaskLists) then
for i:= 0 to Length(FTaskLists.items)-1 do
begin
Entry:=FTaskLists.items[i];
EN:=Entry.title;
LBTaskLists.Items.AddObject(IntToStr(i)+': '+EN,Entry);
end;
BFetchTasks.Enabled:=LBTaskLists.Items.Count>0;
finally
FreeAndNil(Resource);
end;
end;
procedure TMainForm.BSetAccessClick(Sender: TObject);
begin
FAccessState:=acsOK;
GBAccess.Visible:=False;
end;
procedure TMainForm.BCancelClick(Sender: TObject);
begin
FAccessState:=acsCancel;
GBAccess.Visible:=False;
end;
procedure TMainForm.BFetchTasksClick(Sender: TObject);
var
Entry: TTask;
EN : String;
i:integer;
begin
if LBTaskLists.ItemIndex<0 then
Exit;
LBTasks.Items.Clear;
FreeAndNil(FTasks);
FTasks:=FTasksAPI.TasksResource.list(FCurrentList.id,'');
SaveRefreshToken;
if assigned(FTasks) then
for i:= 0 to Length(FTasks.items)-1 do
begin
Entry:=FTasks.items[i];
EN:=Entry.title;
if EN='' then
EN:=Entry.id+' ('+Entry.Status+')';
if Entry.Completed<>0 then
EN:=EN+' (Completed :'+DateToStr(Entry.Completed)+')';
LBTasks.Items.AddObject(IntToStr(i)+': '+EN,Entry);
end;
end;
Procedure TMainForm.DoUserConsent(Const AURL: String; Out AAuthCode: String);
begin
GBAccess.Visible:=True;
EAccessCode.Text:='<enter code here>';
FAccessState:=acsWaiting;
OpenUrl(AURL);
While (FAccessState=acsWaiting) do
Application.ProcessMessages;
if FAccessState=acsOK then
AAuthCode:=EAccessCode.Text;
GBAccess.Visible:=False;
end;
end.

View File

@ -0,0 +1,12 @@
[Credentials]
ClientID=Your client ID
ClientSecret=Your secret key
Scope=https://www.googleapis.com/auth/tasks
[Session]
;RefreshToken=
;AccessToken=
;TokenType=
;AuthExpires=
;AuthPeriod=
;AccessToken=

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="tasksdemo"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="laz_synapse"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="tasksdemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="frmmain.pp"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="MainForm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmmain"/>
</Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="tasksdemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="../..;../../../base"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,21 @@
program tasksdemo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, frmmain
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource := True;
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Some files were not shown because too many files have changed in this diff Show More