当前位置: 首页>>代码示例>>C++>>正文


C++ dt_util_dstrcat函数代码示例

本文整理汇总了C++中dt_util_dstrcat函数的典型用法代码示例。如果您正苦于以下问题:C++ dt_util_dstrcat函数的具体用法?C++ dt_util_dstrcat怎么用?C++ dt_util_dstrcat使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。


在下文中一共展示了dt_util_dstrcat函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: dt_selection_deselect

void dt_selection_deselect(dt_selection_t *selection, uint32_t imgid)
{
  gchar *query = NULL;
  selection->last_single_id = -1;

  if(imgid != -1)
  {
    const dt_image_t *image = dt_image_cache_get(darktable.image_cache, imgid, 'r');
    if(image)
    {
      int img_group_id = image->group_id;
      dt_image_cache_read_release(darktable.image_cache, image);

      if(!darktable.gui || !darktable.gui->grouping || darktable.gui->expanded_group_id == img_group_id)
      {
        query = dt_util_dstrcat(query, "DELETE FROM main.selected_images WHERE imgid = %d", imgid);
      }
      else
      {
        query = dt_util_dstrcat(query, "DELETE FROM main.selected_images WHERE imgid IN "
                                       "(SELECT id FROM main.images WHERE group_id = %d)",
                                img_group_id);
      }

      DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), query, NULL, NULL, NULL);
      g_free(query);
    }
  }

  /* update hint message */
  dt_collection_hint_message(darktable.collection);
}
开发者ID:VolkerChristian,项目名称:darktable,代码行数:32,代码来源:selection.c

示例2: dt_selection_invert

void dt_selection_invert(dt_selection_t *selection)
{
  gchar *fullq = NULL;

  if (!selection->collection)
    return;

  fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images ");
  fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection));

  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "insert into memory.tmp_selection select imgid from selected_images",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "delete from selected_images",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), fullq,
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "delete from selected_images where imgid in (select imgid from memory.tmp_selection)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "delete from memory.tmp_selection",
                        NULL, NULL, NULL);

  g_free(fullq);

  /* update hint message */
  dt_collection_hint_message(darktable.collection);
}
开发者ID:AntonSh,项目名称:darktable,代码行数:30,代码来源:selection.c

示例3: dt_selection_invert

void dt_selection_invert(dt_selection_t *selection)
{
  gchar *fullq = NULL;

  if(!selection->collection) return;

  fullq = dt_util_dstrcat(fullq, "%s", "INSERT OR IGNORE INTO main.selected_images ");
  fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection));

  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "INSERT INTO memory.tmp_selection SELECT imgid FROM main.selected_images", NULL, NULL,
                        NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM main.selected_images", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), fullq, NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "DELETE FROM main.selected_images WHERE imgid IN (SELECT imgid FROM memory.tmp_selection)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM memory.tmp_selection", NULL, NULL, NULL);

  g_free(fullq);

  dt_control_signal_raise(darktable.signals, DT_SIGNAL_SELECTION_CHANGED);

  /* update hint message */
  dt_collection_hint_message(darktable.collection);
}
开发者ID:AlicVB,项目名称:darktable,代码行数:26,代码来源:selection.c

示例4: dt_selection_select_list

void dt_selection_select_list(struct dt_selection_t *selection, GList *list)
{
  if(!list) return;
  while(list)
  {
    int count = 1;
    gchar *query = NULL;

    int imgid = GPOINTER_TO_INT(list->data);
    selection->last_single_id = imgid;
    query = dt_util_dstrcat(query, "INSERT OR IGNORE INTO main.selected_images VALUES (%d)", imgid);
    list = g_list_next(list);
    while(list && count < 400)
    {
      imgid = GPOINTER_TO_INT(list->data);
      count++;
      selection->last_single_id = imgid;
      query = dt_util_dstrcat(query, ",(%d)", imgid);
      list = g_list_next(list);
    }
    char *result = NULL;

    sqlite3_exec(dt_database_get(darktable.db), query, NULL, NULL, &result);

    g_free(query);
  }

  /* update hint message */
  dt_collection_hint_message(darktable.collection);
}
开发者ID:VolkerChristian,项目名称:darktable,代码行数:30,代码来源:selection.c

示例5: dt_selection_select

void dt_selection_select(dt_selection_t *selection, uint32_t imgid)
{
  gchar *query = NULL;

  if(imgid != -1)
  {
    const dt_image_t *image = dt_image_cache_get(darktable.image_cache, imgid, 'r');
    if(image)
    {
      int img_group_id = image->group_id;
      dt_image_cache_read_release(darktable.image_cache, image);

      if(!darktable.gui || !darktable.gui->grouping || darktable.gui->expanded_group_id == img_group_id || !selection->collection)
      {
        query = dt_util_dstrcat(query, "INSERT OR IGNORE INTO main.selected_images VALUES (%d)", imgid);
      }
      else
      {
        query = dt_util_dstrcat(query, "INSERT OR IGNORE INTO main.selected_images SELECT id FROM main.images "
                                       "WHERE group_id = %d AND id IN (%s)",
                                img_group_id, dt_collection_get_query_no_group(selection->collection));
      }

      DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), query, NULL, NULL, NULL);
      g_free(query);
    }
  }

  /* update hint message */
  dt_collection_hint_message(darktable.collection);
}
开发者ID:VolkerChristian,项目名称:darktable,代码行数:31,代码来源:selection.c

示例6: _lib_filmstrip_imgid_in_collection

static gboolean _lib_filmstrip_imgid_in_collection(const dt_collection_t *collection, const int imgid)
{
  sqlite3_stmt *stmt = NULL;
  uint32_t count=1;
  const gchar *query = dt_collection_get_query(collection);
  gchar *count_query = NULL;

  //gchar *fq = g_strstr_len(query, strlen(query), "from");
  gchar *fw = g_strstr_len(query, strlen(query), "where") + 6;

  gchar *qq = NULL;
  qq = dt_util_dstrcat(qq, "id=?3 and %s", fw);

  if ((collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT))
    count_query = dt_util_dstrcat(NULL, "select count(images.id) from images %s and id=?3", collection->where_ext);
  else
    count_query = dt_util_dstrcat(count_query, "select count(id) from images where %s", qq);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), count_query, -1, &stmt, NULL);
  if ((collection->params.query_flags&COLLECTION_QUERY_USE_LIMIT) &&
      !(collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT))
  {
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1);
  }
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid);

  if(sqlite3_step(stmt) == SQLITE_ROW)
    count = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);
  g_free(count_query);
  return count;
}
开发者ID:danielbaak,项目名称:darktable,代码行数:33,代码来源:filmstrip.c

示例7: _dt_collection_compute_count

static uint32_t _dt_collection_compute_count(const dt_collection_t *collection)
{
  sqlite3_stmt *stmt = NULL;
  uint32_t count=1;
  const gchar *query = dt_collection_get_query(collection);
  gchar *count_query = NULL;

  gchar *fq = g_strstr_len(query, strlen(query), "from");
  if ((collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT))
    count_query = dt_util_dstrcat(NULL, "select count(images.id) from images %s", collection->where_ext);
  else
    count_query = dt_util_dstrcat(count_query, "select count(id) %s", fq);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), count_query, -1, &stmt, NULL);
  if ((collection->params.query_flags&COLLECTION_QUERY_USE_LIMIT) &&
      !(collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT))
  {
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1);
  }

  if(sqlite3_step(stmt) == SQLITE_ROW)
    count = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);
  g_free(count_query);
  return count;
}
开发者ID:joergbeyer,项目名称:darktable,代码行数:27,代码来源:collection.c

示例8: dt_selection_select_unaltered

void dt_selection_select_unaltered(dt_selection_t *selection)
{
  char *fullq = NULL;

  if (!selection->collection)
    return;

  /* set unaltered collection filter and update query */
  uint32_t old_filter_flags = dt_collection_get_filter_flags(selection->collection);
  dt_collection_set_filter_flags (selection->collection,
                                  (dt_collection_get_filter_flags(selection->collection) |
                                   COLLECTION_FILTER_UNALTERED));
  dt_collection_update(selection->collection);


  fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images ");
  fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection));


  /* clean current selection and select unaltered images */
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        "delete from selected_images", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
                        fullq, NULL, NULL, NULL);

  /* restore collection filter and update query */
  dt_collection_set_filter_flags(selection->collection, old_filter_flags);
  dt_collection_update(selection->collection);

  g_free(fullq);

  selection->last_single_id = -1;
}
开发者ID:AntonSh,项目名称:darktable,代码行数:33,代码来源:selection.c

示例9: dt_selection_toggle

void dt_selection_toggle(dt_selection_t *selection, uint32_t imgid)
{
  gchar *query = NULL;
  sqlite3_stmt *stmt;
  gboolean exists = FALSE;

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select imgid from selected_images where imgid=?1",-1,&stmt,NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);

  if(sqlite3_step(stmt) == SQLITE_ROW)
    exists = TRUE;

  sqlite3_finalize(stmt);

  if (exists)
  {
    selection->last_single_id = -1;
    query = dt_util_dstrcat(query,"delete from selected_images where imgid = %d", imgid);
  }
  else
  {
    selection->last_single_id = imgid;
    query = dt_util_dstrcat(query,"insert or ignore into selected_images values(%d)", imgid);
  }

  sqlite3_exec(dt_database_get(darktable.db), query, NULL, NULL, NULL);

  g_free(query);

  /* update hint message */
  dt_collection_hint_message(darktable.collection);
}
开发者ID:AntonSh,项目名称:darktable,代码行数:33,代码来源:selection.c

示例10: dt_selection_select_range

void dt_selection_select_range(dt_selection_t *selection, uint32_t imgid)
{
  gchar *fullq = NULL;
  sqlite3_stmt *stmt;
  if (!selection->collection || selection->last_single_id == -1)
    return;

  /* get start and end rows for range selection */
  int rc=0;
  uint32_t sr=-1,er=-1;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              dt_collection_get_query(selection->collection), -1, &stmt, NULL);

  while(sqlite3_step(stmt)==SQLITE_ROW)
  {
    int id = sqlite3_column_int(stmt, 0);
    if (id == selection->last_single_id)
      sr = rc;

    if (id == imgid)
      er = rc;

    if (sr != -1 && er != -1 )
      break;

    rc++;
  }

  sqlite3_finalize(stmt);

  /* selece the images in range from start to end */
  uint32_t old_flags = dt_collection_get_query_flags(selection->collection);

  /* use the limit to select range of images */
  dt_collection_set_query_flags(selection->collection,
                                (old_flags |COLLECTION_QUERY_USE_LIMIT));

  dt_collection_update(selection->collection);

  fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images ");
  fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection));

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              fullq, -1, &stmt, NULL);

  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, MIN(sr,er));
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, (MAX(sr,er)-MIN(sr,er))+1);

  sqlite3_step(stmt);

  /* reset filter */
  dt_collection_set_query_flags(selection->collection,
                                old_flags);
  dt_collection_update(selection->collection);
  selection->last_single_id = -1;
}
开发者ID:AntonSh,项目名称:darktable,代码行数:56,代码来源:selection.c

示例11: dt_selection_select_range

void dt_selection_select_range(dt_selection_t *selection, uint32_t imgid)
{
  gchar *fullq = NULL;

  if(!selection->collection || selection->last_single_id == -1) return;

  /* get start and end rows for range selection */
  sqlite3_stmt *stmt;
  int rc = 0;
  uint32_t sr = -1, er = -1;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), dt_collection_get_query_no_group(selection->collection),
                              -1, &stmt, NULL);

  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    const int id = sqlite3_column_int(stmt, 0);
    if(id == selection->last_single_id) sr = rc;

    if(id == imgid) er = rc;

    if(sr != -1 && er != -1) break;

    rc++;
  }

  sqlite3_finalize(stmt);

  /* select the images in range from start to end */
  const uint32_t old_flags = dt_collection_get_query_flags(selection->collection);

  /* use the limit to select range of images */
  dt_collection_set_query_flags(selection->collection, (old_flags | COLLECTION_QUERY_USE_LIMIT));

  dt_collection_update(selection->collection);

  fullq = dt_util_dstrcat(fullq, "%s", "INSERT OR IGNORE INTO main.selected_images ");
  fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query_no_group(selection->collection));

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), fullq, -1, &stmt, NULL);

  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, MIN(sr, er));
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, (MAX(sr, er) - MIN(sr, er)) + 1);

  sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  /* reset filter */
  dt_collection_set_query_flags(selection->collection, old_flags);
  dt_collection_update(selection->collection);

  // The logic above doesn't handle groups, so explicitly select the beginning and end to make sure those are selected properly
  dt_selection_select(selection, selection->last_single_id);
  dt_selection_select(selection, imgid);

  g_free(fullq);
}
开发者ID:AlicVB,项目名称:darktable,代码行数:56,代码来源:selection.c

示例12: dt_collection_get_sort_query

gchar *
dt_collection_get_sort_query(const dt_collection_t *collection)
{
  gchar *sq = NULL;

  switch(collection->params.sort)
  {
    case DT_COLLECTION_SORT_DATETIME:
      sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "datetime_taken");
      break;

    case DT_COLLECTION_SORT_RATING:
      sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "flags & 7 desc");
      break;

    case DT_COLLECTION_SORT_FILENAME:
      sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "filename");
      break;

    case DT_COLLECTION_SORT_ID:
      sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "id");
      break;

    case DT_COLLECTION_SORT_COLOR:
      sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "color desc, filename");
      break;
  }

  if (collection->params.descending)
  {
    switch(collection->params.sort)
    {
      case DT_COLLECTION_SORT_DATETIME:
      case DT_COLLECTION_SORT_FILENAME:
      case DT_COLLECTION_SORT_ID:
      {
        sq = dt_util_dstrcat(sq, " %s", "desc");
      }
      break;

      /* These two are special as they are descending in the default view */
      case DT_COLLECTION_SORT_RATING:
      {
        g_free(sq);
        sq = NULL;
        sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "flags & 7");
      }
      break;

      case DT_COLLECTION_SORT_COLOR:
      {
        g_free(sq);
        sq = NULL;
        sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "color, filename");
      }
      break;
    }
  }
  return sq;
}
开发者ID:EvilBit,项目名称:darktable,代码行数:60,代码来源:collection.c

示例13: collection_numindex

static int collection_numindex(lua_State *L)
{
  int index = luaL_checkinteger(L, -1);
  if(index < 1)
  {
    return luaL_error(L, "incorrect index in database");
  }

  gchar *query = NULL;
  gchar *sq = NULL;

  /* get collection order */
  if((darktable.collection->params.query_flags & COLLECTION_QUERY_USE_SORT))
    sq = dt_collection_get_sort_query(darktable.collection);


  sqlite3_stmt *stmt = NULL;

  /* build the query string */
  query = dt_util_dstrcat(query, "select distinct id from images ");

  if(darktable.collection->params.sort == DT_COLLECTION_SORT_COLOR
     && (darktable.collection->params.query_flags & COLLECTION_QUERY_USE_SORT))
    query = dt_util_dstrcat(query, "as a left outer join color_labels as b on a.id = b.imgid ");

  query = dt_util_dstrcat(query, "%s limit -1 offset ?1", sq);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, index -1);

  if(sqlite3_step(stmt) == SQLITE_ROW)
  {
    int imgid = sqlite3_column_int(stmt, 0);
    luaA_push(L, dt_lua_image_t, &imgid);
    sqlite3_finalize(stmt);
  }
  else
  {
    g_free(sq);
    g_free(query);
    sqlite3_finalize(stmt);
    return luaL_error(L, "incorrect index in database");
  }
  g_free(sq);
  g_free(query);
  return 1;

}
开发者ID:AdamMajer,项目名称:darktable,代码行数:48,代码来源:database.c

示例14: dt_util_dstrcat

/**
 * @see https://developers.google.com/photos/library/guides/create-albums
 * @return the id of the newly reacted
 */
static const gchar *gphoto_create_album(dt_storage_gphoto_gui_data_t *ui, dt_gphoto_context_t *ctx, gchar *name)
{
  struct curl_slist *headers = NULL;

  gchar *jbody = dt_util_dstrcat(NULL, "{ \"album\": { \"title\": \"%s\"} }", name);

  headers = curl_slist_append(headers, "Content-type: application/json");

  JsonObject *response = gphoto_query_post(ctx, GOOGLE_GPHOTO "v1/albums", headers, NULL, jbody, strlen(jbody));

  // add new album into the list
  dt_gphoto_album_t *album = _json_new_album(response);
  GtkListStore *model_album = GTK_LIST_STORE(gtk_combo_box_get_model(ui->combo_album));

  if(album)
  {
    ui_refresh_albums_fill(album, model_album);
    gtk_combo_box_set_active(ui->combo_album, ui->albums_count);
    ui->albums_count++;
    ui_reset_albums_creation(ui);
  }

  g_free(jbody);

  return album?album->id:NULL;
}
开发者ID:TurboGit,项目名称:darktable,代码行数:30,代码来源:googlephoto.c

示例15: memory

/* splits an input string into a date-time part and an optional operator part.
   operator can be any of "=", "<", ">", "<=", ">=" and "<>".
   range notation [x;y] can also be used
   datetime values should follow the pattern YYYY:mm:dd HH:MM:SS
   but only year part is mandatory

   datetime and operator are returned as pointers to null terminated strings in g_mallocated
   memory (to be g_free'd after use) - or NULL if no match is found.
*/
void dt_collection_split_operator_datetime(const gchar *input, char **number1, char **number2, char **operator)
{
  GRegex *regex;
  GMatchInfo *match_info;
  int match_count;

  *number1 = *number2 = *operator= NULL;

  // we test the range expression first
  // 2 elements : date-time1 and  date-time2
  regex = g_regex_new("^\\s*\\[\\s*(\\d{4}[:\\d\\s]*)\\s*;\\s*(\\d{4}[:\\d\\s]*)\\s*\\]\\s*$", 0, 0, NULL);
  g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
  match_count = g_match_info_get_match_count(match_info);

  if(match_count == 3)
  {
    gchar *txt = g_match_info_fetch(match_info, 1);
    gchar *txt2 = g_match_info_fetch(match_info, 2);

    *number1 = _dt_collection_compute_datetime(">=", txt);
    *number2 = _dt_collection_compute_datetime("<=", txt2);
    *operator= g_strdup("[]");

    g_free(txt);
    g_free(txt2);
    g_match_info_free(match_info);
    g_regex_unref(regex);
    return;
  }

  g_match_info_free(match_info);
  g_regex_unref(regex);

  // and we test the classic comparaison operators
  // 2 elements : operator and date-time
  regex = g_regex_new("^\\s*(=|<|>|<=|>=|<>)?\\s*(\\d{4}[:\\d\\s]*)?\\s*%?\\s*$", 0, 0, NULL);
  g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
  match_count = g_match_info_get_match_count(match_info);

  if(match_count == 3)
  {
    *operator= g_match_info_fetch(match_info, 1);
    gchar *txt = g_match_info_fetch(match_info, 2);

    if(strcmp(*operator, "") == 0 || strcmp(*operator, "=") == 0 || strcmp(*operator, "<>") == 0)
      *number1 = dt_util_dstrcat(*number1, "%s%%", txt);
    else
      *number1 = _dt_collection_compute_datetime(*operator, txt);

    g_free(txt);
  }

  // ensure operator is not null
  if(!*operator) *operator= g_strdup("");

  g_match_info_free(match_info);
  g_regex_unref(regex);
}
开发者ID:CarVac,项目名称:darktable,代码行数:67,代码来源:collection.c


注:本文中的dt_util_dstrcat函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。