Exemplo n.º 1
0
/**
 * \brief Look up the column specified by path.
 *
 * Path can be either relative to the current context (e.g., simply the name of
 * a column in the
 * current table) or absolute (relative to the project root). For backwards
 * compatibility, also
 * "table/column" is supported, where "table" is searched for anywhere in the
 * project. This
 * shouldn't be used in new projects though, since it will be problematic once
 * we drop the
 * requirement of project-wide unique table names.
 *
 * Also, it's possible to escape /'s in the path using \\. Column and folder
 * names can already
 * contain slashes and table names will follow in a future release.
 */
Column *MuParserScript::resolveColumnPath(const QString &path) {
  Column *result = 0;

  // Split path into components.
  // While escape handling would be possible using a regular expression, it
  // would require
  // lookbehind assertions, which are currently not supported by QRegExp. Thus,
  // we can't simply
  // use QString::split() and have to explicitly loop over the characters in
  // path.
  QStringList pathComponents;
  QString current;
  for (int i = 0; i < path.size(); ++i) switch (path.at(i).toAscii()) {
      case '/':
        pathComponents << current;
        current.clear();
        break;
      case '\\':
        if (i + 1 < path.size()) current.append(path.at(++i));
        break;
      default:
        current.append(path.at(i));
        break;
    }
  QString columnName = current;

  Table *table = 0;
  if (pathComponents.isEmpty()) {
    // only column name specified, read from this table
    table = qobject_cast<Table *>(Context);
    if (!table)
      throw mu::Parser::exception_type(qPrintable(tr(
          "Accessing table values is not (yet) supported in this context.")));
  } else {
    // look up the table containing the column
    MyWidget *myContext = qobject_cast<MyWidget *>(Context);
    if (!myContext)
      throw mu::Parser::exception_type(qPrintable(tr(
          "Accessing table values is not (yet) supported in this context.")));
    QString tableName = pathComponents.takeLast();
    if (pathComponents.isEmpty())
      // needed for backwards compatibility, but will be problematic once we
      // drop the requirement
      // of project-wide unique object names
      table = myContext->folder()->rootFolder()->table(tableName, true);
    else {
      Folder *folder;
      if (pathComponents.at(0).isEmpty())
        // absolute path
        folder = myContext->folder()->rootFolder();
      else if (pathComponents.at(0) == "..")
        // relative path
        folder = myContext->folder();
      else
        // invalid path
        throw mu::Parser::exception_type(
            qPrintable(tr("Couldn't find a table named %1.")
                           .arg(pathComponents.join("/") + "/" + tableName)));
      pathComponents.removeFirst();
      foreach (QString f, pathComponents) {
        if (f == "..")
          folder = qobject_cast<Folder *>(folder->parent());
        else
          folder = folder->findSubfolder(f);
        if (!folder)
          throw mu::Parser::exception_type(
              qPrintable(tr("Couldn't find a table named %1.")
                             .arg(pathComponents.join("/") + "/" + tableName)));
      }
      table = folder->table(tableName);
    }
    if (!table)
      throw mu::Parser::exception_type(
          qPrintable(tr("Couldn't find a table named %1.")
                         .arg(pathComponents.join("/") + "/" + tableName)));
  }

  // finally, look up the column in the table
  result = table->d_future_table->column(columnName, false);
  if (!result)
    throw mu::Parser::exception_type(
        qPrintable(tr("There's no column named %1 in table %2!")
                       .arg(columnName)
                       .arg(table->d_future_table->path())));

  return result;
}