Jump to content

John Kouraklis

Members
  • Content Count

    328
  • Joined

  • Last visited

  • Days Won

    5

Posts posted by John Kouraklis


  1. Thanks @corneliusdavid and @Vandrovnik

    16 hours ago, corneliusdavid said:

    A few other pieces of information might be handy to make a good decision. If there are just a few of these corporate customers and the only branding is the logo, getting the logo and building a custom install from your compiled application would be relatively simple to manage--I've done something similar to this. And yes, like @Vandrovnik mentioned, InnoSetup is great for this--either for you embedding a custom logo or with them supplying a logo with the right name and size in the right location so the installer can find it.

    Yes, this is a solution but it means that the app needs to enter the typical "corporate" IT world where the IT prepares an update and then distributes it to the employees

     

    16 hours ago, corneliusdavid said:

    But if your customers want to do a lot more than just the logo, like customize some labels or options or set colors and distribute a whole "themed" application, then I would suggest building a theme packager (could be as simple as zipping some files) and making it simple for them to create a theme and package it for their own distribution. Your installer would have to look for a theme package and apply it and you'd deploy a basic theme.

    Not at the moment. I have a built in theme manager but it is not included in this case. So, it's only about a logo and some additional functionality.

     

    16 hours ago, corneliusdavid said:

    My experience with any sort of theme or customization is that there will always be little changes here and there after it's "done" and you don't want manage all those for all the customers, so giving your customers the ability to mange those for themselves would be highly preferable.

     

    In any case, you want your base application the same between paid and free if at all possible, and some sort of long, encrypted license key or something that unlocks the full power for the paid version.

    I am also a bit torn between having one app with a license key that unlocks more features and having a separate build with IFDEFs. 

     

    As mentioned in the initial post, I am also considering embedding the logo in an exe resource but I am sure I will need to produce a mac version in the near future. Is there something similar on macOS?

     

     


  2. Hi everyone,

     

    I'd like to ask for ideas on how to manage the following situation.

     

    I've got an app free for personal use. The corporate use is paid however and it adds some features but also allows the organisation to brand it (e.g., add a logo, color themes, etc.).

     

    What I find a heavy administrative task is how to manage the paid version. 

     

    There are a couple of scenarios I am considering:

     

    1. They send me their logo and I create org-specific binaries or installers. The downside is that I need to keep track of numerous editions and update files, etc.

     

    2. They are able to unlock the app and load the logo and the theme. Then, they distribute it to their employees.
    A question here is how will they distribute the branded version. Do they need to repackage it in an installer? I also thought of having the exe or installer alter an embedded resource but doesn't sound a good idea to me. And, how will the updates be distributed? 

     

    3. I thought of setting up a website whether they upload their files and it produces the new installer. But this needs a proper build server in the background. Too complicated

     

    What do you think? There must be a simpler way, isn't there?

     

    Thanks


  3. 39 minutes ago, Tom F said:

    @corneliusdavid:  Is it safe to set a form's parent to nil, as in TForm.Create(nil)?  Does a form inherit properties and behaviors from a parent that if we use nil are not inherited?
     

    As others have said, it's very safe. Just don't forger to free the form.

     

    39 minutes ago, Tom F said:

     @John Kouraklis: In some initial testing I was finding even if I explicitly did .Free and := nil (or used FreeAndNil) that the RTL still seemed to be trying to destroy the sub-form when it destroyed its parent form, the app's main form.
     

    I don't think so. Just create a blank project and test again. 

     

    • Like 1

  4. Guys, the official way to interact with GMAIL is via OAuth authentication and JSON. That's what the documentation says.

     

    The app password, 2FA or the IMAP settings are there but they depend on the user to allow and set up the parameters. 

     

     

     

    • Like 1

  5. I've spend a lot of time into OAuth authentication.

     

    I am not familiar with ICS components but normally when you need to interact with an OAuth service the process would be the following:

     

    1. If you have an access token, then attempt the request

    2. If it fails due to authorisation, then use the refresh token to update the access token

    3. if this fails, then a new refresh token is needed and the user needs to repeat the whole process

     

    You can avoid all these attempts if you check programmatically whether an access token has expired before any opartion

     

    Most of the components I am aware of, refresh the tokens automatically until they reach #3 where they launch the browser. What I find annoying here is that this behaviour with the browser is automated and disturbs the normal operations of an application 


  6. Hi everyone,

     

    I've got a visual component with a property which refers to an image list.

     

    In IDE, the component is installed without any problems but when I run the app, I get the error that the property does not exist.

     

    Obviously, the property is published and it exists in the dfm file. Every time I change the source code of the component I Uninstall/reinstall the package to avoid conflicts.

     

    How can I debug this? Any idea anyone? I thought of serialiazing/deserializing the component in code to test but this may not be that useful.

     

    Any ideas anyone?

     

    In any case, thanks and happy new year and Merry Christmas to everyone.

     

     


  7. On 4/23/2020 at 6:26 PM, Tom F said:

    I more recently purchased Nexus Quality Suite and was very happy with it.  Great tool, great support, great modern product: https://www.nexusdb.com/support/index.php?q=node/27156.  

    As someone previously said, "You get what you pay for."  NQS was well worth what we paid for it.

    I tried NQS for a while. The UI is very confusing to me. It is 80s but I don't mind that much; what I don't get is how you load the projects and profile them. Even when you launch it from inside Delphi, it doesn't work smoothly. I found it very cumbersome.

     

    The only other reliable and affordable solution I found is ProDelphi. I haven't tried the x64 version but the x32 works nicely. The only downside is that it alters the source code during what they call instrumentation. But it cleans the sources after that perfectly.

     

    And they are very responsive with support. 

    • Thanks 1

  8. Hi,

     

    I've got an app that launches a few threads. Each thread does different things but they all write in the same log file. Some threads check the internet too. 

     

    Everything works well in the normal course of the application.

     

    The problem I have is when the user tries to shut down the app. What happens is that those threads that are attempting a web query or are writing in the log file raise an AV complaining that another process is attempting to write the log file. The writing process to log file is thread-safe for sure. 

     

    Then, I created a global var to indicate the background running tasks. I use Atomic Inc/Dec to change the value and in FormCloseQuery I am waiting for the value to get to zero before the form is allowed to close.

     

    But the problem with the log file still appears.

     

    What's the strategy to shut down a multi-thread app?

     

    I also contemplated the idea of having another global var to indicate that the app is shutting down and then exit from the threads but this will pollute the code and it does not feel right.   

     

     


  9. Unless you have only Win apps and things like Win utils, FMX or more correctly cross-platform is the only way to go. The landscape in the market is vastly and rapidly changing and more platforms appear every other day. Unless you are an established large company, you can not afford to miss the opportunity of jumping into new markets quickly and with limited resources.

     

    We should not judge FMX's state and value based on what DevExpress says.

     

    I think their decision is more of a business one rather than a technical. Their clients are VCL develops and to me it is not a surprise that not many of them have adopted FMX. In fact, it is surprising they concluded there is no market for them. To me it seems very short-sighted understanding of the market. I am sure if they insisted, in 2-3 years their evaluation would be different. And I am also pretty sure when they started with the VCL suite, they had to iron out bugs, etc. But back then they were not the company they are now.

     

    Having said this, I have to mention here that I am not pleased with the way EMBA sees FMX either. I understand that most of Delphi clients are largely VLC developers. On the other hand, EMBA promotes Delphi as the one code base cross platform dev tool and yet they mostly focus on the introduction of new VLC products. This is a mess with their strategic priorities and every time I attend the webinars for new releases, I am disappointed to see they continue with the same approach.

     

    For example, they introduced a new TNumberBox---why is this not a FMX and VLC compoent? or the Control list?:classic_dry:

     

     

           

    • Like 5

  10. 3 hours ago, Vincent Parrett said:

    I like this plan. I ran FixInsight over the code and there are lots of opportunities to clean up the code. Unfortunately fixinsight also produces a lot of 'noise' because there are lots of empty virtual methods which appear to be for c++builder support (no abstract support in c++ builder?) - but it's still a worthwhile exercise.  

     

    I look forward to the day I can install Delphi, chose not to install the bundled Indy and install Indy via DPM, choosing which particular version I want, and not having to modify my projects as Libsuffix will be set on the packages 😉

     

    Pascal Analyser is more thorough I think


  11. On 2/25/2021 at 9:56 AM, timfrost said:

    In the Webinar yesterday, responding to a question about compiler updates/upgrades, I heard Marco say that 'Getit is a bit of a problem because it always uninstalls the old version before installing'. How can anyone defend this approach? What happens when you test the new version and something fails to work?  Where is the old source code for you to compare the differences and either fix them or adjust your usage?  A component installer should never force an install into the location of the production library; it should always be checked and validated before it is too late to do this.

    Sometimes I am speechless when I hear the way some people in EMBA respond to questions. They have a degree of naivety that makes you think they are talking about a product from another company😏  

    • Haha 1

  12. Quick Questions: 

     

    1. Why do we need the Migration Tool? This is a minor upgrade. If I don' use it, will the settings be lost?

     

    2. Yesterday in the webinar, it was mentioned that the binaries should be compatible with 10.4.2. However, the binaries from 10.4.0 are not compatible with 10.4.1.   


  13. Hi,

    I've got difficulties figuring out what is wrong with the following code:

    
    program Project1;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils,
      System.Generics.Collections;
    
    var
      dic: TObjectDictionary<string, TList<string>>;
      list: TList<string>;
    begin
      try
        dic:=TObjectDictionary<string, TList<string>>.Create([doOwnsValues]);
        list:=TList<string>.Create;
        list.Add('111');
        dic.AddOrSetValue('aaa', list);
        var gg: integer:=dic.Items['aaa'].Count;
        writeln(gg); // 1
    
        var l2: TList<string>:=dic.Items['aaa'];
        var a:integer:=l2.Count;
        writeln(a);        // 1
    
        l2.Add('222');
        a:=l2.Count;
        writeln(a);  // 2
    
        dic.Items['aaa']:=l2;
    
        a:=l2.Count;
        writeln(a);  // 0???
    
        a:=dic.Items['aaa'].count;
        writeln(a);  // 0???
    
        dic.Free;   // Invalid point?
    
        readln;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.

    When I assign the TList to the dictionary Value, it loses all the elements.

     

    What am I doing wrong here? Can't see what is going on.

     

    Thanks

×