15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/app_list_model.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <string>
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_folder_item.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_item.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/app_list_model_observer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/search_box_model.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace app_list {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppListModel::AppListModel()
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : top_level_item_list_(new AppListItemList),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      search_box_(new SearchBoxModel),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      results_(new SearchResults),
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      status_(STATUS_NORMAL),
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      folders_enabled_(false) {
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  top_level_item_list_->AddObserver(this);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppListModel::~AppListModel() { top_level_item_list_->RemoveObserver(this); }
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListModel::AddObserver(AppListModelObserver* observer) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListModel::RemoveObserver(AppListModelObserver* observer) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListModel::SetStatus(Status status) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status_ == status)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status_ = status;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    observers_,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OnAppListModelStatusChanged());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::FindItem(const std::string& id) {
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppListItem* item = top_level_item_list_->FindItem(id);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return item;
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < top_level_item_list_->item_count(); ++i) {
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    AppListItem* child_item =
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        top_level_item_list_->item_at(i)->FindChildItem(id);
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (child_item)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return child_item;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListFolderItem* AppListModel::FindFolderItem(const std::string& id) {
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppListItem* item = top_level_item_list_->FindItem(id);
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item && item->GetItemType() == AppListFolderItem::kItemType)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return static_cast<AppListFolderItem*>(item);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item);
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItem(scoped_ptr<AppListItem> item) {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item->IsInFolder());
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!top_level_item_list()->FindItem(item->id()));
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AddItemToItemListAndNotify(item.Pass());
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToFolder(scoped_ptr<AppListItem> item,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           const std::string& folder_id) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder_id.empty())
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return AddItem(item.Pass());
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DVLOG(2) << "AddItemToFolder: " << item->id() << ": " << folder_id;
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_NE(folder_id, item->folder_id());
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_NE(AppListFolderItem::kItemType, item->GetItemType());
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindOrCreateFolderItem(folder_id);
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!dest_folder)
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return NULL;
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(!dest_folder->item_list()->FindItem(item->id()))
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      << "Already in folder: " << dest_folder->id();
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AddItemToFolderItemAndNotify(dest_folder, item.Pass());
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const std::string AppListModel::MergeItems(const std::string& target_item_id,
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                           const std::string& source_item_id) {
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!folders_enabled()) {
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    LOG(ERROR) << "MergeItems called with folders disabled.";
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return "";
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(2) << "MergeItems: " << source_item_id << " -> " << target_item_id;
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Find the target item.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* target_item = FindItem(target_item_id);
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!target_item) {
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "MergeItems: Target no longer exists.";
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return "";
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CHECK(target_item->folder_id().empty());
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AppListItem* source_item = FindItem(source_item_id);
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!source_item) {
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "MergeItems: Source no longer exists.";
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return "";
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // If the target item is a folder, just add the source item to it.
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (target_item->GetItemType() == AppListFolderItem::kItemType) {
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListFolderItem* target_folder =
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<AppListFolderItem*>(target_item);
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (target_folder->folder_type() == AppListFolderItem::FOLDER_TYPE_OEM) {
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      LOG(WARNING) << "MergeItems called with OEM folder as target";
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return "";
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    scoped_ptr<AppListItem> source_item_ptr = RemoveItem(source_item);
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    source_item_ptr->set_position(
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        target_folder->item_list()->CreatePositionBefore(
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            syncer::StringOrdinal()));
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToFolderItemAndNotify(target_folder, source_item_ptr.Pass());
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return target_folder->id();
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Otherwise remove the source item and target item from their current
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // location, they will become owned by the new folder.
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<AppListItem> source_item_ptr = RemoveItem(source_item);
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CHECK(source_item_ptr);
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> target_item_ptr =
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      top_level_item_list_->RemoveItem(target_item_id);
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CHECK(target_item_ptr);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a new folder in the same location as the target item.
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string new_folder_id = AppListFolderItem::GenerateId();
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(2) << "Creating folder for merge: " << new_folder_id;
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<AppListItem> new_folder_ptr(new AppListFolderItem(
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      new_folder_id, AppListFolderItem::FOLDER_TYPE_NORMAL));
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  new_folder_ptr->set_position(target_item_ptr->position());
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* new_folder = static_cast<AppListFolderItem*>(
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddItemToItemListAndNotify(new_folder_ptr.Pass()));
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Add the items to the new folder.
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  target_item_ptr->set_position(
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_folder->item_list()->CreatePositionBefore(
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::StringOrdinal()));
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddItemToFolderItemAndNotify(new_folder, target_item_ptr.Pass());
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  source_item_ptr->set_position(
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_folder->item_list()->CreatePositionBefore(
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::StringOrdinal()));
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddItemToFolderItemAndNotify(new_folder, source_item_ptr.Pass());
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new_folder->id();
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::MoveItemToFolder(AppListItem* item,
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const std::string& folder_id) {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(2) << "MoveItemToFolder: " << folder_id
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " <- " << item->ToDebugString();
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item->folder_id() == folder_id)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindOrCreateFolderItem(folder_id);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> item_ptr = RemoveItem(item);
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (dest_folder) {
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(!item->IsInFolder());
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToFolderItemAndNotify(dest_folder, item_ptr.Pass());
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToItemListAndNotifyUpdate(item_ptr.Pass());
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool AppListModel::MoveItemToFolderAt(AppListItem* item,
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const std::string& folder_id,
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      syncer::StringOrdinal position) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(2) << "MoveItemToFolderAt: " << folder_id
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << "[" << position.ToDebugString() << "]"
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " <- " << item->ToDebugString();
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item->folder_id() == folder_id)
17723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
17823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  AppListFolderItem* src_folder = FindOrCreateFolderItem(item->folder_id());
17923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (src_folder &&
18023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      src_folder->folder_type() == AppListFolderItem::FOLDER_TYPE_OEM) {
18123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(WARNING) << "MoveItemToFolderAt called with OEM folder as source";
18223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
18323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindOrCreateFolderItem(folder_id);
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> item_ptr = RemoveItem(item);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dest_folder) {
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_ptr->set_position(
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dest_folder->item_list()->CreatePositionBefore(position));
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToFolderItemAndNotify(dest_folder, item_ptr.Pass());
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    item_ptr->set_position(
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        top_level_item_list_->CreatePositionBefore(position));
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToItemListAndNotifyUpdate(item_ptr.Pass());
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return true;
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::SetItemPosition(AppListItem* item,
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   const syncer::StringOrdinal& new_position) {
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->IsInFolder()) {
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    top_level_item_list_->SetItemPosition(item, new_position);
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note: this will trigger OnListItemMoved which will signal observers.
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // (This is done this way because some View code still moves items within
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the item list directly).
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder = FindFolderItem(item->folder_id());
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(folder);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  folder->item_list()->SetItemPosition(item, new_position);
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppListModel::SetItemName(AppListItem* item, const std::string& name) {
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  item->SetName(name);
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(2) << "AppListModel::SetItemName: " << item->ToDebugString();
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    observers_,
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    OnAppListItemUpdated(item));
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppListModel::SetItemNameAndShortName(AppListItem* item,
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           const std::string& name,
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           const std::string& short_name) {
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  item->SetNameAndShortName(name, short_name);
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(2) << "AppListModel::SetItemNameAndShortName: "
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << item->ToDebugString();
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    observers_,
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    OnAppListItemUpdated(item));
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::DeleteItem(const std::string& id) {
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = FindItem(id);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item)
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->IsInFolder()) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(0u, item->ChildItemCount())
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "Invalid call to DeleteItem for item with children: " << id;
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(AppListModelObserver,
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      observers_,
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      OnAppListItemWillBeDeleted(item));
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    top_level_item_list_->DeleteItem(id);
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FOR_EACH_OBSERVER(AppListModelObserver, observers_, OnAppListItemDeleted());
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder = FindFolderItem(item->folder_id());
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(folder) << "Folder not found for item: " << item->ToDebugString();
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> child_item = RemoveItemFromFolder(folder, item);
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(item, child_item.get());
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemWillBeDeleted(item));
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child_item.reset();  // Deletes item.
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver, observers_, OnAppListItemDeleted());
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppListModel::NotifyExtensionPreferenceChanged() {
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < top_level_item_list_->item_count(); ++i)
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    top_level_item_list_->item_at(i)->OnExtensionPreferenceChanged();
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppListModel::SetFoldersEnabled(bool folders_enabled) {
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  folders_enabled_ = folders_enabled;
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (folders_enabled)
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Remove child items from folders.
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::vector<std::string> folder_ids;
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < top_level_item_list_->item_count(); ++i) {
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    AppListItem* item = top_level_item_list_->item_at(i);
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (item->GetItemType() != AppListFolderItem::kItemType)
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      continue;
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    AppListFolderItem* folder = static_cast<AppListFolderItem*>(item);
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (folder->folder_type() == AppListFolderItem::FOLDER_TYPE_OEM)
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      continue;  // Do not remove OEM folders.
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    while (folder->item_list()->item_count()) {
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      scoped_ptr<AppListItem> child = folder->item_list()->RemoveItemAt(0);
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      child->set_folder_id("");
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AddItemToItemListAndNotifyUpdate(child.Pass());
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    folder_ids.push_back(folder->id());
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Delete folders.
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < folder_ids.size(); ++i)
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DeleteItem(folder_ids[i]);
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)std::vector<SearchResult*> AppListModel::FilterSearchResultsByDisplayType(
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SearchResults* results,
2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SearchResult::DisplayType display_type,
2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    size_t max_results) {
2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::vector<SearchResult*> matches;
2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (size_t i = 0; i < results->item_count(); ++i) {
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SearchResult* item = results->GetItemAt(i);
2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (item->display_type() == display_type) {
2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      matches.push_back(item);
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (matches.size() == max_results)
2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return matches;
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Private methods
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::OnListItemMoved(size_t from_index,
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   size_t to_index,
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   AppListItem* item) {
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListFolderItem* AppListModel::FindOrCreateFolderItem(
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& folder_id) {
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder_id.empty())
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindFolderItem(folder_id);
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dest_folder)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return dest_folder;
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!folders_enabled()) {
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    LOG(ERROR) << "Attempt to create folder item when disabled: " << folder_id;
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return NULL;
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(2) << "Creating new folder: " << folder_id;
33023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<AppListFolderItem> new_folder(
33123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      new AppListFolderItem(folder_id, AppListFolderItem::FOLDER_TYPE_NORMAL));
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  new_folder->set_position(
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      top_level_item_list_->CreatePositionBefore(syncer::StringOrdinal()));
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* new_folder_item =
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddItemToItemListAndNotify(new_folder.PassAs<AppListItem>());
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return static_cast<AppListFolderItem*>(new_folder_item);
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToItemListAndNotify(
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<AppListItem> item_ptr) {
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item_ptr->IsInFolder());
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppListItem* item = top_level_item_list_->AddItem(item_ptr.Pass());
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemAdded(item));
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return item;
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToItemListAndNotifyUpdate(
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<AppListItem> item_ptr) {
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item_ptr->IsInFolder());
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppListItem* item = top_level_item_list_->AddItem(item_ptr.Pass());
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return item;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToFolderItemAndNotify(
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListFolderItem* folder,
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<AppListItem> item_ptr) {
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_NE(folder->id(), item_ptr->folder_id());
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = folder->item_list()->AddItem(item_ptr.Pass());
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item->set_folder_id(folder->id());
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return item;
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<AppListItem> AppListModel::RemoveItem(AppListItem* item) {
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->IsInFolder())
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return top_level_item_list_->RemoveItem(item->id());
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder = FindFolderItem(item->folder_id());
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return RemoveItemFromFolder(folder, item);
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<AppListItem> AppListModel::RemoveItemFromFolder(
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListFolderItem* folder,
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListItem* item) {
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string folder_id = folder->id();
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_EQ(item->folder_id(), folder_id);
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> result = folder->item_list()->RemoveItem(item->id());
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result->set_folder_id("");
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder->item_list()->item_count() == 0) {
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(2) << "Deleting empty folder: " << folder->ToDebugString();
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DeleteItem(folder_id);
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result.Pass();
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace app_list
394