Example #1
0
QModelIndexList BtTreeModel::allChildren(QModelIndex ndx)
{
   QModelIndexList leafNodes;
   QList<BtTreeItem*> folders;
   int i;

   // Don't send an invalid index or something that isn't a folder
   if ( ! ndx.isValid() || type(ndx) != BtTreeItem::FOLDER )
      return leafNodes;

   BtTreeItem* start = item(ndx);
   folders.append(start);

   while ( ! folders.isEmpty() )
   {
      BtTreeItem* target = folders.takeFirst();

      for (i=0; i < target->childCount(); ++i)
      {
         BtTreeItem* next = target->child(i);
         // If a folder, push it onto the folders stack for later processing
         if ( next->type() == BtTreeItem::FOLDER ) 
            folders.append(next);
         else // Leafnode
            leafNodes.append(createIndex(i,0,next));
      }
   }
   return leafNodes;
}
Example #2
0
// The actual magic shouldn't be hard. Once we trap the signal, find the
// recipe, remove it from the parent and add it to the target folder.
// It is not easy. Indexes are ephemeral things. We MUST calculate the insert
// index after we have removed the recipe. BAD THINGS happen otherwise.
// 
void BtTreeModel::folderChanged(QString name)
{
   BeerXMLElement* test = qobject_cast<BeerXMLElement*>(sender());
   QModelIndex ndx, pIndex;
   bool expand = true;

   if ( ! test )
      return;

   // Find it.
   ndx = findElement(test);
   if ( ! ndx.isValid() )
   {
      Brewtarget::logW("folderChanged:: could not find element");
      return;
   }

   pIndex = parent(ndx); // Get the parent
   // If the parent isn't valid, its the root
   if ( ! pIndex.isValid() )
      pIndex = createIndex(0,0,rootItem->child(0));
   
   int i = item(ndx)->childNumber();

   // Remove it
   if ( ! removeRows(i, 1, pIndex) )
   {
      Brewtarget::logW("folderChanged:: could not remove row");
      return;
   }

   // Find the new parent
   // That's awkward, but dropping a folder prolly does need a the folder
   // created.
   QModelIndex newNdx = findFolder(test->folder(), rootItem->child(0), true);
   if ( ! newNdx.isValid() )
   {
      newNdx = createIndex(0,0,rootItem->child(0));
      expand = false;
   }
   
   BtTreeItem* local = item(newNdx);
   int j = local->childCount();

   if ( !  insertRow(j,newNdx,test,_type) )
   {
      Brewtarget::logW("folderChanged:: could not insert row");
      return;
   }
   // If we have brewnotes, set them up here.
   if ( treeMask & RECIPEMASK )
      addBrewNoteSubTree(qobject_cast<Recipe*>(test),j,local);

   if ( expand )
      emit expandFolder(treeMask,newNdx);
   return;
}
Example #3
0
QVariant BtTreeModel::data(const QModelIndex &index, int role) const
{
   int maxColumns;

   switch(treeMask)
   {
   case RECIPEMASK:
      maxColumns = BtTreeItem::RECIPENUMCOLS;
      break;
   case EQUIPMASK:
      maxColumns = BtTreeItem::EQUIPMENTNUMCOLS;
      break;
   case FERMENTMASK:
      maxColumns = BtTreeItem::FERMENTABLENUMCOLS;
      break;
   case HOPMASK:
      maxColumns = BtTreeItem::HOPNUMCOLS;
      break;
   case MISCMASK:
      maxColumns = BtTreeItem::MISCNUMCOLS;
      break;
   case YEASTMASK:
      maxColumns = BtTreeItem::YEASTNUMCOLS;
      break;
   case STYLEMASK:
      maxColumns = BtTreeItem::STYLENUMCOLS;
      break;
   case FOLDERMASK:
      maxColumns = BtTreeItem::FOLDERNUMCOLS;
      break;
   default:
      // Backwards compatibility. This MUST be fixed prior to releasing the code
      maxColumns = BtTreeItem::RECIPENUMCOLS;
   }

   if ( !rootItem || !index.isValid() || index.column() < 0 || index.column() >= maxColumns)
      return QVariant();

   if ( role == Qt::ToolTipRole )
      return toolTipData(index);

   if ( role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::DecorationRole)
      return QVariant();

   BtTreeItem* itm = item(index);
   if ( role == Qt::DecorationRole && index.column() == 0) 
   {
      if ( itm->type() == BtTreeItem::FOLDER )
         return QIcon(":images/folder.png");
      else
         return QVariant();
   }

   return itm->data(index.column());
}
Example #4
0
bool BtTreeModel::removeRows(int row, int count, const QModelIndex &parent)
{
   BtTreeItem *pItem = item(parent);
   bool success = true;
    
   beginRemoveRows(parent, row, row + count -1 );
   success = pItem->removeChildren(row,count);
   endRemoveRows();

   return success;
}
Example #5
0
QModelIndex BtTreeModel::first()
{
   QModelIndex parent;
   BtTreeItem* pItem; 

   // get the first item in the list, which is the place holder
   pItem = rootItem->child(0);
   if ( pItem->childCount() > 0 )
      return createIndex(0,0,pItem->child(0));

   return QModelIndex();
}
Example #6
0
bool BtTreeModel::renameFolder(BtFolder* victim, QString newName)
{
   QModelIndex ndx = findFolder(victim->fullPath(), 0, false);
   QModelIndex pInd; 
   QString targetPath = newName % "/" % victim->name();
   QPair<QString,BtTreeItem*> f;
   QList<QPair<QString, BtTreeItem*> > folders;
   // This space is important       ^
   int i, kids,src;

   if ( ! ndx.isValid() )
      return false;

   pInd = parent(ndx);
   if ( ! pInd.isValid() )
      return false;

   BtTreeItem* start = item(ndx);
   f.first  = targetPath;
   f.second = start;

   folders.append(f);

   while ( ! folders.isEmpty() )
   {
      // This looks weird, but it is needed for later
      f = folders.takeFirst();
      targetPath = f.first;
      BtTreeItem* target = f.second;

      // As we move things, childCount changes. This makes sure we loop
      // through all of the kids
      kids = target->childCount();
      src = 0;
      // Ok. We have a start and an index.
      for (i=0; i < kids; ++i)
      {
         // This looks weird and it is. As we move children out, the 0 items
         // changes to the next child. In the case of a folder, though, we
         // don't move it, so we need to get the item beyond that.
         BtTreeItem* next = target->child(src);
         // If a folder, push it onto the folders stack for latter processing
         if ( next->type() == BtTreeItem::FOLDER ) 
         {
            QPair<QString,BtTreeItem*> newTarget;
            newTarget.first = targetPath % "/" % next->name();
            newTarget.second = next;
            folders.append(newTarget);
            src++;
         }
         else // Leafnode
            next->thing()->setFolder(targetPath);
      }
   }
   // Last thing is to remove the victim. 
   i = start->childNumber();
   return removeRows(i, 1, pInd); 
}
Example #7
0
bool BtTreeModel::removeFolder(QModelIndex ndx)
{
   if ( ! ndx.isValid() )
      return false;

   int i = -1;
   QModelIndex pInd = parent(ndx);

   if ( ! pInd.isValid() )
      return false;

   BtTreeItem* start = item(ndx);

   // Remove the victim. 
   i = start->childNumber();
   return removeRows(i, 1, pInd); 
}
Example #8
0
bool BtTreeModel::renameFolder(BtFolder* victim, QString newName)
{
   QModelIndex ndx = findFolder(victim->fullPath(), 0, false);
   QModelIndex pInd; 
   QString targetPath = newName % "/" % victim->name();
   QPair<QString,BtTreeItem*> f;
   QList<QPair<QString, BtTreeItem*> > folders;
   // This space is important       ^
   int i;

   if ( ! ndx.isValid() )
      return false;

   pInd = parent(ndx);
   if ( ! pInd.isValid() )
      return false;

   BtTreeItem* start = item(ndx);
   f.first  = targetPath;
   f.second = start;

   folders.append(f);

   while ( ! folders.isEmpty() )
   {
      // This looks weird, but it is needed for later
      f = folders.takeFirst();
      targetPath = f.first;
      BtTreeItem* target = f.second;

      // Ok. We have a start and an index.
      for (i=0; i < target->childCount(); ++i)
      {
         BtTreeItem* next = target->child(i);
         // If a folder, push it onto the folders stack for latter processing
         if ( next->type() == BtTreeItem::FOLDER ) 
         {
            QPair<QString,BtTreeItem*> newTarget;
            newTarget.first = targetPath % "/" % next->name();
            newTarget.second = next;
            folders.append(newTarget);
         }
         else // Leafnode
            next->thing()->setFolder(targetPath);
      }
   }
   // Last thing is to remove the victim. 
   i = start->childNumber();
   return removeRows(i, 1, pInd); 
}
Example #9
0
void BtTreeModel::loadTreeModel()
{
   int i;

   QModelIndex ndxLocal;
   BtTreeItem* local = 0;
   QList<BeerXMLElement*> elems = elements();

   foreach( BeerXMLElement* elem, elems )
   {

      if (! elem->folder().isEmpty() )
      {
         ndxLocal = findFolder( elem->folder(), rootItem->child(0), true );
         // I cannot imagine this failing, but what the hell
         if ( ! ndxLocal.isValid() )
         {
            Brewtarget::logW("Invalid return from findFolder in loadTreeModel()");
            continue;
         }
         local = item(ndxLocal);
         i = local->childCount();
      }
      else
      {
         local = rootItem->child(0);
         i = local->childCount();
         ndxLocal = createIndex(i,0,local);
      }

      if ( ! insertRow(i,ndxLocal,elem,_type) )
      {
         Brewtarget::logW("Insert failed in loadTreeModel()");
         continue;
      }

      // If we have brewnotes, set them up here.
      if ( treeMask & RECIPEMASK )
         addBrewNoteSubTree(qobject_cast<Recipe*>(elem),i,local);
      
      observeElement(elem);
   }
}
Example #10
0
QModelIndex BtTreeModel::createFolderTree( QStringList dirs, BtTreeItem* parent, QString pPath)
{
   BtTreeItem* pItem = parent;

   // Start the loop. We are going to return ndx at the end, 
   // so we need to declare and initialize outside of the loop
   QModelIndex ndx = createIndex(pItem->childCount(),0,pItem);

   // Need to call this because we are adding different things with different
   // column counts. Just using the rowsAboutToBeAdded throws ugly errors and
   // then a sigsegv
   emit layoutAboutToBeChanged();
   foreach ( QString cur, dirs )
   {
      QString fPath;
      BtFolder* temp = new BtFolder();
      int i;

      // If the parent item is a folder, use its full path
      if ( pItem->type() == BtTreeItem::FOLDER )
         fPath = pItem->folder()->fullPath() % "/" % cur;
      else
         fPath = pPath % "/" % cur; // If it isn't we need the parent path

      fPath.replace(QRegExp("//"), "/");

      // Set the full path, which will set the name and the path
      temp->setfullPath(fPath);
      i = pItem->childCount();

      pItem->insertChildren(i, 1, BtTreeItem::FOLDER);
      pItem->child(i)->setData(BtTreeItem::FOLDER, temp);

      // Insert the item into the tree. If it fails, bug out
      //if ( ! insertRow(i, ndx, temp, BtTreeItem::FOLDER) )
      //{
      //   emit layoutChanged();
      //   return QModelIndex();
      //}

      // Set the parent item to point to the newly created tree
      pItem = pItem->child(i);

      // And this for the return
      ndx = createIndex(pItem->childCount(), 0, pItem);
   }
Example #11
0
// One find method for all things. This .. is nice
QModelIndex BtTreeModel::findElement(BeerXMLElement* thing, BtTreeItem* parent)
{
   BtTreeItem* pItem;
   QModelIndex pIndex;
   QList<BtTreeItem*> folders;

   int i;

   if ( parent == NULL )
      pItem = rootItem->child(0);
   else
      pItem = parent;

   if (! thing )
      return createIndex(0,0,pItem);

   folders.append(pItem);

   // Recursion. Wonderful.
   while ( ! folders.isEmpty() )
   {
      BtTreeItem* target = folders.takeFirst();
      for(i=0; i < target->childCount(); ++i)
      {
         // If we've found what we are looking for, return
         if ( target->child(i)->thing() == thing )
            return createIndex(i,0,target->child(i));

         // If we have a folder, or we are looking for a brewnote and have a
         // recipe in hand, push the child onto the stack
         if ( target->child(i)->type() == BtTreeItem::FOLDER ||
              (qobject_cast<BrewNote*>(thing) && target->child(i)->type() == BtTreeItem::RECIPE ) )
            folders.append(target->child(i));
      }
   }
   return QModelIndex();
}
Example #12
0
bool BtTreeModel::insertRow(int row, const QModelIndex &parent, QObject* victim, int victimType )
{
   if ( ! parent.isValid() )
      return false;

   BtTreeItem *pItem = item(parent);
   int type = pItem->type();

   bool success = true;

   beginInsertRows(parent,row,row);
   success = pItem->insertChildren(row,1,type);
   if ( victim && success ) 
   {
      type = victimType == -1 ? type : victimType;
      BtTreeItem* added = pItem->child(row);
      added->setData(type, victim);
   }
   endInsertRows();

   return success;
}