void CellMLAnnotationViewMetadataEditDetailsWidget::updateGui(iface::cellml_api::CellMLElement *pElement,
                                                              const bool &pUpdateItemsGui)
{
    // Keep track of the CellML element

    mElement = pElement;

    // Update the add term button, depending on whether the direct term is
    // already associated with the CellML element

    if (mTermIsDirect) {
        QStringList termInformation = mTerm.split("/");

        if (mQualifierIndex < CellMLSupport::CellMLFileRdfTriple::LastBioQualifier)
            mAddTermButton->setEnabled(!mCellMLFile->rdfTripleExists(mElement,
                                                                     CellMLSupport::CellMLFileRdfTriple::BioQualifier(mQualifierIndex+1),
                                                                     termInformation[0], termInformation[1]));
        else
            mAddTermButton->setEnabled(!mCellMLFile->rdfTripleExists(mElement,
                                                                     CellMLSupport::CellMLFileRdfTriple::ModelQualifier(mQualifierIndex-CellMLSupport::CellMLFileRdfTriple::LastBioQualifier+1),
                                                                     termInformation[0], termInformation[1]));
    } else {
        mAddTermButton->setEnabled(false);
    }

    // Update our items' GUI, if required

    if (pUpdateItemsGui)
        updateItemsGui(Items(), QString(), !mTermIsDirect);

    // Enable or disable the add buttons for our retrieved terms, depending on
    // whether they are already associated with the CellML element

    for (int row = 0; mGridLayout->itemAtPosition(++row, 0);) {
        QPushButton *addButton = qobject_cast<QPushButton *>(mGridLayout->itemAtPosition(row, 3)->widget());

        Item item = mItemsMapping.value(addButton);

        if (mQualifierIndex < CellMLSupport::CellMLFileRdfTriple::LastBioQualifier)
            addButton->setEnabled(!mCellMLFile->rdfTripleExists(mElement,
                                                                CellMLSupport::CellMLFileRdfTriple::BioQualifier(mQualifierIndex+1),
                                                                item.resource, item.id));
        else
            addButton->setEnabled(!mCellMLFile->rdfTripleExists(mElement,
                                                                CellMLSupport::CellMLFileRdfTriple::ModelQualifier(mQualifierIndex-CellMLSupport::CellMLFileRdfTriple::LastBioQualifier+1),
                                                                item.resource, item.id));
    }
}
void CellmlAnnotationViewMetadataEditDetailsWidget::updateGui(iface::cellml_api::CellMLElement *pElement,
                                                              const bool &pResetItemsGui)
{
    // Keep track of the CellML element

    mElement = pElement;

    // Enable/disable our add term button, depending on whether the direct term
    // is already associated with the CellML element

    bool fileReadableAndWritableAndNoIssues =     Core::FileManager::instance()->isReadableAndWritable(mCellmlFile->fileName())
                                              && !mCellmlFile->issues().count();
    bool termIsDirect = isDirectTerm(mTermValue->text());

    if (termIsDirect) {
        QStringList termInformation = mTermValue->text().split("/");

        if (mQualifierValue->currentIndex() < CellMLSupport::CellmlFileRdfTriple::LastBioQualifier)
            mAddTermButton->setEnabled(    fileReadableAndWritableAndNoIssues
                                       && !mCellmlFile->rdfTriple(mElement,
                                                                  CellMLSupport::CellmlFileRdfTriple::BioQualifier(mQualifierValue->currentIndex()+1),
                                                                  termInformation[0],
                                                                  termInformation[1]));
        else
            mAddTermButton->setEnabled(    fileReadableAndWritableAndNoIssues
                                       && !mCellmlFile->rdfTriple(mElement,
                                                                  CellMLSupport::CellmlFileRdfTriple::ModelQualifier(mQualifierValue->currentIndex()-CellMLSupport::CellmlFileRdfTriple::LastBioQualifier+1),
                                                                  termInformation[0],
                                                                  termInformation[1]));
    } else {
        mAddTermButton->setEnabled(false);
    }

    // Reset our items' GUI, if needed and if our busy widget is not already
    // visible
    // Note: the reason for checking whether our busy widget is visible is that
    //       we come here every time the user modifies the term to look up. So,
    //       we don't want to call updateItemsGui() for no reasons. Indeed, if
    //       we were then our busy widget would get 'reset' every time, which
    //       doesn't look nice...

    if (   (pResetItemsGui && !mParent->parent()->isBusyWidgetVisible())
        || termIsDirect) {
        updateItemsGui(CellmlAnnotationViewMetadataEditDetailsItems(),
                       !termIsDirect, QString());
    }

    // Enable or disable the add buttons for our retrieved terms, depending on
    // whether the file is un/locked and whether they are already associated
    // with the CellML element

    QWebElement documentElement = mOutputOntologicalTerms->page()->mainFrame()->documentElement();

    foreach (const QString &itemInformationSha1, mItemInformationSha1s) {
        CellmlAnnotationViewMetadataEditDetailsItem item = mItemsMapping.value(itemInformationSha1);
        bool enabledButton;

        if (mQualifierValue->currentIndex() < CellMLSupport::CellmlFileRdfTriple::LastBioQualifier)
            enabledButton =     fileReadableAndWritableAndNoIssues
                            && !mCellmlFile->rdfTriple(mElement,
                                                       CellMLSupport::CellmlFileRdfTriple::BioQualifier(mQualifierValue->currentIndex()+1),
                                                       item.resource(), item.id());
        else
            enabledButton =     fileReadableAndWritableAndNoIssues
                            && !mCellmlFile->rdfTriple(mElement,
                                                       CellMLSupport::CellmlFileRdfTriple::ModelQualifier(mQualifierValue->currentIndex()-CellMLSupport::CellmlFileRdfTriple::LastBioQualifier+1),
                                                       item.resource(), item.id());

        if (enabledButton != mEnabledItems.value(itemInformationSha1)) {
            mEnabledItems.insert(itemInformationSha1, enabledButton);

            documentElement.findFirst(QString("td[id=button_%1]").arg(itemInformationSha1)).setStyleProperty("display", enabledButton?"table-cell":"none");
            documentElement.findFirst(QString("td[id=disabledButton_%1]").arg(itemInformationSha1)).setStyleProperty("display", !enabledButton?"table-cell":"none");
        }
    }
void CellMLAnnotationViewMetadataEditDetailsWidget::updateGui(const Items &pItems,
                                                              const QString &pErrorMsg,
                                                              const bool &pLookupTerm,
                                                              const int &pItemsVerticalScrollBarPosition,
                                                              const bool &pRetranslate)
{
    // Note: we are using certain layouts to dislay the contents of our view,
    //       but this unfortunately results in some very bad flickering on OS X.
    //       This can, however, be addressed using a stacked widget, so...

    // Prevent ourselves from being updated (to avoid any flickering)

    setUpdatesEnabled(false);

    // Create a widget which will contain our GUI

    QWidget *newMainWidget = new QWidget(this);
    QVBoxLayout *newMainLayout = new QVBoxLayout(newMainWidget);

    newMainLayout->setMargin(0);

    newMainWidget->setLayout(newMainLayout);

    // Create a form widget which will contain our qualifier and term fields

    QWidget *newFormWidget = new QWidget(newMainWidget);
    QFormLayout *newFormLayout = new QFormLayout(newFormWidget);

    newFormWidget->setLayout(newFormLayout);

    // Add our qualifier field

    // Create a widget which will contain both our qualifier value widget and a
    // button to look up the qualifier

    QWidget *qualifierWidget = new QWidget(newFormWidget);

    QHBoxLayout *qualifierWidgetLayout = new QHBoxLayout(qualifierWidget);

    qualifierWidgetLayout->setMargin(0);

    qualifierWidget->setLayout(qualifierWidgetLayout);

    // Create our qualifier value widget

    mQualifierValue = new QComboBox(qualifierWidget);

    mQualifierValue->addItems(CellMLSupport::CellMLFileRdfTriple::qualifiersAsStringList());

    mQualifierValue->setCurrentIndex(mQualifierIndex);

    connect(mQualifierValue, SIGNAL(currentIndexChanged(int)),
            this, SLOT(qualifierChanged(const int &)));
    connect(mQualifierValue, SIGNAL(currentIndexChanged(const QString &)),
            this, SLOT(qualifierChanged(const QString &)));

    // Create our qualifier lookup button widget

    mLookupQualifierButton = new QPushButton(qualifierWidget);
    // Note #1: ideally, we could assign a QAction to our QPushButton, but this
    //          cannot be done, so... we assign a few properties by hand...
    // Note #2: to use a QToolButton would allow us to assign a QAction to it,
    //          but a QToolButton doesn't look quite the same as a QPushButton
    //          on some platforms, so...

    mLookupQualifierButton->setCheckable(true);
    mLookupQualifierButton->setChecked(mLookupQualifierButtonIsChecked);
    mLookupQualifierButton->setIcon(QIcon(":/oxygen/categories/applications-internet.png"));
    mLookupQualifierButton->setStatusTip(tr("Look up the qualifier"));
    mLookupQualifierButton->setToolTip(tr("Look Up"));
    mLookupQualifierButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    connect(mLookupQualifierButton, SIGNAL(clicked()),
            this, SLOT(lookupQualifier()));

    // Add our QComboBox and QPushButton to our cmeta:id widget

    qualifierWidgetLayout->addWidget(mQualifierValue);
    qualifierWidgetLayout->addWidget(mLookupQualifierButton);

    // Add our qualifier widget to our main layout

    newFormLayout->addRow(Core::newLabel(tr("Qualifier:"), 1.0, true, newFormWidget),
                          qualifierWidget);

    // Add our term field

    // Create a widget which will contain both our qualifier value widget and a
    // button to look up the qualifier

    QWidget *termWidget = new QWidget(newFormWidget);

    QHBoxLayout *termWidgetLayout = new QHBoxLayout(termWidget);

    termWidgetLayout->setMargin(0);

    termWidget->setLayout(termWidgetLayout);

    // Create our term value widget

    mTermValue = new QLineEdit(termWidget);

    mTermValue->setText(mTerm);
    // Note: we set the text to whatever term was previously being looked up and
    //       this before tracking changes to the term since we don't want to
    //       trigger a call to termChanged(). Indeed, we might come here as a
    //       result of a retranslation so we shouldn't look up for the term and,
    //       instead, we should call updateItemsGui() which we do at the end of
    //       this procedure...

    connect(mTermValue, SIGNAL(textChanged(const QString &)),
            this, SLOT(termChanged(const QString &)));

    // Create our add term button widget

    mAddTermButton = new QPushButton(termWidget);

    mAddTermButton->setEnabled(false);
    mAddTermButton->setIcon(QIcon(":/oxygen/actions/list-add.png"));
    mAddTermButton->setStatusTip(tr("Add the term"));
    mAddTermButton->setToolTip(tr("Add"));
    mAddTermButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    connect(mAddTermButton, SIGNAL(clicked()),
            this, SLOT(addTerm()));

    // Add our QComboBox and QPushButton to our cmeta:id widget

    termWidgetLayout->addWidget(mTermValue);
    termWidgetLayout->addWidget(mAddTermButton);

    // Add our term widget to our main layout

    newFormLayout->addRow(Core::newLabel(tr("Term:"), 1.0, true, newFormWidget),
                          termWidget);

    // Reset the tab order from our parent's CellML list's tree view widget
    // Note: ideally, we would take advantage of Qt's signal/slot approach with
    //       the signal being emitted here and the slot being implemented in
    //       mParent, but this wouldn't work here since updateGui() gets called
    //       as part of the creation of this metadata details widget, so...

    setTabOrder(qobject_cast<QWidget *>(mParent->cellmlList()->treeViewWidget()),
                mQualifierValue);
    setTabOrder(mQualifierValue, mLookupQualifierButton);
    setTabOrder(mLookupQualifierButton, mTermValue);
    setTabOrder(mTermValue, mAddTermButton);

    // Create a stacked widget (within a scroll area, so that only the items get
    // scrolled, not the whole metadata edit details widget) which will contain
    // a grid with the results of our terms lookup

    QScrollArea *newItemsScrollArea = new QScrollArea(newMainWidget);

    newItemsScrollArea->setFrameShape(QFrame::NoFrame);
    newItemsScrollArea->setWidgetResizable(true);

    // Add our 'internal' widgets to our new main widget

    newMainLayout->addWidget(newFormWidget);
    newMainLayout->addWidget(new Core::BorderedWidget(newItemsScrollArea,
                                                      true, false, false, false));

    // Keep track of the position of our items vertical scroll bar
    // Note: this is required to make sure that the position doesn't get reset
    //       as a result of retranslating the GUI...

    connect(newItemsScrollArea->verticalScrollBar(), SIGNAL(sliderMoved(int)),
            this, SLOT(trackItemsVerticalScrollBarPosition(const int &)));

    // Add our new widget to our stacked widget

    mWidget->addWidget(newMainWidget);

    // Remove the contents of our old form layout

    if (mFormWidget)
        for (int i = 0, iMax = mFormLayout->count(); i < iMax; ++i) {
            QLayoutItem *item = mFormLayout->takeAt(0);

            delete item->widget();
            delete item;
        }

    // Reset the widget of our old items scroll area and stop tracking the
    // position of its vertical scroll bar
    // Note: the resetting this will automatically delete our old grid widget...

    if (mItemsScrollArea) {
        mItemsScrollArea->setWidget(0);

        disconnect(mItemsScrollArea->verticalScrollBar(), SIGNAL(sliderMoved(int)),
                   this, SLOT(trackItemsVerticalScrollBarPosition(const int &)));
    }

    // Get rid of our old main widget and layout (and its contents)

    if (mMainWidget) {
        mWidget->removeWidget(mMainWidget);

        for (int i = 0, iMax = mMainLayout->count(); i < iMax; ++i) {
            QLayoutItem *item = mMainLayout->takeAt(0);

            delete item->widget();
            delete item;
        }

        delete mMainWidget;
    }

    // Keep track of our new main widgets and layouts

    mMainWidget = newMainWidget;
    mMainLayout = newMainLayout;

    mFormWidget = newFormWidget;
    mFormLayout = newFormLayout;

    mItemsScrollArea = newItemsScrollArea;

    mGridWidget = 0;   // Note: this will be set by our
    mGridLayout = 0;   //       other updateGui() function...

    // Allow ourselves to be updated again

    setUpdatesEnabled(true);

    // Update our items GUI

    updateItemsGui(pItems, pErrorMsg, pLookupTerm);

    // Request for something to be looked up, if needed

    if (mLookupInformation)
        // Look up an 'old' qualifier, resource or resource id

        genericLookup(mInformation, mType, pRetranslate);

    // Set the position of our vertical scroll bar

    mItemsScrollArea->verticalScrollBar()->setValue(pItemsVerticalScrollBarPosition);
}