-
Content Count
1237 -
Joined
-
Last visited
-
Days Won
25
Everything posted by David Schwartz
-
D10.4.2: I've been getting a lot of instances lately with the IDE locking up when I opened a Debug Inspector window and tried to adjust the divider after making the window wider. All I can do is kill Delphi then restart it. It's not what I would call "reproducible" although it does sometimes happen repeatedly on the same variable a few times.
-
IDE locks up on Debug instpectors
David Schwartz replied to David Schwartz's topic in Delphi IDE and APIs
Maintenance fees seem to pay for more useless features in future releases, not ensuring previous releases get bugs fixed. I'm done playing that game. If it wasn't for all the corporate licenses that get automatically renewed every year even when they're using much older versions for their production needs, we might see bug fix releases for older versions. -
IDE locks up on Debug instpectors
David Schwartz replied to David Schwartz's topic in Delphi IDE and APIs
Nope. It has been happening in 10.4.2 and 10.4.3. I have not upgrade my Delphi to 11 yet so I can't tell you about that. -
Suppose you have a video and a list of times that identify where specific words or topics appear. (Here is an example of what YouTube generates when it transcribes a video you post) I'd like to basically import this data into a ListView with 2 cols (time, text), allow it to be filtered, then click on a line and have the video start playing at the time indicated. I'm curious what options are available to do that. I'm sure there are several, but I've never done anything to control videos other than just PLAY, PAUSE, and STOP.
-
Sorry, I was referring to using the VCL's embedded media player to play local video files. (Does it let you play videos on other sites via URLs?)
-
I've got a bunch of live performance videos (> 1hr) open in QuickTime Player on one of my Mac's desktops (Spaces). I typically just select one and start it playing. But I'm thinking it would be nice to have a tabbed interface with a tab for each video; or maybe just one tab with a listbox + a list of flienames and Titles that you can select to play, then flip it to a player tab to play it. If you were going to build a simple video player app this, what would you use for the player component? I'm mainly interested in something that runs on a Mac. I know there's TMediaPlayer, but I think it's for Windows only. FMX has one I imagine (I don't do much with FMX). TMS has some options, including FNC and WebCore I believe. Maybe something already exists? (I did a bit of Google searching, but didn't find anything but a lot of requests for such a tool.)
-
CONTEXT: (this is an analogy to make it easier to explain) A class has a bunch of students. You keep their scores on a variety of required and optional assignments. Each one has a record with their name and a few scores in different categories. <name>, <score#1>, <score#2>, <score#3>, <score#4> I want to create a TListView that has one <name> line per student, and each column has a TOTAL of the scores for that column in all records with the same name. Some may only have one <name> record, and some might have 10, and any number in between. It's rather clumsy to use the columns themselves to do the math (they're strings), so I made this object TSnapTally, to carry some integer fields that's attached to the .Data property where I update the numbers then update the line in the LV. I'm having some problems with the TSnapTally instances either getting freed multiple times or NOT being freed (seems to be mostly the former). So I defined an interface ISnapTally and derived class TSnapTally and I wanted to attach the interfaced object to the .Data property so that later on I can simply assign NIL to .Data and let the interface deal with deleting the instances. In this code snippet, I'm looping over the contents of a TListview to see if the string deets[n] is in the LV's Caption column; if so, it assigns that TListItem to 'li' and also returns it. If not, li and returned value = NIL. The first time it sees this name and it's not in the list, it adds a new item to the LV, sets the caption and four subitems, then assigns the newly created snap_tally to the .Data property. Then I call TallyToListItem with the list item (li) that was either just created or already existed in the LV. Here's the problem: At the top of TallyToListItem, it blows up when I assign li.Data to 'st' (of type ISnapTally). I don't understand why. It works fine if I use TSnapTally rather than ISnapTally. This is Delphi 10.4.2, and li.Data is typed as a POINTER. Can you not assign an Interfaced object instance to a POINTER? Maybe there's a better way to do this; I'm certainly open to suggestions. if not Assigned( ARDomainsLV_ItemWithCaption( deets[n], li ) ) then begin var snap_tally : ISnapTally; snap_tally := TSnapTally.Create( aSnap ); li := AnalysisResultsDomains_lview.Items.Add; li.Caption := deets[n]; li.SubItems.Add( '' ); // #detail recs li.SubItems.Add( '' ); // LM (1,2,3) li.SubItems.Add( '' ); // Org 1-10 li.SubItems.Add( '' ); // Org 11-20 li.Data := snap_tally; // TSnapTally end; TallyToListItem( li, dom_deets, aSnap ); . . . procedure TallyToListItem( li : TListItem; aDomDeets : TDomainDetails; aSnap : TLSHMSnapshot ); var st : ISnapTally; begin st := TSnapTally( li.Data ); <-- Blows up here st.IncNumDetailRecs;
-
I gave up trying to send these files via email ages ago. Most MTAs have squeezed down the size of attachments they'll deliver to 25MB, which even makes sending PPTs and some PDFs dicey. Most places I've worked really crank down on this stuff, and insist everything be sent using links to things in SharePoint or version control. Personally, I use Dropbox to host files and send links to folders or files there. Some places block Dropbox, some block all outside URLs. So you finagle the text so it doesn't recognize it as a URL. Curiously, a lot of places I've worked at that have ridiculously tight security have no problem letting you access Dropbox directly in your browser, and some even allow you to run the Dropbox app on the computer.
-
It seems to rely on the same logic that the refactoring uses, and the inline var declarations break both of them. Try looking at a unit with no inline var declarations and see if it looks more useful. It's useless in 10.4.2, along with most Refactoring functions.
-
Anybody know of any simple SFTP-like servers I can run on a windows server to avoid having to deal with the built-in Windows crap? I just want a simple way to push files from my dev machine to a host running a service. Setting them up in Explorer gives Windows fits ... I don't know how many times it has to download every file just to display the directory! But it seems to go out to lunch for several minutes and freeze up the entire frigging desktop and the RDP itself. Something like Dropbox would be perfect. I just don't want to install Dropbox there b/c I only want it to mirror one single small folder, not my entire Dropbox. I have a list of files and I want to click a button and they'll be sent up to a folder on this other machine completely in the background, nothing on either end will freeze-up or even know something is going on. They'll just pop out the other end a minute or so later. Any ideas what might work?
-
simple SFTP-like server for Windows?
David Schwartz replied to David Schwartz's topic in General Help
This is perfect for what I'm looking for. It's secure and there are lots of help videos on YouTube. HFS looks interesting, but the lack of secure connections bothers me. Also, I tried to build it and there are all sorts of components that need to be installed but I didn't see them documented anywhere. Not fun. I'm going with SyncThing. -
best way to structure an application
David Schwartz replied to al17nichols's topic in RTL and Delphi Object Pascal
TMS Web Update https://www.tmssoftware.com/site/wupdate.asp -
Delphi on Windows 11 on MacBook Pro 16 (2021)
David Schwartz replied to Lars Fosdal's topic in Cross-platform
I'm still getting used to Win 10 after being pretty much forced to give up Win 7. Win 11 is not even on the horizon for me yet. I'm using Delphi 10.4.2 and even though my maint subscription expired, I wouldn't bother with D11 because there are still too many bugs in 10.4.2 IDE that haven't been fixed in D11 and nothing that seems worth the bother of upgrading. My main computer right now is a Late 2018 Mac Mini with 6-core i7, 36 GB of RAM, and 2TB of SSD. The only thing it's slow at is rendering long videos on Camtasia. 🙂 It's faster than any other computer anybody has ever given me to work on! When Apple introduces a Mac Mini with an M2 Max, I might upgrade. But it bugs me that it's not possible to upgrade the RAM and/or SSD yourself any more. Apple charges WAY too much for them. The biggest problem is not Delphi or the VM, but the fricking browsers. They seem to fragment the crap out of the system's memory and it just slows down to the point where it reboots itself after a month or so. For what I do, a faster CPU would not make much of a difference to me. But for really huge projects, I can see how it might shorten compile times a bit. One tip I have for anybody using VMs for stuff like this: they tend to grow. And grow. And GROW. Mine are pushing 125 GB now and take forever to backup to spinning HDs. (I exclude the VM folder from Time Machine.) I do periodically copy them to the backup drive by hand. It bugs me that there's no easy way to do a diff back up of them, because they'd be awfully small diffs. I also make periodic backups to a Samsung T5 1TB USB drive. You can get the T7's now that are twice as fast as the T5's. It takes about 5 mins to copy the VM to the T5. I expect the T7 would take half that. (It doesn't make much sense to pay for a super-fast box then have to wait 30+ minutes to copy your VM in or out!) That's my tip: get a Samsung T7 1TB USB 3.2 Gen 2 device to back up your VMs to. Also, if you get one or two T7's, you can probably get by with just 256GB of SSD and plug one of the T7's in and use it as a backing store while keeping your currently active files on-board. -
Interface question
David Schwartz replied to David Schwartz's topic in Algorithms, Data Structures and Class Design
Uwe, I've been meaning to thank you for this. Not for anything related to the Interface, per se, but it solves a problem I've encountered many times in the past dealing with the fact that these TListItem.Data members are Pointers rather than Objects, and they get gnarly to deal with because you constantly have to cast them. Sometimes I cast them improperly and sometimes they get deleted or orphaned unintentionally. Here just pretend that ISnapTally is really TSnapTally, and that's really just some type <T> that I happen to be working with. In this case, I thought creating an interface would make managing the Data members easier, but it didn't. What I ended up doing was creating a TListItemHelper class that has three different "overlays" for the Data member depending on context. (Different ListViews save different objects in their Data members. Since you can only have one helper per class, I just put support for all three types into the helper, since the TListItem is unrelated to the ListView that's holding the data. I mean, I could derive different ListViews but the TListItem is the same for all of them; it isn't easily subclassed to override the type of the Data element depending on the ListView. So while this is not a very elegant solution, it's simple and it works nicely.) However, what I did to solve the persistency issues was I created a separate TList<TSnapTally> and called it SnapTallyBag. Then modified the Set and Get to work indirectly by saving the index into the list as the value of the Data item, rather than a pointer to the item itself. I simply add stuff to the bag, doing a test for existing instances so there are no duplicates. And I never delete anything until I get to a point where I need to clear the ListView, then I just flush the contents of the bag. When the form closes, if it's not empty, then I flush it at that point as well. It just never occurred to me to use a class helper this way. So that's what I got from this, and it was far more helpful than the Interface hack. 🙂 In fact, I ended up ditching the use of the Interface, and all of the other issues I was having disappeared with this approach. -
simple SFTP-like server for Windows?
David Schwartz replied to David Schwartz's topic in General Help
This looks very interesting. -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
sometimes the test routines to check that my own memory is still working go a little haywire.... -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
I don't throw away dollars to save pennies. That is to say, I value my time more than the cost of computer memory and CPU cycles, because the value of my time keeps going up while the cost of memory and CPU cycles drops much faster. -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
I'm really not sure what to make of this because you have to declare these things somewhere, right? Putting them in a DataModule is one option, of many. There is no "bloat" if there are no components other than two lines in the DFM: object TmyDataModule end nothing else is stored in the DFM, and there's no more code required than you'd have if you understood the proper role of "encapsulation" in OOP design. Which explains why you obsessively prefer the use of records over classes -- so you don't have to bother with calling Create or Free or dealing with any sort of memory management. Which is to say, you make them all global variable to avoid "bloat". That's NOT proper OOP design! But yes, it certainly is another option. Just for the record, the point you're trying to make is that one should avoid the use of proper OOP design techniques in a full OOP language simply to avoid unavoidable "bloat" that comes with using an OOP language. There are people who claim you can do everything in C that you can do in C++ without the supposed "overhead". Then they proceed to write code that has 5x the SLOC as the equivalent C++ code would have, is harder to maintain, has a similar memory footprint, and benchmarks within a few percent of the other. Only it took a lot longer to write and costs more to maintain. This is the thing that opponents of OOP don't understand: the faster computers get, the less that alleged "bloat" actually costs. That is, bloat costs less and less every year. But the cost of programming and maintenance just keep going UP and UP! So sticking with programming methods that forsake programming and maintenance costs in favor of reducing "bloat" is a fool's errand -- you're constantly increasing your budget, spending more to save less over time. And that is a choice you have as well. -
Class properties: Wins prettyness over functionality ?
David Schwartz replied to Rollo62's topic in Algorithms, Data Structures and Class Design
Just more of the same debate about how many angels can dance on the head of a pin, and the debate either devolves into what the angels are wearing or how big the head of the pin is. If you don't like using properties, don't use them. It's that simple. If you think having functions called by a property adds more overhead than calling a function yourself (as if that's a big deal) then just put "inline" after the function declaration. If you'd rather have longer, more descriptive names, then just give them longer more descriptive names: property GetThisViaRESTService : integer read gtvrs; I find far more advantage to using properties than not using them. And for every (infrequent) instance where there's a limitation, it's easy to get around it. I only wish it were easier to type in a bunch of property declarations that follow a simple pattern: a popup box that asks for the property name, its type, checkbox for read and write and whether they're a local var or a method. Is there anything that simple that doesn't require me to install a huge amount of other stuff at the same time? The most frequent problem I have is when I try to pass one into a var or out parameter in a method call. Thankfully those are not very common. -
The Curiously Recurring Generic Pattern
David Schwartz replied to Erik@Grijjy's topic in Tips / Blogs / Tutorials / Videos
You're saying this is simpler than saying something like: var TAddressList = TList<TAddress>; // or var TAddressList = TList<TEyObjectList>; I don't understand the last paragraph at all. What are you referring to? -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
I don't see multi-threading as a solution for reducing the complexity of having too many global variables. I imagine it just creates more complexity. Also, I don't say this to be critical, but you don't seem to understand OOP. There are a LOT of programmers who don't. And that's fine. Delphi's language is called "Object Pascal" to differentiate it from original Pascal that was more like 'C'. The Delphi IDE generates forms that are all objects and a 'main' procedure that's used to create everything. The entire Visual Control Library (VCL) as well as FireMonkey (FMX) is based around objects. The component libraries are all objects. Everything in Delphi is oriented around objects. If there are a bunch of global variables in a Delphi form unit, that means that whomever wrote it was probably not skilled with OOP. You should probably refactor the code to get all of those global vars into classes, along with all of the methods that read and write to them. It's not entirely straightforward, but a lot of it is. There's a free book available that teaches a lot of this basic OOP stuff. Object Pascal Handbook by Marco Cantu If you login to your Embarcadero Code Central portal, it's hiding there somewhere as a free download. I also found this link: http://forms.embarcadero.com/DownloadMarcoCantueBook -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
I think that if Delphi was created today, the DFM file would be a JSON file. Since you're familiar with JSON, you know that if there's nothing in it, it's very small. The format used by DFM files is like JSON only simpler. DFM files are used to save property values defined in the Object Inspector at design time for a given form or DFM. If there are no components on the form or DM canvas, then the DFM file is basically empty. Also, since it's managed the same way as any other form in Delphi, you have the same degree of control of when they're created. By default, they're created automatically. But you can right-click on your project, select Options... then Forms and move it to the right-hand column which represents all of the forms and DMs that you do NOT want to be created automatically. A simpler way is to just right-click on the project, select View Source, and delete the line where a form or DM is created, then save it. In your code, simply call Create where you want an instance and save the reference in a variable somewhere. You can use the one that's emitted in the file by default (a global var in the unit), or you can use any other variable. You can also call it multiple times to create multiple instances. When you're done, just just Free them. I'm sorry for so many words, but I take a lot of words to explain stuff because it seems a lot of people cannot read between the lines of one-line answers. Since I have taken so many words to explain this, I hope you'll actually try it out and see that what I said earlier is correct. -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
Yeah, I caught the "... and so on" part. That's where you wave your hands to refer to everything that happens when you push the button to launch the space shuttle, right? It does not matter what kind of bucket or box or container you put global variables into -- they're still defined at the global level, and they do not belong there. A Data Module is simply a class, which is a container just like records. It's referenced by the global instance var that every auto-created form in Delphi has, and there's usually just one of them. You can put anything into it that you want because, as I said, it's just a class. If one is senseless to use as a container, then the other is equally senseless for the same reasons. It's not worth arguing about or defending. You are free to have a preference for records over classes, and forms over data modules. It doesn't matter. They're all containers available to Delphi programmers and mostly interchangeable. Encapsulation in OOP terms is a way of creating abstractions around collections of related data and methods. Classes are an abstraction mechanism that lets you encapsulate state and model related behaviors that maintain the state, all in a single "object". Forms and Data Modules are both classes. Records are very similar only they have "pass by value" semantics rather than "pass by reference", so local instances usually take up a LOT of space on the stack. You also need to manage dynamic instances of them wtih additional syntactical decorations. I'm not talking about your personal preferences here, I'm talking about basic OOP principles, and particularly encapsulation. Because that's what the OP asked for help with. -
A better way to share global data structures than as global variables?
David Schwartz replied to DavidJr.'s topic in Algorithms, Data Structures and Class Design
why? That might make sense if they're all related. It's roughly equivalent to moving them into a Data Module, because there's usually only one of them ever instantiated. But most of the time a bunch of global vars represent collections of related state vars that belong inside of distinct classes with setter and getter methods moved into the class as well. So you're simply putting bunch of global vars into a bucket that itself is a global var? All you've accomplished is adding a namespace to the global variables that makes references to the vars longer. It's like taking a long list of variables in a C program and putting STRUCT { ... } MYGLOBALS; around them. You're still dealing with the same bunch of global variables, and if you try defining multiple instances, you'll end up with quite a mess. -
I have this code: join := Parallel.Join .NumTasks( NumThreads_spinner.Value ) .OnStopInvoke( // called after EACH task completes procedure begin doSomething; end ) .TaskConfig( Parallel.TaskConfig.OnTerminated( // called when ALL tasks have completed procedure (const task: IOmniTaskControl) begin doSomethingElse; end ) ); The OnStopInvoke method only takes a TProc parameter. However, Parallel.TaskConfig.OnTerminated takes both a TProc and a procedure (const task: IOmniTaskControl). This seems sort of backwards, because the first one operates on a single task, while the second one is the entire list of tasks. (What task is being passed to OnTerminated? The last one what finished up?) Anyway, my question is ... how can I get the OnStopInvoke proc to know which task just finished?