 Hey everybody, this is Brian and this video we're going to cover filtering and paging cute models. This is not a beginner's video and this is not for the faint of heart, but we're going to try and dump it down and make it simple. Unfortunately with that simplicity, we're also probably going to introduce a vast amount of bugs. So this will not be perfect, but it will be a good framework for starting. We're going to make essentially what you see in that graphic, which is a little search area, and then you can search a model which filters it and returns the results back paged. You can then navigate through those pages. We're going to create a data class, a filter class, which filters the data, the user interface design, the user interface code, which is different than the design. Those are two distinct different things. And then we're going to test this little application and see how it works. Okay, before we dive in, the code will be available on GitHub. There will be a link below. Without questions, check out the Voidrums Facebook group. I get way too many questions out on YouTube land to even remotely keep up with them. The Voidrums Facebook group has 4,000 plus developers out there and I'm in there all the time asking and answering questions myself. And if you like this video, be sure to subscribe, give me a like, and check out my Udemy courses. There is also a link below where I cover cute in depth. Model view programming is a little bit complex and it takes some explaining and cute does it a little bit differently. So in short, you see two triangles and they look almost identical and they are pretty much identical. There's a couple little caveats here. So normally you have a model, which is the representation of your data. Note it's not your data, it's a representation of the data. You have a view, which is what the end user views and you can view that data in different formats. For example, a grid or a table or some sort of tree view, whatever you wanted. And you have a controller and the controller really coordinates this delicate dance between the view and the model. For example, if the user wanted to edit something, they would type it into the view, but the controller handles updating that model. The model then updates the view. It's this beautiful little dance that happens. Now, cute does it a little bit differently. Instead of a controller, they have a delegate and the delegate acts as the controller. So the delegate really handles all the communications between the model and the view. And it gets way more in depth than that, but that's really what you need to know to survive this video. And because we're in cute, we need to talk about the cute classes we're going to use. We're going to use the cute standard item model, which provides a generic model for storing custom data. Remember, the model is not the data. The model is a representation of the data. We're going to use the cute sort filter proxy model, and that is a very big, long word, and we're not going to use all of its functionality. But it provides support for sorting and filtering data pass between another model and a view. What does that really mean? Well, it acts as that delegate between the model and the view. And we're going to touch on the cute model index, which this one really mystifies people. The index is used in item views, delegates, and selection models to locate an item in the model. What does that really mean, though? It means the index of the data in the data may be different than the index of the data in the model. They may be two different numbers. So for example, if you're trying to access record 57 in your data, it may be record 2 in the model. And this really bridges the gap and maps those two numbers together. So really what we're working with here is called a proxy model, which allows us to do things like sorting, filtering, or any sort of custom functionality we want to do. Now, we're not going to touch on every single aspect of this, but we are going to touch on filtering and paging that data. Understand that the proxy model really coordinates with the delegate and kind of inserts itself between the delegate and the actual model and acts as kind of like a traffic cop between the two. The view usually doesn't even know any of this stuff's even going on because the view reads from whatever you guessed at the model or the delegates telling it to do. Okay, let's look at the data class. The goal of this class is to write test data to a file, and then we're going to load data to a Q standard item model. Now remember, a model is not the data. It's a representation of the data. So when we're loading the data, we don't necessarily have to load the entire file. We could load just a section of it if we really wanted to. That's what we mean by the model is not the data. The model is a representation. Let's take a look. So before you, we have a blank application. This thing does absolutely nothing. We've written no code. It's just a main window application. Let's take a look. Right click. We need to build our data class. I'm going to say add new C++ class. And let's call this the ever descriptive name of data. And I want the base class of Q object. It's going to give us a preview of what it's going to do. I'm just going to say, next, next, finished. Going to trust this thing to do everything it's supposed to do. Clap some of that down. All right. Now I am going to, just to save a little bit of typing here, paste in some includes. So we have Q object, Q to bug, Q file, Q IO device, Q text stream, and Q standard item model. If you don't know what all of these are, you need to hit the pause button on this video and watch all of my other videos because we cover most of these in depth. But just to summarize, we got our Q object. We're going to write out some consoles. And we're going to work with a file, which is a Q IO device through a text stream. And of course, we're going to load information into the Q standard item model. This class, super simple actually. Let's say bull, write test. And we want this to have a path. Hope if I could actually spell. And let's say int rows. So we want to know how many rows we're going to write to that file. And then we're going to have a bull load table, which is going to do exactly what it sounds like. It's going to load that file into the Q standard item model. Now let's go ahead and implement both of those. Now comes the fun bit. And I say fun almost sarcastically because this code is actually pretty boring. Let's go ahead and say Q file. And we want to call this file. It's going to use our path. I'm going to make sure the file exists because if it does, I don't want to overwrite this thing. There we go. So if the file already exists, we're going to say, hey, our test file already exists. Let's not rewrite it. Let's not reinvent the wheel because this is going to be a fairly large file. And from here, we're going to say, if not, file open. And we want the QIO device right only. If we could not open that file up, I want to know what the file was. And I want to know why. And let's say, file error string. Sometimes that's not very helpful. You may get like access denied or something. That's just really not fun. So we're going to return false. Horrible typing excused because this font is super, super big so everybody can see it. If we've gotten to this point, then I'm going to go down here and just say return true. And now we're going to actually generate that data. Q-text stream. And in a production app, yes, she would do a bit more robust error handling. We're going to take our text stream and we're just going to say, for int i equals 0, i is going to be less than the number of rows. And then increment, Q-string, data equals, and we want the string representation of whatever our number is. So we could make just a massive amount of numbers we're really going to though. And then I'm going to pump that out to the underlying stream. Could use indel or anything else that we wanted to do, but I'm just going to do it that way. So it's very obvious to even newbies what's going on there. Believe it or not, I've had people ask me, what's indel? Why are you using indel? I've never heard of this. It's just like, what? Okay, guys, come on. So anyways, file close after we flush that stream out. And we want to know that something happened. So I'm going to say Q-info, maybe scroll down a little bit so we can see what's going on here. And I want to know that we created this file. All right, now that we have created the file, we want to be able to load it. And it's called load table, but it really could be called load file or whatever we want. The premise here being we're going to take whatever path we give it and we're going to load that into our Q-standard item model. All right. First things first, load the file. But we want to make sure this model is actually cleared out. So we're going to say clear. I'm going to go down here and just put some hard returns, get some screen real estate here, as we call it. We're going to set up the model. So I'm going to say Q-ring list, headers, headers append, headers append, and we're just going to say item. So really, in case you're wondering what this is, it's the header across the view that we're going to put. Now I want to say model, set the column count. And we want just one column, because we're only going to display shockingly one column, but you can put as many as you want. This is the beautiful part about the Q-standard item model. You can create pretty much any data that you want here. And now we want to set horizontal header labels, long, long name, but we're going to set that to our headers. That string list that we already set, which is going to say, okay, when we're viewing this model, we want to use this string list to define what we're viewing. And you'll see that later on in the video, where at the top it's going to say item. Now we need to fill the model with data. Got a little ahead of myself there. Sometimes I type faster than I think, and that's always scary. All right, so we've got our file. Now we, you guessed it, just need to open that. So we can, if we really wanted to, jump up here, grab this, save just a fraction of a second in typing. So if we could not open that and read only, we're going to say, could not read that path. And we want to know why, and then we're going to return false. And then, of course, we are going to use our anti-queue text stream to the beauty of copy and paste. Now we want to read that file all the way to the end. So I'm going to say while, and I want not stream at end. So it's smart enough to know when we reach the end of that stream, which is essentially the end of the file. View string, let's call this line, and let's say stream, read line. And it does exactly what it sounds like. It's going to read it one line at a time, probably not the most efficient way of doing this, but it's very simple to understand. Now we're going to append row into our model. And this is where we're actually taking the data from the file and putting it into the model. And we can't just shove a string in there. This is the unfortunate bit about it. We're going to say, queue standard item. We're using queue standard item because we're working with the queue standard item model. That sounds super confusing. Just remember, we're using a queue standard item because we're working with a queue standard item model. So just take the word model out of there, and it shows you exactly what data type we're working with. All right. So that really does just shove the data right in there without a care in the world and says, I don't care, just put it there. No verification of what that data is or why it exists. All right. Now we're going to close that out and I'm going to say return, true. And we can if we want to be a little bit fancy here and say queue info and want to know that we loaded this file. That's so fancy. I forgot the O and info. There we go. And I want to know how many rows we actually loaded. So I'm going to say model, row count. That way, if there's ever a question of how much data we loaded, I want to know we loaded that file and how many rows or how many lines from the file we actually loaded up. Pretty simple. Pretty straightforward. Let's give it a good build. Make sure we didn't make any errors. Voila. Next up is the filter class. So the goal of this class is three things. First, it inherits the Qsort filter proxy model. Say that five times real fast. Just know that the Qsort filter proxy model is really the powerhouse of this application. It's what's doing all the heavy lifting but we have to inherit that and do some custom code. Not for the faint of heart. But this is going to work with the Q standard item model. Remember, our model is our representation of the data that we're working with. And what we're going to be doing with that is filtering and paging the data. So that is really the most complex part of this application. Let's dive in and take a look. Okay, let's go ahead and make our filter. So we're going to right click, add new. Want a class? Give it the ever descriptive name of filter. It's going to be a Q object. And we want it to be a Q object because we want signals and slots. And by default, I make pretty much most of my classes Q objects if I'm in Qtlan. That way, if I decide later on, I want them to have signals and slots. It's very, very simple to add them. All right, let's go ahead and I'm going to do a fair amount of copy and pasting in this little segment here. But towards the end, I am going to slow way down to explain what's going on. So first things first, it's going to be a Q object. We're going to use Qtabug. And we want to include the Q sort filter proxy model. And we want to actually inherit that. So let's make sure we're inheriting that appropriately, which means now we've got to flip over to our implementation file and fix that little problem. Slip back to the header and there is going to be a metric ton of copy and paste going on here. So I've got some notes off the screen. Just going to save a lot of time typing all this out. So we're going to have some functions here. Page data, set page data, page size, set page size, page count, filtered page, current page, and set current page. And all these are pretty much self-explanatory. Now filter page, this is where we're going to give it a pattern. And this is where we're going to say, hey, I want to look for whatever it is we're searching for. But we have to give it any special format. And we're going to look at that in a little bit. Now for our signals, because we are going to use signals and slots, we're going to say, started and finished. We want some public slots back and next. In case you're wondering, we're going to page the data. So we want to be able to go backwards and forward through that data. Now we are going to have a protected. Let's just paste that right in there. Filter, rows, filter except rows. Can't even say it. So what this really does, and you can feel free to read the documentation, but we're looking to see if this row is allowed. So filter accepts row. We are the filter and we're determining if we're accepting this row. And it gives us the integer for it and we have to determine based off the Q-Model index whether or not we even want this based off of the filter. It's a little confusing. All right. And the last, but certainly not least, a whole metric ton of privates. Boom. Ones and tons of them. So we've got the page data, page size, current page, a Q-String regget pattern. I'm not sure if we're going to use all this, but we'll find out. Mutable int, total added, total pass, total process, total page, min, max, search calc and process. That is a lot of stuff. I'm going to go ahead and just implement all this super, super fast. And I'm going to pause the video real quick. Okay, welcome back. I've done a lot of work on the background. Now one notable change is I've commented out this calc range. I just don't think I'm going to use it. It was a last minute change. It was in the previous segment and I just wanted to update you so you're not wondering, hey, where did it go? So let's switch over. Our implementation, I've added a lot of stuff and this is all boiler plate code. We're going to go through it real quick. I just didn't want to waste a lot of time typing this out because I want to focus on what's important. But first off, we are inheriting the QsortFilterProxy model. We're going to set our defaults. The totals are pretty much when we search. We're going to set our pattern to blank. This is the regular expression pattern we're using. We're going to set the current page to zero. We are not going to page by default and we're going to set the page size to 100. Everything else is pretty much a getter or setter until we get down to back and next. These are slots. So these will tie into our user interface. When the user hits the back button, it's going to decrement our count, make sure we're within a valid range and search. And when they hit the next button, same thing, it's going to increment where we are, make sure we're in a valid range and then search. Like I said, not rocket science code here, so I just didn't want to spend a lot of time typing it out. Search is, well, not as exciting as you think it would be. So really all we're doing is resetting our totals, saying what is the minimum we're going to want, what is the maximum we're going to want, we're going to tell the outside world that we're doing something by emitting starting and then we're going to call this setFilterRegularExpression. And that is part of the QSortFilterProxyModel and what that does is it takes that regular expression and filters based off that expression. From there, what's going to happen is this FilterExceptsRow is going to be called and it's going to be called for every single row. We've got this other function that we've added here called Process, which this is not going to make a lot of sense and we're going to fill this out first so you're going to kind of be looking at the screen like what is going on here. But really what we're doing is we're going to process this and determine what the heck is going on. So I'm going to just copy and paste a blob of text out here and we'll just kind of step through it. We're going to increment our total process. We're going to say if it's allowed and count only then we're going to add. If it's count only then we're going to total past. Total page is going to be total pass divided by page size. Really all we're doing here is we're trying to figure out what we're actually doing. That's the whole point of this function and there is probably a better way of doing this. What I want to draw your attention to is really at this trail end here. If total process is greater than or equal to the source model row count, we are done. So we're really trying to figure out at what point we're done searching. Because the total process is going to determine whether or not we have actually made it to the end of our page. And then we're going to return a bowl saying whether or not it's allowed. We're going to use this whole thing, this nightmare little function, in our filter accepts row. Now filter accepts row is part of the Q sort filter proxy model. And this is where people get super, super confused connecting the dots. Basically when we call the set filter regular expression, it's going to do some stuff in the background and then this is going to be fired off. We're going to use this to determine what we need to do. So this is the real bulk of the program here and this is what I wanted to slow way down on. And this is where you're going to watch me type horribly. And we're going to try and explain this. So first thing we need to do is get the index of the item. And it's pretty bad when you've got to take five minutes to explain what you're about to do. So Q model index, let's call this index equals, and this is going to be the source model index. Now you notice how it's not going to just give us a number. We have to tell it exactly what we're looking for here. So it wants a row, a column and let's go from there. So I want to say the source row, which is the integer pass to our function here. It's part of our parameters. See? Source row. That tells us what row we're looking at. Now we need to look at the filter column key. And the filter column key is, well, it's not super expressive, but basically it says what column are we actually looking at here. And then we only have one column in this model, by the way. Then we need to know what is the source parent. Super, super confusing. But remember, the Q model index exists solely to map the index between our data and the model. And because we're working with Q sort filter proxy model, we actually have two miniature models. We have our model and then this thing, which acts as like a delegate between them, which is where all of this filtering is taking place. That is super confusing. Alright, so from here, we're going to make sure it meets our filter. This is where we're actually filtering the data and saying, hey, is this thing even allowed? Say, if not source model and I want to know the data and notice how this wants a Q model index, not an integer. So we have to use that Q model index that we just created. And we want to say to string. You could convert that into whatever data type you needed to work with. But I want to say contains and I want to make sure that this actually contains our filter regular expression. And that is just horrible. I hate this, but it just works. And following the Q documentation doesn't really make this seem like it makes a lot of sense, but it is what it is. So basic steps. We're going to get the index. We're going to make sure that it meets our filter and we use that index to get the data, string representation. Now that we've got that, we need to do something with it. So I'm going to return and we're going to use this process function and this is going way off the screen. I apologize. So I step it down a line. We're going to use this function to determine whether or not it's going to work. And I'm going to just simply say false, false, and fail the filter. So if this looks super confusing, it's because it is. So what we're really doing is we're saying source model, data, get the index, the Q model index that we're working with, which is from the source row convert that to a string and then take that string and make sure it contains our filter regular expression. And we want to base all of this around this guy right here, which is we're going to say return process, false, false, fail the filter, which really what that does is it's saying is it allowed faults? Is it count only faults and the reason is fail the filter and then it's going to do its little magic here. Like I said, much simpler way of doing that and that is way too cumbersome, but I wanted anybody who's even new to C++ to be able to follow through with that. Okay, now once we've made sure that it meets our filter and I'm going to just bump this up just a line here, I want to allow if not paging the data. Because remember, we're going to have different result types paged versus non-paged. So if we've gotten this far, we know that this has met our filter criteria. And so if we are not paging the data, then what we need to do is return and you may be wondering what we're going to do here. It's this same thing. So we're going to change this a little bit here. We're going to say true, true and I want to say not paging. So if we've made it down to here, we're going to say it has met our filter criteria. If we're not paging the data, then we're going to process it and we're going to say it is allowed. It is a count only and we're not paging the data and then it's going to go through and run this code. From here, we're going to say this is the important bit. This is where we're really deviating from a lot of the tutorials out there. If we are here, we are big bold letters paging the results and we need to, and I'm going to put a bunch of exclamations that way. It's very obvious what we're doing. So we want to explicitly deny anything that goes outside the boundaries of our page size. So I'm going to say deny anything that goes out of the boundaries. I'm going to say out of the range. So I'm going to say if I want the total added is greater than or equal to the page size, then I'm going to return and if you guessed I was going to do this, you would be absolutely right. By now you're probably wondering what is the pull point of this process function? Well, it's really just mostly so we can figure out what's going on and why one thing went and why one thing didn't. So it looks really confusing and annoying and it is confusing and annoying, but really it just helps you in debug land figure out what the heck something is and why it made it through. So for example not in page range deny anything that goes out of the range and we're going to say return process false true and then not in page range. So false, it's not allowed true it is a count only because we are paging now, we're counting and the reason is not in the range and then from here it's past the filters and in the page. So this is where good times happen. Now I'm going to say make sure it's in the current page and that really shouldn't say page, it's in the range. There we go and I want to say total past these are the total numbers that have passed checks and balances and we are now adding them to the page and we want to say greater than or equal to our min, you knew we were going to use those at some point and the total past is less than the max this is how we get our page size if you thought that we were going to grab this you would be absolutely right this is our buddy here and we're going to process and this is going to be true true and let's go ahead and change this to in page range now I'm going to add at the very end a catch all just because we're going to get this non void function blah blah blah it's just going to say return process false meaning we're not going to add it true and it is the default catch all here so really I tried to simplify this by using this process function which may be a little bit cumbersome to understand but now you understand why we're using process let's actually step through process and see what it does here so every time we go to filter accepts row we're going to call this process function and we're going to say is it allowed is it a count only and what is the reason we're even looking at this so we're going to increment our process we're going to say if it's allowed and count only is false then we're going to say total added meaning we're actually going to add that thing if it's count only though meaning we're only just going to count this number we're going to say total past and then pages equals pages past divided by the page size so we're trying to find the total number of pages here out of all of the data that we're searching there's much better ways a little bit more complex ways of doing this but this is a super simple beginner way of doing it and then we just want to know through Q debug that actually change that to a Q info if we really wanted to allowed and then the reason and if you're curious the difference between Q debug and Q info I cover that in other videos but really it's just it's the way Q does it's it's debugs and things like that it allows for logging and filtering so instead of a debug message it's an info message but it both goes through the standard output and then we're going to see if we're done and we're going to say if the total process and I have this in here don't really need it but the total process is greater than or equal to the source models row count then we're going to say we are done and then last but not least we're going to return whether or not this thing is even allowed okay lots of fun stuff in there let's go ahead and rebuild make sure I don't have any little gremlins in our code we've gotten to this point we've got a good build we're able to run the app but it does absolutely nothing yet but we've got the bulk of the application done okay user interface design this is the fun part welcome to art class basically so we have three major goals here we want to allow for filtering allow for paging and use cute model views let's take a look and see how this works okay if the last segment hurt your brain don't worry I hurt mine too I really am not a fan of the way that works but it actually works really beautifully just to recap here we have our data class we have our filter class and this thing is an abysmal mass but it just works as we're about to see but what we're in now is art class so welcome to art class we are going to design our little form here so we have our Q main window and we're going to let me bring it up maybe there we go a screenshot of what we're going to be building here and it's not going to be fully functional you see how we have like these menus and things I'm not sure if we're going to do all that but the bulk of what we're really curious about here is this line edit that button this little table view right here this is a view not a widget the back the next and then we want to be able to show that little guy right there that count that's what we're really really focused on here so you can add all sorts of you know menus and toolbar buttons and all that but really we want just the bare bones functionality of this because as you've seen so far this is not super simple so let's dive in first thing we want here is a button and you notice how we are in a main window but we're dragging around if you know anything about the Q main window we need to set a central widget which we will do shortly but I just wanted to point that out I'll take a line edit drop that on here and you can scale these out and do whatever you want to do but it's really kind of pointless to even do it there's just a better way it's called layouts so we're going to say search and let's call this btn search and I'm just going to leave that as line edit the ever descriptive we're going to select those two and now what we're going to do is we're going to set that to a horizontal layout this is what I mean by it's really pointless to try and scale that out because once you put it to layout it scales automatically kind of cool the way that works alright from there what we need to do now is let's grab a table view notice how there's a view and a widget and I get asked all the time what's the difference between these two like if you were to look for a list instead there's a list view and a list widget well the fundamental difference here is when you see view we are working with model views you know the model view controller the model view delegate pattern if you use a widget you have to manage that directly there is no model so we want the view because we're in model view land I'm just going to drag and drop that here and my scale is up just a little bit give me some screen room here alright so down at the bottom here I want, let's bring up our screen shot again we've got our search area we've got our view now we need to build this little guy and this is just the status bar down here that's already baked in but we need these two buttons in that label so let's drag those in button and button what shall I call you let's say back and let's say btn back and btn next I want a label this is where I'm going to say count and I want to give this a descriptive name like LBLCount now we're going to grab those three and drop them in there like that if we bring up our screen shot again you can see how we've got this search area, our view, this and then everything is all laid out together nice and neat so notice the keyword here laid out we're going to put this in another layout so I'm going to grab all of this stuff you notice how it also selects it over here and this is the fun bit now I'm going to put it in another layout I'm going to say lay that out vertically bang now it's just nice and neat it can become a little challenging to actually select it and that's where you can select it over here if you want an individual item so we're just going to grab it and we can scale it out and see how it would look pretty pretty cool ladies and gentlemen I'm very sorry now is the boring part of the video the user interface code we have three major objectives this is the plumbing it's going to connect everything together we're going to make the application functional and then we're going to generate test data and load it okay now that art class is over there's a couple things I want to cover real quick but we've got to do all of the plumbing code or the user interface code as I call it and we're going to go in here now there's a couple subtle issues first of all if you see this central widget thing you're often inclined and cute to go in here and say I want that central widget and then I want UI I want the vertical layout and I'm going to do this now you'll notice how it's not going to allow us to do that it's going to actually piss you off because it will not allow you to do that so one simple way of getting around that there's other ways but this is the simplest way is going to grab that vertical layout and you can either right click and then go down to break which goes off the screen make sure you've got this selected and you break the layout and it does exactly as advertised it breaks it or removes it now we're going to click on the main window and in case you're wondering you can actually click on something else and then select main window here or click it here and it will show these little boxes that it's selected and you can set it up here so we're going to set the layout in the main window so now our central widget has a layout and everything's laid out in that widget now everything scales with the window or previously it wouldn't have the other thing I wanted to cover before we really start down into the what I call plumbing code here is we're going to make an action and there's two ways of doing this you can either right click down here and say new which brings up this little editor or you can just simply go up here and I've already typed in file but you can type right here and you can say create test file and boom creates it right down here for us and you can double click it and bring up the editor in case you misspelled something you want a different object or you can set the icon checkable whatever you want to do so what really is an action well it's an entirely separate video series but basically actions objects that you can put into menus or into toolbars or whatever you want to do so in case you see these in other videos and you're wondering what the heck is that just it's super simple watch all the other videos I've done but just wanted to touch on that super quick here so what we can do now that we have this action is right click it and go to slot which is going to say what do you want to do as far as slots we're going to go to trigger notice it's not clicked because you can trigger the slot by hitting the enter key as well if it's highlighted so we're going to go to triggered and hit OK that's going to create this little function down here and we're going to do that for the rest of our user interface for example we're going to right click our search button go to slot and because it's a button we're going to use clicked and then same thing here for the back and we're going to go clicked and right click and let's go to slot on the next so now we've got back next search and then on our create trigger so there's really not a whole lot in this main window so far this is the not fun part I call this the plumbing code so I'm going to zip through a lot of this just because I really don't like doing a lot of plumbing code we're going to grab some stuff off the screen we're going to use the Q file dialog, Q input, Q message box, Q standard item model, Q sort filter proxy model I love saying that really really fast the data class we made and the filter that we made now we're going to add in two little guys in our slots we want started and finished in case you're wondering whoa whoa how did you get started and finished it's part of our filter remember we have signals started and finished it's right part of this Q sort filter proxy model so I want to know when we start and when we finished alright so now that we've got that in there we're going to set up our privates I mean what you do with your privates is your business but we're going to do this so what we've got is a standard item model, a filter and our make test data and our load file so normally what I would do is I'd pause the video and I'd fill all this in but what I'm going to do is actually just do it in real time most of the stuff is already done for us we just have a couple little things so let's go switch back, finished switch back make our test data switch back and bang alright the rest of this is pretty much just plumbing code so I'm going to start setting this up here some of the stuff I'm going to type some of it I'm going to copy and paste if it's not really relevant so I'm going to say filter and we're going to set the page data and we're going to set this to true meaning we're going to now page the results back when we search I'm going to say filter and we want to set the page size and I want only 10 items, no more than 10 and then I want to of course filter and I want to set the current page and we're going to set that to 0 for the very first page and then I want to connect up some signals and slots so we're going to connect our filter started and our main window started and our filter finished to our main window finished that way we get some feedback of what's going on with this class in the background and from that you could connect up any numbers of signal slots enablement to say any sort of graphical interface thing that you want to do and say filter and this is where we're going to set the source model I know that was a little bit confusing when we were writing out the filter code so the source model is our actual model remember the filter kind of sits between the model and the view so it filters what we're really doing so think of it like a model for the model or a filter for the model we're going to set that to our model now we want to take our UI table view and we're going to set the model now one thing I want to kind of point out here I get this question quite a bit if you're typing away and you say UI dot and nothing happens this doesn't have all your like the labels and all that fun stuff in there simply comment it out and hit build and that builds all the code in the background that this needs and really all it's doing is it's going through here reading the XML file generating the classes and stuff in the background and all the code that you need and then IntelliSense will work so I've run into that before and some people have said how does this work I don't understand so and you don't really need to type that out you can just do a dot and it'll automatically switch it that's one thing I love about QCreator smart enough to know if it's a pointer or not so set model and we're going to set this as the filter did you catch that we're setting the view model as our filter not as the actual model so the filter uses a source model the view is going to use the filter so we want a filtered version of this model alright it's from here what we're going to do is say make test data so as soon as this application starts I want to say boom make me some test data and if the test data already exists it's going to say don't worry about it the rest of this is pretty much just plumbing code so I'm going to plow through a lot of this real quick here so where is my search here it is say filter and I want filter paged and this is the pattern we're going to use here now when I say pattern don't worry you don't have to write any crazy regular expressions you can if you want but we're not going to for this and we're just going to say we want the UI line edit definitely consult the Q documentation because it is a little bit different than what you're probably thinking if you're an expert in regular expressions so we're just going to say take whatever the user types in and that's what we're going to filter and page back now back big drum roll filter back we very much could have just done signals and slots and connected those up but I just wanted to be very obvious what was going on same thing with our next now started and finished this is where I really just wanted some sort of feedback right so I'm going to say started searching and we can change this to a Q info a lot of this stuff is simply so we know what's going on like I want to know when it's starting and in our filter I want to know what we're doing for each and every single individual row could have drastically simplified all that now in the finished little bit of copy and paste action here I'm going to say we are finished searching again I can make that Q info if you don't like Q to bug it all goes through standard output anyways and then we're just going to get the current get the total update our count and then pump that out to the user interface not super complex here alright so where are we now we want make test data now the make test data what we're going to do here is very simply take our data class say we want to get our applications path call it test.txt and then we're going to write out a thousand items and we could very easily have done this very differently but I just want this to be very simple and then we're going to call load file now remember make test data is being called in our constructor so if we do anything too crazy it is going to lock up the interface so if you do like a billion lines it's just not going to work well ok almost there load file we're going to say data status bar no file and then we're going to say data load table and if you remember right that's this guy right here load table and it's going to go through and load that file into the queue standard item model now that's important because up here we're saying our filter is using this model and so there's a lot of signals and slots that get connected in the background so the filter knows when the model updates and now the view knows when the filter updates and then all of that magic just happens in the background alright so from there we're going to say if we cannot load that we're going to say we got some sort of boo boo that's the official term as a boo boo and then we're going to just update our user interface alright we are pretty much almost done what we want to do now is I want to fill out this guy and this is more of a test function if you will I just want to grab this and say if you wanted to create some different file you could just definitely create one and it's going to show how you would do all that just because I know I'm going to get somebody's going to ask me a question how would you go about and open a dialogue and do all that but if you're watching this video I'm going to just assume that a lot of this is beneath you you already know how to do this so basically what we're doing is a file dialog and we're going to say get save file name and we're going to say make sure it actually does not exist and if it does we're going to say are you sure and then we're going to say if we can actually do it we're going to get an integer using a queue input dialog of how many items you want to create now we're automating this a bit in where is it where is it make test data we're automating that whole process so there's just two different ways of doing the same thing and then we would take the data write that out and then load it up pretty pretty simple okay the hard parts over now we just need to do some testing hopefully fingers crossed I didn't make any typos or glaring issues or errors or anything like that we're going to test this and say can we filter and are the results paged let's take a look let's save this make sure real quick we haven't blown anything up let's give this a good build fingers crossed oh we got a good build okay save run and voila everything just works now we have data so what happened when we started this you can see how it created this file this file has all that data in it and it's showing the data and we have page 0 of 100 you can definitely say one of 101 but you can now page through this data see how that's changing over here now here's the fun bit you can page through this data but if we want to go all the way back to beginner land here you can now search for this data so let's say we only want to see things that have the number nine now anything that has a number nine in it we are now in there and now we have 27 pages notice how that went down because we are filtering the data and we could do things like we only want to see things that are double zero's much shorter zero zero now a slight bug in this program if we go back to beginner land notice how it's not updated correctly so that's a bug you'd have to work out but I really just wanted to show the fundamentals of doing this and I'll show you another bug just because I like I like people picking on me sometimes let's say I go out to some arbitrary page 22 why not and I only want to see things that have 55 in them notice how we're on 22 of one and we could back this out and nothing's displayed until we get to the very beginning now it suddenly shows we have exactly two pages so those are two minor bugs that are in this app but this really shows you a fundamental starting point of how you could filter and page the data vast room for improvement this is really just the beginning step of a larger complex application if you really wanted to filter and page the data out so some main takeaways from this video is yes this is hard yes this is cumbersome yes you've got to read the cute documentation which is not super helpful in some areas I've had a lot of people say I've tried to do this and it just not make sense what we're doing is we're building a data class which will write the data and load the data into a model we're building our filter which is a cute sort filter proxy model absolutely love that name whoever named that thing and the sole function for this class is to sit between the view and the model and filter and page that information and there's vast room for improvement in this class you could allow sorting and all sorts of other fun stuff and then we have our user interface which we've fleshed out and made it very beautiful I would say this is almost worthy of like the apple iphone kind of thing but anyway you get the point so then a nutshell is how you would make a filtered page view using cute models I hope you enjoyed this video click the like and subscribe below and I hope to see you out in the void robes facebook group