app_list_model.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_folder_item.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_item.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/app_list_model_observer.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/search_box_model.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/search_result.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace app_list {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppListModel::AppListModel()
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : item_list_(new AppListItemList),
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      search_box_(new SearchBoxModel),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      results_(new SearchResults),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status_(STATUS_NORMAL) {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->AddObserver(this);
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppListModel::~AppListModel() {
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->RemoveObserver(this);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
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) {
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = item_list_->FindItem(id);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return item;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < item_list_->item_count(); ++i) {
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListItem* child_item = item_list_->item_at(i)->FindChildItem(id);
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (child_item)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return child_item;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListFolderItem* AppListModel::FindFolderItem(const std::string& id) {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = item_list_->FindItem(id);
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item && item->GetItemType() == AppListFolderItem::kItemType)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return static_cast<AppListFolderItem*>(item);
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItem(scoped_ptr<AppListItem> item) {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item->IsInFolder());
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item_list()->FindItem(item->id()));
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AddItemToItemListAndNotify(item.Pass());
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToFolder(scoped_ptr<AppListItem> item,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           const std::string& folder_id) {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder_id.empty())
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return AddItem(item.Pass());
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item->IsInFolder() || item->folder_id() == folder_id);
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(item->GetItemType() != AppListFolderItem::kItemType);
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindOrCreateFolderItem(folder_id);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!dest_folder->item_list()->FindItem(item->id()));
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AddItemToFolderItemAndNotify(dest_folder, item.Pass());
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const std::string& AppListModel::MergeItems(const std::string& target_item_id,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            const std::string& source_item_id) {
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(2) << "MergeItems: " << source_item_id << " -> " << target_item_id;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // First, remove the source item from the model.
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> source_item_ptr =
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      RemoveItem(FindItem(source_item_id));
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Next, find the target item.
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* target_item = FindItem(target_item_id);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(target_item);
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(target_item->folder_id().empty());
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the target item is a folder, just add |source_item| to it.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (target_item->GetItemType() == AppListFolderItem::kItemType) {
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListFolderItem* target_folder =
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<AppListFolderItem*>(target_item);
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    source_item_ptr->set_position(
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        target_folder->item_list()->CreatePositionBefore(
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            syncer::StringOrdinal()));
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToFolderItemAndNotify(target_folder, source_item_ptr.Pass());
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return target_folder->id();
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Otherwise, remove the target item from |item_list_|, it will become owned
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // by the new folder.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> target_item_ptr =
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      item_list_->RemoveItem(target_item_id);
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a new folder in the same location as the target item.
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> new_folder_ptr(
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new AppListFolderItem(AppListFolderItem::GenerateId()));
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  new_folder_ptr->set_position(target_item->position());
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* new_folder = static_cast<AppListFolderItem*>(
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddItemToItemListAndNotify(new_folder_ptr.Pass()));
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Add the items to the new folder.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  target_item_ptr->set_position(
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_folder->item_list()->CreatePositionBefore(
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::StringOrdinal()));
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddItemToFolderItemAndNotify(new_folder, target_item_ptr.Pass());
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  source_item_ptr->set_position(
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_folder->item_list()->CreatePositionBefore(
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::StringOrdinal()));
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddItemToFolderItemAndNotify(new_folder, source_item_ptr.Pass());
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new_folder->id();
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::MoveItemToFolder(AppListItem* item,
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const std::string& folder_id) {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(2) << "MoveItemToFolder: " << folder_id
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " <- " << item->ToDebugString();
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item->folder_id() == folder_id)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindOrCreateFolderItem(folder_id);
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> item_ptr = RemoveItem(item);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dest_folder)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToFolderItemAndNotify(dest_folder, item_ptr.Pass());
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToItemListAndNotifyUpdate(item_ptr.Pass());
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::MoveItemToFolderAt(AppListItem* item,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const std::string& folder_id,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      syncer::StringOrdinal position) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(2) << "MoveItemToFolderAt: " << folder_id
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << "[" << position.ToDebugString() << "]"
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " <- " << item->ToDebugString();
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item->folder_id() == folder_id)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindOrCreateFolderItem(folder_id);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> item_ptr = RemoveItem(item);
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dest_folder) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_ptr->set_position(
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dest_folder->item_list()->CreatePositionBefore(position));
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToFolderItemAndNotify(dest_folder, item_ptr.Pass());
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_ptr->set_position(item_list_->CreatePositionBefore(position));
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddItemToItemListAndNotifyUpdate(item_ptr.Pass());
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::SetItemPosition(AppListItem* item,
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   const syncer::StringOrdinal& new_position) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->IsInFolder()) {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_list_->SetItemPosition(item, new_position);
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note: this will trigger OnListItemMoved which will signal observers.
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // (This is done this way because some View code still moves items within
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the item list directly).
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder = FindFolderItem(item->folder_id());
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(folder);
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  folder->item_list()->SetItemPosition(item, new_position);
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::DeleteItem(const std::string& id) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = FindItem(id);
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->IsInFolder()) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(0u, item->ChildItemCount())
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "Invalid call to DeleteItem for item with children: " << id;
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(AppListModelObserver,
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      observers_,
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      OnAppListItemWillBeDeleted(item));
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_list_->DeleteItem(id);
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder = FindFolderItem(item->folder_id());
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(folder) << "Folder not found for item: " << item->ToDebugString();
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> child_item = RemoveItemFromFolder(folder, item);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(item, child_item.get());
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemWillBeDeleted(item));
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child_item.reset();  // Deletes item.
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Private methods
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListModel::OnListItemMoved(size_t from_index,
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   size_t to_index,
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   AppListItem* item) {
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListFolderItem* AppListModel::FindOrCreateFolderItem(
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& folder_id) {
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder_id.empty())
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* dest_folder = FindFolderItem(folder_id);
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dest_folder)
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return dest_folder;
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListFolderItem> new_folder(new AppListFolderItem(folder_id));
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  new_folder->set_position(
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      item_list_->CreatePositionBefore(syncer::StringOrdinal()));
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* new_folder_item =
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddItemToItemListAndNotify(new_folder.PassAs<AppListItem>());
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return static_cast<AppListFolderItem*>(new_folder_item);
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToItemListAndNotify(
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<AppListItem> item_ptr) {
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item_ptr->IsInFolder());
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = item_list_->AddItem(item_ptr.Pass());
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemAdded(item));
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return item;
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToItemListAndNotifyUpdate(
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<AppListItem> item_ptr) {
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!item_ptr->IsInFolder());
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = item_list_->AddItem(item_ptr.Pass());
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return item;
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItem* AppListModel::AddItemToFolderItemAndNotify(
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListFolderItem* folder,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<AppListItem> item_ptr) {
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* item = folder->item_list()->AddItem(item_ptr.Pass());
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item->set_folder_id(folder->id());
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(AppListModelObserver,
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    observers_,
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAppListItemUpdated(item));
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return item;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<AppListItem> AppListModel::RemoveItem(AppListItem* item) {
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->IsInFolder())
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return item_list_->RemoveItem(item->id());
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder = FindFolderItem(item->folder_id());
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(folder);
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return RemoveItemFromFolder(folder, item);
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<AppListItem> AppListModel::RemoveItemFromFolder(
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListFolderItem* folder,
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListItem* item) {
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string folder_id = folder->id();
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(item->folder_id(), folder_id);
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<AppListItem> result = folder->item_list()->RemoveItem(item->id());
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result->set_folder_id("");
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder->item_list()->item_count() == 0) {
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(2) << "Deleting empty folder: " << folder->ToDebugString();
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DeleteItem(folder_id);
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result.Pass();
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace app_list
286