Steven Kamradt
Members-
Content Count
28 -
Joined
-
Last visited
-
Days Won
1
Everything posted by Steven Kamradt
-
ANN: SvgIconViewer 1.2 update (includes over 46,500 svg icons)
Steven Kamradt posted a topic in Delphi Third-Party
I just posted another update for SVGIconViewer. This version increases the icon count to over 46,500 with the addition of the Bootstrap icon library, the ability to view a user specified folder containing .svg files and export those files as a Delphi TImageCollection with generated png versions of the files with a single click. https://github.com/skamradt/SVGIconViewer -
Lately I have found myself spending way to much time locating and converting my various toolbars and buttons to use SVG images. Part of that time was searching multiple archives only to find the same list of icons, however in different weights and sizes. The Microsoft Fluent UI icon repository is difficult to easily navigate and requires multiple steps to grab an icon... there had to be an easier way. So I wrote one that not only allows one to save SVG files, but also PNG files with an included -x size added to make it super easy when adding to an existing image collection (if you, like me, have projects that are still not quite in the latest version of Delphi). The project requires Delphi 12 (or minimally Delphi 10.4 with Skia4Delphi added) to recompile, I have included a compiled executable as a release asset if you do not have the required Delphi version. There are currently 27,400 individual SVG icons, additionally those that have both a filled and outline version have the option to also generate a "TwoTone" icon. You have complete control over colors and export sizes. https://github.com/skamradt/SVGIconViewer Currently included Icon libraries: Microsoft Fluent UI, Tablar-Icons If you find this project useful, I would appreciate a star. If it saves you time and effort, feel free to buy me a coffee (or several, code signing is so expensive lately). 🙂
-
This is now complete and available from the latest release from https://github.com/skamradt/SVGIconViewer
-
Thank you for the suggestion. I'll consider it. (assigned as issue #1)
-
Did you unzip the exe AND the dll into the same directory? Which directory did you install it?
-
How come .dcu files aren't the same across builds ?
Steven Kamradt replied to dormky's topic in RTL and Delphi Object Pascal
Are you doing full builds or just compiles? I personally wouldn't trust a compile as it could pick up a stray dcu elsewhere in the search path (possibly with opposing debug info than a full build would generate) rather than the one you would build. I would expect two builds done back to back to have the same byte signature if there are no other changes. Don't get me started on .dfm changes when saving a unit that includes one. The streaming system likes to recompress images (I believe its the color palette) which throws off binary equality, even if no changes were actually made, and there is the possibility that if you touch an inherited component on the form that it will bring in an inherited version in the inherited .dfm as well that serves no purpose. I also use https://github.com/ahausladen/DDevExtensions and "Remove Explicit properties" from the DFM which also generates quite a bit of useless noise each save, at least when working in a group. -
A Question of Style
Steven Kamradt replied to rgdawson's topic in Algorithms, Data Structures and Class Design
My personal preference is to decouple the database field logic completely. Use a mapping object to map property name to field name and just deal with an object model and its properties. If I have to pick from only your examples, I would pick pattern 2. I dislike pattern 3 the most from a future maintenance point of view. It hides the context of the assignment and could make some logic bugs difficult to locate. Pattern 1 doesn't give you the ability to add additional attributes to the column. Pattern 2 allows you to extend the concept of a column record/class to have additional methods which might be useful that could be used in a loop. if not Stmt.Column[x].isNull then .... if Stmt.Column[x].valueType = vtString then ... ColumnHeading[x] := Stmt.Column[x].fieldname; Yes, you can do the same with pattern 3, but that pattern of using implicits will make it harder to read intent later, especially if you are mixing types in the same block with the same syntax. -
wuppdi Welcome Page for Delphi 11 Alexandria?
Steven Kamradt replied to PeterPanettone's topic in Delphi IDE and APIs
It offers a different way to manage your projects over what Embarcadero has. For example, I have over a dozen versions of the same few projects, all are the same project names stored in separate version specific directories. With this plugin I can create branches in the favorites for each version and group like projects for the same version together. This makes opening a specific version very simple, unlike the default favorite "hearts" which are only sorted by most recently opened, so separate versions of the projects get shuffled and to find a specific one is time consuming. -
wuppdi Welcome Page for Delphi 11 Alexandria?
Steven Kamradt replied to PeterPanettone's topic in Delphi IDE and APIs
The source for example welcome page plugins is available at https://github.com/Embarcadero/RADStudio12Demos/tree/main/Object Pascal/VCL/VCL WelcomePage or if you checked the samples checkbox in the installer. -
Strange behaviour Windows VCL app on specific laptop
Steven Kamradt replied to mvanrijnen's topic in VCL
The mouse cursor being different might be a clue. Is there any other software installed that is different on this machine than others? Are any of the Accessibility options enabled? Are you using themes? I recall that there was a screen to speech service (designed for blind usage) somewhere that really created havoc many years ago in a app that I developed as it was intercepting low level windows calls and caused the application to not render properly. If you are using themes, try to rebuild and deploy a version without them and see if it works. -
If you was to create a rhyming dictionary, how would you structure the database?
Steven Kamradt replied to Al T's topic in Databases
Maybe the soundex algorithm might be a way to start? I have used it before to check for misspellings of names as two words which sound the same will generate the same value. Unfortunately there are false positives, and you might want to not use the first character, just the numeric value, but it might get fairly close. (see https://en.wikipedia.org/wiki/Soundex). I wouldn't truncate at 3 digits, let it go all the way to maxint if necessary. As for database layout, you could just store the word with the soundex value (integer portion). When you need sounds like words, just return all records with the same soundex integer from your database.- 8 replies
-
- dictionary
- rhyming
-
(and 2 more)
Tagged with:
-
Count requests in different intervals
Steven Kamradt replied to chkaufmann's topic in Algorithms, Data Structures and Class Design
I would use a simple record with an int for 5 seconds, minute, hour and day, an expires time for seconds, minute, hour, day. At each request, see if it has gone past the expiration time (set on the first request for that period) and if so then subtract the amount from the next fields, reset the expiration time for the and log the 5 second interval to the db. If you have hit a limit at any point across the steps then you can deny the request. On startup, initialize your record from the 5 second db intervals for the previous day, hour, minute and 5 second interval. This gives you the ability to reporting against the 5 second intervals, and keeps what is in memory to a minimum. Of course there are some issues that you may need to consider. What happens if you load balance multiple servers to handle increasing growth? How does it handle hundreds of thousands of single requests from unique users rather than hundreds of thousands of multiple requests from a few users? -
wuppdi Welcome Page for Delphi 11 Alexandria?
Steven Kamradt replied to PeterPanettone's topic in Delphi IDE and APIs
There is one in development right now which was listed earlier in this thread (https://dwp.gksoft.ch/) and I believe that the experimental version of gExperts (or it was a patch you have to apply yourself) has an importer for its "favorite files". There is a sample for creating your own welcome page plugin that gets installed if you click the checkbox for samples (see https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Samples_Repositories, specifically the https://github.com/Embarcadero/RADStudio11Demos/tree/main/Object Pascal/VCL/VCL WelcomePage projects). I believe Daniel (the original author of Wuppdi) stated that he is no longer going to maintain that project moving forward. -
11.2 Pre-Upgrade Checklist / back out plan
Steven Kamradt replied to SwiftExpat's topic in Delphi IDE and APIs
You will still have to remove 1.1, but you can run the migration tool to save your settings. The "get it" packages for me didn't all install properly, so I had to grab those separately after. -
You asked how to ignore the exception type in that block of code. If you were using a compiler directive for a block of code you would also be making changes. I would actually suggest that your rule should be more of a guideline than a rule. If your maintaining production code, you really want your external components to also be in version control under the project they are being used in. Otherwise, how can you possibly make sure that you are rebuilding a specific version if you have to roll back to diagnose an issue in the field? How do you insure that anyone new to the team has the exact components installed? Often I have had the need to modify a 3rd party component or source to do what I needed and it was unique enough that the vendor wasn't willing to add support for my necessary changes. In the case where its a "bypass" for debugging, you can always revert your changes once your confident that its working properly unless its something you deal with every time you debug. Either way, if its in version control you have a diff with the changes and its not difficult to merge some minor changes in with the next component update.
-
While I see what your getting at, this feature kind of already exists if you right click on the project, not the folder. When you add a new unit, it creates a dirty buffer that has not yet been saved. Saving it prompts you for the name, which defaults to unit1.pas (or next available number) in the project directory. In the save dialog its trivial to click on a folder (or create a new one) and save it there instead. The first thing I generally do when I create a new unit is save the file and give it a proper name and location. The folders don't show up until you add a file that is in a folder other than the dproj project folder location. As far as adding multiple existing units from a directory, I just drag and drop from explorer to the project and it "automagically" puts them in the appropriate folder (based on the existing location of course). Much simpler than clicking the button or right clicking to add to the project, unless its a one off.
-
You could just rewrite the CheckOSError line to: if TSynDWrite.GDIInterop.CreateFontFromLOGFONT(LogFont, DWFont) <> ERROR_SUCCESS then exit(False); and then the exception will not be raised by the CheckOSError function wrapper.
-
Parnassus Bookmarks for Delphi 11 Alexandria?
Steven Kamradt replied to PeterPanettone's topic in Delphi IDE and APIs
Really, all that is missing from this GExperts expert is mapping the CTRL-B to add a new bookmark (or if your on a bookmark already just remove it), and the concept of a bookmark stack (the ctrl-shift-b to drop a temporary bookmark, and escape to pop the bookmark stack, shift-escape would swap the current position for the last position). There was some custom drawing of the bookmark stack into the editor, which is possibly why we haven't seen it updated to Delphi 11.1 yet? -
Cast an array of numbers to array of bytes without re-allocating
Steven Kamradt replied to Der schöne Günther's topic in Algorithms, Data Structures and Class Design
I see nothing wrong with using absolute in this case, however you could make it a tiny bit stronger by placing it all in a class and hiding the storage. Maybe use TList as a starting point, but add accessor methods to fetch/append/insert/delete for each type. Keep a state variable so you know what mode its in and only have to switch modes when you change. Also, keep counts for each supported type so you can set the length appropriately. The list would always be an array of integers behind the scenes, but it then could contain an odd number of bytes or words. A ForEachByte or ForEachWord routine could be coded to use a stack to set and reset the state variable if necessary. I have done something similar with absolute when I needed to compare large blocks of data. An integer compares or moves at just short of 4x as fast as looping through 4 bytes. Disclaimer: This doesn't mean you should use this technique because you can. Its good practice to always measure to find the real bottlenecks and not add complexity to optimize when the net result is still nearly identical. -
Trial RAD 11 expired Delphi CE is 10.x
Steven Kamradt replied to Michael Collier's topic in Delphi IDE and APIs
I believe they are talking about the most recent version of the Community Edition, not the current paid version. The current community edition (as far as I can tell) is based on 10.4, not 11.x. See question 9 where it clearly states that the community edition is NOT the same as a trial of the latest release. In your quoted question the actual answer states that the community edition license is valid (ONLY) for the most recent community version not previous versions of Delphi regardless of community or not. Also keep in mind that a benefit of being on at least a professional sku is that you get access to the latest releases, which would include 11.1 and that a community edition license is only valid for a single year, at which time you must request a new license, and that license will be valid for the "most recent version" of the Community Edition. -
Duplicate entries in the identifier list of the GExperts Uses Clause Manager
Steven Kamradt replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Well, since you opened this up for comments. 🙂 I think it would be useful to have some sort of indicator in the available units to show which ones are ALREADY in the interface/implementation. Maybe use italics or dark grey for any match? Or grey circle icons where either the top half or bottom half are a specific color if its used in the interface or implementation respectfully? -
Another trick is to use ExtractFilePath(paramstr(0)) to get the executable location. It really depends on your use case and how the executable is deployed. using your example above, this would be: TIFFileini:= TIniFile.Create(ExtractFilePath(paramstr(0))+'ComPortServer.ini');
-
A better way to share global data structures than as global variables?
Steven Kamradt replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
In your case, I would put the variables you are working with in a class or even a record and set the scope to what you selected as private to the thread. Keep it simple, its all about preventing access from multiple threads. If you have a global variable that needs to be accessed by multiple threads, protect the access using some sort of semaphore, such as a critical section or spin lock. -
Is there any "standard protocol" for recovery from a failure in non atomic operations?
Steven Kamradt replied to roPopa's topic in Algorithms, Data Structures and Class Design
Maybe a state variable and a work queue? You would add to the work queue the item that needs to be processed and its current state. Somewhere in your application (maybe a separate thread or on idle) loop through the queue and investigate each state to see if its eligible to move to the next state or be removed from the queue. If you persist this queue (database or file) you can then on program crash and reload determine if there is a state which would need to be restarted or not. -
How to get ThisFormClass (TForm1) from Form1
Steven Kamradt replied to Qasim Shahzad's topic in Algorithms, Data Structures and Class Design
First, lets agree to disagree. Yes, there is no problem with that pattern as long as it is used consistently for those forms. However, if you start to mix patterns with those forms, where sometimes you use the method you pointed out, and other times use the try/finally block with a variable you will likely run into AV when the destructor gets called twice in the later pattern (once on form close, then again on the explicit free). This is not something that is not always easy to find the cause of. Sure, if you have a small team or project it won't be that large of a deal, but if your project becomes more complex or has a larger team working on it the deviation from the norm can have an unexpected cost.- 20 replies
-
- form creation
- refactoring
-
(and 3 more)
Tagged with: