 Hey, everybody, it's Brian. And in this episode, we are going to talk about Q Object, signal slots, mock and the build process. We're going to do this a little bit different than everybody else does it. Almost every video out on the internet says Q Object Class. The Q Object Class is the base class of all Qt Objects. But they don't really explain why or how or how any of this stuff works. So that's what we're really going to dive into. Alright, so what is a Q Object? Well, according to this, the Q Object Class is the base class of all Qt Objects. And that's actually not entirely true. Most classes in Qt are Q Objects. But there are template class like lists and things like that that do not inherit Q Object Q string, for example, is not a Q Object. So when you see this kind of take it with a grain of salt that not everything is a Q Object. Qt Objects, more appropriately, are the heart of the Qt Object Model. Now, in case you skip that day in C++ land, what is a class? What's a blueprint for an object? It's not the object itself. It's simply the blueprint. Let's say you're going to build a house. You need a blueprint. You need a plan on what you're going to build. And from that blueprint, you can build any number of houses. So that's really what a class is. We're inheriting the Q Object, which means we get all the functionality of it. So let's say we're going to build a house. But we want a house with a hot tub, right? Because hot tubs are kind of cool. So we would inherit a house and then add a hot tub onto it. And that's basically how inheritance works a little bit more complex. We're going to cover that later. But when look at Q Object, you see it's inherited by a lot of different classes. So the vast majority of Qt uses Qt Object. And when you scroll down, the first thing they tell you is these functions are thread safe. And then you see connect and disconnect. So this is signals and slots. We're going to touch on that later in this video. And really, we're going to have an entire video on just signals and slots, but we're going to briefly touch on it. Really Q Object comes action packed with the ability to talk to other Q objects. Think about it like this, you have a house, you have a car. As you're pulling the car into the driveway, you want the house to automatically know the car is coming and open the garage door. You can do that kind of stuff with this. It's actually very cool. Now signals and slots are not acute centric technology, they just do it really, really well. And scrolling down, you see there's a lot of functionality baked into Q Object. We're not going to cover all of this, but just know that it can have children automatic memory management signals and slots, which is communicating between objects, you can move them between threads. That means you have multi threaded applications baked right into the core of Qt, and it just gets really, really cool. And again, there are different signals and slots and things of that nature. And we're going to talk about all that in depth in another video. We're going to highlight it here. So first things first, let's go and make a console application. And let's call this Qt 6. And this is episode. What are we on for now, I think we're just going to next, next, next default all the way through that. And we're going to build a class. So I'm going to right click, add new and go C++ class. And let's give it a name. Let's just call this test, the infamous test class. Base class, we're going to set this to Q object. You notice how if we do custom, there's nothing checked, we want to make sure this is a Q object. So we're inheriting Q object as our base class. You notice it's also going to check this include Q object and add the Q underscore object. Don't worry about any of this other stuff. Widgets main window, those are for Qt widgets. If you're building like a graphical interface, and then you got some QML stuff here. Really, you want Q object and Q underscore object that's done automatically, and it's going to show you the header and the source file. I'm assuming you know what these are. And then the path. And notice how it's going to not add them automatically. But I'm going to copy to the clipboard. And let's go ahead and go test.h and test that CPP. So we're going to add those. Save our C make list. And then you'll notice as soon as you save it scans it, if you get that little green bar, you should see your header and your implementation file. All right. C plus plus classes 101. The header is the well header. This is what you would include or other things. And then later in an implementation file, this is where you would actually make the functionality. So the premise being you could compile this into some sort of binary and then you just give your end users the headers and they would include that in their project. And then they could compile it into their application using that binary. All right. So we have our include Q object. So we are now going to make our class and inherit Q object. And right off the bat, you see this explicit test Q object pointer parent equal null pointer. What is this? Right here is just simply the constructor. We're saying we can optionally add a parent. And when we do this, we're creating what's called a parent child hierarchy. This is something we're going to cover in another video in depth, but it's cute way of very simple memory management. So if we were to make a pointer instead of calling delete ourselves, we just simply make this a child of something else. So we're defining what the parent is. Notice that parents acute object. So when that parent is deleted, let's say the parents on the stack and this is out on the heap. Guess what? The parents going to automatically delete all its children. That's kind of morbid when you say it out loud, the parents going to delete all of the children. But that's basically what it does. Now there's some other things going on here too, you see this Q underscore object, we're going to highlight this and just mouse over it and you see what this does here. And it has a defined Q underscore object and a whole bunch of stuff. Basically, this goes into the build process, which we're going to cover later in this video, but I wanted to highlight that you're not officially a Q object unless you have this. And this goes into the build process through the meta object compiler, and it'll go through and add a bunch of special code for us. We're going to cover that later in the video as well. I just wanted to define you need to have public Q object, this macro in the private section, and at a minimum, you need to have this right here, a parent child hierarchy. You also have signals, and you can have the public slots. Again, we're going to cover signals and slots in depth in another video, but we're going to highlight it here. This is built right into Q object, you have that communication channel between this and other Q objects baked right into Q object, you literally don't have to do anything, it's just there for you to use. The fundamental flaw that Q has is it's very challenging to wrap your head around it at first, but once you understand it, you have that light bulb moment where you're like, oh my gosh, this is awesome. So you look at the Q object and a lot of things look very foreign to you if you've never worked with Q. You are inheriting Q object, you have this Q object macro, which builds into mock, which we haven't really talked about yet, and then signals and slots. So let's focus on signals and slots. I keep saying we're going to going to going to let's talk about a little bit at a high level. So signals and slots are a communication channel between objects. And stop reading right there, because if you go any further, you're going to see this little meta object system, and then you're going to click on this, and you're going to be very confused very quickly, and it's going to talk about Q object to Q underscore object macro and the meta object compiler or mock, and you're going to really deep dive into what I call the mouth of insanity, because you're not going to understand any of this at a high level, because really, at a fundamental level just to use Q, you don't need to understand that. You just need to know it exists and it's a thing. So scroll down and go to this graphic. And this is beautiful. I I've actually used this to teach people this is awesome. So you have object one and you have signals, and object two has slots. Notice it also has a signal. The point is a signal is a lot like shooting a flare gun up into the sky and saying, Hey, this is happening. And you can connect that to a slot to one or more objects, you see how object one is connected to object two and four. So when this signal fires off, this guy is going to see it on this slot. So if you're coming from another language, another framework, think of it like producer consumer, or a callback handler or something of that nature, but really under the hood, what we're doing is a signal is emitted. And anything that is connected to it can see that event. And that can happen across multiple threads too. So if you ever worked with multi threaded applications, it's just a complete train wreck trying to send some sort of event handling across thread. Cute does it ridiculously easy. I absolutely love the way it works. So at its core, when you talk about signals and slots, a signal is emitted. So let's go ahead and make a signal here. So I'm going to say void blows. And a slot would be something that would be called. So I'm going to say void do stuff. And you notice how I'm very bad with my spelling or my indentation, I should say, I don't know why I called it spelling, but we can right click. And we can auto indent selection and it beautifies the code for us. I love that feature about the IDE. Now that we've got this, there's some things we need to do. So for example, close you're inclined to well implement this because it looks like a function, right click refractor and you notice there's no option to do anything. You actually don't implement that. It actually is done for you by mock the better object compiler, which of course is we're going to talk about later. But this is what I mean by you have to understand things to understand things right now. Take it on a leap of faith. You don't implement that you just simply define it a slot. On the other hand, you do have to define. So I'm going to right click refractor and then you have some options. We're going to add the definition inside the implementation file. And it just adds it automatically for us. And in here, we can do something like let's go ahead and just include a bug, which I talked about in the previous video just allows us to rip things out on the screen. I must say cute info. It actually does a lot more than that under the hood, but you get my drift. So this looks like a normal function. And it is actually a normal function. This is the beauty of signals and slots. So when you say it is a slot. And you now modified this to be a slot, you can call this like a normal function, or you can connect it to a signal and it will automatically fire off for you. This is just ridiculously cool. So what we're going to demonstrate in the next little section here is how to connect all this up and make it do things. But what I want to do first is I want to go in here and I want to switch to the source. And we're going to show you we're going to emit that signal. Notice the little icon and let me move off here. It's got this little Wi Fi bar on it. That means it's going to be emitted out into the world. Think of it like Wi Fi. We're just sending some sort of signal. You use the emit keyword to let cute know hey, this happened. Very important you really wrap your head around that concept. So this is a slot, but it's also a function. And we are emitting a signal inside of it. All right, quick recap all we've done so far is we've created a class we defined a signal we defined a slot we've implemented the slot. Let me switch over and in our little slot we are emitting this guy here. So let's make this do something we're in our main here. Let's go ahead and include this and we're going to actually close this application. So let's go ahead and include our test class. And then we can say test. Just call it test. And we can actually say test. Do stuff. Now I'm going to move the mouse off the function here. You see how it's got those little indentations. It's almost like an outlet that indicates that it's a slot. So a signal has the Wi Fi bars a slot has a little outlet indentation. Notice how we're just calling that like a normal function. This is incredibly cool. So I'm going to just run this. And you'll see that well absolutely nothing happens when I run this other than it says doing stuff. We've emitted the signal but nothing is connected to it yet. So now we need to take that signal this guy and we're going to connect it to a slot. We could connect it to this slot but because it's in there it's just going to become an infinite loop and eventually Qt's going to attempt to stop us. But what we're going to do is we're going to take this Q core application this little A variable right here which also has signals and slots because remember Q object is the base class of pretty much all Qt objects. So because this is a Q object we can work with it. So what I'm going to do here is we're going to connect signal and the slots. So I'm going to say Q object and there's a ton of different ways to do this we're going to cover it in depth when we get into a signals and slots video I'm just showing you at a high level some of the functionality of Q object. We're going to say Q object connect and we need a sender then we need a signal a receiver slot and optionally a type. We are going to touch on the type in this video real quick. So the sender see if I can get rid of that little annoying yellow box there. The sender is what's going to emit the signal and we need to give it a pointer or an address so I'm going to say it's our test object and now we need a signal that we are sending and going to go ahead and say it's from the test class and we want the close signal and the beautiful part here is the ID smart off to only show us the signals so we're going to take the close signal unfortunately it does have those little parentheses gets a little annoying just fill those now we need the receiver or the destination and we're going to say we want the a or the application which is this Q core application up here and I'm going to just copy this to save me just a smidge typing then we need to say it's in the Q core application class and now we need a slot and I'll say kill that down know what is it sometimes you can just find it by doing this I think it was quit let's find out yep there it is and if you ever just kind of curious what it is and like you're just having a complete brain fart you can just scroll through this list and see oh that's a signal that's a signal that's a signal there's a whole bunch of signals in here and I need something that will actually help me close this application it's not delete later let's just it must be quit right here and it's got that little slot icon or if you're really really smart you can simply select the object press F1 it'll bring up the help system and then you can scroll down and the beautiful thing about the help system is it tells you the slots quit and then you can take it right there ask the application to quit their documentation is world-class and it actually almost annoys me when people say but how do I and then I just literally point them to the documentation so what we've done here we've said Q object go ahead and connect up these two Q objects so we're connecting test to our application here we're saying when close is admitted we're you know sending that signal out we want to quit and then we're going to call test do stuff remember this is a slot but we can call it like a function inside of there if I right click this and I follow symbol under cursor you can see we are emitting close so when we call do stuff we're meeting close and because we're meeting close Q is going to call quit in our application drum roll prepare to be underwhelmed it doesn't close our application this is another confusing thing about signals and slots there's a special way we need to do this normally 99% of the time this works just fine but we need that little extra step here notice how the default here is auto connection which tries to figure out what's going on it doesn't automatically it's not working because we're in auto mode so we need cute connection because guess what part of this actually lives off somewhere else and we need to queue it in order for it to work properly very confusing that it works that way but it's just how it is so I just wanted to throw that out there and we're going to cover all this in depth in another video I'm just showing you this is baked into Q object it's good save run and now this time you see doing stuff and then press return to close this window because we have all closed our application and if we wanted to we could get the return value from this guy right here let's go ahead and do that I'm saying it value equal exact remember exact is just an event loop we got here so you see key core application exact enters the main event loop which just keeps that application alive and I want to return that value but before I do real quick I just want to get a bug and I'm going to print this out on the screen so we can see what our exit value outside of our event loop was and this will show you that our application is indeed quitting and it's doing it appropriately so doing stuff we emit that signal the slot consumes it we close the application down and it says exit value zero which is exactly what you expect exit value is a return code that we give back to the operating system and other applications zero is the universal for everything when a okay this work does expected if it's something other than zero it's some sort of error code and we would have to look at the documentation to figure out what that was so that was actually pretty cool so a q object has a lot of functionality baked into it we can now talk between objects and they don't even have to know the other exists for example q core application had no idea test existed because test didn't even exist when q core application was actually made the actual class so we can do a lot of really cool things very quickly very easily but how does this happen and why let's go ahead and jump out to a hard drive real quick I'm going to go to the folder that I have our code at and here's our actual source code and then here's our bill directory and again this may be slightly different depending on your operating system but it all fundamentally boils down to the same darn thing we have our binary here and on windows this would be like dot exe and then you see this cute six auto gen what is this we jump in there we have this underscore mock pre depths and then mox compilation what is all this well this is the meta object compiler coming in here and intercepting the build process and doing things and creating select we just crack this open see how this file is auto generated changes will be overwritten but go ahead and include this guy right here huh okay well there's the folder and shockingly there it is so let's go ahead and open this up and this is what mox is doing in the background it is auto generating this code which connects this stuff you see there's our test class there is our signal there's a slot and it's connecting all this stuff up in the background for us and this is how this works highly highly recommend you don't even try to dive into this figure out what it's doing just let cute do its thing but this under the hood is fundamentally what's going on the meta object compiler is jumping in and creating all this for us so we don't have to that is really really cool so let's go ahead and look at the standard build process here so I'm going to probably explain this very badly because this is not a c++ class this is me trying to explain cute's build process so we have our dot h and dot cpp files or our source code and let's just kind of take that on a huge leap of faith that that is our source code that we've typed it out correctly this would be your main file your classes and all that stuff from there what happens is the preprocessor goes in and prepares the code got misspelled preprocessor that's embarrassing it prepares the code to be compiled so it's not actually compiling it's just saying let's go ahead and figure out what needs to happen for this to be compiled and at this point this is where we deviate from the standard c++ build and cute and we give that the bright cute color comes in here and mock or the meta object compiler comes in and scans your files and it says okay no not a q object this is a q object but it's built into cute but I've got this guy up here so let's go over and oh this is a q object so we need to actually convert this c++ class into a cute object and it does all of that mock goodness in the background and then it sees it's got the signals and slots and it does generate all these files and all these things that I just talked about all that magic happens in the background and then it comes back up here and let's go ahead and give this the pretty little build color then the compiler comes in and compiles and then it comes in and of course the linker comes in and the linker goes ahead and it generates our binary whether it's an executable or library or something like that so that in a nutshell is probably a very poorly explained version of what mock is actually doing but basically cute is saying hey run mock add the cute goodness into it and then finish the normal compile process this is very simple very elegant but it can also be very frustrating because sometimes things happen and it blows up and you are presented with you know this is where it went wrong and you've never seen this code and you can't find it anywhere in the cute source archives it's because it's code generated by mock okay so let's rewind real quick and let's talk about mock or the meta object compiler I don't want you to be an expert in this by any means but let's just kind of rewind here remember when I said signals and slots and we go back up here to ignore this little meta object system link if we click on this this is what's going on so the meta object system is based on three things the cute object class provides base class we've talked about that the cute object macro inside the private section of the class is used to enable meta object features such as dynamic property signals and slots so you have to have that macro to make all that magic work and then the meta object compiler supplies each cute object subclass our classes with the necessary code so it generates that code for us in the background you can go on to read this but really at its core what cute has done is they are avoiding you know without requiring native run type type information through the C++ compiler so they're making their own meta object or their own typing system they're creating pretty much in real time their own data types and this is extremely cool and you can do a lot of really cool things with it on top of that we're going to talk about casting later on in other videos they've also added features like you can perform dynamic cast using cute object cast so now you can dynamically cast one cute object into a completely different type of cute object this is just awesome I love this and of course you have built in memory management and all that and then meta information on top of it which if you're always confused whenever you hear the word meta think data about data so information describing your class and you can put it through some really really cool situations if you're really curious you can deep I mean really deep dive into their documentation through signal slots property system and the meta object but just know fundamentally at a beginners level you don't really need to dive into all this you need to have a background for you I hope you enjoyed this video you can find the source code out on github.com if you need additional help myself and thousands of other developers are hanging out in the void realms Facebook group this is a large group with lots of developers and we talk about everything technology related not just the technology that you just watched and if you want official training I do develop courses out on there drop me a note I'm either working on it or I will actually develop it I will put a link down below for all three of those and as always help me help you smash that like and subscribe button the more popular these videos become the more I'll create and publish out on YouTube thank you for watching