void UAVObjectUtilManager::saveNextObject()
{
    if (queue.isEmpty()) {
        return;
    }

    Q_ASSERT(saveState == IDLE);

    // Get next object from the queue
    UAVObject *obj = queue.head();
    qDebug() << "Send save object request to board " << obj->getName();

    ObjectPersistence *objper = dynamic_cast<ObjectPersistence *>(getObjectManager()->getObject(ObjectPersistence::NAME));
    connect(objper, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject *, bool)));
    connect(objper, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(objectPersistenceUpdated(UAVObject *)));
    saveState = AWAITING_ACK;
    if (obj != NULL) {
        ObjectPersistence::DataFields data;
        data.Operation  = ObjectPersistence::OPERATION_SAVE;
        data.Selection  = ObjectPersistence::SELECTION_SINGLEOBJECT;
        data.ObjectID   = obj->getObjID();
        data.InstanceID = obj->getInstID();
        objper->setData(data);
        objper->updated();
    }
    // Now: we are going to get two "objectUpdated" messages (one coming from GCS, one coming from Flight, which
    // will confirm the object was properly received by both sides) and then one "transactionCompleted" indicating
    // that the Flight side did not only receive the object but it did receive it without error. Last we will get
    // a last "objectUpdated" message coming from flight side, where we'll get the results of the objectPersistence
    // operation we asked for (saved, other).
}
void UAVObjectBrowserWidget::onTreeItemExpanded(QModelIndex currentProxyIndex)
{
    QModelIndex currentIndex = proxyModel->mapToSource(currentProxyIndex);
    TreeItem *item = static_cast<TreeItem*>(currentIndex.internalPointer());
    TopTreeItem *top = dynamic_cast<TopTreeItem*>(item->parent());

    //Check if current tree index is the child of the top tree item
    if (top)
    {
        ObjectTreeItem *objItem = dynamic_cast<ObjectTreeItem*>(item);
        //If the cast succeeds, then this is a UAVO
        if (objItem)
        {
            UAVObject *obj = objItem->object();
            // Check for multiple instance UAVO
            if(!obj){
                objItem = dynamic_cast<ObjectTreeItem*>(item->getChild(0));
                obj = objItem->object();
            }
            Q_ASSERT(obj);
            UAVObject::Metadata mdata = obj->getMetadata();

            // Determine fastest update
            quint16 tmpUpdatePeriod = MAXIMUM_UPDATE_PERIOD;
            int accessType = UAVObject::GetGcsTelemetryUpdateMode(mdata);
            if (accessType != UAVObject::UPDATEMODE_MANUAL){
                switch(accessType){
                case UAVObject::UPDATEMODE_ONCHANGE:
                    tmpUpdatePeriod = 0;
                    break;
                case UAVObject::UPDATEMODE_PERIODIC:
                case UAVObject::UPDATEMODE_THROTTLED:
                    tmpUpdatePeriod = std::min(mdata.gcsTelemetryUpdatePeriod, tmpUpdatePeriod);
                    break;
                }
            }

            accessType = UAVObject::GetFlightTelemetryUpdateMode(mdata);
            if (accessType != UAVObject::UPDATEMODE_MANUAL){
                switch(accessType){
                case UAVObject::UPDATEMODE_ONCHANGE:
                    tmpUpdatePeriod = 0;
                    break;
                case UAVObject::UPDATEMODE_PERIODIC:
                case UAVObject::UPDATEMODE_THROTTLED:
                    tmpUpdatePeriod = std::min(mdata.flightTelemetryUpdatePeriod, tmpUpdatePeriod);
                    break;
                }
            }

            expandedUavoItems.insert(obj->getName(), tmpUpdatePeriod);

            if (tmpUpdatePeriod < updatePeriod){
                updatePeriod = tmpUpdatePeriod;
                treeView->updateTimerPeriod(updatePeriod);
            }
        }
    }
}
void UAVObjectBrowserWidget::onTreeItemCollapsed(QModelIndex currentProxyIndex)
{
    QModelIndex currentIndex = proxyModel->mapToSource(currentProxyIndex);
    TreeItem *item = static_cast<TreeItem*>(currentIndex.internalPointer());
    TopTreeItem *top = dynamic_cast<TopTreeItem*>(item->parent());

    //Check if current tree index is the child of the top tree item
    if (top)
    {
        ObjectTreeItem *objItem = dynamic_cast<ObjectTreeItem*>(item);
        //If the cast succeeds, then this is a UAVO
        if (objItem)
        {
            UAVObject *obj = objItem->object();

            // Check for multiple instance UAVO
            if(!obj){
                objItem = dynamic_cast<ObjectTreeItem*>(item->getChild(0));
                obj = objItem->object();
            }
            Q_ASSERT(obj);

            //Remove the UAVO, getting its stored value first.
            quint16 tmpUpdatePeriod = expandedUavoItems.value(obj->getName());
            expandedUavoItems.take(obj->getName());

            // Check if this was the fastest UAVO
            if (tmpUpdatePeriod == updatePeriod){
                // If so, search for the new fastest UAVO
                updatePeriod = MAXIMUM_UPDATE_PERIOD;
                foreach(tmpUpdatePeriod, expandedUavoItems)
                {
                    if (tmpUpdatePeriod < updatePeriod)
                        updatePeriod = tmpUpdatePeriod;
                }
                treeView->updateTimerPeriod(updatePeriod);
            }


        }
    }
/**
 * @brief UAVObjectUtilManager::saveNextObject
 *
 * Processes the save queue.
 */
void UAVObjectUtilManager::saveNextObject()
{
    if ( queue.isEmpty() ) {
        return;
    }

    Q_ASSERT(saveState == IDLE);

    // Get next object from the queue (don't dequeue yet)
    UAVObject* obj = queue.head();
    Q_ASSERT(obj);
    qDebug() << "Send save object request to board " << obj->getName();

    ObjectPersistence * objectPersistence = ObjectPersistence::GetInstance(getObjectManager());
    Q_ASSERT(objectPersistence);

    // "transactionCompleted" is emitted once the objectPersistence object is sent over the telemetry link.
    // Since its metadata state that it should be ACK'ed on flight telemetry, the transactionCompleted signal
    // will be triggered once the GCS telemetry manager receives an ACK from the flight controller, or times
    // out. the success value will reflect success or failure.
    connect(objectPersistence, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject*,bool)));
    // After we update the objectPersistence UAVO, we need to listen to its "objectUpdated" event, which will occur
    // once the flight controller sends this object back to the GCS, with the "Operation" field set to "Completed"
    // or "Error".
    connect(objectPersistence, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectPersistenceUpdated(UAVObject *)));
    saveState = AWAITING_ACK;
    qDebug() << "[saveObjectToFlash] Moving on to AWAITING_ACK";

    ObjectPersistence::DataFields data;
    data.Operation = ObjectPersistence::OPERATION_SAVE;
    data.Selection = ObjectPersistence::SELECTION_SINGLEOBJECT;
    data.ObjectID = obj->getObjID();
    data.InstanceID = obj->getInstID();
    objectPersistence->setData(data);
    objectPersistence->updated();
    // Now: we are going to get the following:
    // - two "objectUpdated" messages (one coming from GCS, one coming from Flight, which will confirm the object
    //   was properly received by both sides). This is because the metadata of objectPersistence has "FlightUpdateOnChange"
    //   set to true.
    //  - then one "transactionCompleted" indicating that the Flight side did not only receive the object but it did
    //    receive it without error (that message will be triggered by reception of the ACK).
    //  - Last we will get one last "objectUpdated" message coming from flight side, where we'll get the results of
    //    the objectPersistence operation we asked for (saved, other).
}
    foreach (QString objStr, strList) {
        // Add defaults
        UAVObject *obj = objManager->getObject(objStr);
        Q_ASSERT(obj);
        UAVObject::Metadata mdataDefault = obj->getDefaultMetadata();
        QModelIndex index = schedulerModel->index(rowIndex,0, QModelIndex());
        schedulerModel->setData(index, QString("%1ms").arg(mdataDefault.flightTelemetryUpdatePeriod));

        // Save default metadata for later use
        defaultMdata.insert(obj->getName().append("Meta"), mdataDefault);

        // Connect live values to the "Current" column
        UAVDataObject *dobj = dynamic_cast<UAVDataObject*>(obj);
        Q_ASSERT(dobj);
        UAVMetaObject *mobj = dobj->getMetaObject();
        connect(mobj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateCurrentColumn(UAVObject*)));

        // Updates the "Current" column with the live value
        updateCurrentColumn(mobj);
        rowIndex++;
    }