 Hey everybody, it's Brian. Welcome to the 91st Qt tutorial with C++ and GUI programming. We're just going to select GUI application and today we're going to make a notepad. We're just going to call it Qpad. I've been getting a ton of email more than I can really keep up with and a lot of them have been saying, hey can you kind of make tutorials that just glue everything we've learned so far together into simple little projects. So today we're going to build a notepad style application. Notice how I did a Q main window. First thing we want to do is bring up our main window here and throw a text edit on there. Now if you've tried doing this before and you've tried using layouts you've had pretty pretty bad results here. Like let's actually do that. You notice how there's this little little space around this. Let's actually save and run this so you can see what I mean here. We want this widget to take the entire frame and yet you've got this funky extra space. Well what we need to do is call set central widget so it takes up all that real estate. So let's actually go in here. Let's break the layout because we really don't need it. Save it. Open this up and we can say this set central widget UI text edit. Now remember UI is a reference to the main window UI. So now when we run this it takes up the entire real estate of the central widget. You also notice how we have this toolbar that we can kind of move around. There's no buttons on it but we can move it around do whatever and there's believe it or not a menu you don't see it. See where it says type here that's where the menus are going to be. So we're just going to set up a very simple toolbar and very simple menu items. So let's just say file and let's get rid of this down here so we can see a little bit of what's going on and we want an edit menu too. So in the file menu we want just the standard new open and let's just add a separator here. Just double click. We'll say save save as and then edit. We just want the standard you know copy cut paste and then add a separator let's just say undo and redo. Did I miss paste? I sure did. We just take paste and drag it right up there. Now you notice how every time you made a menu item it created an action. These actions can of course be moved on to the toolbar. So like you can take action new and just drag and drop it right up there and see how it says new. Well that's fine and all but we really want an icon so we kind of need to add a resource file something we've done before add new and this may take me a second to find it here you have a cute resource file and let's just call this app resources. I'm going to add it to our project then we want to add a prefix. Remember how this works we're just going to say images. Now we want to add some files to this resource and it's always good to kind of have some picked out and advanced. I've already picked some of them out. I just got the standard ones. If you're wondering where I got these I think these are out of the the fam fam silk icons I think. I don't know I found them out on the internet. I just I googled application icons and I found this free library with a bunch of icons in it. So first thing you need to do here is go file add files. So go add files. Go to where your resources are. I've already got them pulled out here. I'm just going to select them all and add them. It says that is not a sub directory and we want to copy. Basically what this is saying is it has to be in a sub directory of our application for this to work correctly. So we're just going to choose copy and it's going to choose copy location and notice how it's bringing up a different one each time. It's kind of annoying that it does this. Kind of like my little pet peeve about cute. Not so much cute more cute creator and notice how it adds them all in there and they are under the images and then the image name bring up our UI again and then let's just go new and you see icon normal off. Well we don't want that. What we want is our images. So we want the new icon and notice how when you do that the text mode goes away and it's just an icon and it shows the icon next to it. So let's just go ahead and flesh all these out real quick here. That was open. Then we want to save. Whoops hit the wrong button there and save as. I'm going to try and fly through this here. I don't want to take a bunch of time just filling in icons. What was that copy and there's cut. What was this undo? There's undo. Lost it for a second there. I'm kind of scatter brain today. I've been studying for VMware training for my job and it's been it's been interesting. It's a lot of information to take in though especially on a beautiful Sunday afternoon where the last thing you really want to do is study. Okay now you should notice that all of your actions because these are actually actions have the icons next to them. Now we're just going to drag and drop some of the icons up here. So we want open and we'll say save. Save as. Let's just throw copy, cut, paste. Let's move this over here real quick. Notice how you can add a separator in there and then we want undo and redo. So now we've got just a very basic you know kind of standardized standardized toolbar here with some separators. Looks nice and neat. Let's go ahead and give this a good run. Make sure it builds correctly. And there is our window and we've got our file menu, our edit menu complete with toolbar and actions. Now what we need to do is what I affectionately call the plumbing code. It's called plumbing because well it connects one thing to another. With some languages you'd have to do an event for the new, an event for that button, event for this button, you know, etc, etc, etc. Because these are actions you only have to do a signal slot for the action. Let me kind of demonstrate here. So you select new, right click, go to slot, triggered is what we want. So when that is, when that action is triggered either via the toolbar or via the menu it's going to call this code. Pretty neat, huh? So what I'm going to do here is I'm going to go through each one of these and do the, where you right click, go to slot, triggered and I'm just going to keep doing this. But I'm going to pause the video real quick because I really don't want to chew up a bunch of your time with meaningless drudge work. Of course and while I'm working on this I found a better way. You can just select multiple, go to slot, triggered and shame on me for not knowing that in advance. So now we have our actions here, new, open, save, copy, paste. Hmm, where'd Save As go? Might be that I missed a couple of these. Alright so we have some things we need to do here. What is the basic functionality of a notepad? Well you need to be able to create a new document, save a document, open a document. So what we're going to do here is we're going to add some variables here. We're just going to say queue string, file name. Let's add some includes while we're in here. In mind you this is going to be a very very basic notepad here. So now we've got a reference to a string. I shouldn't say reference to it. We have a string that we're going to use to store the file name. Let's go in here and so when we create a new one we want to blank out that file name. We don't want it to have anything in it. When we open it well we want to set the file name, etc, etc. So let's go back in here, new. So here's our new. We just want to say file name equals nothing and then we want to say UI, text edit, set plain text and we just want to give it nothing. That'll blank out the text. Then we want to fill the rest of these in here. So before we really get started on the file functionality let's fill in some of these easier ones first. For example copy. We just want to say UI, text edit, copy, UI, text edit, paste. Did I add one in for cut? I don't think I did. Maybe I was wrong about selecting multiple ones. There it is. UI, text edit. So now we've got some just very, very simple things. Got copy, cut, paste. Let's jump back out here. Let's go undo. We'll say UI, text edit, undo. You notice how there's an undo and undo available and you've probably seen that with the other ones too. What that does is it really allows you to flesh out the functionality of your editor. You can actually consume this undo available and read the boolean value and then enable and disable the button. We're not going to get that complex. We just want to show the basic functionality here. I know some of you are probably going, oh come on, but I've got to keep it simple. I get a little press for time here. So let's just save and run this. Maybe if it builds, come on. There we go. Then we can just test the functionality out here. Let's do undo. Let's just go copy and let's just paste it. There we go. Let's see if it cut works. Yes, it does. Paste it again. Let's do undo, redo, undo, redo. So we've got the base functionality here and we've done very little programming because it's all provided by the Qt libraries. Now we want to fill in the new open save and save as the basic you know file functionality here. So we've got our new and now we want open. So what we need to do here is we need to actually open a file dialogue. So we'll say Q, file dialogue. There we go. And what we want to do next is we want to say, oh sorry, I got a little ahead of myself here, a Q string. We'll just call this file equals. And we're going to say Q, file dialogue. And we want get open file name. And then wow, look, we got a bunch of stuff we can do here. Well, we want the parent and then we want the caption. So we'll just say open a file. And we're just going to leave the rest of this blank because well, we really don't want to modify it too much. Now what we need to do is test to see if the user actually selected a file. So we'll say if file is empty, whoops, sorry, I forgot the not. If not file is empty, then we're going to actually read this in and do something with it. So you guessed it, this comes our next part where we have to actually open up that file and do something with it. So we want a Q file and file actually let's call this S file because this is our stream here. And then we want to say if S file open and we want to do this in read only mode because we're going to read this. So we'll say Q file read only. And we want to order this with Q file plain text. So sorry, not plain text, just text. That way it doesn't try to do any processing to it. So if we can open this up, then we want to make a Q text stream. And I'm sure there's probably an easier way of doing this, but I'm just going to do it my way just because well, I'm making the video. All right, so we'll say give it a reference to our Q file object. And then we're just going to read this in and we're just going to say Q string and we'll just say text equal and read all. Now that we've got the text, well we want to of course close. And then we want to put this into our editor. So we'll say UI text edit set plain text and we give it a Q string, which in this case is of course the text. Now I'm sure there is a much more streamlined, better, elegant solution, but we're just trying to keep this very simple, very easy to understand. I'm sure you could probably combine a bunch of these into one giant line of code, but we really don't want to mess with that right now. We just want to see if it works. Uh-oh, expected expression before token. What did we do? Oh, yes. That's why you keep things simple just see if they work. Now when we open this, let's just randomly give it a file and see, sure enough, it opens it. And if we select now, well it blanks it out. Now one thing we forgot to do here was set our file name. Remember we've got this file name variable. So what we're going to do is we're just going to say if it opens successfully, then we're going to say m file equal file. There we go. Now you may be wondering why we even have this m file variable. Well, we want to be able to click the save button and just automatically save the original file. But to do that, we need to know what file we had opened in the first place, which brings us down here. Now we also have a save as. This is where it gets a little tricky. Save as, let's the user save it as a different file where save will save it to a specific file. So what I typically do is I put a dialog in save as, set the file name and then call save because, well, you're going to do the same function. So just pretty much take this code that we did, split this up into two different functions here. So let's just write the save code and verify that that works. So we're going to make a q file and just call this s file for that. And we want m file name. And I know some of you're probably screaming at my variable names. I'm just very tired right now. So bear with me here. Whoops. There we go. Open and we want q file. And we want write only. We want to order that with q file. Now some of you have written to me in the past and say, Well, why do you do the text? Why don't you just do write only because we don't want cute to take that text and as it's reading through it do any sort of actions with it that could really mess your file up if you're working with it. We just want them to know that this is plain text, process line breaks, things like that, but leave everything else kind of intact. So now that we have our open file, we need to do a q text stream. And we'll just call this out. Give it a reference here. Maybe if I can find the ampersand, there we go to s file. And we also want to make sure that we of course close it when we're done. Ah, maybe if I can type. I'm having the hardest time typing that. Geez. Close. Okay. All right now what we need to do is output the text from our text edit into the file. And we do that by saying out text edit to plain text. There we go. What that does is it takes the contents and outputs it to plain text. Now, if you back up here for a second and say two, you notice how there's two HTML also. That's because it can have HTML styling in there to give like bold italics underlying things of that nature. But for this tutorial, I know a million size just happened. We're just going to do two plain text. Now you notice how this entire function hinges on this m file name? Well, that's what we're going to set in the save as. The first thing we need to do here, of course, is actually verify that this is working correctly. So let's just give this a good run here. And let me pause this for quick. I want to make a junk file. We just don't care about. All right. I made a dummy file. I just don't care about here. Let's just go test Q pad. Where's the test file? There we go. So this is a test. Don't panic. And I'm just going to make some explanations behind here. And when I click save, it saves the file. We can verify this by going new, open and then reopening the file. And there's our exclamations. Now what we want is the ability to save as say we don't want to save the original file. We don't want to overwrite it. So we're going to make an entirely new file. So what we can do is actually cannibalize some of this code up here from our open function. Instead of get open, we're going to say get save, give it the same parameters. And then we're going to if not file empty, then we're going to call this. The first thing we want to do, of course, is set the file name. So quick review. What we're doing here is we're saying, okay, if the user selects a new file to save, then set our variable and file name to file, then call that save action, which triggers the code, which writes it out to the desk. Quick save in a build and we can test this thing and see if it's working. So let's go open. There's our test file. Want to save as and we'll say let's call this test two dot txt new open. And let me drag it into the video here so you can see it. So now we have our test two and our original text. So let's open test two and sure enough, there it is. So that's all for this tutorial. This is Brian. Thank you for watching. I hope you found this educational and entertaining. And as always, drop me feedback anytime. I really like hearing from you guys. Now, I should add a disclaimer here before you go using this for a professional program, there are some horrendous bugs in this thing. For example, if you go new, which blanks out the file and then hit save, what's going to happen? Well, let's look here. Let's see real quick. When you go new, it sets it to nothing. So if you were to hit save, it's going to try and open a blank file name and you're going to get an error. So what you should really do here is test for file name. And I'm just going to put a little comment there in case you guys download the code. That way, if the file name is empty, you know, raise an error and call the save as, et cetera, et cetera. I could do that right now for you in this tutorial, but I really want you guys just to get the basics here and don't focus too much on the code. Just focus how everything kind of ties together. Quick review before we really, you know, close the video here. What have we covered? Well, we have covered resources. We've covered the central widget, the Q main window. We've covered how actions tie together. So you don't have to make a billion, you know, functions for one thing. We've shown how to tie resources into the actions. We've shown how to trigger them. And when we go back into the code, we've shown just the, you know, bare bones basics of how to make a text editor. So pretty simple, pretty easy tutorial. I say simple and easy, but I'm sure this thing's pushing well over 10 minutes. If you have any other ideas for simple, easy tutorials that we can slap together in 10 minutes or less, let me know. Anyways, I'm running short on time. Gotta go. Bye.