Recent

Author Topic: TvPlanIt fixes  (Read 38389 times)

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: TvPlanIt fixes
« Reply #15 on: June 09, 2016, 03:05:11 pm »
@JD: What is CRUD?

@magu: I think many of our problems are due to the fact that we are using the FlexDatastore and we don't know all the details how to do this correctly. The FlexDatastore is very general and works with every database. As a consequence, it does not make any assumptions on how the generate AutoInc values, how to post records etc. I made considerable progress after I learned this:
  • The ID fields in the database tables must be AutoIncrement fields; in this case, the database takes care of it and the Datastore does not need an OnNextID event handler. I must say that I am not very experienced with sqlite and it took some time to create an empty database; it only worked using the code in the sqlite_encryption_pragma demo in the Lazarus examples/database folder. See the code below.
  • Next, when posting a value to the database sqlite requires an ApplyUpdate for the changed query. call this in the AfterPost event of each query.
With these changes, the current ccr version saves data entered to the WeekView and ContactsGrid. The taskview still crashes in a date edit, maybe some localization thing. DayView and MonthView do not react on doubleclicks.

This is the code how to prepare an empty sqlite database suitable for TvPlanit (just a form with a button (BtnCreate) and a label (InfoLabel) ):
Code: Pascal  [Select][+][-]
  1. unit cpMain;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, sqlite3conn, sqldb, FileUtil, Forms, Controls, Graphics,
  9.   Dialogs, StdCtrls;
  10.  
  11. type
  12.  
  13.   { TMainForm }
  14.  
  15.   TMainForm = class(TForm)
  16.     BtnCreate: TButton;
  17.     InfoLabel: TLabel;
  18.     SQLite3Connection: TSQLite3Connection;
  19.     SQLTransaction: TSQLTransaction;
  20.     procedure BtnCreateClick(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.   private
  23.     { private declarations }
  24.     procedure CreateRecordIDs;
  25.     procedure CreateResources;
  26.     procedure CreateContacts;
  27.     procedure CreateEvents;
  28.     procedure CreateTasks;
  29.   public
  30.     { public declarations }
  31.     procedure CreateDB(AFileName: String);
  32.   end;
  33.  
  34. var
  35.   MainForm: TMainForm;
  36.  
  37. implementation
  38.  
  39. {$R *.lfm}
  40.  
  41. const
  42.   DB_NAME = 'TvPlanit_Demo.db';
  43.  
  44.   // More information on the use of these values is below.
  45.   // They need not be set as constants in your application. They can be any valid value
  46.   APPLICATION_ID = 1189021115; // must be a 32-bit Unsigned Integer (Longword 0 .. 4294967295)
  47.   USER_VERSION = 23400001;  // must be a 32-bit Signed Integer (LongInt -2147483648 .. 2147483647)
  48.  
  49. { TMainForm }
  50.  
  51. procedure TMainForm.BtnCreateClick(Sender: TObject);
  52. begin
  53.   CreateDB(DB_NAME);
  54. end;
  55.  
  56. procedure TMainForm.CreateDB(AFileName: String);
  57. var
  58.   newFile : Boolean;
  59. begin
  60.   SQLite3Connection.Close; // Ensure the connection is closed when we start
  61.  
  62.   if FileExists(AFileName) then
  63.     DeleteFile(AFileName);
  64.  
  65.   // Create the database and the tables
  66.   try
  67.     SQLite3Connection.DatabaseName := AFileName;
  68.     SQLite3Connection.Open;
  69.     SQLTransaction.Active := true;
  70.  
  71.     // Per the SQLite Documentation (edited for clarity):
  72.     // The pragma user_version is used to set or get the value of the user-version.
  73.     // The user-version is a big-endian 32-bit signed integer stored in the database header at offset 60.
  74.     // The user-version is not used internally by SQLite. It may be used by applications for any purpose.
  75.     // http://www.sqlite.org/pragma.html#pragma_schema_version
  76.     SQLite3Connection.ExecuteDirect('PRAGMA user_version = ' + IntToStr(user_version) + ';');
  77.  
  78.     // Per the SQLite Documentation:
  79.     // The application_id PRAGMA is used to query or set the 32-bit unsigned big-endian
  80.     // "Application ID" integer located at offset 68 into the database header.
  81.     // Applications that use SQLite as their application file-format should set the
  82.     // Application ID integer to a unique integer so that utilities such as file(1) can
  83.     // determine the specific file type rather than just reporting "SQLite3 Database".
  84.     // A list of assigned application IDs can be seen by consulting the magic.txt file
  85.     // in the SQLite source repository.
  86.     // http://www.sqlite.org/pragma.html#pragma_application_id
  87.     SQLite3Connection.ExecuteDirect('PRAGMA application_id = ' + IntToStr(application_id) + ';');
  88.  
  89.     CreateContacts;
  90.     CreateEvents;
  91.     CreateTasks;
  92.     CreateResources;
  93.     CreateRecordIDs;
  94.  
  95.     SQLTransaction.Commit;
  96.     SQLite3Connection.Close;
  97.  
  98.     InfoLabel.Caption := Format('Database "%s" created successfully.', [AFileName]);
  99.   except
  100.     Infolabel.Caption := Format('Unable to create database "%s".', [AFileName]);
  101.   end;
  102. end;
  103.  
  104. procedure TMainForm.FormCreate(Sender: TObject);
  105. begin
  106.   InfoLabel.Caption := '';
  107.   InfoLabel.Show;
  108. end;
  109.  
  110. procedure TMainForm.CreateRecordIDs;
  111. begin
  112.   SQLite3Connection.ExecuteDirect(
  113.     'CREATE TABLE "RecordIDs" (' +
  114.       '"ResourceID" INT NOT NULL, ' +
  115.       '"EventID"    INT NOT NULL, ' +
  116.       '"TaskID"     INT NOT NULL, ' +
  117.       '"ContactID"  INT NOT NULL );'
  118.   );
  119.   SQLite3Connection.ExecuteDirect(
  120.     'CREATE INDEX "RecordIDs_ResourceID_idx" ON "RecordIDs" ("ResourceID");'
  121.   );
  122.   SQLite3Connection.ExecuteDirect(
  123.     'CREATE INDEX "RecordIDs_EventID_idx" ON "RecordIDs" ("EventID");'
  124.   );
  125.   SQLite3Connection.ExecuteDirect(
  126.     'CREATE INDEX "RecordIDs_TaskID_idx" ON "RecordIDs" ("TaskID");'
  127.   );
  128.   SQLite3Connection.ExecuteDirect(
  129.     'CREATE INDEX "RecordIDs_ContactID_idx" ON "RecordIDs" ("ContactID");'
  130.   );
  131. end;
  132.  
  133. procedure TMainForm.CreateEvents;
  134. begin
  135.   SQLite3Connection.ExecuteDirect(
  136.     'CREATE TABLE Events (' +
  137.       '"RecordID"       INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' +
  138.       '"ResourceID"     INT NOT NULL, ' +
  139.       '"StartTime"      DATETIME NOT NULL, ' +
  140.       '"EndTime"        DATETIME NOT NULL, ' +
  141.       '"Description"    VARCHAR (255), ' +
  142.       '"Notes"          VARCHAR (1024), ' +
  143.       '"Category"       INT, ' +
  144.       '"AllDayEvent"    BOOLEAN, ' +
  145.       '"DingPath"       VARCHAR (255), ' +
  146.       '"AlarmSet"       BOOLEAN, ' +
  147.       '"AlarmAdv"       INT, ' +
  148.       '"AlarmAdvType"   INT, ' +
  149.       '"SnoozeTime"     DATETIME, ' +
  150.       '"RepeatCode"     INT, ' +
  151.       '"RepeatRangeEnd" DATETIME, ' +
  152.       '"CustomInterval" INT, ' +
  153.       '"UserField0"     VARCHAR (100), ' +
  154.       '"UserField1"     VARCHAR (100), ' +
  155.       '"UserField2"     VARCHAR (100), ' +
  156.       '"UserField3"     VARCHAR (100), ' +
  157.       '"UserField4"     VARCHAR (100), ' +
  158.       '"UserField5"     VARCHAR (100), ' +
  159.       '"UserField6"     VARCHAR (100), ' +
  160.       '"UserField7"     VARCHAR (100), ' +
  161.       '"UserField8"     VARCHAR (100), ' +
  162.       '"UserField9"     VARCHAR (100) ); '
  163.   );
  164.   SQLite3Connection.ExecuteDirect(
  165.     'CREATE UNIQUE INDEX "Events_RecordID_idx" ON "Events" ("RecordID");'
  166.   );
  167.   SQLite3Connection.ExecuteDirect(
  168.     'CREATE INDEX "Events_ResourceID_idx" ON "Events" ("ResourceID");'
  169.   );
  170. end;
  171.  
  172. procedure TMainForm.CreateResources;
  173. begin
  174.   SQLite3Connection.ExecuteDirect(
  175.     'CREATE TABLE Resources (' +
  176.       '"ResourceID"     INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '+
  177.       '"Description"    VARCHAR (255), ' +
  178.       '"Notes"          VARCHAR (1024), ' +
  179.       '"ImageIndex"     INT, ' +
  180.       '"ResourceActive" BOOLEAN, ' +
  181.       '"UserField0"     VARCHAR (100), ' +
  182.       '"UserField1"     VARCHAR (100), ' +
  183.       '"UserField2"     VARCHAR (100), ' +
  184.       '"UserField3"     VARCHAR (100), ' +
  185.       '"UserField4"     VARCHAR (100), ' +
  186.       '"UserField5"     VARCHAR (100), ' +
  187.       '"UserField6"     VARCHAR (100), ' +
  188.       '"UserField7"     VARCHAR (100), ' +
  189.       '"UserField8"     VARCHAR (100), ' +
  190.       '"UserField9"     VARCHAR (100) );'
  191.   );
  192.   SQLite3Connection.ExecuteDirect(
  193.     'CREATE UNIQUE INDEX "Resources_ResourceID_idx" ON "Resources" ("ResourceID");'
  194.   );
  195. end;
  196.  
  197. procedure TMainForm.CreateTasks;
  198. begin
  199.   SQLite3Connection.ExecuteDirect(
  200.     'CREATE TABLE Tasks (' +
  201.       '"RecordID"       INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' +
  202.       '"ResourceID"     INTEGER NOT NULL, ' +
  203.       '"Complete"       BOOLEAN, ' +
  204.       '"Description"    VARCHAR(255), ' +
  205.       '"Details"        VARCHAR(1024), ' +
  206.       '"CreatedOn"      DATETIME, ' +
  207.       '"Priority"       INTEGER, ' +
  208.       '"Category"       INTEGER, ' +
  209.       '"CompletedOn"    DATETIME, ' +
  210.       '"DueDate"        DATETIME, ' +
  211.       '"UserField0"     VARCHAR(100), ' +
  212.       '"UserField1"     VARCHAR(100), ' +
  213.       '"UserField2"     VARCHAR(100), ' +
  214.       '"UserField3"     VARCHAR(100), ' +
  215.       '"UserField4"     VARCHAR(100), ' +
  216.       '"UserField5"     VARCHAR(100), ' +
  217.       '"UserField6"     VARCHAR(100), ' +
  218.       '"UserField7"     VARCHAR(100), ' +
  219.       '"UserField8"     VARCHAR(100), ' +
  220.       '"UserField9"     VARCHAR(100) );'
  221.   );
  222.   SQLite3Connection.ExecuteDirect(
  223.     'CREATE UNIQUE INDEX "Tasks_RecordID_idx" ON "Tasks" ("RecordID");'
  224.   );
  225.   SQLite3Connection.ExecuteDirect(
  226.     'CREATE INDEX "Tasks_ResourceID_idx" ON "Tasks" ("ResourceID");'
  227.   );
  228. end;
  229.  
  230. procedure TMainForm.CreateContacts;
  231. begin
  232.   SQLite3Connection.ExecuteDirect(
  233.     'CREATE TABLE "Contacts" (' +
  234.       '"RecordID"       INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '+
  235.       '"ResourceID"     INTEGER NOT NULL, ' +
  236.       '"FirstName"      VARCHAR(50), '+
  237.       '"LastName"       VARCHAR(50), '+
  238.       '"Birthdate"      DATETIME, '+
  239.       '"Anniversary"    DATETIME, '+
  240.       '"Title"          VARCHAR(50), '+
  241.       '"Company"        VARCHAR(50), '+
  242.       '"Job_Position"   VARCHAR(30), '+
  243.       '"Address"        VARCHAR(100), '+
  244.       '"City"           VARCHAR(50), '+
  245.       '"State"          VARCHAR(25), '+
  246.       '"Zip"            VARCHAR(10), '+
  247.       '"Country"        VARCHAR(25), '+
  248.       '"Note"           VARCHAR(1024), '+
  249.       '"Phone1"         VARCHAR(25), '+
  250.       '"Phone2"         VARCHAR(25), '+
  251.       '"Phone3"         VARCHAR(25), '+
  252.       '"Phone4"         VARCHAR(25), '+
  253.       '"Phone5"         VARCHAR(25), '+
  254.       '"PhoneType1"     INT, '+
  255.       '"PhoneType2"     INT, '+
  256.       '"PhoneType3"     INT, '+
  257.       '"PhoneType4"     INT, '+
  258.       '"PhoneType5"     INT, '+
  259.       '"Category"       INT, '+
  260.       '"EMail"          VARCHAR (100), '+
  261.       '"Custom1"        VARCHAR (100), '+
  262.       '"Custom2"        VARCHAR (100), '+
  263.       '"Custom3"        VARCHAR (100), '+
  264.       '"Custom4"        VARCHAR (100), '+
  265.       '"UserField0"     VARCHAR (100), '+
  266.       '"UserField1"     VARCHAR (100), '+
  267.       '"UserField2"     VARCHAR (100), '+
  268.       '"UserField3"     VARCHAR (100), '+
  269.       '"UserField4"     VARCHAR (100), '+
  270.       '"UserField5"     VARCHAR (100), '+
  271.       '"UserField6"     VARCHAR (100), '+
  272.       '"UserField7"     VARCHAR (100), '+
  273.       '"UserField8"     VARCHAR (100), '+
  274.       '"UserField9"     VARCHAR (100) );'
  275.   );
  276.   SQLite3Connection.ExecuteDirect(
  277.     'CREATE UNIQUE INDEX "Contacts_RecordID_idx" ON "Contacts" ("RecordID");'
  278.   );
  279.   SQLite3Connection.ExecuteDirect(
  280.     'CREATE INDEX "Contacts_ResourceID_idx" ON "Contacts" ("ResourceID");'
  281.   );
  282. end;
  283.  
  284. end.    
« Last Edit: June 09, 2016, 03:15:56 pm by wp »

Thaddy

  • Hero Member
  • *****
  • Posts: 18938
  • Glad to be alive.
Re: TvPlanIt fixes
« Reply #16 on: June 09, 2016, 03:12:57 pm »
@JD: What is CRUD?

Create, Read, Update, Delete. See: https://en.wikipedia.org/wiki/Create,_read,_update_and_delete

It is a rather important acronym ;)
Recovered from removal of tumor in tongue following tongue reconstruction with a part from my leg.

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: TvPlanIt fixes
« Reply #17 on: June 09, 2016, 04:24:42 pm »
Never stop learning...

There is not much to be done about this with TvPlanIt, it's all built into the library.

C = Create: I don't know if there is a built-in datastore for postgresql. If not, you must use the FlexDatastore which can handle any database. See the post above for some instructions on the database must be prepared (the built-in datastores can create a new database on their own - I think). For mapping the field names in the database to those expected by TvPlanit you must right-click on the datastore in the form designer and select the Map database fields command. Select corresponding items in both lists and click on the center button to store this mapping. Repeat with all fields! When done, don't forget to disconnect the SQLconnection, otherwise the db will be locked. That the field mapper can open all required tables the database name must be stored in the SQLconnection with an absolute path (otherwise the program will look for the db file starting from the Lazarus folder). The db file name can be relative otherwise. BUT: Never open the field mapper again with a relative file name, you'll have to do the field mappings again!

R = Read: basically just run the program. When you do this for the first time you must create a "Resource" (= employee, room, equipment - whatever requires some kind of time and resource management).

U = Update: Double-click on the controls provided by TurboPower (there are still a few issues here and there), or use the context menu.

D = Delete: Right-click on an item and select "Delete" from the context menu.

I am attaching my current test project using an sqlite3 database. Note that sqlite3.dll must be available, copy it to the exe folder if you don't have it in the system's search path. The program runs with a sample db provided (containing a few sample data).

Ah, and of course: you must use the current version of TvPlanit from lazarus-ccr, all the other versions around will not work.

 

JD

  • Hero Member
  • *****
  • Posts: 1913
Re: TvPlanIt fixes
« Reply #18 on: June 09, 2016, 04:33:38 pm »
@ wp & magu

Thanks a lot for your joint efforts. TvPlanit really needs a makeover. I use EssentialPIM & it was that model I had in mind when I first tried TvPlanit. EssentialPIM uses Firebird as a backend database & I wanted to try something similar. However I did not properly understand the workings of FlexDatastore & I wanted to bypass it completely or at the most use an in-memory dataset to temporarily store the data & then update a remote database when the data is validated. I got stumped when I saw that TvPlanit does not recognize even in-memory datasets in its IDE.

In the long run, it may be best to remove the tight coupling between the component & FlexDatastore in preference for something loose & modern like JSON/XML. Just my opinion of course. Yours may differ.

JD
Linux Mint - Lazarus 4.6/FPC 3.2.2,
Windows - Lazarus 4.6/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: TvPlanIt fixes
« Reply #19 on: June 09, 2016, 04:42:20 pm »
In the long run, it may be best to remove the tight coupling between the component & FlexDatastore in preference for something loose & modern like JSON/XML.
No, there is no tight coupling between the Planner components and the FlexDatastore. The library contains datastores for several database types. Its just that they are pretty much outdated (there is even a BDE datastore...), and they are not installed by default, and I think the required packages for Lazarus are missing, but I saw them in Delphi. It should be possible to write a datastore for something "modern like JSON/XML" as you say. The only requirement is that the data must be reached via a TDataset-descendant, i.e. a simple array of records will not work.

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: TvPlanIt fixes
« Reply #20 on: June 09, 2016, 04:44:50 pm »
I have worked with TvPlanit in the past.
And made a working implementation with using mORMot as a database backend.
This makes it possible to use all kinds of databases, supported by mORMot and Zeos.
Just had a look at it again. Still working a bit !
If there is any interest, I am willing to share code.

Yes, sharing the code would be a good idea

JD

  • Hero Member
  • *****
  • Posts: 1913
Re: TvPlanIt fixes
« Reply #21 on: June 09, 2016, 06:30:18 pm »
It should be possible to write a datastore for something "modern like JSON/XML" as you say. The only requirement is that the data must be reached via a TDataset-descendant, i.e. a simple array of records will not work.

I believe we already have fpjsondataset.pas but I've never used it. It is likely to be a TDataset descendant.

JD
Linux Mint - Lazarus 4.6/FPC 3.2.2,
Windows - Lazarus 4.6/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

JD

  • Hero Member
  • *****
  • Posts: 1913
Re: TvPlanIt fixes
« Reply #22 on: June 09, 2016, 06:45:04 pm »
I just verified the file. Is is called fpjsondataset.pp It has a TBaseJSONDataset class that descends from TDataset

Code: Pascal  [Select][+][-]
  1.   { TBaseJSONDataSet }
  2.  
  3.   // basic JSON dataset. Does nothing ExtJS specific.
  4.   TBaseJSONDataSet = class (TDataSet)
  5. .........
  6.  

JD
Linux Mint - Lazarus 4.6/FPC 3.2.2,
Windows - Lazarus 4.6/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

magu

  • New Member
  • *
  • Posts: 37
Re: TvPlanIt fixes
« Reply #23 on: June 10, 2016, 12:35:07 am »
@JD. Given that there is a TDataset class it should be possible to use, best to check once wp gets tvplanit working perfectly again.
@wp. Your updates are excellent. thanks.

With regards to VpWeekView it is mostly working, an error still happens when you use the inplace editor, and you exit from this editor using the mouse. That is first click on an event with the mouse once, you will get an editor allowing you to change the title. Click anywhere else on the WeekView and you should get a SIGSEGV error.
I think the problem arises from this line
wvInPlaceEditor.OnExit := EndEdit; (found in procedure TVpWeekView.EditEvent; - around line 1830)

The EndEdit procedure tries to free the wvInPlaceEditor that called the procedure in the first place, so I guess this leads to the loop that causes the error.

Otherpoints: the afterpostevents, etc don't seem to be firing for me,  haven't really seen why.
doubleclicking on the Dayview is working, on the month view its not.

Good night
Mark


DonAlfredo

  • Hero Member
  • *****
  • Posts: 1875
Re: TvPlanIt fixes
« Reply #24 on: June 10, 2016, 02:55:53 pm »
Here you go !!

https://github.com/LongDirtyAnimAlf/mORMotPlanIt

A release is here: https://github.com/LongDirtyAnimAlf/mORMotPlanIt/releases

Needs the mORMot, and sqlite3.dll if you compile dynamic (see synopse.inc)

Not 100%, but working.

xinyiman

  • Hero Member
  • *****
  • Posts: 2261
    • Lazarus and Free Pascal italian community
Re: TvPlanIt fixes
« Reply #25 on: June 10, 2016, 03:12:25 pm »
on mac does not fill me the package

visualplaint.lpk


Compile package visualplanit 1.3: Codice di uscita 256, Errori: 1
vpbase.pas(969,0) Error: Can't open resource file "/Users/francesco/Documents/lazarus_pkg/planit/source/vpbase.res"
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

DonAlfredo

  • Hero Member
  • *****
  • Posts: 1875
Re: TvPlanIt fixes
« Reply #26 on: June 10, 2016, 03:25:13 pm »
@xinyiman

You do not have to use the tvplanit version that comes with this release.
Just use your own.

This release is about the mORMot backend for tvplanit.
Have a look at unit1.pas to know how it is done.

And, as an extra, I have included a tvplanit version with some fixes.
But this is non-critical.

xinyiman

  • Hero Member
  • *****
  • Posts: 2261
    • Lazarus and Free Pascal italian community
Re: TvPlanIt fixes
« Reply #27 on: June 10, 2016, 03:28:54 pm »
Ok, thank you
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

JD

  • Hero Member
  • *****
  • Posts: 1913
Re: TvPlanIt fixes
« Reply #28 on: June 10, 2016, 04:09:29 pm »
Here you go !!

https://github.com/LongDirtyAnimAlf/mORMotPlanIt

A release is here: https://github.com/LongDirtyAnimAlf/mORMotPlanIt/releases

Needs the mORMot, and sqlite3.dll if you compile dynamic (see synopse.inc)

Not 100%, but working.

Thanks a lot for this. I'll take a look a this over the weekend.

JD
Linux Mint - Lazarus 4.6/FPC 3.2.2,
Windows - Lazarus 4.6/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: TvPlanIt fixes
« Reply #29 on: June 10, 2016, 05:03:17 pm »
With regards to VpWeekView it is mostly working, an error still happens when you use the inplace editor, and you exit from this editor using the mouse. That is first click on an event with the mouse once, you will get an editor allowing you to change the title. Click anywhere else on the WeekView and you should get a SIGSEGV error.
I think the problem arises from this line
wvInPlaceEditor.OnExit := EndEdit; (found in procedure TVpWeekView.EditEvent; - around line 1830)

The EndEdit procedure tries to free the wvInPlaceEditor that called the procedure in the first place, so I guess this leads to the loop that causes the error.
Good catch: The inplace editor is killed in the EditEvent but tries to live on in TCustomEdit's DoExit method. Now the inplace editor is not destroyed any more, but just hidden, similar to the case with stringgrids. The same bug occurs in the contact grid and the month view. I fixed the contact grid, but there are some side effects for the month view which I still have to understand. The month view has other issues because sometimes events are displayed at incorrect times.

In the new version I also activated the Lazarus translation system using po files. Translations are welcome. If anybody would like to contribute please submit the translated po file here or in the bugtracker. Soon I'll upload a demo program using translations.

 

TinyPortal © 2005-2018