Changeset View
Standalone View
kcms/componentchooser/componentchooser.cpp
Show All 28 Lines | |||||
29 | #include <kstandarddirs.h> | 29 | #include <kstandarddirs.h> | ||
30 | #include <kmimetypetrader.h> | 30 | #include <kmimetypetrader.h> | ||
31 | #include <kurlrequester.h> | 31 | #include <kurlrequester.h> | ||
32 | #include <ktoolinvocation.h> | 32 | #include <ktoolinvocation.h> | ||
33 | #include <kconfiggroup.h> | 33 | #include <kconfiggroup.h> | ||
34 | #include <KServiceTypeTrader> | 34 | #include <KServiceTypeTrader> | ||
35 | #include <KGlobal> | 35 | #include <KGlobal> | ||
36 | #include <QIcon> | 36 | #include <QIcon> | ||
37 | #include <QLabel> | ||||
37 | #include <KLocalizedString> | 38 | #include <KLocalizedString> | ||
38 | 39 | #include <KBuildSycocaProgressDialog> | |||
39 | | ||||
40 | //BEGIN General kpart based Component selection | | |||
41 | | ||||
42 | CfgComponent::CfgComponent(QWidget *parent) | | |||
43 | : QWidget(parent), Ui::ComponentConfig_UI(), CfgPlugin() | | |||
44 | { | | |||
45 | setupUi( this ); | | |||
46 | connect(ComponentSelector,SIGNAL(activated(const QString&)),this,SLOT(slotComponentChanged(const QString&))); | | |||
47 | } | | |||
48 | | ||||
49 | CfgComponent::~CfgComponent() | | |||
50 | { | | |||
51 | } | | |||
52 | | ||||
53 | void CfgComponent::slotComponentChanged(const QString&) { | | |||
54 | emit changed(true); | | |||
55 | } | | |||
56 | | ||||
57 | void CfgComponent::save(KConfig *cfg) { | | |||
58 | // yes, this can happen if there are NO KTrader offers for this component | | |||
59 | if (!m_lookupDict.contains(ComponentSelector->currentText())) | | |||
60 | return; | | |||
61 | | ||||
62 | KConfigGroup mainGroup = cfg->group(QByteArray()); | | |||
63 | QString serviceTypeToConfigure=mainGroup.readEntry("ServiceTypeToConfigure"); | | |||
64 | KConfig store(mainGroup.readPathEntry("storeInFile", QStringLiteral("null"))); | | |||
65 | KConfigGroup cg(&store, mainGroup.readEntry("valueSection")); | | |||
66 | cg.writePathEntry(mainGroup.readEntry("valueName", "kcm_componenchooser_null"), | | |||
67 | m_lookupDict.value(ComponentSelector->currentText())); | | |||
68 | store.sync(); | | |||
69 | emit changed(false); | | |||
70 | } | | |||
71 | | ||||
72 | void CfgComponent::load(KConfig *cfg) { | | |||
73 | | ||||
74 | ComponentSelector->clear(); | | |||
75 | m_lookupDict.clear(); | | |||
76 | m_revLookupDict.clear(); | | |||
77 | | ||||
78 | const KConfigGroup mainGroup = cfg->group(QByteArray()); | | |||
79 | const QString serviceTypeToConfigure = mainGroup.readEntry("ServiceTypeToConfigure"); | | |||
80 | | ||||
81 | const KService::List offers = KServiceTypeTrader::self()->query(serviceTypeToConfigure); | | |||
82 | | ||||
83 | for (const auto &service: offers) { | | |||
84 | ComponentSelector->addItem(service->name()); | | |||
85 | m_lookupDict.insert(service->name(), service->desktopEntryName()); | | |||
86 | m_revLookupDict.insert(service->desktopEntryName(), service->name()); | | |||
87 | } | | |||
88 | | ||||
89 | KConfig store(mainGroup.readPathEntry("storeInFile",QStringLiteral("null"))); | | |||
90 | const KConfigGroup group(&store, mainGroup.readEntry("valueSection")); | | |||
91 | QString setting = group.readEntry(mainGroup.readEntry("valueName","kcm_componenchooser_null"), QString()); | | |||
92 | | ||||
93 | if (setting.isEmpty()) | | |||
94 | setting = mainGroup.readEntry("defaultImplementation", QString()); | | |||
95 | QString tmp = m_revLookupDict.value(setting); | | |||
96 | if (!tmp.isEmpty()) { | | |||
97 | for (int i=0;i<ComponentSelector->count();i++) | | |||
98 | if (tmp==ComponentSelector->itemText(i)) | | |||
99 | { | | |||
100 | ComponentSelector->setCurrentIndex(i); | | |||
101 | break; | | |||
102 | } | | |||
103 | } | | |||
104 | emit changed(false); | | |||
105 | } | | |||
106 | | ||||
107 | void CfgComponent::defaults() | | |||
108 | { | | |||
109 | //todo | | |||
110 | } | | |||
111 | | ||||
112 | bool CfgComponent::isDefaults() const | | |||
113 | { | | |||
114 | return false; | | |||
115 | } | | |||
116 | | ||||
117 | //END General kpart based Component selection | | |||
118 | | ||||
119 | | ||||
120 | | ||||
121 | | ||||
122 | 40 | | |||
123 | 41 | | |||
124 | ComponentChooser::ComponentChooser(QWidget *parent): | 42 | ComponentChooser::ComponentChooser(QWidget *parent): | ||
125 | QWidget(parent), Ui::ComponentChooser_UI(), somethingChanged(false), configWidget(nullptr) | 43 | QWidget(parent), Ui::ComponentChooser_UI() | ||
126 | { | 44 | { | ||
127 | setupUi(this); | 45 | setupUi(this); | ||
128 | static_cast<QGridLayout*>(layout())->setRowStretch(1, 1); | | |||
129 | 46 | | |||
130 | const QStringList directories = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kcm_componentchooser"), QStandardPaths::LocateDirectory); | 47 | const QStringList directories = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kcm_componentchooser"), QStandardPaths::LocateDirectory); | ||
131 | QStringList services; | 48 | QStringList services; | ||
132 | for(const QString &directory : directories) { | 49 | for(const QString &directory : directories) { | ||
133 | const QDir dir(directory); | 50 | const QDir dir(directory); | ||
134 | for(const QString &f: dir.entryList(QStringList("*.desktop"))) { | 51 | for(const QString &f: dir.entryList(QStringList("*.desktop"))) { | ||
135 | services += dir.absoluteFilePath(f); | 52 | services += dir.absoluteFilePath(f); | ||
136 | } | 53 | } | ||
137 | } | 54 | } | ||
138 | 55 | | |||
139 | for (const QString &service : qAsConst(services)) | 56 | for (const QString &service : qAsConst(services)) | ||
140 | { | 57 | { | ||
141 | KConfig cfg(service, KConfig::SimpleConfig); | 58 | KConfig cfg(service, KConfig::SimpleConfig); | ||
142 | KConfigGroup cg = cfg.group(QByteArray()); | 59 | KConfigGroup cg = cfg.group(QByteArray()); | ||
143 | QListWidgetItem *item = new QListWidgetItem( | | |||
144 | QIcon::fromTheme(cg.readEntry("Icon",QStringLiteral("preferences-desktop-default-applications"))), | | |||
145 | cg.readEntry("Name",i18n("Unknown"))); | | |||
146 | item->setData(Qt::UserRole, service); | | |||
147 | ServiceChooser->addItem(item); | | |||
148 | loadConfigWidget(service, cfg.group(QByteArray()).readEntry("configurationType"), item->text()); | | |||
149 | } | | |||
150 | ServiceChooser->setFixedWidth(ServiceChooser->sizeHintForColumn(0) + 20); | | |||
151 | ServiceChooser->sortItems(); | | |||
152 | connect(ServiceChooser,&QListWidget::currentItemChanged,this,&ComponentChooser::slotServiceSelected); | | |||
153 | ServiceChooser->setCurrentRow(0); | | |||
154 | } | | |||
155 | 60 | | |||
156 | void ComponentChooser::loadConfigWidget(const QString &service, const QString &cfgType, const QString &name) | 61 | // fill the form layout | ||
157 | { | 62 | const auto name = cg.readEntry("Name",i18n("Unknown")); | ||
158 | QWidget *loadedConfigWidget = nullptr; | 63 | const auto loadedConfigWidget = loadConfigWidget(cfg.group(QByteArray()).readEntry("configurationType")); | ||
159 | if (cfgType.isEmpty() || (cfgType == QLatin1String("component"))) | 64 | | ||
160 | { | 65 | QLabel *label = new QLabel(i18nc("The label for the combobox : browser, terminal emulator...)", "%1:", name), this); | ||
161 | loadedConfigWidget = new CfgComponent(configContainer); | 66 | label->setToolTip(cfg.group(QByteArray()).readEntry("Comment", QString())); | ||
broulik: It appears you dropped the generic component configuration? If that even was a thing... makes… | |||||
162 | static_cast<CfgComponent*>(loadedConfigWidget)->ChooserDocu->setText(i18n("Choose from the list below which component should be used by default for the %1 service.", name)); | 67 | | ||
68 | formLayout->addRow(label, loadedConfigWidget); | ||||
69 | | ||||
70 | connect(loadedConfigWidget, SIGNAL(changed(bool)), this, SLOT(emitChanged(bool))); | ||||
71 | | ||||
72 | configWidgetMap.insert(service, loadedConfigWidget); | ||||
73 | } | ||||
163 | } | 74 | } | ||
164 | else if (cfgType==QLatin1String("internal_email")) | 75 | | ||
76 | QWidget *ComponentChooser::loadConfigWidget(const QString &cfgType) | ||||
165 | { | 77 | { | ||
166 | loadedConfigWidget = new CfgEmailClient(configContainer); | 78 | QComboBox *loadedConfigWidget = nullptr; | ||
79 | | ||||
80 | if (cfgType==QLatin1String("internal_email")) { | ||||
I know it's older code but since you touched it, what about adding the spaces around == ? ervin: I know it's older code but since you touched it, what about adding the spaces around == ? | |||||
81 | loadedConfigWidget = new CfgEmailClient(this); | ||||
167 | } | 82 | } | ||
168 | #ifdef Q_OS_UNIX | 83 | #ifdef Q_OS_UNIX | ||
169 | else if (cfgType==QLatin1String("internal_terminal")) | 84 | else if (cfgType==QLatin1String("internal_terminal")) { | ||
170 | { | 85 | loadedConfigWidget = new CfgTerminalEmulator(this); | ||
171 | loadedConfigWidget = new CfgTerminalEmulator(configContainer); | | |||
172 | } | 86 | } | ||
173 | #endif | 87 | #endif | ||
174 | else if (cfgType==QLatin1String("internal_filemanager")) | 88 | else if (cfgType==QLatin1String("internal_filemanager")) { | ||
175 | { | 89 | loadedConfigWidget = new CfgFileManager(this); | ||
ervin: Missing space after comma | |||||
176 | loadedConfigWidget = new CfgFileManager(configContainer); | 90 | } else if (cfgType==QLatin1String("internal_browser")) { | ||
177 | } | 91 | loadedConfigWidget = new CfgBrowser(this); | ||
178 | else if (cfgType==QLatin1String("internal_browser")) | | |||
179 | { | | |||
180 | loadedConfigWidget = new CfgBrowser(configContainer); | | |||
181 | } | 92 | } | ||
93 | loadedConfigWidget->setSizeAdjustPolicy(QComboBox::AdjustToContents); | ||||
182 | 94 | | |||
183 | if (loadedConfigWidget) { | 95 | return loadedConfigWidget; | ||
184 | configWidgetMap.insert(service, loadedConfigWidget); | | |||
185 | configContainer->addWidget(loadedConfigWidget); | | |||
186 | connect(loadedConfigWidget, SIGNAL(changed(bool)), this, SLOT(emitChanged(bool))); | | |||
187 | } | | |||
188 | } | 96 | } | ||
broulik: Superfluous space before `:` | |||||
189 | 97 | | |||
190 | void ComponentChooser::slotServiceSelected(QListWidgetItem* it) { | 98 | void ComponentChooser::emitChanged(bool val) { | ||
ervin: Curly brace on its own line. | |||||
broulik: Use new connect syntax | |||||
191 | if (!it) return; | | |||
192 | 99 | | |||
193 | if (somethingChanged) { | 100 | bool somethingChanged = val; | ||
Does that make any sense to keep the val parameter on that method if you loop through all the plugins because of defaulted anyway? ervin: Does that make any sense to keep the val parameter on that method if you loop through all the… | |||||
ervin: I still think val is useless. | |||||
I kept it as the compiler might be able to do some optimization in the loop when val is true line 105. meven: I kept it as the compiler might be able to do some optimization in the loop when val is true… | |||||
I don't think you'd find a compiler doing this, there's nothing ensuring that hasChanged doesn't modify some mutable variable (cache management or such). I don't think one can safely spare the call in the general case. ervin: I don't think you'd find a compiler doing this, there's nothing ensuring that hasChanged… | |||||
194 | if (KMessageBox::questionYesNo(this,i18n("<qt>You changed the default component of your choice, do want to save that change now ?</qt>"),QString(),KStandardGuiItem::save(),KStandardGuiItem::discard())==KMessageBox::Yes) save(); | 101 | if (!somethingChanged) { | ||
102 | // check if another plugin has changed | ||||
103 | for (auto it= configWidgetMap.constKeyValueBegin(); it != configWidgetMap.constKeyValueEnd(); ++it) { | ||||
ervin: Space before = missing | |||||
broulik: `isDefaults` | |||||
104 | CfgPlugin *plugin = dynamic_cast<CfgPlugin *>( (*it).second ); | ||||
ervin: No need for the spaces within the parenthesis | |||||
105 | somethingChanged |= plugin->hasChanged(); | ||||
broulik: You don't actually use the `key`, so you can just use range-for. | |||||
ervin: No space after * and missing qAsConst | |||||
195 | } | 106 | } | ||
196 | const QString &service = it->data(Qt::UserRole).toString(); | | |||
197 | KConfig cfg(service, KConfig::SimpleConfig); | | |||
198 | | ||||
199 | ComponentDescription->setText(cfg.group(QByteArray()).readEntry("Comment",i18n("No description available"))); | | |||
200 | ComponentDescription->setMinimumSize(ComponentDescription->sizeHint()); | | |||
201 | | ||||
202 | configWidget = configWidgetMap.value(service); | | |||
203 | if (configWidget) { | | |||
204 | configContainer->setCurrentWidget(configWidget); | | |||
205 | const auto plugin = dynamic_cast<CfgPlugin*>(configWidget); | | |||
206 | headerGroupBox->setTitle(it->text()); | | |||
207 | plugin->load(&cfg); | | |||
208 | emit defaulted(plugin->isDefaults()); | | |||
209 | } | 107 | } | ||
108 | emit changed(somethingChanged); | ||||
broulik: Check if `loadedConfigWidget` is null | |||||
meven: I'd rather have a Q_ASSERT : this isn't supposed to happen | |||||
210 | 109 | | |||
211 | emitChanged(false); | 110 | bool isDefault = true; | ||
212 | latestEditedService = service; | 111 | for (auto it= configWidgetMap.constKeyValueBegin(); it != configWidgetMap.constKeyValueEnd(); ++it) { | ||
ervin: Ditto | |||||
112 | CfgPlugin *plugin = dynamic_cast<CfgPlugin *>( (*it).second ); | ||||
ervin: Ditto | |||||
113 | isDefault &= plugin->isDefaults(); | ||||
213 | } | 114 | } | ||
214 | 115 | | |||
215 | 116 | emit defaulted(isDefault); | |||
216 | void ComponentChooser::emitChanged(bool val) { | | |||
217 | somethingChanged=val; | | |||
218 | emit changed(val); | | |||
219 | | ||||
220 | CfgPlugin *plugin = dynamic_cast<CfgPlugin *>( configWidget ); | | |||
221 | emit defaulted(plugin->isDefaults()); | | |||
222 | } | 117 | } | ||
223 | 118 | | |||
224 | | ||||
225 | ComponentChooser::~ComponentChooser() | 119 | ComponentChooser::~ComponentChooser() | ||
226 | { | 120 | { | ||
227 | for (QWidget *configWidget : configWidgetMap) { | 121 | for (QWidget *configWidget : configWidgetMap) { | ||
228 | delete configWidget; | 122 | delete configWidget; | ||
229 | } | 123 | } | ||
230 | } | 124 | } | ||
231 | 125 | | |||
232 | void ComponentChooser::load() { | 126 | void ComponentChooser::load() { | ||
233 | if( configWidget ) | 127 | for (auto it= configWidgetMap.constKeyValueBegin(); it != configWidgetMap.constKeyValueEnd(); ++it) { | ||
ervin: Space before = | |||||
234 | { | 128 | | ||
235 | CfgPlugin * plugin = dynamic_cast<CfgPlugin*>( configWidget ); | 129 | const auto service = (*it).first; | ||
236 | if( plugin ) | 130 | const auto widget = (*it).second; | ||
237 | { | 131 | | ||
238 | KConfig cfg(latestEditedService, KConfig::SimpleConfig); | 132 | CfgPlugin * plugin = dynamic_cast<CfgPlugin*>( widget ); | ||
ervin: No space after *, no space within parenthesis | |||||
ervin: No space within parenthesis | |||||
133 | if (plugin) { | ||||
134 | KConfig cfg(service, KConfig::SimpleConfig); | ||||
239 | plugin->load( &cfg ); | 135 | plugin->load( &cfg ); | ||
240 | } | 136 | } | ||
broulik: normal `constBegin()` and then `it.key()` and `it.value()` below | |||||
241 | } | 137 | } | ||
242 | } | 138 | } | ||
243 | 139 | | |||
244 | void ComponentChooser::save() { | 140 | void ComponentChooser::save() { | ||
245 | if( configWidget ) | 141 | for (auto it= configWidgetMap.constKeyValueBegin(); it != configWidgetMap.constKeyValueEnd(); ++it){ | ||
ervin: Ditto | |||||
246 | { | 142 | | ||
247 | CfgPlugin* plugin = dynamic_cast<CfgPlugin*>( configWidget ); | 143 | const auto service = (*it).first; | ||
248 | if( plugin ) | 144 | const auto widget = (*it).second; | ||
249 | { | 145 | | ||
250 | KConfig cfg(latestEditedService, KConfig::SimpleConfig); | 146 | CfgPlugin* plugin = dynamic_cast<CfgPlugin*>( widget ); | ||
ervin: Ditto | |||||
ervin: No space between parenthesis | |||||
147 | if (plugin) { | ||||
In some places you check if your dynamic_cast worked and sometimes you don't. Since we only put CfgPlugin instanes in there, I don't think we need to check. See my note on the ominous plug-in architecture above. broulik: In some places you check if your `dynamic_cast` worked and sometimes you don't. Since we only… | |||||
148 | KConfig cfg(service, KConfig::SimpleConfig); | ||||
ervin: Missing space before { | |||||
251 | plugin->save( &cfg ); | 149 | plugin->save( &cfg ); | ||
252 | } | 150 | } | ||
253 | } | 151 | } | ||
152 | | ||||
153 | // refresh System configuration cache | ||||
154 | KBuildSycocaProgressDialog::rebuildKSycoca(this); | ||||
254 | } | 155 | } | ||
255 | 156 | | |||
256 | void ComponentChooser::restoreDefault() { | 157 | void ComponentChooser::restoreDefault() { | ||
257 | if (configWidget) | 158 | for (const auto &configWidget : configWidgetMap) { | ||
broulik: The hash contains pointers, so `auto *` | |||||
258 | { | | |||
259 | dynamic_cast<CfgPlugin*>(configWidget)->defaults(); | 159 | dynamic_cast<CfgPlugin*>(configWidget)->defaults(); | ||
260 | emitChanged(true); | 160 | emitChanged(true); | ||
Space before the * and not after. Also you could have used auto or auto * for all those loops (just that const auto & makes no sense in that context). ervin: Space before the * and not after. Also you could have used auto or auto * for all those loops… | |||||
261 | } | 161 | } | ||
262 | | ||||
263 | /* | | |||
264 | txtEMailClient->setText("kmail"); | | |||
265 | chkRunTerminal->setChecked(false); | | |||
266 | | ||||
267 | // Check if -e is needed, I do not think so | | |||
268 | terminalLE->setText("xterm"); //No need for i18n | | |||
269 | terminalCB->setChecked(true); | | |||
270 | emitChanged(false); | | |||
271 | */ | | |||
272 | } | 162 | } | ||
273 | 163 | | |||
274 | // vim: sw=4 ts=4 noet | 164 | // vim: sw=4 ts=4 noet |
It appears you dropped the generic component configuration? If that even was a thing... makes me wonder why this KCM uses desktop files when it effectively only operates on a fixed set of options.
Well, so much for that I guess?