summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/search_engine_list_model.mm
blob: 50eac2139f3e021c3c1c132d14b21ba8eea39bc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "chrome/browser/cocoa/search_engine_list_model.h"

#include "base/sys_string_conversions.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"

NSString* const kSearchEngineListModelChangedNotification =
    @"kSearchEngineListModelChangedNotification";

@interface SearchEngineListModel(Private)
- (void)buildEngineList;
@end

// C++ bridge from TemplateURLModel to our Obj-C model. When it's told about
// model changes, notifies us to rebuild the list.
class SearchEngineObserver : public TemplateURLModelObserver {
 public:
  SearchEngineObserver(SearchEngineListModel* notify)
      : notify_(notify) { }
  virtual ~SearchEngineObserver() { };

 private:
  // TemplateURLModelObserver methods.
  virtual void OnTemplateURLModelChanged() { [notify_ buildEngineList]; }

  SearchEngineListModel* notify_;  // weak, owns us
};

@implementation SearchEngineListModel

// The windows code allows for a NULL |model| and checks for it throughout
// the code, though I'm not sure why. We follow suit.
- (id)initWithModel:(TemplateURLModel*)model {
  if ((self = [super init])) {
    model_ = model;
    if (model_) {
      observer_.reset(new SearchEngineObserver(self));
      model_->Load();
      model_->AddObserver(observer_.get());
      [self buildEngineList];
    }
  }
  return self;
}

- (void)dealloc {
  if (model_)
    model_->RemoveObserver(observer_.get());
  [super dealloc];
}

// Returns an array of NSString's corresponding to the user-visible names of the
// search engines.
- (NSArray*)searchEngines {
  return engines_.get();
}

- (void)setSearchEngines:(NSArray*)engines {
  engines_.reset([engines retain]);

  // Tell anyone who's listening that something has changed so they need to
  // adjust the UI.
  [[NSNotificationCenter defaultCenter]
      postNotificationName:kSearchEngineListModelChangedNotification
                    object:nil];
}

// Walks the model and builds an array of NSStrings to display to the user.
// Assumes there is a non-NULL model.
- (void)buildEngineList {
  scoped_nsobject<NSMutableArray> engines([[NSMutableArray alloc] init]);

  typedef std::vector<const TemplateURL*> TemplateURLs;
  TemplateURLs modelURLs = model_->GetTemplateURLs();
  for (size_t i = 0; i < modelURLs.size(); ++i) {
    if (modelURLs[i]->ShowInDefaultList())
      [engines addObject:base::SysWideToNSString(modelURLs[i]->short_name())];
  }

  [self setSearchEngines:engines.get()];
}

// The index into |-searchEngines| of the current default search engine.
- (NSUInteger)defaultIndex {
  if (!model_) return 0;

  NSUInteger index = 0;
  const TemplateURL* defaultSearchProvider = model_->GetDefaultSearchProvider();
  if (defaultSearchProvider) {
    typedef std::vector<const TemplateURL*> TemplateURLs;
    TemplateURLs urls = model_->GetTemplateURLs();
    for (std::vector<const TemplateURL*>::iterator it = urls.begin();
         it != urls.end(); ++it) {
      const TemplateURL* url = *it;
      if (url->id() == defaultSearchProvider->id())
        return index;
      if (url->ShowInDefaultList())
        ++index;
    }
  }
  return 0;
}

- (void)setDefaultIndex:(NSUInteger)index {
  if (model_) {
    typedef std::vector<const TemplateURL*> TemplateURLs;
    TemplateURLs urls = model_->GetTemplateURLs();
    DCHECK(index < urls.size());
    model_->SetDefaultSearchProvider(urls[index]);
  }
}

@end