 Hey everybody, this is Brian. Welcome to the 128th CUTE tutorial with C++ and GUI programming. If you've found any of these useful, feel free to visit my website voidrealms.com, click on Donate and make a donation of any size or denomination. Also, on the site you have the full source code for this and all other tutorials. Just select CUTE as the language and search for whatever you're looking for. Alright, so, actually, you know what, let me back up. This was about how my day's been. It's like blistering cold and it's snowing like crazy. Americans say, holy crap, before hitting the ditch on the snow-covered road, Canadians say, hold my coffee and watch this. I'm telling you, the roads were like almost impassable. It was ridiculous. So, we're going to make a new Q-Widget project. And we're just going to call this my watcher. We're going to give this a Q-Dialog, not a Q-Widget. There we go. I'm going to add the concurrent library. We're going to set up our GUI real quick here. I'm thinking about getting an MBA or a Master's of Business Administration. I actually work in IT, but I'm just kind of like looking for some extra oomph on my resume, you know? I mean, I can get a programming job but there really aren't many of them and most of them around here are very low pay and they're not my favorite languages. We're just going to get the clicked slot. There we go. So, like, I could go get like a Java job or a C-Sharp job at their entry level because I don't have 10,000 years of experience in that language, which is sad, but it's kind of what the industry is coming to. All right, so, we're going to just add our includes in here. We're going to add a Q-Progress dialog. We're going to include the Q-Current and, of course, our trusty Qt Debug, which I wish they would just add that right in so we wouldn't have to declare it, but I'm going to add Q-Thread and give you a little bit of what this tutorial is about. We're going to add the Q-Future Watcher. All right, let's just give this thing a good build, make sure it actually builds and runs and all that fun stuff. There we go. So, the premise of this is we're going to enter a value, hit go, and a progress dialog will come up with a little cancel button that we can cancel at any time, and we'll see the progress of this as it goes. So, let's actually make our little static, and we'll say int reference to the number. All right, so now we've got our function that we're going to actually call on a separate thread, and we're just going to add some boring time-consuming stuff here. So, say Q-Debug. My fingers are cold. I can't type. I mean, when I say cold, it is like negative 10 degrees outside. It's just blistering cold. I like winter, but this is getting to be a bit much for me, and winter's just started. Last year, we had two weeks in a row where it was negative 14. See? I'm thinking about it. I'm going to say negative 10, but it's actually negative 14. So, for int, and we're just going to basically make a really boring time-consuming thing that does absolutely nothing, just because I want to focus on the actual QFutureWatcher class, and we're going to say Q thread, current thread, and we're going to say MS sleep, and we're going to sleep for 50 milliseconds, and then we're going to Q-Debug out. I'm playing this video game called Dota 2, D-O-T-A-2. It's called Defense of the Ancients, and it's got me kind of addicted. I don't really get hooked on games that much. I mean, I play them, and then I just don't care, but... All right, so processing number I of... I'm just... Sorry, I lost my train of thought. I've been playing this game, and it's really challenging. It's very dynamic. So, if you're out in steam, sorry, I'm losing my voice, you look me up, and maybe we'll play around a Dota together. So, we're just going to sleep for 50 milliseconds. We're going to say processing number I of max, and let's actually just... I can't be there. So, like I said, we're really just not doing anything important. This is just a time-consuming task, and we're going to do this on each item in our vector. And if you remember right, we're going to do a Q vector, and of course there's a template class, so we have to give it a template. We'll call it vector. I always want to say vector for some reason. And we're going to say I is zero, and we're going to say I is less than UISpinbox value. We're just going to fill this array with... Sorry, the array, the vector, which is junk values. Vector append. So, before we go any further, let me kind of explain this a little bit what's going on here. So, when we run this, we're going to intervalue, like 99, and we're going to click go. And when we click go, it's going to take this Q vector, and it's just going to fill it with 99 or whatever we put in here values. Then, we're going to actually make a Q future watcher and map. Remember what a map does? It maps a vector to a function and calls that function on each item in the container. So, that's really what we're doing. But the Q future watcher class is going to allow us to control that and actually monitor it. Actually, let me back up here and do a Q progress dialog. And we'll just call this P-diag. All right, let's call it log because P-diag is just going to drive me crazy. P-diag, all right. And we're going to say set label text. And in a real world kind of thing, you would do like a computer hash or do some and calculate the trajectory of the stars or whatever. So, Q future watcher. And we're not going to return anything from this. There's no big grand value that we're going to return. We just want to actually control this directly. Now, we're going to say watcher, set future. And we're going to actually do the acute concurrent map. And this function actually returns a new Q future. So, notice how the Q future is void, which is why our future watcher is also void. All right, so we're going to map our, if I can get that out of there, vector. And we're going to map it to the dialog class's do task. So, when we run this bad boy, we're going to actually map that, which remember this because we're using the Q concurrent is going to run that in a thread, many different threads depending on what's available in the global Q thread pool. Now, we want to actually see what's going on here. So, we need to connect up some signals and slots. All right, so we're going to say P loss, what's that? P-diag is what I want. I'm doing it, if you notice, kind of the old fashioned way just because it's what I'm used to. And I also had a complaint about the new way they were having problems with it, so they had asked that I do this final tutorial with this way. All right, so, watcher, we're going to say cancel. Make sure that's actually in there, yep. And then we're going to hook up the watcher here, finished on P-dialog. And I've seen this similar tutorial out there, so I almost feel like I'm plagiarizing, but this is like the de facto way of showing how to use the Q-feature watcher. I've tried to come up with more better illustrative examples, but this is really about the best there is. Some actually like, you know, modify JPEG, others will like, you know, just do something funky with an array. So, watcher, if I can get that out of there, geez. All right, so watcher, and we're going to say signal. And we want the progress range changed. We're going to set that to the P-dialog, and we're going to set the set range. I don't know, I mean, I, it's kind of a wash. I'm just so used to doing the old way of signals and slots, but it is very time-consuming, and it's much more error-prone. But I have had some complaints from people, I suspect they're still using Q4, saying that it wasn't working, or that it didn't connect, or something, but you know, they got mad and kicked their cat or something. All right, so we're going to say progress value changed, and we're going to say, so if you are using Q4 from this tutorial on, we will be using the new way of connecting signals and slots, unless there's some gross problem at which point we'll address it when we get there. All right, so we're connecting up our signals and slots, and now we are just going to go P-dialog, exec, which if you remember exec will actually show it module, meaning that the underlying window cannot really be modified. Watcher, and we are going to wait for finished. All right, now I should actually just connect up these signals and slots first, now that I think about it. That way, because this could potentially fire off before these are connected, that's just the nature of multi-threading. So we're going to wait for finished. Now let's actually give this a good build, just to make sure I didn't goof anything up. All right, and we're going to say if watcher is cancelled, then we're going to do something else. We'll do something else, and let's actually just, for giggles here, add in a Q message box. All right, so we're going to say Q to bug. Somebody asked me, what are some of my favorite video games? I really just, like I said, I've been hooked on Defense of the Ancients 2, or Dota 2 as it's called, but I just, I don't know, I fall in and out of video games pretty fast. Like I bought, was it Shadows of Mordor, and it was actually a really amazing game, but I got kind of bored with it. I did eventually beat it, but like I said, I got kind of bored with it. And it's not, it's not a fault of the game itself. I just, I have very low attention span. If you haven't watched too many of my videos, you will definitely notice. I'll be like, oh, and this very blah, blah, blah. Oh, hey kitty. You click cancel. Let's see if I can hold my attention long enough to finish this program here. And through the magic of copy and paste, we're just going to say all done. So that was a lot more typing than I anticipated for some reason. All right. So when we click the button, we're going to fill the vector with just junk data. We're going to make a progress dialogue. We're going to set the label. We're going to make a QFuture watcher. And then we're going to connect our signals and slots. And then we're going to watch your set future. Basically, we're saying we're going to watch the future. The future is being returned from the QConcurrentMap. You could very easily say QFuture equals QConcurrentMap. Just copy this whole thing out here to task. You could very easily do something like that, but it's much more in line if you do this. And so we're going to set the future, which is the map. And the map, of course, takes a vector, our little list here, or the container, as it's called, and maps each item to a function. In this case, the do task, which does absolutely nothing. It's just a time-consuming task. The reason why it's time-consuming is because I have a pretty beefy computer, and it'll whip through that thing pretty quickly. We're going to show the dialogue. Then we're going to wait for finished. And then if it's canceled, we're going to say, hey, it was canceled. Otherwise, we're going to say finished. Now if it's all works as expected, this should actually be pretty spiffy. So let's just say 99. Okay, all right. So you can see it's showing the progress, and you can see we're processing. And if we just let it go, it'll say all done. I should probably change that because it looks like an error. Let's actually do that. Let's not say critical. Let's say it was info information. So let's do 99 again. And if we just let this go, we've seen what happens. It gets all the way through. And we click cancel. It says you clicked cancel. Notice how we stopped multi-threaded programming here is you can see how it's processing 77, 80, 74, 76. It's just jumping all around because it's just going to get these as threads become available in the thread pool. And some threads may take longer than others. It's just how threads work. Well, that's all for this tutorial. I hope you found this educational entertaining. And this is actually kind of slightly addictive just to watch this thing go. Feel free to visit my website, donate if you'd like. Otherwise, feel free not to. The source code is freely available.