 Okay, we're going to introduce two new concepts here. First, how to work with graphics. Second, how to work with the Qt resource system. This is actually pretty complex and a lot of people like to skip over this topic, but I think it's pretty fundamental to working with Qt widgets. So what is a resource system? Part of the compilation process is that you take your source code, compile it into objects and then assemble all of that into, you guessed it, our binary. Now, what a resource system does is it says, hey, before you put everything in the binary, take some extra information, whether they're files or strings or whatever we want and put them directly into the binary. So a better illustration here is you have your Qt application that gets compiled into object files and that makes it part of the binary. But before, or I should say, during the process of creating this binary, it takes these extra files and makes a little section in here called the resource section and it puts all those images right in there. There's some pros and cons to doing this. For example, you can compress things and you have a single binary distribution as far as images. So the user can't change the new icon to a happy face or something like that. It's all baked right into your binary. Now, if you're looking for a one executable that you would distribute, that's called a static installation. That's a much, much more advanced topic. I've actually covered that in my Qt Core Unimi series on distributing your applications. And that is vastly more complex. You actually have to use an entirely different version of Qt called a static build. So we're not talking about a static build. We are just talking about baking these images right into our binary. So let's take a look at that. We're gonna go here, let's say new and we're gonna go in here. First things first, we're going to add new. I'm gonna go to Qt and we're gonna go to resource file. You want to make sure it's a creates a Qt resource file. We're gonna do that over again. Just so you know, right click on your project, go to add new, go to Qt, go to resource file. Should be creates a Qt resource file or a dot QRC. Then you have a name. And it looks like nothing happened but under the hood actually a lot's happening. We're building this entire resource file. Now we have to add what's called a prefix and what a prefix really means is this. Think of this as a file model. This blank area is the root and now we've just made a folder called slash new slash prefix one. Let's change this to slash files and we're gonna add another. Oops, gonna cancel that. I hit files instead of prefix. We're gonna cover that here in a second and we're gonna say slash dialog. Notice how you don't have to save or anything. It just does it in real time. Now I'm gonna jump back out here. Here's the folder we just had. And off the screen I'm gonna paste a folder I had that just contains some images. Doesn't really matter where you get these images from. It's preferred for what we're doing that they're in PNG format because we're gonna use some transparency. But we're just gonna take these five files and put them right into our app. Go here, go file new, or yeah, file add. And we're gonna say we wanna do, let's say disk file and folder and then we're gonna slick on our dialog prefix and we're gonna go add, not filing, but add, add files. Go under images and we wanna do accept and cancel. Hit save, notice how bang builds our resource file out. And if we build this, it just bakes it right in there. There's no extra dialogs, no extra magic you need to do. Just boom, it's built right into our actual binary file. So let's look at how to actually work with that now. We can always go back in here, right click this. And where is it? Where is it? Open an editor. So under resources, because you can have multiple resource files, select the resource file you want and open an editor and you go right back where you were. You also have this nice little dialog view and you can just double click on, let me find a better one. Double click on them and actually view them. It's actually pretty cool. Let's go here and we're going to just scale that in. Add some push buttons here. Let's add a plain text editor. We're just gonna build a very simple text editor and I mean extremely simple. Say new, open, save, let's call this button new, button open, let's call this button save. Put those there, put that like this. Beautiful little text editor we've got here. And let's get rid of the standard buttons just cause they are super annoying. Get rid of that, get rid of that. And let's give it a good build just to make sure we don't have any little gremlins. Now we wanna add these icons in and I'm gonna show you two ways of doing this. The editor way and the programmatic way. So you're gonna go down after you've select the button, you're gonna go to Q-Abstract button, you're gonna go and just expand out icon and then go to normal on. It doesn't really matter which one you do, but do normal on. You could select this little drop down, you could choose a resource and choose a file. That kind of goes off the screen. I apologize for that. Or you just choose this little guy here. And ta-da. We are now viewing the images we put into our resource file. And notice how it's got the prefixes in there as well, dialog and files. Gonna do the same thing here. Now you might have noticed off to the right here that when we do that we have our main icon but then we have all these extra theme things like normal on, normal off, disabled off, disabled on. So what Qt's doing is using the theme system which is a much more complex topic we're not gonna really touch too much into. But then it's automatically creating these icons for you. So if you enable or disable these buttons it'll do that automatically. It's actually really cool. So for example, it's enabled if we just uncheck that. You notice how the graphic changed as well. Enable, disabled, enable, disabled. Really cool that it does that. That's a lot of functionality built in there that you don't have to mess with. And if we save and run, you can see the icons are there. It just works. It's like magic. I love it. Now let's go ahead and build out the rest of our application here. Let's go here. Gonna add some includes. We're gonna include Q icon and this is what's gonna load the actual icon files, those PNGs, Q file. We're gonna work with the Q text stream because again, we're just making a very bare bomb basic text editor. Now what we wanna do is actually going here and we want to flesh these out. So we're gonna go to slot. And if this is annoying you, all this clutter you can just simply collapse that. Doesn't hurt it at all. Now we've got our slots there. And what we're going to do is we're going to add in a few extra buttons. But before we do that, let's go back in here. Let's go to our private area. I'm gonna say I'm saved. That's gonna track the status of whether or not we've saved the document. And then we're gonna say avoid load and avoid save. Now we wanna take it a step further. Have you ever had that annoying thing? And we've talked about this briefly where you're in an editor and you're typing away and you click that and it just doesn't save your work. It just boop, gone. Well, yeah, we're gonna fix that. So we're gonna go in here, go to slot. Go to text changed. And let's go back here. Right click dialog, refractor, insert virtual function of base class. And we are looking for, again, the close event for the queue dialog. Check it, don't just double click it. Hit okay. And then right click that and add definition. And we wanna accept that, otherwise it's just gonna sit there and hang indefinitely. And then we can intercept that event. So then we can say, if not saved, do something. Let's go back in here. Say load. So then what we can do is say load right at the very start of this. And so we're doing full application lifecycle. When we first start up, we're gonna load and that's gonna say if there's a document, blah, blah, blah. Now in this close event, this is where we wanna pay special attention because it's super, super annoying to close a document accidentally. If it's not saved, meaning the user's typed something, then we wanna actually give them the opportunity to save this. So we say queue message box and we want the standard button. We're gonna ask them a question. And we're gonna just simply say, hey, what do you want? Do you want us to save this thing or not? And we're just gonna say, if button equals queue message box, standard buttons. Yes, then let's go ahead and save. Either way, we're gonna accept that close event. We're just adding this little logic in here to just kind of give the user one last-ditch effort to say, hey, are you sure? This is what you wanna do in life. So let's just start flushing this out. Let's say new. We wanna actually say UI, plain text edit clear. No, actually, because we haven't saved that, let's get that out of there. And then on open, we just wanna call that load code. Save, of course, we wanna save it. Also wanna give that user some feedback just in case they're confused about what's going on. Otherwise they're gonna sit there and mash that button over and over again. I'm gonna say your changes have been saved. We're almost done. So really what we need to do now is just load up some logic here. Now let's go ahead and flesh out this load and save stuff really super quick here. If the file doesn't exist, we wanna get out of here. Then we're gonna say, if not file open. And we have to, of course, do a QIO device and we wanna tell it we wanna read only on this file. Just adding a little bit of logic here to save the user from any mistakes. Say Q message box and we wanna say critical. And let's actually add in the file.air string. So all we're doing is saying, grab whatever error occurred from the file when they're trying to open it. By here we should have an open files from say file.close. Again, we've covered the vast majority of this in the Qt Core for Beginners, Intermediate and Advanced and the Udemy courses. So we're just kind of flying through these topics. Qtext stream, so we're gonna grab a stream of text. Give that a reference to our file. And then we just wanna say UI plain text edit. Set plain text. Just wanna do stream, read all. So we're not reading gigs and gigs and gigs in, we're just gonna read small little text file. Because this is now loaded and no changes have been made, we're gonna set that flag to true. Copy and paste can save us a lot of time here. Get rid of that. We wanna write only. And then of course, we want to do the reverse on this. We're gonna say stream. Grab that plain text from the user, pump that out to the file. All right, pretty quick, pretty easy. What we wanna do next is add in some buttons. So if you remember right from here, we got rid of these standard buttons. The functionality exists already, but we just wanna add some custom buttons down here. Let's test our functionality before we move on just to make sure. So we're gonna say, this is a test. Uh-oh, would you like to save it? If we click no, all our changes are gone. Try that again. If we click yes, our changes should be saved on the next load, ta-da. We can also say new, blah, blah, blah. And then just load it back up. So the functionality's there. Let's just add or accept and reject buttons down here. And let's go back here, go here. This is the different way of showing how to load resources. We're gonna load them programmatically now. So if you've been fast-forwarding now, it's time to slow down. We'll say Q push button. We're gonna say button accept equals new Q push button. And if we kinda look at these, we can see one of the options is to do a Q icon. So spoiler alert, that's what we're gonna do. We're gonna say Q icon. And then we're going to say accept and this. So we have to give it some sort of string. And if we look at Q icon, you can see we can use icon engine or a Q string file name. So what have we done with this resource? Well, we've created a mini file system. So we're just going to right-click on the guy we want. You notice how there's this copy to path or copy path. Copy that, make a string. And because it has a special character right here, it's telling Q, hey, in Q icon, when you go to load this path, because it's got the special character, do not go out to the operating system, but instead look internally through all your resource files, because remember you can have more than one of these things. Now this is fine and dandy, but let's say, hey, we already made this button. And you've got some weird company policy that says, do not do it in the constructor, which makes no sense, but I've seen crazier policies before. It just looks like that the way we've been doing it. So what we could do is pretty much same thing, right? Set icon, notice it takes a Q icon. So we can do just the same thing, grab this. We can hand jam this in here, little bit error prone. See how I've misspelled that, won't load it. Go in and out, right click, copy path, and life will just simply go on. Now let's add these to our button box. And we're gonna say, what the accept roll, save and run. Now this is a little bit misleading. We've added them with accept and reject, and you think that under the hood, this would call it for us, but it doesn't. We gotta wire those up through signals and slots, but we have our custom icons. We don't have that standard icon anymore. So to wrap this up, we can just very simply do some connection code. So we'll say connect, and we're gonna connect the button accept, and we wanna connect the Q push button, click signal with this, and we wanna say the dialogue. Now you notice how we didn't add that. So what we can do is just say Q dialogue, and we want the accept, there we go. Same thing with reject. Now you may be tempted to make your own special accept and reject functions for these buttons, but you really don't need to. You can just call the built-in Q dialogue. Same thing happens. For example, we can reject it, we can accept it. Let's go ahead and modify this. Uh-oh, what happened here? Well, this is where I say, hey, you actually have to do that. So because you want to call that accept, you need to intercept that somehow. So let's go in here. And let's make a slot, and we'll call accept me for who I am, and then we're going to change this to dialogue, call the accept me slot, and then down here we can actually save it, and then call accept. So why did I say don't create a special one? You may be sitting here confused. So what I'm talking about is you'll see people that will, and I've done this before, they'll take this reject button, they want it to reject. So instead of calling the Q dialogue reject directly, they'll call a function or a slot, and they'll just simply say reject. I've done that before for illustrative purposes, but in a production level app, do not do that. You're just wasting time. Granted, it's not much time, but you're still wasting it. Save and run. Now we can say don't, don't, don't accept. We've called saved, everything's good. Life goes on. Save and run. There's our exclamations. I hope you enjoyed this video. It's part of a larger project out of you to me called Cute Widgets for Beginners with C++. This is a large course with 73 lectures and 17 hours of video footage. This course covers everything from what is a widget all the way down to complete example applications using the skills you've learned in this course. Sorry, there's no QML in this course. This is strictly Cute Widgets. I will make a QML course later on, but this just focus on widgets from a beginner's perspective. Even though this is a beginner's course, you do need to have some fundamental information available. You need to know C++ and the Cute Core Libs. I do have some courses available out on Udemy, Cute Core Beginners Intermediate Advance. It's not necessary you take these courses, but it is highly recommended. And as always, I'm available out on the Boydromes Facebook group, along with 3,000 other programmers. See you there.