/** Populate the RepoModel with RepoItem entries that reproduce the hierarchical * organization of ScriptRepository entries. * * It will get the information from ScriptRepository from the listFiles, which means, * that it will reconstruct the hierarchical organization of the files and folders * through the list of strings with the relative path of each entry. * * @param root: The RepoItem root */ void RepoModel::setupModelData(RepoItem *root) { QStringList lines; // check server for updates to repository repo_ptr->check4Update(); // get the list of entries inside the scriptrepository std::vector<std::string> list = repo_ptr->listFiles(); // auxiliary list of pointers to repoitem that are related to folders QList<RepoItem*> parents; // the first one will always be the root parents << root; QString last_directory = ""; //FOREACH entry in LISTFILES for (unsigned int number = 0; number < list.size(); number++) { // folder or file inside the repository QString lineData = QString::fromStdString(list[number]); // Read the column data from the rest of the line. QStringList pathStrings = lineData.split("/"); // separate the folder and the current entry (folder or file) QString current_file = pathStrings.last(); QString folder = ""; pathStrings.removeLast(); if (pathStrings.size() > 0) folder = pathStrings.join("/"); // get parent for this entry RepoItem * parent = getParent(folder, parents); // a new folder has started if (parent == root){ // this test is just for the sake of performance, to reduce the numbers of parents parents.clear(); parents << root; } // check if the current entry is a directory if (repo_ptr->info(lineData.toStdString()).directory){ // directories will be appended to parents list RepoItem * aux = new RepoItem(current_file, lineData, parent); parent->appendChild(aux); parents << aux; }else{ // files will just be created and appended to the parent parent->appendChild(new RepoItem(current_file, lineData, parent)); } } }
/**Auxiliary method to help setupModelData to populate all the entries of RepoModel. For any entry of ScriptRepository should have a parent (by definition, all the entries are children of the root entry). Besides, given an entry, if the path contains a '/' this means that the entry is child of one folder. And all the folders are parents by definition. So, the idea of this getParent is that given a folder name, it must be related to a RepoItem that is a parent. If it does not exists, it should be created. @param folder: relative path inside the repository for the folder. @param parents Reference to the list of parents @return Pointer to the RepoItem related to the given folder. **/ RepoModel::RepoItem * RepoModel::getParent(const QString & folder, QList<RepoItem*>&parents) { // in order to speed the algorithm, check if the // folder is the same of the last folder. if (parents.last()->path() == folder) return parents.last(); // try to find this if (folder.isEmpty()) return parents.first(); // the parents first will always contain the root // it will iterate through all the parents of the given folder, in order to // create any folder that has not been created. QStringList folder_parts = folder.split("/"); QString aux_folder; RepoItem * father = parents.first(); // there is no reason to try to find entry A/B/C if the entry A/B was not found bool try_to_find = true; for(int i = 0; i< folder_parts.size(); i++) { if (i ==0) aux_folder = folder_parts[i]; else aux_folder += "/" + folder_parts[i]; bool found = false; if (try_to_find) { // this means that the previous folders were found foreach(RepoItem* the_parent, parents) { if (the_parent->path() == aux_folder) { found = true; father = the_parent; break; } } } // there is not RepoItem related to the current folder, // create it if (!found) { RepoItem * m = new RepoItem(folder_parts[i], aux_folder, father); father->appendChild(m); parents.append(m); father = m; try_to_find = false; } } return father; }