This easy solution should fix problems with long urls that pass right icons
[rekonq:nikhilms-mainline.git] / src / urlbar / urlbar.cpp
1 /* ============================================================
2 *
3 * This file is a part of the rekonq project
4 *
5 * Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
6 * Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>
7 * Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
8 * Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>
9 *
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License or (at your option) version 3 or any later version
15 * accepted by the membership of KDE e.V. (or its successor approved
16 * by the membership of KDE e.V.), which shall act as a proxy
17 * defined in Section 14 of version 3 of the license.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26 *
27 * ============================================================ */
28
29
30 // Self Includes
31 #include "urlbar.h"
32 #include "urlbar.moc"
33
34 // Auto Includes
35 #include "rekonq.h"
36
37 // Local Includes
38 #include "application.h"
39 #include "mainwindow.h"
40 #include "webtab.h"
41 #include "webpage.h"
42 #include "webview.h"
43 #include "completionwidget.h"
44
45 // KDE Includes
46 #include <KCompletionBox>
47
48 // Qt Includes
49 #include <QtGui/QPainter>
50 #include <QtGui/QPaintEvent>
51 #include <QtGui/QPalette>
52 #include <QtGui/QVBoxLayout>
53
54
55
56 IconButton::IconButton(QWidget *parent)
57         : QToolButton(parent)
58 {
59     setToolButtonStyle(Qt::ToolButtonIconOnly);
60     setStyleSheet("IconButton { background-color:transparent; border: none; padding: 0px}");
61     setCursor(Qt::ArrowCursor);
62 }
63
64
65 void IconButton::mouseReleaseEvent(QMouseEvent* event)
66 {
67     emit clicked(event->globalPos());
68 }
69
70
71 // -----------------------------------------------------------------------------------------------------------
72
73
74 UrlBar::UrlBar(QWidget *parent)
75         : KLineEdit(parent)
76         , _tab(0)
77         , _privateMode(false)
78         , _icon(new IconButton(this))
79         , _suggestionTimer(new QTimer(this))
80 {
81     // initial style
82     setStyleSheet(QString("UrlBar { padding: 0 0 0 %1px;} ").arg(_icon->sizeHint().width()));
83
84     // doesn't show the clear button
85     setClearButtonShown(false);
86
87     // trap Key_Enter & Key_Return events, while emitting the returnPressed signal
88     setTrapReturnKey(true);
89
90     // insert decoded URLs
91     setUrlDropsEnabled(true);
92
93     // tooltip
94     setToolTip(i18n("Type here to search your bookmarks, history and the web..."));
95
96     // accept focus, via tabbing, clicking & wheeling
97     setFocusPolicy(Qt::WheelFocus);
98
99     // disable completion object (we have our own :) )
100     setCompletionObject(0);
101
102     _tab = qobject_cast<WebTab *>(parent);
103
104     connect(_tab, SIGNAL(loadProgressing()), this, SLOT(update()));
105     
106     connect(_tab->view(), SIGNAL(urlChanged(const QUrl &)), this, SLOT(setQUrl(const QUrl &)));
107     connect(_tab->view(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
108     connect(_tab->view(), SIGNAL(loadStarted()), this, SLOT(clearRightIcons()));
109
110     // load typed urls
111     connect(this, SIGNAL(returnPressed(const QString &)), this, SLOT(loadTyped(const QString &)));
112
113     _suggestionTimer->setSingleShot(true);
114     connect(_suggestionTimer, SIGNAL(timeout()), this, SLOT(suggest()));
115     
116     activateSuggestions(true);
117 }
118
119
120 UrlBar::~UrlBar()
121 {
122     activateSuggestions(false);
123     delete _icon;
124     _box.clear();
125 }
126
127
128 void UrlBar::setQUrl(const QUrl& url)
129 {
130     if (url.scheme() == QL1S("about"))
131     {
132         _icon->setIcon(KIcon("arrow-right"));
133         clear();
134         setFocus();
135     }
136     else
137     {
138         clearFocus();
139         KLineEdit::setUrl(url);
140         setCursorPosition(0);
141         _icon->setIcon(Application::icon(url));
142     }
143 }
144
145
146 void UrlBar::activated(const KUrl& url, Rekonq::OpenType type)
147 {
148     activateSuggestions(false);
149
150     clearFocus();
151     setUrl(url);
152     Application::instance()->loadUrl(url, type);
153 }
154
155
156 void UrlBar::paintEvent(QPaintEvent *event)
157 {   
158     QColor backgroundColor;
159     if (_privateMode)
160     {
161         backgroundColor = QColor(220, 220, 220);  // light gray
162     }
163     else
164     {
165         backgroundColor = Application::palette().color(QPalette::Base);
166     }
167
168     // set background color of UrlBar
169     QPalette p = palette();
170
171     int progr = _tab->progress();
172     if (progr == 0)
173     {
174         if (_tab->url().scheme() == QL1S("https"))
175         {
176             backgroundColor = QColor(255, 255, 171);  // light yellow
177         }
178         p.setBrush(QPalette::Base, backgroundColor);
179     }
180     else
181     {
182         // NOTE: I chose this instead of the old QColor(116, 192, 250)
183         // to try respecting style colors
184         QColor loadingColor = Application::palette().color(QPalette::ToolTipBase);
185
186         QLinearGradient gradient( QPoint(0, 0), QPoint(width(), height()) );
187         gradient.setColorAt(0, loadingColor);
188         gradient.setColorAt(((double)progr) / 100 - .000001, loadingColor);
189         gradient.setColorAt(((double)progr) / 100, backgroundColor);
190         p.setBrush(QPalette::Base, gradient);
191     }
192     setPalette(p);
193
194     // you need this before our code to draw inside the line edit..
195     KLineEdit::paintEvent(event);
196
197     if( text().isEmpty() && progr == 0 )
198     {
199         QStyleOptionFrame option;
200         initStyleOption(&option);
201         QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &option, this);
202         QPainter painter(this);
203         painter.setPen(Qt::gray);
204         painter.drawText(textRect,
205                          Qt::AlignVCenter | Qt::AlignCenter,
206                          i18n("Type here to search your bookmarks, history and the web...")
207                         );
208     }
209 }
210
211
212 void UrlBar::keyPressEvent(QKeyEvent *event)
213 {
214     // this handles the Modifiers + Return key combinations
215     QString currentText = text().trimmed();
216     if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
217             && !currentText.startsWith(QL1S("http://"), Qt::CaseInsensitive))
218     {
219         QString append;
220         if (event->modifiers() == Qt::ControlModifier)
221         {
222             append = QL1S(".com");
223         }
224         else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier))
225         {
226             append = QL1S(".org");
227         }
228         else if (event->modifiers() == Qt::ShiftModifier)
229         {
230             append = QL1S(".net");
231         }
232
233         QUrl url(QL1S("http://www.") + currentText);
234         QString host = url.host();
235         if (!host.endsWith(append, Qt::CaseInsensitive))
236         {
237             host += append;
238             url.setHost(host);
239             setText(url.toString());
240         }
241     }
242
243     if (event->key() == Qt::Key_Escape)
244     {
245         clearFocus();
246         event->accept();
247     }
248
249     KLineEdit::keyPressEvent(event);
250 }
251
252
253 void UrlBar::focusInEvent(QFocusEvent *event)
254 {
255     activateSuggestions(true);
256
257     KLineEdit::focusInEvent(event);
258 }
259
260
261 void UrlBar::setPrivateMode(bool on)
262 {
263     _privateMode = on;
264 }
265
266
267 void UrlBar::dropEvent(QDropEvent *event)
268 {
269     KLineEdit::dropEvent(event);
270     activated(text());
271 }
272
273
274 void UrlBar::loadFinished()
275 {
276     if (_tab->progress() != 0)
277         return;
278
279     if (_tab->url().scheme() == QL1S("about"))
280     {
281         update();
282         return;
283     }
284
285     // show KGet downloads??
286     if (ReKonfig::kgetList())
287     {
288         IconButton *bt = addRightIcon(UrlBar::KGet);
289         connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(downloadAllContentsWithKGet(QPoint)));
290     }
291
292     // show RSS
293     if (_tab->hasRSSInfo())
294     {
295         IconButton *bt = addRightIcon(UrlBar::RSS);
296         connect(bt, SIGNAL(clicked(QPoint)), _tab, SLOT(showRSSInfo(QPoint)));
297     }
298
299     // show SSL
300     if (_tab->url().scheme() == QL1S("https"))
301     {
302         IconButton *bt = addRightIcon(UrlBar::SSL);
303         connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(showSSLInfo(QPoint)));
304     }
305
306     // we need to update urlbar after the right icon settings
307     // removing this code (where setStyleSheet automatically calls update) needs adding again 
308     // an update call
309     kDebug() << "resetting stylesheet";
310     int rightIconWidth = 25 * (_rightIconsList.count());
311     setStyleSheet(QString("UrlBar { padding: 0 %2px 0 %1px;} ").arg(_icon->sizeHint().width()).arg(rightIconWidth));
312 }
313
314
315 void UrlBar::loadTyped(const QString &text)
316 {
317     activated( KUrl(text) );
318 }
319
320
321 void UrlBar::activateSuggestions(bool b)
322 {
323     if (b)
324     {
325         if (_box.isNull())
326         {
327             _box = new CompletionWidget(this);
328             installEventFilter(_box.data());
329             connect(_box.data(), SIGNAL(chosenUrl(const KUrl &, Rekonq::OpenType)), this, SLOT(activated(const KUrl &, Rekonq::OpenType)));
330
331             // activate suggestions on edit text
332             connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(detectTypedString(const QString &)));
333         }
334     }
335     else
336     {
337         disconnect(this, SIGNAL(textChanged(const QString &)), this, SLOT(detectTypedString(const QString &)));
338         removeEventFilter(_box.data());
339         _box.data()->deleteLater();
340     }
341 }
342
343
344 void UrlBar::mouseDoubleClickEvent(QMouseEvent *)
345 {
346     selectAll();
347 }
348
349
350 IconButton *UrlBar::addRightIcon(UrlBar::icon ic)
351 {
352     IconButton *rightIcon = new IconButton(this);
353
354     switch (ic)
355     {
356     case UrlBar::KGet:
357         rightIcon->setIcon(KIcon("download"));
358         rightIcon->setToolTip(i18n("List all links with KGet"));
359         break;
360     case UrlBar::RSS:
361         rightIcon->setIcon(KIcon("application-rss+xml"));
362         rightIcon->setToolTip(i18n("List all available RSS feeds"));
363         break;
364     case UrlBar::SSL:
365         rightIcon->setIcon(KIcon("object-locked"));
366         rightIcon->setToolTip(i18n("Show SSL Info"));
367         break;
368     default:
369         kDebug() << "ERROR.. default non extant case!!";
370         break;
371     }
372
373     _rightIconsList << rightIcon;
374     int iconsCount = _rightIconsList.count();
375     int iconHeight = (height() - 18) / 2;
376     rightIcon->move(width() - 23*iconsCount, iconHeight);
377     rightIcon->show();
378
379     return rightIcon;
380 }
381
382
383 void UrlBar::clearRightIcons()
384 {
385     qDeleteAll(_rightIconsList);
386     _rightIconsList.clear();
387 }
388
389
390 void UrlBar::resizeEvent(QResizeEvent *event)
391 {
392     int newHeight = (height() - 18) / 2;
393     _icon->move(4, newHeight);
394
395     int iconsCount = _rightIconsList.count();
396     int w = width();
397
398     for (int i = 0; i < iconsCount; ++i)
399     {
400         IconButton *bt = _rightIconsList.at(i);
401         bt->move(w - 25*(i + 1), newHeight);
402     }
403
404     KLineEdit::resizeEvent(event);
405 }
406
407
408 void UrlBar::detectTypedString(const QString &typed)
409 {
410     if(typed.count() == 1)
411     {
412         QTimer::singleShot(0, this, SLOT(suggest()));
413         return;
414     }
415     
416     if(_suggestionTimer->isActive())
417         _suggestionTimer->stop();
418     _suggestionTimer->start(50);
419 }
420
421
422 void UrlBar::suggest()
423 {
424     if(!_box.isNull())
425         _box.data()->suggestUrls( text() );
426 }