tvplanit: Refactor ical import preview to facilitate future import of vcards.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8379 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2022-08-11 16:46:32 +00:00
parent 4596ff2bef
commit c22ce64166
23 changed files with 815 additions and 351 deletions

View File

@ -559,6 +559,14 @@ msgstr "Stunden"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr "iCalendar Dateien ('*.ical;*.ics)|*.ical;*.ics"
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr "Zoll"
@ -1753,3 +1761,4 @@ msgstr "Unbekannte Achsen-Spezifikation: %s"
#: vpsr.sxmldecnotatbeg
msgid "The XML declaration must appear before the first element"
msgstr "Die XML-Deklaration muss vor dem ersten Element erscheinen"

View File

@ -553,6 +553,14 @@ msgstr "Hours"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr "Inches"
@ -1734,3 +1742,4 @@ msgstr "Unknown axis specifier: %s"
#: vpsr.sxmldecnotatbeg
msgid "The XML declaration must appear before the first element"
msgstr "The XML declaration must appear before the first element"

View File

@ -550,6 +550,14 @@ msgstr "Tunnit"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr ""
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr ""

View File

@ -565,6 +565,14 @@ msgstr "Heures"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr ""
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr ""

View File

@ -559,6 +559,14 @@ msgstr "Uren"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr ""
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr ""

View File

@ -559,6 +559,14 @@ msgstr "Godziny"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr "Pliki iCalendar (*.ical;*.ics)|*.ical;*.ics"
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr "Cale"

View File

@ -543,6 +543,14 @@ msgstr ""
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr ""
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr ""

View File

@ -559,6 +559,14 @@ msgstr "Часы"
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
msgstr ""
#: vpsr.rsimporticalevent
msgid "Import ICalendar Event"
msgstr ""
#: vpsr.rsimporticaltask
msgid "Import ICalendar Task"
msgstr ""
#: vpsr.rsinches
msgid "Inches"
msgstr "Дюймы"

View File

@ -32,7 +32,7 @@ Portions created by TurboPower Software Inc. are Copyright (C) 2002 TurboPower S
Contributor(s): "/>
<Version Major="1" Minor="7"/>
<Files Count="63">
<Files Count="65">
<Item1>
<Filename Value="source\vpbase.pas"/>
<UnitName Value="VpBase"/>
@ -282,9 +282,17 @@ Contributor(s): "/>
<UnitName Value="VpFileDS"/>
</Item62>
<Item63>
<Filename Value="source\vpicalpreview.pas"/>
<UnitName Value="VpIcalPreview"/>
<Filename Value="source\vpimportpreview.pas"/>
<UnitName Value="VpImportPreview"/>
</Item63>
<Item64>
<Filename Value="source\vpimportpreview_icalevent.pas"/>
<UnitName Value="VpImportPreview_ICalEvent"/>
</Item64>
<Item65>
<Filename Value="source\vpimportpreview_icaltask.pas"/>
<UnitName Value="VpImportPreview_ICalTask"/>
</Item65>
</Files>
<CompatibilityMode Value="True"/>
<i18n>

View File

@ -182,6 +182,8 @@ resourcestring
RSOverlayedEvent = 'overlayed';
RSOverlayed = 'Overlayed';
RSICalFilter = 'iCalendar files (*.ical;*.ics)|*.ical;*.ics';
RSImportICalEvent = 'Import ICalendar Event';
RSImportICalTask = 'Import ICalendar Task';
RSRepeat = 'Repeat:';
RSNoEventItemsFoundInICAL = 'No event items found in "%s".';
RSNoTaskItemsFoundInICAL = 'No task items found in "%s".';

View File

@ -711,7 +711,8 @@ implementation
uses
Math, DateUtils,
VpException, VpConst, VpMisc, VpBaseDS, VpICalPreview;
VpException, VpConst, VpMisc, VpBaseDS,
VpImportPreview_ICalEvent, VpImportPreview_ICalTask;
const
TIME_EPS = 1.0 / SecondsInDay; // Epsilon for comparing times
@ -1754,7 +1755,7 @@ var
event: TVpEvent;
eventCounter: Integer;
datastore: TVpCustomDatastore;
previewForm: TVpIcalPreviewForm = nil;
previewForm: TVpImportPreviewICalEventForm = nil;
begin
Result := nil;
SetLength(Result, BLOCK_SIZE);
@ -1771,9 +1772,8 @@ begin
end;
if APreview then
begin
previewForm := TVpICalPreviewForm.Create(nil);
previewForm := TVpImportPreviewICalEventForm.Create(nil);
previewForm.Position := poMainFormCenter;
previewForm.Kind := icEvent;
previewForm.Calendar := ical;
previewForm.Datastore := datastore;
if ADefaultCategory <> -1 then
@ -3008,7 +3008,7 @@ var
task: TVpTask;
taskCounter: Integer;
datastore: TVpCustomDatastore;
previewForm: TVpICalPreviewForm = nil;
previewForm: TVpImportPreviewICalTaskForm = nil;
begin
Result := nil;
SetLength(Result, BLOCK_SIZE);
@ -3026,9 +3026,8 @@ begin
end;
if APreview then
begin
previewForm := TVpICalPreviewForm.Create(nil);
previewForm := TVpImportPreviewICalTaskForm.Create(nil);
previewForm.Position := poMainFormCenter;
previewForm.Kind := icToDo;
previewForm.Calendar := ical;
previewForm.Datastore := datastore;
if ADefaultCategory <> -1 then

View File

@ -10,8 +10,6 @@ uses
type
TVpICalendar = class;
TVpIcalItemKind = (icEvent, icToDo);
TVpICalItem = class(TVpFileItem)
public
function GetAttribute(AName: String): string;

View File

@ -1,338 +0,0 @@
unit VpIcalPreview;
{$mode ObjFPC}{$H+}
interface
uses LazLogger,
Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
Grids,
VpData, VpIcal, VpBaseDS;
type
{ TVpICalPreviewForm }
TVpICalPreviewForm = class(TForm)
Button1: TButton;
Button2: TButton;
Panel1: TPanel;
Grid: TDrawGrid;
procedure GridDrawCell(Sender: TObject; aCol, aRow: Integer; aRect: TRect;
aState: TGridDrawState);
procedure GridGetCheckboxState(Sender: TObject; ACol, ARow: Integer;
var Value: TCheckboxState);
procedure GridPrepareCanvas(sender: TObject; aCol, aRow: Integer;
aState: TGridDrawState);
procedure GridSetCheckboxState(Sender: TObject; ACol, ARow: Integer;
const Value: TCheckboxState);
procedure SetCalendar(const AValue: TVpICalendar);
procedure SetKind(const AValue: TVpICalItemKind);
private
FCalendar: TVpICalendar;
FDatastore: TVpCustomDatastore;
FDefaultCategory: String;
FKind: TVpICalItemKind;
FTimeFormat: String;
FItems: TFPList;
procedure CalcRowHeights;
function GetCellText(ACol, ARow: Integer): String;
function GetEventText(AEvent: TVpICalEvent): String;
function GetToDoText(AToDo: TVpICalToDo): String;
procedure PrepareItems;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute: Boolean;
property Calendar: TVpICalendar read FCalendar write SetCalendar;
property Datastore: TVpCustomDatastore read FDatastore write FDatastore;
property DefaultCategory: String read FDefaultCategory write FDefaultCategory;
property Kind: TVpICalItemKind read FKind write SetKind;
end;
var
VpICalPreviewForm: TVpICalPreviewForm;
implementation
{$R *.lfm}
uses
LCLIntf, LCLType, vpsr;
constructor TVpICalPreviewForm.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItems := TFPList.Create;
FTimeFormat := 'c'; // short date + long time format
end;
destructor TVpICalPreviewForm.Destroy;
begin
FItems.Free;
inherited Destroy;
end;
procedure TVpICalPreviewForm.CalcRowHeights;
var
bmp: TBitmap;
row: Integer;
R: TRect;
flags: Integer;
s: String;
begin
flags := DT_CALCRECT + DT_WORDBREAK;
bmp := TBitmap.Create;
try
bmp.SetSize(1, 1);
bmp.Canvas.Font := Grid.Font;
for row := 1 to Grid.RowCount-1 do
begin
R := Rect(0, 0, MaxInt, 0);
s := GetCellText(1, row);
DrawText(bmp.Canvas.Handle, PChar(s), Length(s), R, flags);
Grid.RowHeights[row] := R.Bottom - R.Top + 2*varCellPadding;
end;
finally
bmp.Free;
end;
end;
function TVpICalPreviewForm.Execute: Boolean;
begin
Result := ShowModal = mrOK;
end;
function TVpICalPreviewForm.GetCellText(ACol, ARow: Integer): String;
var
item: TVpICalEntry;
begin
Result := '';
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item = nil then
exit;
case ACol of
1: case Kind of
icEvent: Result := GetEventText(TVpICalEvent(item));
icToDo: Result := GetToDoText(TVpICalToDo(item));
end;
end;
end;
function TVpICalPreviewForm.GetEventText(AEvent: TVpICalEvent): String;
var
startTime, endTime: TDateTime;
sStartTime, sEndTime: String;
advTime: Integer;
advTimeUnits: TVpAlarmAdvType;
dingPath: String;
s: String;
cat: String;
begin
startTime := AEvent.StartTime[false];
endTime := AEvent.EndTime[false];
sStartTime := FormatDateTime(FTimeFormat, startTime);
sEndTime := FormatDateTime(FTimeFormat, endTime);
if TVpEvent.IsAllDayEvent(startTime, endTime) then
begin
if trunc(startTime) = trunc(endTime) then
Result := Format('%s (%s)', [sStartTime, RSAllDay])
else
Result := Format('%s - %s (%s)', [sStartTime, sEndTime, RSAllDay]);
end else
Result :=
RSStartTimeLbl + ' ' + sStartTime + LineEnding +
RSEndTimeLbl + ' ' + sEndTime;
Result := Result + LineEnding +
RSDescriptionLbl + ' ' + AEvent.Summary + LineEnding +
RSCategoryLbl + ' ';
// Categories
if Assigned(FDatastore) then
begin
cat := FDatastore.FindBestEventCategory(AEvent.Categories);
if cat = '' then cat := FDefaultCategory;
Result := Result + cat;
end;
// Recurrence
if AEvent.RecurrenceFrequency <> '' then
begin
s := '';
case Uppercase(AEvent.RecurrenceFrequency) of
'YEARLY':
if AEvent.RecurrenceInterval in [0, 1] then
s := Format(RSYearlyOn, [FormatDateTime('dd/mm',startTime)])
else
s := Format(RSEveryYearsOn, [AEvent.RecurrenceInterval, FormatDateTime('dd/mm', startTime)]);
'MONTHLY':
if AEvent.RecurrenceInterval in [0, 1] then
s := Format(RSMonthlyOn, [FormatDateTime('d', startTime)])
else
s := Format(RSEveryMonthsOn, [AEvent.RecurrenceInterval, FormatDateTime('d', startTime)]);
'WEEKLY':
if AEvent.RecurrenceInterval in [0, 1] then
s := Format(RSWeeklyOn, [FormatDateTime('dddd',startTime)])
else
s := Format(RSEveryWeeksOn, [AEvent.RecurrenceInterval, FormatDateTime('ddd', startTime)]);
'DAILY':
if AEvent.RecurrenceInterval in [0, 1] then
s := RSDaily
else
s := Format(RSEveryDays, [AEvent.RecurrenceInterval]);
end;
if s <> '' then
Result := Result + LineEnding + RSRepeat + ' ' + s;
end;
// Alarm
if AEvent.Alarm <> nil then
begin
TVpEvent.GetAlarmParams(AEvent.Alarm.Trigger, advTime, advTimeUnits);
dingPath := AEvent.Alarm.AudioSrc;
if advTime <> 1 then
begin
case advTimeUnits of
atMinutes: s := Format(RSXMinutes, [advTime]);
atHours: s := Format(RSXHours, [advTime]);
atDays: s := Format(RSXDays, [advTime]);
end;
s := Format(RSAlarmIn, [s]);
end else
case advTimeUnits of
atMinutes: s := Format(RSAlarmIn, [RS1Minute]);
atHours: s := Format(RSAlarmIn, [RS1Hour]);
atDays: s := Format(RSAlarmIn, [RS1Day]);
end;
Result := Result + LineEnding + s;
if FileExists(dingPath) then
Result := Format('%s, %s: %s', [Result, RSSound, dingPath]);
end else
Result := Result + LineEnding + RSNoAlarm;
end;
function TVpICalPreviewForm.GetToDoText(AToDo: TVpICalToDo): String;
var
s: String;
cat: String;
begin
Result := RSDescriptionLbl + ' ' + AToDo.Summary + LineEnding +
RSDueDateLabel + ' ' + FormatDateTime(FTimeFormat, AToDo.DueTime[false]) + LineEnding +
RSCreatedOn + ' ' + FormatDateTime(FTimeFormat, AToDo.StartTime[false]);
case TVpTask.GetTaskPriority(AToDo.Priority) of
tpLow: s := RSLow;
tpNormal: s := RSNormal;
tpHigh: s := RSHigh;
end;
Result := Result + LineEnding + RSPriorityLabel + ' ' + s + LineEnding + RSCategoryLabel + ' ';
if Assigned(FDatastore) then
begin
cat := FDatastore.FindBestTaskCategory(AToDo.Categories);
if cat = '' then cat := FDefaultCategory;
Result := Result + cat;
end;
end;
procedure TVpICalPreviewForm.GridDrawCell(Sender: TObject; aCol, aRow: Integer;
aRect: TRect; aState: TGridDrawState);
var
s: String;
R: TRect;
begin
R := ARect;
InflateRect(R, -varCellPadding, - varCellPadding);
s := GetCellText(ACol, ARow);
Grid.Canvas.TextRect(R, R.Left, R.Top, s);
end;
procedure TVpICalPreviewForm.GridGetCheckboxState(Sender: TObject; ACol,
ARow: Integer; var Value: TCheckboxState);
var
item: TVpICalEntry;
begin
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item = nil then
exit;
if item.Skip then
Value := cbUnchecked
else
Value := cbChecked;
end;
procedure TVpICalPreviewForm.GridPrepareCanvas(sender: TObject; aCol,
aRow: Integer; aState: TGridDrawState);
var
ts: TTextStyle;
begin
if ACol = 1 then
begin
ts := Grid.Canvas.TextStyle;
ts.SingleLine := false;
ts.Wordbreak := true;
Grid.Canvas.TextStyle := ts;
end;
end;
procedure TVpICalPreviewForm.GridSetCheckboxState(Sender: TObject; ACol,
ARow: Integer; const Value: TCheckboxState);
var
item: TVpICalEntry;
begin
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item = nil then
exit;
item.Skip := (Value <> cbChecked);
end;
procedure TVpICalPreviewForm.PrepareItems;
var
i: Integer;
begin
FItems.Clear;
if FCalendar <> nil then
begin
case FKind of
icEvent:
for i := 0 to FCalendar.Count-1 do
if (FCalendar.Entry[i] is TVpICalEvent) then
FItems.Add(FCalendar.Entry[i]);
icToDo:
for i := 0 to FCalendar.Count-1 do
if (FCalendar.Entry[i] is TVpICalToDo) then
FItems.Add(FCalendar.Entry[i]);
end;
Grid.RowCount := Grid.FixedRows + FItems.Count;
CalcRowHeights;
end else
Grid.RowCount := Grid.FixedRows;
end;
procedure TVpICalPreviewForm.SetCalendar(const AValue: TVpICalendar);
begin
if AValue = FCalendar then
exit;
FCalendar := AValue;
PrepareItems;
end;
procedure TVpICalPreviewForm.SetKind(const AValue: TVpICalItemKind);
begin
if AValue = FKind then
exit;
FKind := AValue;
PrepareItems;
end;
end.

View File

@ -0,0 +1,82 @@
object VpImportPreviewForm: TVpImportPreviewForm
Left = 327
Height = 295
Top = 127
Width = 603
Caption = 'VpImportPreviewForm'
ClientHeight = 295
ClientWidth = 603
object Grid: TDrawGrid
Left = 0
Height = 258
Top = 0
Width = 603
Align = alClient
AutoFillColumns = True
ColCount = 2
Columns = <
item
Alignment = taCenter
ButtonStyle = cbsCheckboxColumn
SizePriority = 0
Title.Caption = ''
Width = 33
end
item
ReadOnly = True
Title.Caption = 'Items'
Width = 566
end>
ExtendedSelect = False
FixedCols = 0
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goEditing, goThumbTracking, goSmoothScroll]
TabOrder = 0
OnDrawCell = GridDrawCell
OnGetCheckboxState = GridGetCheckboxState
OnPrepareCanvas = GridPrepareCanvas
OnSetCheckboxState = GridSetCheckboxState
ColWidths = (
33
566
)
end
object ButtonPanel: TPanel
Left = 6
Height = 25
Top = 264
Width = 591
Align = alBottom
AutoSize = True
BorderSpacing.Around = 6
BevelOuter = bvNone
ClientHeight = 25
ClientWidth = 591
TabOrder = 1
object btnExecute: TButton
AnchorSideTop.Control = ButtonPanel
AnchorSideRight.Control = btnCancel
Left = 375
Height = 25
Top = 0
Width = 141
Anchors = [akTop, akRight]
AutoSize = True
Caption = 'Import checked items'
ModalResult = 1
TabOrder = 0
end
object btnCancel: TButton
AnchorSideTop.Control = ButtonPanel
AnchorSideRight.Control = ButtonPanel
AnchorSideRight.Side = asrBottom
Left = 516
Height = 25
Top = 0
Width = 75
Anchors = [akTop, akRight]
Caption = 'Cancel'
ModalResult = 2
TabOrder = 1
end
end
end

View File

@ -0,0 +1,7 @@
{"version":1,"strings":[
{"hash":185343357,"name":"tvpimportpreviewform.caption","sourcebytes":[86,112,73,109,112,111,114,116,80,114,101,118,105,101,119,70,111,114,109],"value":"VpImportPreviewForm"},
{"hash":4294967295,"name":"tvpimportpreviewform.grid.columns[0].title.caption","sourcebytes":[],"value":""},
{"hash":5286979,"name":"tvpimportpreviewform.grid.columns[1].title.caption","sourcebytes":[73,116,101,109,115],"value":"Items"},
{"hash":202226323,"name":"tvpimportpreviewform.btnexecute.caption","sourcebytes":[73,109,112,111,114,116,32,99,104,101,99,107,101,100,32,105,116,101,109,115],"value":"Import checked items"},
{"hash":77089212,"name":"tvpimportpreviewform.btncancel.caption","sourcebytes":[67,97,110,99,101,108],"value":"Cancel"}
]}

View File

@ -0,0 +1,203 @@
unit VpImportPreview;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Graphics, Types,
Forms, Controls, Dialogs, Grids, ExtCtrls, StdCtrls;
type
{ TVpImportPreviewForm }
TVpImportPreviewForm = class(TForm)
btnExecute: TButton;
btnCancel: TButton;
Grid: TDrawGrid;
ButtonPanel: TPanel;
procedure GridDrawCell(Sender: TObject; aCol, aRow: Integer; aRect: TRect;
{%H-}aState: TGridDrawState);
procedure GridGetCheckboxState(Sender: TObject; {%H-}ACol, ARow: Integer;
var Value: TCheckboxState);
procedure GridPrepareCanvas({%H-}sender: TObject; aCol, {%H-}aRow: Integer;
{%H-}aState: TGridDrawState);
procedure GridSetCheckboxState(Sender: TObject; {%H-}ACol, ARow: Integer;
const Value: TCheckboxState);
private
protected
FItems: TFPList;
procedure CalcRowHeights;
function GetCellText({%H-}ACol, {%H-}ARow: Integer): String; virtual;
procedure PrepareItems; virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CheckItem({%H-}ARow: Integer; {%H-}AChecked: Boolean); virtual;
function Execute: Boolean;
function IsChecked({%H-}ARow: Integer): Boolean; virtual;
end;
var
VpImportPreviewForm: TVpImportPreviewForm;
implementation
{$R *.lfm}
uses
LCLIntf, LCLType;
{ TVpImportPreviewForm }
constructor TVpImportPreviewForm.Create(AOwner: TComponent);
begin
inherited;
Grid.Options := Grid.Options + [goRowSelect];
FItems := TFPList.Create;
end;
destructor TVpImportPreviewForm.Destroy;
begin
FItems.Free;
inherited;
end;
procedure TVpImportPreviewForm.CalcRowHeights;
var
bmp: TBitmap;
row: Integer;
R: TRect;
flags: Integer;
s: String;
begin
flags := DT_CALCRECT + DT_WORDBREAK;
bmp := TBitmap.Create;
try
bmp.SetSize(1, 1);
bmp.Canvas.Font := Grid.Font;
for row := 1 to Grid.RowCount-1 do
begin
R := Rect(0, 0, MaxInt, 0);
s := GetCellText(1, row);
if s <> '' then
begin
DrawText(bmp.Canvas.Handle, PChar(s), Length(s), R, flags);
Grid.RowHeights[row] := R.Bottom - R.Top + 2*varCellPadding;
end else
Grid.RowHeights[row] := Grid.DefaultRowHeight;
end;
finally
bmp.Free;
end;
end;
{ Marks the item in the specified row to be accepted for import.
To be overridden by ancestors. }
procedure TVpImportPreviewForm.CheckItem(ARow: Integer; AChecked: Boolean);
begin
//
end;
function TVpImportPreviewForm.Execute: Boolean;
begin
Result := ShowModal = mrOK;
end;
{ Returns the text to be displayed in the grid.
To be overridden by ancestors. }
function TVpImportPreviewForm.GetCellText(ACol, ARow: Integer): String;
begin
Result := '';
end;
procedure TVpImportPreviewForm.GridDrawCell(Sender: TObject; aCol,
aRow: Integer; aRect: TRect; aState: TGridDrawState);
var
s: String;
R: TRect;
begin
R := ARect;
InflateRect(R, -varCellPadding, - varCellPadding);
s := GetCellText(ACol, ARow);
Grid.Canvas.TextRect(R, R.Left, R.Top, s);
end;
procedure TVpImportPreviewForm.GridGetCheckboxState(Sender: TObject; ACol,
ARow: Integer; var Value: TCheckboxState);
begin
if ARow >= Grid.FixedRows then
begin
if IsChecked(ARow) then
Value := cbChecked
else
Value := cbUnChecked;
end;
end;
procedure TVpImportPreviewForm.GridPrepareCanvas(sender: TObject; aCol,
aRow: Integer; aState: TGridDrawState);
var
ts: TTextStyle;
begin
if ACol = 1 then
begin
ts := Grid.Canvas.TextStyle;
ts.SingleLine := false;
ts.Wordbreak := true;
Grid.Canvas.TextStyle := ts;
end;
end;
procedure TVpImportPreviewForm.GridSetCheckboxState(Sender: TObject; ACol,
ARow: Integer; const Value: TCheckboxState);
begin
if ARow >= Grid.FixedRows then
CheckItem(ARow, Value = cbChecked);
end;
{ Returns that the item in the given row should be included in the import process.
To be overridden by ancestors. }
function TVpImportPreviewForm.IsChecked(ARow: Integer): Boolean;
begin
Result := false;
end;
{ Must be overridden to add the items to be imported from the external list to
the internal list FList.
Must call inherited at the end to set the grid's RowCount and row heights. }
procedure TVpImportPreviewForm.PrepareItems;
begin
// populate FList here...
Grid.RowCount := Grid.FixedRows + FItems.Count;
CalcRowHeights;
end;
{
var
i: Integer;
begin
FItems.Clear;
if FCalendar <> nil then
begin
case FKind of
icEvent:
for i := 0 to FCalendar.Count-1 do
if (FCalendar.Entry[i] is TVpICalEvent) then
FItems.Add(FCalendar.Entry[i]);
icToDo:
for i := 0 to FCalendar.Count-1 do
if (FCalendar.Entry[i] is TVpICalToDo) then
FItems.Add(FCalendar.Entry[i]);
end;
Grid.RowCount := Grid.FixedRows + FItems.Count;
CalcRowHeights;
end else
Grid.RowCount := Grid.FixedRows;
end;
}
end.

View File

@ -0,0 +1,41 @@
inherited VpImportPreviewICalEventForm: TVpImportPreviewICalEventForm
Height = 400
Width = 667
Caption = ''
ClientHeight = 400
ClientWidth = 667
inherited Grid: TDrawGrid
Height = 363
Width = 667
Columns = <
item
Alignment = taCenter
ButtonStyle = cbsCheckboxColumn
PickList.Strings = ( )
SizePriority = 0
Title.Caption = ''
Width = 33
end
item
PickList.Strings = ( )
ReadOnly = True
Title.Caption = 'Items'
Width = 634
end>
ColWidths = (
33
634
)
end
inherited ButtonPanel: TPanel
Top = 369
Width = 655
ClientWidth = 655
inherited btnExecute: TButton
Left = 439
end
inherited btnCancel: TButton
Left = 580
end
end
end

View File

@ -0,0 +1,5 @@
{"version":1,"strings":[
{"hash":4294967295,"name":"tvpimportpreviewicaleventform.caption","sourcebytes":[],"value":""},
{"hash":4294967295,"name":"tvpimportpreviewicaleventform.grid.columns[0].title.caption","sourcebytes":[],"value":""},
{"hash":5286979,"name":"tvpimportpreviewicaleventform.grid.columns[1].title.caption","sourcebytes":[73,116,101,109,115],"value":"Items"}
]}

View File

@ -0,0 +1,207 @@
unit VpImportPreview_ICalEvent;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
VpData, VpBaseDS, VpImportPreview, VpICal;
type
{ TVpImportPreviewICalEventForm }
TVpImportPreviewICalEventForm = class(TVpImportPreviewForm)
private
FCalendar: TVpICalendar;
FDatastore: TVpCustomDatastore;
FDefaultCategory: String;
FTimeFormat: String;
function GetEventText(AEvent: TVpICalEvent): String;
procedure SetCalendar(const AValue: TVpICalendar);
protected
function GetCellText(ACol, ARow: Integer): String; override;
procedure PrepareItems; override;
public
constructor Create(AOwner: TComponent); override;
procedure CheckItem(ARow: Integer; AChecked: Boolean); override;
function IsChecked(ARow: Integer): Boolean; override;
property Calendar: TVpICalendar read FCalendar write SetCalendar;
property Datastore: TVpCustomDatastore read FDatastore write FDatastore;
property DefaultCategory: String read FDefaultCategory write FDefaultCategory;
// property Kind: TVpICalItemKind read FKind write SetKind;
end;
var
VpImportPreviewICalEventForm: TVpImportPreviewICalEventForm;
implementation
{$R *.lfm}
uses
VpSR;
constructor TVPImportPreviewICalEventForm.Create(AOwner: TComponent);
begin
inherited;
Caption := RSImportICalEvent;
FTimeFormat := 'c'; // short date + long time format
end;
procedure TVpImportPreviewICalEventForm.CheckItem(ARow: Integer; AChecked: Boolean);
var
item: TVpICalEntry;
begin
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item <> nil then
item.Skip := not AChecked;
end;
function TVpImportPreviewICalEventForm.GetCellText(ACol, ARow: Integer): String;
var
item: TVpICalEntry;
begin
Result := '';
if (ACol = 1) and (ARow >= Grid.FixedRows) then
begin
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item <> nil then
Result := GetEventText(TVpICalEvent(item));
end;
end;
function TVpImportPreviewICalEventForm.GetEventText(AEvent: TVpICalEvent): String;
var
startTime, endTime: TDateTime;
sStartTime, sEndTime: String;
advTime: Integer;
advTimeUnits: TVpAlarmAdvType;
dingPath: String;
s: String;
cat: String;
begin
startTime := AEvent.StartTime[false];
endTime := AEvent.EndTime[false];
sStartTime := FormatDateTime(FTimeFormat, startTime);
sEndTime := FormatDateTime(FTimeFormat, endTime);
if TVpEvent.IsAllDayEvent(startTime, endTime) then
begin
if trunc(startTime) = trunc(endTime) then
Result := Format('%s (%s)', [sStartTime, RSAllDay])
else
Result := Format('%s - %s (%s)', [sStartTime, sEndTime, RSAllDay]);
end else
Result :=
RSStartTimeLbl + ' ' + sStartTime + LineEnding +
RSEndTimeLbl + ' ' + sEndTime;
Result := Result + LineEnding +
RSDescriptionLbl + ' ' + AEvent.Summary + LineEnding +
RSCategoryLbl + ' ';
// Categories
if Assigned(FDatastore) then
begin
cat := FDatastore.FindBestEventCategory(AEvent.Categories);
if cat = '' then cat := FDefaultCategory;
Result := Result + cat;
end;
// Recurrence
if AEvent.RecurrenceFrequency <> '' then
begin
s := '';
case Uppercase(AEvent.RecurrenceFrequency) of
'YEARLY':
if AEvent.RecurrenceInterval in [0, 1] then
s := Format(RSYearlyOn, [FormatDateTime('dd/mm',startTime)])
else
s := Format(RSEveryYearsOn, [AEvent.RecurrenceInterval, FormatDateTime('dd/mm', startTime)]);
'MONTHLY':
if AEvent.RecurrenceInterval in [0, 1] then
s := Format(RSMonthlyOn, [FormatDateTime('d', startTime)])
else
s := Format(RSEveryMonthsOn, [AEvent.RecurrenceInterval, FormatDateTime('d', startTime)]);
'WEEKLY':
if AEvent.RecurrenceInterval in [0, 1] then
s := Format(RSWeeklyOn, [FormatDateTime('dddd',startTime)])
else
s := Format(RSEveryWeeksOn, [AEvent.RecurrenceInterval, FormatDateTime('ddd', startTime)]);
'DAILY':
if AEvent.RecurrenceInterval in [0, 1] then
s := RSDaily
else
s := Format(RSEveryDays, [AEvent.RecurrenceInterval]);
end;
if s <> '' then
Result := Result + LineEnding + RSRepeat + ' ' + s;
end;
// Alarm
if AEvent.Alarm <> nil then
begin
TVpEvent.GetAlarmParams(AEvent.Alarm.Trigger, advTime, advTimeUnits);
dingPath := AEvent.Alarm.AudioSrc;
if advTime <> 1 then
begin
case advTimeUnits of
atMinutes: s := Format(RSXMinutes, [advTime]);
atHours: s := Format(RSXHours, [advTime]);
atDays: s := Format(RSXDays, [advTime]);
end;
s := Format(RSAlarmIn, [s]);
end else
case advTimeUnits of
atMinutes: s := Format(RSAlarmIn, [RS1Minute]);
atHours: s := Format(RSAlarmIn, [RS1Hour]);
atDays: s := Format(RSAlarmIn, [RS1Day]);
end;
Result := Result + LineEnding + s;
if FileExists(dingPath) then
Result := Format('%s, %s: %s', [Result, RSSound, dingPath]);
end else
Result := Result + LineEnding + RSNoAlarm;
end;
function TVpImportPreviewICalEventForm.IsChecked(ARow: Integer): Boolean;
var
item: TVpICalEntry;
begin
Result := false;
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if (item <> nil) then
Result := not item.Skip;
end;
procedure TVpImportPreviewICalEventForm.PrepareItems;
var
i: Integer;
begin
FItems.Clear;
if FCalendar <> nil then
for i := 0 to FCalendar.Count-1 do
if (FCalendar.Entry[i] is TVpICalEvent) then
FItems.Add(FCalendar.Entry[i]);
inherited;
end;
procedure TVpImportPreviewICalEventForm.SetCalendar(const AValue: TVpICalendar);
begin
if AValue <> FCalendar then
begin
FCalendar := AValue;
PrepareItems;
end;
end;
end.

View File

@ -0,0 +1,41 @@
inherited VpImportPreviewICalTaskForm: TVpImportPreviewICalTaskForm
Height = 400
Width = 667
Caption = ''
ClientHeight = 400
ClientWidth = 667
inherited Grid: TDrawGrid
Height = 363
Width = 667
Columns = <
item
Alignment = taCenter
ButtonStyle = cbsCheckboxColumn
PickList.Strings = ( )
SizePriority = 0
Title.Caption = ''
Width = 33
end
item
PickList.Strings = ( )
ReadOnly = True
Title.Caption = 'Items'
Width = 630
end>
ColWidths = (
33
630
)
end
inherited ButtonPanel: TPanel
Top = 369
Width = 655
ClientWidth = 655
inherited btnExecute: TButton
Left = 439
end
inherited btnCancel: TButton
Left = 580
end
end
end

View File

@ -0,0 +1,5 @@
{"version":1,"strings":[
{"hash":4294967295,"name":"tvpimportpreviewicaltaskform.caption","sourcebytes":[],"value":""},
{"hash":4294967295,"name":"tvpimportpreviewicaltaskform.grid.columns[0].title.caption","sourcebytes":[],"value":""},
{"hash":5286979,"name":"tvpimportpreviewicaltaskform.grid.columns[1].title.caption","sourcebytes":[73,116,101,109,115],"value":"Items"}
]}

View File

@ -0,0 +1,138 @@
unit VpImportPreview_ICalTask;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
VpData, VpBaseDS, VpImportPreview, VpICal;
type
{ TVpImportPreviewICalTaskForm }
TVpImportPreviewICalTaskForm = class(TVpImportPreviewForm)
private
FCalendar: TVpICalendar;
FDatastore: TVpCustomDatastore;
FDefaultCategory: String;
FTimeFormat: String;
function GetTaskText(AToDo: TVpICalToDo): String;
procedure SetCalendar(const AValue: TVpICalendar);
protected
function GetCellText(ACol, ARow: Integer): String; override;
procedure PrepareItems; override;
public
constructor Create(AOwner: TComponent); override;
procedure CheckItem(ARow: Integer; AChecked: Boolean); override;
function IsChecked(ARow: Integer): Boolean; override;
property Calendar: TVpICalendar read FCalendar write SetCalendar;
property Datastore: TVpCustomDatastore read FDatastore write FDatastore;
property DefaultCategory: String read FDefaultCategory write FDefaultCategory;
// property Kind: TVpICalItemKind read FKind write SetKind;
end;
var
VpImportPreviewICalTaskForm: TVpImportPreviewICalTaskForm;
implementation
{$R *.lfm}
uses
VpSR;
constructor TVPImportPreviewICalTaskForm.Create(AOwner: TComponent);
begin
inherited;
Caption := RSImportICalTask;
FTimeFormat := 'c'; // short date + long time format
end;
procedure TVpImportPreviewICalTaskForm.CheckItem(ARow: Integer; AChecked: Boolean);
var
item: TVpICalEntry;
begin
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item <> nil then
item.Skip := not AChecked;
end;
function TVpImportPreviewICalTaskForm.GetCellText(ACol, ARow: Integer): String;
var
item: TVpICalEntry;
begin
Result := '';
if (ACol = 1) and (ARow >= Grid.FixedRows) then
begin
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if item <> nil then
Result := GetTaskText(TVpICalToDo(item));
end;
end;
function TVpImportPreviewICalTaskForm.GetTaskText(AToDo: TVpICalToDo): String;
var
s: String;
cat: String;
begin
Result := RSDescriptionLbl + ' ' + AToDo.Summary + LineEnding +
RSDueDateLabel + ' ' + FormatDateTime(FTimeFormat, AToDo.DueTime[false]) + LineEnding +
RSCreatedOn + ' ' + FormatDateTime(FTimeFormat, AToDo.StartTime[false]);
case TVpTask.GetTaskPriority(AToDo.Priority) of
tpLow: s := RSLow;
tpNormal: s := RSNormal;
tpHigh: s := RSHigh;
end;
Result := Result + LineEnding + RSPriorityLabel + ' ' + s + LineEnding + RSCategoryLabel + ' ';
if Assigned(FDatastore) then
begin
cat := FDatastore.FindBestTaskCategory(AToDo.Categories);
if cat = '' then cat := FDefaultCategory;
Result := Result + cat;
end;
end;
function TVpImportPreviewICalTaskForm.IsChecked(ARow: Integer): Boolean;
var
item: TVpICalEntry;
begin
Result := false;
if ARow < Grid.FixedRows then
exit;
item := TVpICalEntry(FItems[ARow - Grid.FixedRows]);
if (item <> nil) then
Result := not item.Skip;
end;
procedure TVpImportPreviewICalTaskForm.PrepareItems;
var
i: Integer;
begin
FItems.Clear;
if FCalendar <> nil then
for i := 0 to FCalendar.Count-1 do
if (FCalendar.Entry[i] is TVpICalToDo) then
FItems.Add(FCalendar.Entry[i]);
inherited;
end;
procedure TVpImportPreviewICalTaskForm.SetCalendar(const AValue: TVpICalendar);
begin
if AValue <> FCalendar then
begin
FCalendar := AValue;
PrepareItems;
end;
end;
end.

View File

@ -264,7 +264,7 @@ implementation
uses
SysUtils, Forms, Dialogs,
VpDlg, VpTaskEditDlg, VpTasklistPainter, VpICal;
VpDlg, VpTaskEditDlg, VpTasklistPainter;
(*****************************************************************************)