qtResourceItem.cxx 4.83 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "smtk/extension/qt/qtResourceItem.h"
#include "smtk/extension/qt/qtReferenceItemData.h"

#include "smtk/common/Paths.h"

#include "smtk/extension/qt/qtBaseView.h"
#include "smtk/extension/qt/qtUIManager.h"

#include "smtk/view/ResourcePhraseModel.h"
#include "smtk/view/SubphraseGenerator.h"
#include "smtk/view/VisibilityContent.h"

#include "smtk/attribute/ResourceItem.h"
#include "smtk/attribute/ResourceItemDefinition.h"

#include "smtk/model/Resource.h"

namespace smtk
{
namespace extension
{

qtItem* qtResourceItem::createItemWidget(const AttributeItemInfo& info)
{
  // So we support this type of item?
  if (info.itemAs<smtk::attribute::ResourceItem>() == nullptr)
  {
    return nullptr;
  }
39 40 41 42 43 44 45 46
  auto qi = new qtResourceItem(info);
  // Unlike other classes, qtResourceItem does not call createWidget()
  // in its constructor since the base class, qtReferenceItem, is
  // concrete and cannot call virtual methods of subclases. So, for
  // qtReferenceItem and its subclasses, we create the widget after
  // constructing the item.
  qi->createWidget();
  return qi;
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
}

qtResourceItem::qtResourceItem(const AttributeItemInfo& info)
  : qtReferenceItem(info)
{
}

qtResourceItem::~qtResourceItem()
{
}

smtk::view::PhraseModelPtr qtResourceItem::createPhraseModel() const
{
  // Constructing the PhraseModel with a View properly initializes the SubphraseGenerator
  // to point back to the model (thus ensuring subphrases are decorated). This is required
  // since we need to decorate phrases to show+edit "visibility" as set membership:
  auto view = smtk::view::View::New("ResourceItem", "stuff");
  auto phraseModel = smtk::view::ResourcePhraseModel::create(view);
  phraseModel->root()->findDelegate()->setModel(phraseModel);
  auto def = std::dynamic_pointer_cast<const smtk::attribute::ResourceItemDefinition>(
    m_itemInfo.item()->definition());
  std::static_pointer_cast<smtk::view::ResourcePhraseModel>(phraseModel)
    ->setResourceFilters(def->acceptableEntries());

  return phraseModel;
}

std::string qtResourceItem::synopsis(bool& ok) const
{
  auto item = m_itemInfo.itemAs<smtk::attribute::ResourceItem>();
  if (!item)
  {
    ok = false;
    return "uninitialized item";
  }

  if (m_p->m_members.size())
  {
    auto foo = m_p->m_members.begin()->first;
  }
  std::size_t numRequired = item->numberOfRequiredValues();
  std::size_t maxAllowed = (item->isExtensible() ? item->maxNumberOfValues() : numRequired);
  std::ostringstream label;
  std::size_t numSel = 0;
  for (auto entry : m_p->m_members)
  {
    if (entry.second > 0)
    {
      ++numSel;
    }
  }
  ok = true;
  if (numRequired < 2 && maxAllowed == 1)
  {
    auto resource = (m_p->m_members.empty()
        ? smtk::resource::ResourcePtr()
        : std::static_pointer_cast<smtk::resource::Resource>(m_p->m_members.begin()->first));

    if (resource != nullptr)
    {
      // TODO: this routine was lifted from ResourcePhraseContent. It should not
      // be duplicated here.
      std::string locn = resource->location();
      std::string file = smtk::common::Paths::filename(locn);
      std::string dir = smtk::common::Paths::directory(locn);
112 113 114 115
      if (dir.size() > 31)
      {
        dir = dir.substr(0, 14) + "..." + dir.substr(dir.size() - 14, 14);
      }
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
      std::string name = dir.empty() ? "New Resource" : (file + " (" + dir + ")");
      label << (numSel == 1 ? (resource ? name : "NULL!!") : (numSel > 0 ? "too many" : "(none)"));
    }
    else
    {
      label << (numSel == 1 ? "(none)" : (numSel > 0 ? "too many" : "(none)"));
    }
    ok = numSel >= numRequired && numSel <= maxAllowed;
  }
  else
  {
    label << numSel;
    if (numRequired > 0)
    {
      label << " of ";
      if (numRequired == maxAllowed)
      { // Exactly N values are allowed and required.
        label << numRequired;
      }
      else if (maxAllowed > 0)
      { // There is a minimum required, but a limited additional number are acceptable
        label << numRequired << "—" << maxAllowed;
      }
      else
      { // Any number are allowed, but there is a minimum.
        label << numRequired << "+";
      }
      ok &= (numSel >= numRequired);
    }
    else
    { // no values are required, but there may be a cap on the maximum number.
      if (maxAllowed > 0)
      {
        label << " of 0–" << maxAllowed;
      }
      else
      {
        label << " chosen";
      }
    }
  }
  ok &= (maxAllowed == 0 || numSel <= maxAllowed);
  return label.str();
}
}
}