Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: chrome/browser/views/keyword_editor_view.cc

Issue 146138: Refactor the win KeywordEditorView for cross platform friendliness. (Closed)
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/views/keyword_editor_view.h" 5 #include "chrome/browser/views/keyword_editor_view.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "app/l10n_util.h" 9 #include "app/l10n_util.h"
10 #include "app/resource_bundle.h"
11 #include "base/gfx/png_decoder.h"
12 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
13 #include "base/string_util.h" 11 #include "base/string_util.h"
14 #include "chrome/browser/history/history.h"
15 #include "chrome/browser/profile.h" 12 #include "chrome/browser/profile.h"
16 #include "chrome/browser/metrics/user_metrics.h"
17 #include "chrome/browser/search_engines/template_url.h" 13 #include "chrome/browser/search_engines/template_url.h"
18 #include "chrome/browser/search_engines/template_url_model.h" 14 #include "chrome/browser/search_engines/template_url_model.h"
15 #include "chrome/browser/search_engines/template_url_table_model.h"
19 #include "chrome/browser/views/browser_dialogs.h" 16 #include "chrome/browser/views/browser_dialogs.h"
20 #include "chrome/common/pref_names.h" 17 #include "chrome/common/pref_names.h"
21 #include "chrome/common/pref_service.h" 18 #include "chrome/common/pref_service.h"
22 #include "googleurl/src/gurl.h" 19 #include "googleurl/src/gurl.h"
23 #include "grit/app_resources.h"
24 #include "grit/generated_resources.h" 20 #include "grit/generated_resources.h"
25 #include "grit/locale_settings.h" 21 #include "grit/locale_settings.h"
26 #include "grit/theme_resources.h" 22 #include "grit/theme_resources.h"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "views/background.h" 23 #include "views/background.h"
29 #include "views/grid_layout.h" 24 #include "views/grid_layout.h"
30 #include "views/controls/button/native_button.h" 25 #include "views/controls/button/native_button.h"
31 #include "views/controls/table/table_view.h" 26 #include "views/controls/table/table_view.h"
32 #include "views/controls/textfield/textfield.h" 27 #include "views/controls/textfield/textfield.h"
33 #include "views/standard_layout.h" 28 #include "views/standard_layout.h"
34 #include "views/widget/widget.h" 29 #include "views/widget/widget.h"
35 #include "views/window/dialog_delegate.h" 30 #include "views/window/dialog_delegate.h"
36 #include "views/window/window.h" 31 #include "views/window/window.h"
37 32
38 using views::GridLayout; 33 using views::GridLayout;
39 using views::NativeButton; 34 using views::NativeButton;
40 35
41 // Group IDs used by TemplateURLTableModel.
42 static const int kMainGroupID = 0;
43 static const int kOtherGroupID = 1;
44
45 namespace browser { 36 namespace browser {
46 37
47 // Declared in browser_dialogs.h so others don't have to depend on our header. 38 // Declared in browser_dialogs.h so others don't have to depend on our header.
48 void ShowKeywordEditorView(Profile* profile) { 39 void ShowKeywordEditorView(Profile* profile) {
49 KeywordEditorView::Show(profile); 40 KeywordEditorView::Show(profile);
50 } 41 }
51 42
52 } // namespace browser 43 } // namespace browser
53 44
54 // ModelEntry ----------------------------------------------------
55
56 // ModelEntry wraps a TemplateURL as returned from the TemplateURL.
57 // ModelEntry also tracks state information about the URL.
58
59 // Icon used while loading, or if a specific favicon can't be found.
60 static SkBitmap* default_icon = NULL;
61
62 class ModelEntry {
63 public:
64 explicit ModelEntry(TemplateURLTableModel* model,
65 const TemplateURL& template_url)
66 : model_(model),
67 template_url_(template_url) {
68 load_state_ = NOT_LOADED;
69 if (!default_icon) {
70 default_icon = ResourceBundle::GetSharedInstance().
71 GetBitmapNamed(IDR_DEFAULT_FAVICON);
72 }
73 }
74
75 const TemplateURL& template_url() {
76 return template_url_;
77 }
78
79 SkBitmap GetIcon() {
80 if (load_state_ == NOT_LOADED)
81 LoadFavIcon();
82 if (!fav_icon_.isNull())
83 return fav_icon_;
84 return *default_icon;
85 }
86
87 // Resets internal status so that the next time the icon is asked for its
88 // fetched again. This should be invoked if the url is modified.
89 void ResetIcon() {
90 load_state_ = NOT_LOADED;
91 fav_icon_ = SkBitmap();
92 }
93
94 private:
95 // State of the favicon.
96 enum LoadState {
97 NOT_LOADED,
98 LOADING,
99 LOADED
100 };
101
102 void LoadFavIcon() {
103 load_state_ = LOADED;
104 HistoryService* hs =
105 model_->template_url_model()->profile()->GetHistoryService(
106 Profile::EXPLICIT_ACCESS);
107 if (!hs)
108 return;
109 GURL fav_icon_url = template_url().GetFavIconURL();
110 if (!fav_icon_url.is_valid()) {
111 // The favicon url isn't always set. Guess at one here.
112 if (template_url_.url() && template_url_.url()->IsValid()) {
113 GURL url = GURL(template_url_.url()->url());
114 if (url.is_valid())
115 fav_icon_url = TemplateURL::GenerateFaviconURL(url);
116 }
117 if (!fav_icon_url.is_valid())
118 return;
119 }
120 load_state_ = LOADING;
121 hs->GetFavIcon(fav_icon_url,
122 &request_consumer_,
123 NewCallback(this, &ModelEntry::OnFavIconDataAvailable));
124 }
125
126 void OnFavIconDataAvailable(
127 HistoryService::Handle handle,
128 bool know_favicon,
129 scoped_refptr<RefCountedBytes> data,
130 bool expired,
131 GURL icon_url) {
132 load_state_ = LOADED;
133 if (know_favicon && data.get() &&
134 PNGDecoder::Decode(&data->data, &fav_icon_)) {
135 model_->FavIconAvailable(this);
136 }
137 }
138
139 const TemplateURL& template_url_;
140 SkBitmap fav_icon_;
141 LoadState load_state_;
142 TemplateURLTableModel* model_;
143 CancelableRequestConsumer request_consumer_;
144
145 DISALLOW_EVIL_CONSTRUCTORS(ModelEntry);
146 };
147
148 // TemplateURLTableModel -----------------------------------------
149
150 TemplateURLTableModel::TemplateURLTableModel(
151 TemplateURLModel* template_url_model)
152 : observer_(NULL),
153 template_url_model_(template_url_model) {
154 DCHECK(template_url_model);
155 Reload();
156 }
157
158 TemplateURLTableModel::~TemplateURLTableModel() {
159 STLDeleteElements(&entries_);
160 entries_.clear();
161 }
162
163 void TemplateURLTableModel::Reload() {
164 STLDeleteElements(&entries_);
165 entries_.clear();
166
167 std::vector<const TemplateURL*> urls = template_url_model_->GetTemplateURLs();
168
169 // Keywords that can be made the default first.
170 for (std::vector<const TemplateURL*>::iterator i = urls.begin();
171 i != urls.end(); ++i) {
172 const TemplateURL& template_url = *(*i);
173 // NOTE: we don't use ShowInDefaultList here to avoid items bouncing around
174 // the lists while editing.
175 if (template_url.show_in_default_list())
176 entries_.push_back(new ModelEntry(this, template_url));
177 }
178
179 last_search_engine_index_ = static_cast<int>(entries_.size());
180
181 // Then the rest.
182 for (std::vector<const TemplateURL*>::iterator i = urls.begin();
183 i != urls.end(); ++i) {
184 const TemplateURL* template_url = *i;
185 // NOTE: we don't use ShowInDefaultList here to avoid things bouncing
186 // the lists while editing.
187 if (!template_url->show_in_default_list())
188 entries_.push_back(new ModelEntry(this, *template_url));
189 }
190
191 if (observer_)
192 observer_->OnModelChanged();
193 }
194
195 int TemplateURLTableModel::RowCount() {
196 return static_cast<int>(entries_.size());
197 }
198
199 std::wstring TemplateURLTableModel::GetText(int row, int col_id) {
200 DCHECK(row >= 0 && row < RowCount());
201 const TemplateURL& url = entries_[row]->template_url();
202
203 switch (col_id) {
204 case IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN: {
205 std::wstring url_short_name = url.short_name();
206 // TODO(xji): Consider adding a special case if the short name is a URL,
207 // since those should always be displayed LTR. Please refer to
208 // http://crbug.com/6726 for more information.
209 l10n_util::AdjustStringForLocaleDirection(url_short_name,
210 &url_short_name);
211 return (template_url_model_->GetDefaultSearchProvider() == &url) ?
212 l10n_util::GetStringF(IDS_SEARCH_ENGINES_EDITOR_DEFAULT_ENGINE,
213 url_short_name) : url_short_name;
214 }
215
216 case IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN: {
217 const std::wstring& keyword = url.keyword();
218 // Keyword should be domain name. Force it to have LTR directionality.
219 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
220 std::wstring localized_keyword = keyword;
221 l10n_util::WrapStringWithLTRFormatting(&localized_keyword);
222 return localized_keyword;
223 }
224 return keyword;
225 break;
226 }
227
228 default:
229 NOTREACHED();
230 return std::wstring();
231 }
232 }
233
234 SkBitmap TemplateURLTableModel::GetIcon(int row) {
235 DCHECK(row >= 0 && row < RowCount());
236 return entries_[row]->GetIcon();
237 }
238
239 void TemplateURLTableModel::SetObserver(TableModelObserver* observer) {
240 observer_ = observer;
241 }
242
243 bool TemplateURLTableModel::HasGroups() {
244 return true;
245 }
246
247 TemplateURLTableModel::Groups TemplateURLTableModel::GetGroups() {
248 Groups groups;
249
250 Group search_engine_group;
251 search_engine_group.title =
252 l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR);
253 search_engine_group.id = kMainGroupID;
254 groups.push_back(search_engine_group);
255
256 Group other_group;
257 other_group.title =
258 l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR);
259 other_group.id = kOtherGroupID;
260 groups.push_back(other_group);
261
262 return groups;
263 }
264
265 int TemplateURLTableModel::GetGroupID(int row) {
266 DCHECK(row >= 0 && row < RowCount());
267 return row < last_search_engine_index_ ? kMainGroupID : kOtherGroupID;
268 }
269
270 void TemplateURLTableModel::Remove(int index) {
271 scoped_ptr<ModelEntry> entry(entries_[static_cast<int>(index)]);
272 entries_.erase(entries_.begin() + static_cast<int>(index));
273 if (index < last_search_engine_index_)
274 last_search_engine_index_--;
275 if (observer_)
276 observer_->OnItemsRemoved(index, 1);
277 }
278
279 void TemplateURLTableModel::Add(int index, const TemplateURL* template_url) {
280 DCHECK(index >= 0 && index <= RowCount());
281 ModelEntry* entry = new ModelEntry(this, *template_url);
282 entries_.insert(entries_.begin() + index, entry);
283 if (observer_)
284 observer_->OnItemsAdded(index, 1);
285 }
286
287 void TemplateURLTableModel::ReloadIcon(int index) {
288 DCHECK(index >= 0 && index < RowCount());
289
290 entries_[index]->ResetIcon();
291
292 NotifyChanged(index);
293 }
294
295 const TemplateURL& TemplateURLTableModel::GetTemplateURL(int index) {
296 return entries_[index]->template_url();
297 }
298
299 int TemplateURLTableModel::IndexOfTemplateURL(
300 const TemplateURL* template_url) {
301 for (std::vector<ModelEntry*>::iterator i = entries_.begin();
302 i != entries_.end(); ++i) {
303 ModelEntry* entry = *i;
304 if (&(entry->template_url()) == template_url)
305 return static_cast<int>(i - entries_.begin());
306 }
307 return -1;
308 }
309
310 void TemplateURLTableModel::MoveToMainGroup(int index) {
311 if (index < last_search_engine_index_)
312 return; // Already in the main group.
313
314 ModelEntry* current_entry = entries_[index];
315 entries_.erase(index + entries_.begin());
316 if (observer_)
317 observer_->OnItemsRemoved(index, 1);
318
319 const int new_index = last_search_engine_index_++;
320 entries_.insert(entries_.begin() + new_index, current_entry);
321 if (observer_)
322 observer_->OnItemsAdded(new_index, 1);
323 }
324
325 void TemplateURLTableModel::NotifyChanged(int index) {
326 if (observer_)
327 observer_->OnItemsChanged(index, 1);
328 }
329
330 void TemplateURLTableModel::FavIconAvailable(ModelEntry* entry) {
331 std::vector<ModelEntry*>::iterator i =
332 find(entries_.begin(), entries_.end(), entry);
333 DCHECK(i != entries_.end());
334 NotifyChanged(static_cast<int>(i - entries_.begin()));
335 }
336 45
337 // KeywordEditorView ---------------------------------------------------------- 46 // KeywordEditorView ----------------------------------------------------------
338 47
339 // If non-null, there is an open editor and this is the window it is contained 48 // If non-null, there is an open editor and this is the window it is contained
340 // in. 49 // in.
341 static views::Window* open_window = NULL; 50 static views::Window* open_window = NULL;
342 51
343 // static 52 // static
344 void KeywordEditorView::Show(Profile* profile) { 53 void KeywordEditorView::Show(Profile* profile) {
345 if (!profile->GetTemplateURLModel()) 54 if (!profile->GetTemplateURLModel())
346 return; 55 return;
347 56
348 if (open_window != NULL) 57 if (open_window != NULL)
349 open_window->Close(); 58 open_window->Close();
350 DCHECK(!open_window); 59 DCHECK(!open_window);
351 60
352 // Both of these will be deleted when the dialog closes. 61 // Both of these will be deleted when the dialog closes.
353 KeywordEditorView* keyword_editor = new KeywordEditorView(profile); 62 KeywordEditorView* keyword_editor = new KeywordEditorView(profile);
354 63
355 // Initialize the UI. By passing in an empty rect KeywordEditorView is 64 // Initialize the UI. By passing in an empty rect KeywordEditorView is
356 // queried for its preferred size. 65 // queried for its preferred size.
357 open_window = views::Window::CreateChromeWindow(NULL, gfx::Rect(), 66 open_window = views::Window::CreateChromeWindow(NULL, gfx::Rect(),
358 keyword_editor); 67 keyword_editor);
359 68
360 open_window->Show(); 69 open_window->Show();
361 } 70 }
362 71
363 KeywordEditorView::KeywordEditorView(Profile* profile) 72 KeywordEditorView::KeywordEditorView(Profile* profile)
364 : profile_(profile), 73 : profile_(profile),
365 url_model_(profile->GetTemplateURLModel()) { 74 controller_(new KeywordEditorController(profile)) {
366 DCHECK(url_model_); 75 DCHECK(controller_->url_model());
76 controller_->url_model()->AddObserver(this);
367 Init(); 77 Init();
368 } 78 }
369 79
370 KeywordEditorView::~KeywordEditorView() { 80 KeywordEditorView::~KeywordEditorView() {
371 // Only remove the listener if we installed one. 81 table_view_->SetModel(NULL);
372 if (table_model_.get()) { 82 controller_->url_model()->RemoveObserver(this);
373 table_view_->SetModel(NULL);
374 url_model_->RemoveObserver(this);
375 }
376 } 83 }
377 84
378 void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url, 85 void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url,
379 const std::wstring& title, 86 const std::wstring& title,
380 const std::wstring& keyword, 87 const std::wstring& keyword,
381 const std::wstring& url) { 88 const std::wstring& url) {
382 if (template_url) { 89 if (template_url) {
383 ModifyTemplateURL(template_url, title, keyword, url); 90 controller_->ModifyTemplateURL(template_url, title, keyword, url);
91
92 // Force the make default button to update.
93 OnSelectionChanged();
384 } else { 94 } else {
385 AddTemplateURL(title, keyword, url); 95 table_view_->Select(controller_->AddTemplateURL(title, keyword, url));
386 } 96 }
387 } 97 }
388 98
389 void KeywordEditorView::AddTemplateURL(const std::wstring& title,
390 const std::wstring& keyword,
391 const std::wstring& url) {
392 DCHECK(!url.empty());
393
394 UserMetrics::RecordAction(L"KeywordEditor_AddKeyword", profile_);
395
396 TemplateURL* template_url = new TemplateURL();
397 template_url->set_short_name(title);
398 template_url->set_keyword(keyword);
399 template_url->SetURL(url, 0, 0);
400
401 // There's a bug (1090726) in TableView with groups enabled such that newly
402 // added items in groups ALWAYS appear at the end, regardless of the index
403 // passed in. Worse yet, the selected rows get messed up when this happens
404 // causing other problems. As a work around we always add the item to the end
405 // of the list.
406 const int new_index = table_model_->RowCount();
407 url_model_->RemoveObserver(this);
408 table_model_->Add(new_index, template_url);
409 url_model_->Add(template_url);
410 url_model_->AddObserver(this);
411
412 table_view_->Select(new_index);
413 }
414
415 void KeywordEditorView::ModifyTemplateURL(const TemplateURL* template_url,
416 const std::wstring& title,
417 const std::wstring& keyword,
418 const std::wstring& url) {
419 const int index = table_model_->IndexOfTemplateURL(template_url);
420 if (index == -1) {
421 // Will happen if url was deleted out from under us while the user was
422 // editing it.
423 return;
424 }
425
426 // Don't do anything if the entry didn't change.
427 if (template_url->short_name() == title &&
428 template_url->keyword() == keyword &&
429 ((url.empty() && !template_url->url()) ||
430 (!url.empty() && template_url->url() &&
431 template_url->url()->url() == url))) {
432 return;
433 }
434
435 url_model_->RemoveObserver(this);
436 url_model_->ResetTemplateURL(template_url, title, keyword, url);
437 if (url_model_->GetDefaultSearchProvider() == template_url &&
438 !TemplateURL::SupportsReplacement(template_url)) {
439 // The entry was the default search provider, but the url has been modified
440 // so that it no longer supports replacement. Reset the default search
441 // provider so that it doesn't point to a bogus entry.
442 url_model_->SetDefaultSearchProvider(NULL);
443 }
444 url_model_->AddObserver(this);
445 table_model_->ReloadIcon(index); // Also calls NotifyChanged().
446
447 // Force the make default button to update.
448 OnSelectionChanged();
449
450 UserMetrics::RecordAction(L"KeywordEditor_ModifiedKeyword", profile_);
451 }
452 99
453 gfx::Size KeywordEditorView::GetPreferredSize() { 100 gfx::Size KeywordEditorView::GetPreferredSize() {
454 return gfx::Size(views::Window::GetLocalizedContentsSize( 101 return gfx::Size(views::Window::GetLocalizedContentsSize(
455 IDS_SEARCHENGINES_DIALOG_WIDTH_CHARS, 102 IDS_SEARCHENGINES_DIALOG_WIDTH_CHARS,
456 IDS_SEARCHENGINES_DIALOG_HEIGHT_LINES)); 103 IDS_SEARCHENGINES_DIALOG_HEIGHT_LINES));
457 } 104 }
458 105
459 bool KeywordEditorView::CanResize() const { 106 bool KeywordEditorView::CanResize() const {
460 return true; 107 return true;
461 } 108 }
(...skipping 14 matching lines...) Expand all
476 bool KeywordEditorView::Cancel() { 123 bool KeywordEditorView::Cancel() {
477 open_window = NULL; 124 open_window = NULL;
478 return true; 125 return true;
479 } 126 }
480 127
481 views::View* KeywordEditorView::GetContentsView() { 128 views::View* KeywordEditorView::GetContentsView() {
482 return this; 129 return this;
483 } 130 }
484 131
485 void KeywordEditorView::Init() { 132 void KeywordEditorView::Init() {
486 DCHECK(!table_model_.get());
487
488 url_model_->Load();
489 url_model_->AddObserver(this);
490
491 table_model_.reset(new TemplateURLTableModel(url_model_));
492
493 std::vector<TableColumn> columns; 133 std::vector<TableColumn> columns;
494 columns.push_back( 134 columns.push_back(
495 TableColumn(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN, 135 TableColumn(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN,
496 TableColumn::LEFT, -1, .75)); 136 TableColumn::LEFT, -1, .75));
497 columns.back().sortable = true; 137 columns.back().sortable = true;
498 columns.push_back( 138 columns.push_back(
499 TableColumn(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN, 139 TableColumn(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN,
500 TableColumn::LEFT, -1, .25)); 140 TableColumn::LEFT, -1, .25));
501 columns.back().sortable = true; 141 columns.back().sortable = true;
502 table_view_ = new views::TableView(table_model_.get(), columns, 142 table_view_ = new views::TableView(controller_->table_model(), columns,
503 views::ICON_AND_TEXT, false, true, true); 143 views::ICON_AND_TEXT, false, true, true);
504 table_view_->SetObserver(this); 144 table_view_->SetObserver(this);
505 145
506 add_button_ = new views::NativeButton( 146 add_button_ = new views::NativeButton(
507 this, l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON)); 147 this, l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON));
508 add_button_->SetEnabled(url_model_->loaded()); 148 add_button_->SetEnabled(controller_->loaded());
509 149
510 edit_button_ = new views::NativeButton( 150 edit_button_ = new views::NativeButton(
511 this, l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON)); 151 this, l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON));
512 edit_button_->SetEnabled(false); 152 edit_button_->SetEnabled(false);
513 153
514 remove_button_ = new views::NativeButton( 154 remove_button_ = new views::NativeButton(
515 this, l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON)); 155 this, l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON));
516 remove_button_->SetEnabled(false); 156 remove_button_->SetEnabled(false);
517 157
518 make_default_button_ = new views::NativeButton( 158 make_default_button_ = new views::NativeButton(
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 contents_layout->AddPaddingRow(1, 0); 199 contents_layout->AddPaddingRow(1, 0);
560 } 200 }
561 201
562 void KeywordEditorView::OnSelectionChanged() { 202 void KeywordEditorView::OnSelectionChanged() {
563 const int selected_row_count = table_view_->SelectedRowCount(); 203 const int selected_row_count = table_view_->SelectedRowCount();
564 edit_button_->SetEnabled(selected_row_count == 1); 204 edit_button_->SetEnabled(selected_row_count == 1);
565 bool can_make_default = false; 205 bool can_make_default = false;
566 bool can_remove = false; 206 bool can_remove = false;
567 if (selected_row_count == 1) { 207 if (selected_row_count == 1) {
568 const TemplateURL* selected_url = 208 const TemplateURL* selected_url =
569 &table_model_->GetTemplateURL(table_view_->FirstSelectedRow()); 209 controller_->GetTemplateURL(table_view_->FirstSelectedRow());
570 can_make_default = 210 can_make_default = controller_->CanMakeDefault(selected_url);
571 (selected_url != url_model_->GetDefaultSearchProvider() && 211 can_remove = controller_->CanRemove(selected_url);
572 selected_url->url() &&
573 selected_url->url()->SupportsReplacement());
574 can_remove = (selected_url != url_model_->GetDefaultSearchProvider());
575 } 212 }
576 remove_button_->SetEnabled(can_remove); 213 remove_button_->SetEnabled(can_remove);
577 make_default_button_->SetEnabled(can_make_default); 214 make_default_button_->SetEnabled(can_make_default);
578 } 215 }
579 216
580 void KeywordEditorView::OnDoubleClick() { 217 void KeywordEditorView::OnDoubleClick() {
581 if (edit_button_->IsEnabled()) 218 if (edit_button_->IsEnabled())
582 ButtonPressed(edit_button_); 219 ButtonPressed(edit_button_);
583 } 220 }
584 221
585 void KeywordEditorView::ButtonPressed(views::Button* sender) { 222 void KeywordEditorView::ButtonPressed(views::Button* sender) {
586 if (sender == add_button_) { 223 if (sender == add_button_) {
587 browser::EditSearchEngine(GetWindow()->GetNativeWindow(), NULL, this, 224 browser::EditSearchEngine(GetWindow()->GetNativeWindow(), NULL, this,
588 profile_); 225 profile_);
589 } else if (sender == remove_button_) { 226 } else if (sender == remove_button_) {
590 DCHECK(table_view_->SelectedRowCount() > 0); 227 DCHECK(table_view_->SelectedRowCount() == 1);
591 // Remove the observer while we modify the model, that way we don't need to
592 // worry about the model calling us back when we mutate it.
593 url_model_->RemoveObserver(this);
594 int last_view_row = -1; 228 int last_view_row = -1;
595 for (views::TableView::iterator i = table_view_->SelectionBegin(); 229 for (views::TableView::iterator i = table_view_->SelectionBegin();
596 i != table_view_->SelectionEnd(); ++i) { 230 i != table_view_->SelectionEnd(); ++i) {
597 last_view_row = table_view_->model_to_view(*i); 231 last_view_row = table_view_->model_to_view(*i);
598 const TemplateURL* template_url = &table_model_->GetTemplateURL(*i); 232 controller_->RemoveTemplateURL(*i);
599 // Make sure to remove from the table model first, otherwise the
600 // TemplateURL would be freed.
601 table_model_->Remove(*i);
602 url_model_->Remove(template_url);
603 } 233 }
604 if (last_view_row >= table_model_->RowCount()) 234 if (last_view_row >= controller_->table_model()->RowCount())
605 last_view_row = table_model_->RowCount() - 1; 235 last_view_row = controller_->table_model()->RowCount() - 1;
606 if (last_view_row >= 0) 236 if (last_view_row >= 0)
607 table_view_->Select(table_view_->view_to_model(last_view_row)); 237 table_view_->Select(table_view_->view_to_model(last_view_row));
608 url_model_->AddObserver(this);
609 UserMetrics::RecordAction(L"KeywordEditor_RemoveKeyword", profile_);
610 } else if (sender == edit_button_) { 238 } else if (sender == edit_button_) {
611 const int selected_row = table_view_->FirstSelectedRow(); 239 const int selected_row = table_view_->FirstSelectedRow();
612 const TemplateURL* template_url = 240 const TemplateURL* template_url =
613 &table_model_->GetTemplateURL(selected_row); 241 controller_->GetTemplateURL(selected_row);
614 browser::EditSearchEngine(GetWindow()->GetNativeWindow(), template_url, 242 browser::EditSearchEngine(GetWindow()->GetNativeWindow(), template_url,
615 this, profile_); 243 this, profile_);
616 } else if (sender == make_default_button_) { 244 } else if (sender == make_default_button_) {
617 MakeDefaultSearchProvider(); 245 MakeDefaultTemplateURL();
618 } else { 246 } else {
619 NOTREACHED(); 247 NOTREACHED();
620 } 248 }
621 } 249 }
622 250
623 void KeywordEditorView::OnTemplateURLModelChanged() { 251 void KeywordEditorView::OnTemplateURLModelChanged() {
624 table_model_->Reload(); 252 add_button_->SetEnabled(controller_->loaded());
625 add_button_->SetEnabled(url_model_->loaded());
626 } 253 }
627 254
628 void KeywordEditorView::MakeDefaultSearchProvider() { 255 void KeywordEditorView::MakeDefaultTemplateURL() {
629 MakeDefaultSearchProvider(table_view_->FirstSelectedRow()); 256 int new_index =
257 controller_->MakeDefaultTemplateURL(table_view_->FirstSelectedRow());
258 if (new_index >= 0)
259 table_view_->Select(new_index);
630 } 260 }
631
632 void KeywordEditorView::MakeDefaultSearchProvider(int index) {
633 if (index < 0 || index >= table_model_->RowCount()) {
634 NOTREACHED();
635 return;
636 }
637 const TemplateURL* keyword = &table_model_->GetTemplateURL(index);
638 const TemplateURL* current_default = url_model_->GetDefaultSearchProvider();
639 if (current_default == keyword)
640 return;
641
642 url_model_->RemoveObserver(this);
643 url_model_->SetDefaultSearchProvider(keyword);
644 url_model_->AddObserver(this);
645
646 // The formatting of the default engine is different; notify the table that
647 // both old and new entries have changed.
648 if (current_default != NULL) {
649 table_model_->NotifyChanged(table_model_->IndexOfTemplateURL(
650 current_default));
651 }
652 const int new_index = table_model_->IndexOfTemplateURL(keyword);
653 table_model_->NotifyChanged(new_index);
654
655 // Make sure the new default is in the main group.
656 table_model_->MoveToMainGroup(index);
657
658 // And select it.
659 table_view_->Select(table_model_->IndexOfTemplateURL(keyword));
660 }
OLDNEW
« no previous file with comments | « chrome/browser/views/keyword_editor_view.h ('k') | chrome/browser/views/keyword_editor_view_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698