KIO

kurlnavigatorschemecombo.cpp
1/*
2 SPDX-FileCopyrightText: 2006 Aaron J. Seigo <aseigo@kde.org>
3 SPDX-FileCopyrightText: 2009 Peter Penz <peter.penz@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kurlnavigatorschemecombo_p.h"
9
10#include <QAction>
11#include <QMenu>
12#include <QPaintEvent>
13#include <QPainter>
14#include <QStyleOption>
15
16#include <KLocalizedString>
17#include <kprotocolinfo.h>
18#include <kprotocolmanager.h>
19#include <kurlnavigator.h>
20
21namespace
22{
23const int ArrowSize = 10;
24}
25
26namespace KDEPrivate
27{
28KUrlNavigatorSchemeCombo::KUrlNavigatorSchemeCombo(const QString &scheme, KUrlNavigator *parent)
29 : KUrlNavigatorButtonBase(parent)
30 , m_menu(nullptr)
31 , m_schemes()
32 , m_categories()
33{
34 m_menu = new QMenu(this);
35 connect(m_menu, &QMenu::triggered, this, &KUrlNavigatorSchemeCombo::setSchemeFromMenu);
36 setText(scheme);
37 setMenu(m_menu);
38}
39
40void KUrlNavigatorSchemeCombo::setSupportedSchemes(const QStringList &schemes)
41{
42 m_schemes = schemes;
43 m_menu->clear();
44
45 for (const QString &scheme : schemes) {
46 QAction *action = m_menu->addAction(scheme);
47 action->setData(scheme);
48 }
49}
50
51QSize KUrlNavigatorSchemeCombo::sizeHint() const
52{
53 const QSize size = KUrlNavigatorButtonBase::sizeHint();
54
55 int width = fontMetrics().boundingRect(KLocalizedString::removeAcceleratorMarker(text())).width();
56 width += (3 * BorderWidth) + ArrowSize;
57
58 return QSize(width, size.height());
59}
60
61void KUrlNavigatorSchemeCombo::setScheme(const QString &scheme)
62{
63 setText(scheme);
64}
65
66QString KUrlNavigatorSchemeCombo::currentScheme() const
67{
68 return text();
69}
70
71void KUrlNavigatorSchemeCombo::showEvent(QShowEvent *event)
72{
73 KUrlNavigatorButtonBase::showEvent(event);
74 if (!event->spontaneous() && m_schemes.isEmpty()) {
75 m_schemes = KProtocolInfo::protocols();
76
77 auto it = std::remove_if(m_schemes.begin(), m_schemes.end(), [](const QString &s) {
78 QUrl url;
79 url.setScheme(s);
80 return !KProtocolManager::supportsListing(url);
81 });
82 m_schemes.erase(it, m_schemes.end());
83
84 std::sort(m_schemes.begin(), m_schemes.end());
85
86 updateMenu();
87 }
88}
89
90void KUrlNavigatorSchemeCombo::paintEvent(QPaintEvent *event)
91{
92 Q_UNUSED(event);
93
94 QPainter painter(this);
95 const int buttonWidth = width();
96 const int buttonHeight = height();
97
98 drawHoverBackground(&painter);
99
100 const QColor fgColor = foregroundColor();
101 painter.setPen(fgColor);
102
103 // draw arrow
104 const int arrowX = buttonWidth - ArrowSize - BorderWidth;
105 const int arrowY = (buttonHeight - ArrowSize) / 2;
106
107 QStyleOption option;
108 option.rect = QRect(arrowX, arrowY, ArrowSize, ArrowSize);
109 option.palette = palette();
110 option.palette.setColor(QPalette::Text, fgColor);
111 option.palette.setColor(QPalette::WindowText, fgColor);
112 option.palette.setColor(QPalette::ButtonText, fgColor);
113 style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &option, &painter, this);
114
115 // draw text
116 const int textWidth = arrowX - (2 * BorderWidth);
117 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
118 if (!style()->styleHint(QStyle::SH_UnderlineShortcut, &option, this)) {
119 alignment |= Qt::TextHideMnemonic;
120 }
121 style()->drawItemText(&painter, QRect(BorderWidth, 0, textWidth, buttonHeight), alignment, option.palette, isEnabled(), text());
122}
123
124void KUrlNavigatorSchemeCombo::setSchemeFromMenu(QAction *action)
125{
126 const QString scheme = action->data().toString();
127 setText(scheme);
128 Q_EMIT activated(scheme);
129}
130
131void KUrlNavigatorSchemeCombo::updateMenu()
132{
133 initializeCategories();
134 std::sort(m_schemes.begin(), m_schemes.end());
135
136 // move all schemes into the corresponding category of 'items'
137 QList<QString> items[CategoryCount];
138 for (const QString &scheme : std::as_const(m_schemes)) {
139 if (m_categories.contains(scheme)) {
140 const SchemeCategory category = m_categories.value(scheme);
141 items[category].append(scheme);
142 } else {
143 items[OtherCategory].append(scheme);
144 }
145 }
146
147 // Create the menu that includes all entries from 'items'. The categories
148 // CoreCategory and PlacesCategory are placed at the top level, the remaining
149 // categories are placed in sub menus.
150 QMenu *menu = m_menu;
151 for (int category = 0; category < CategoryCount; ++category) {
152 if (!items[category].isEmpty()) {
153 switch (category) {
154 case DevicesCategory:
155 menu = m_menu->addMenu(i18nc("@item:inmenu", "Devices"));
156 break;
157
158 case SubversionCategory:
159 menu = m_menu->addMenu(i18nc("@item:inmenu", "Subversion"));
160 break;
161
162 case OtherCategory:
163 menu = m_menu->addMenu(i18nc("@item:inmenu", "Other"));
164 break;
165
166 case CoreCategory:
167 case PlacesCategory:
168 default:
169 break;
170 }
171
172 for (const QString &scheme : std::as_const(items[category])) {
173 QAction *action = menu->addAction(scheme);
174 action->setData(scheme);
175 }
176
177 if (menu == m_menu) {
178 menu->addSeparator();
179 }
180 }
181 }
182}
183
184void KUrlNavigatorSchemeCombo::initializeCategories()
185{
186 if (m_categories.isEmpty()) {
187 m_categories.insert(QStringLiteral("file"), CoreCategory);
188 m_categories.insert(QStringLiteral("ftp"), CoreCategory);
189 m_categories.insert(QStringLiteral("fish"), CoreCategory);
190 m_categories.insert(QStringLiteral("nfs"), CoreCategory);
191 m_categories.insert(QStringLiteral("sftp"), CoreCategory);
192 m_categories.insert(QStringLiteral("smb"), CoreCategory);
193 m_categories.insert(QStringLiteral("webdav"), CoreCategory);
194
195 m_categories.insert(QStringLiteral("desktop"), PlacesCategory);
196 m_categories.insert(QStringLiteral("fonts"), PlacesCategory);
197 m_categories.insert(QStringLiteral("programs"), PlacesCategory);
198 m_categories.insert(QStringLiteral("settings"), PlacesCategory);
199 m_categories.insert(QStringLiteral("trash"), PlacesCategory);
200
201 m_categories.insert(QStringLiteral("floppy"), DevicesCategory);
202 m_categories.insert(QStringLiteral("camera"), DevicesCategory);
203 m_categories.insert(QStringLiteral("remote"), DevicesCategory);
204
205 m_categories.insert(QStringLiteral("svn"), SubversionCategory);
206 m_categories.insert(QStringLiteral("svn+file"), SubversionCategory);
207 m_categories.insert(QStringLiteral("svn+http"), SubversionCategory);
208 m_categories.insert(QStringLiteral("svn+https"), SubversionCategory);
209 m_categories.insert(QStringLiteral("svn+ssh"), SubversionCategory);
210 }
211}
212
213} // namespace KDEPrivate
214
215#include "moc_kurlnavigatorschemecombo_p.cpp"
static QString removeAcceleratorMarker(const QString &label)
static QStringList protocols()
Returns list of all known protocols.
Widget that allows to navigate through the paths of an URL.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
Category category(StandardShortcut id)
QVariant data() const const
void setData(const QVariant &data)
void append(QList< T > &&value)
void clear()
QAction * addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
QAction * addMenu(QMenu *menu)
QAction * addSeparator()
void triggered(QAction *action)
int height() const const
PE_IndicatorArrowDown
SH_UnderlineShortcut
AlignCenter
TextShowMnemonic
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:52 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.