1 | /* This file is part of the KDE project |
2 | |
3 | Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #include <KDE/KStandardDirs> |
22 | #include <KDE/KGlobal> |
23 | #include <KDE/KComponentData> |
24 | #include <KDE/KGlobalSettings> |
25 | #include <KDE/KStyle> |
26 | #include <KDE/KConfigGroup> |
27 | #include <KDE/KIcon> |
28 | #include <KDE/KFileDialog> |
29 | #include <KDE/KColorDialog> |
30 | #include <QtCore/QHash> |
31 | #include <QtCore/QTimer> |
32 | #include <QtGui/QFileDialog> |
33 | #include <QtGui/QColorDialog> |
34 | #include <QtGui/QApplication> |
35 | #include <QtGui/QToolButton> |
36 | #include <QtGui/QToolBar> |
37 | #include <QtGui/QMainWindow> |
38 | #include "qguiplatformplugin_p.h" |
39 | |
40 | #include <kdebug.h> |
41 | |
42 | /* |
43 | * Map a Qt filter string into a KDE one. |
44 | * (from kfiledialog.cpp) |
45 | */ |
46 | static QString qt2KdeFilter(const QString &f) |
47 | { |
48 | QString filter; |
49 | QTextStream str(&filter, QIODevice::WriteOnly); |
50 | const QStringList list(f.split(";;" ).replaceInStrings("/" , "\\/" )); |
51 | QStringList::const_iterator it(list.begin()), |
52 | end(list.end()); |
53 | bool first=true; |
54 | |
55 | for(; it!=end; ++it) |
56 | { |
57 | int ob=(*it).lastIndexOf('('), |
58 | cb=(*it).lastIndexOf(')'); |
59 | |
60 | if(-1!=cb && ob<cb) |
61 | { |
62 | if(first) |
63 | first=false; |
64 | else |
65 | str << '\n'; |
66 | str << (*it).mid(ob+1, (cb-ob)-1) << '|' << (*it).mid(0, ob); |
67 | } |
68 | } |
69 | return filter; |
70 | } |
71 | |
72 | /* |
73 | * Map a KDE filter string into a Qt one. |
74 | * (from kfiledialog.cpp) |
75 | */ |
76 | static void kde2QtFilter(const QString &orig, const QString &kde, QString *sel) |
77 | { |
78 | if(sel) |
79 | { |
80 | const QStringList list(orig.split(";;" )); |
81 | QStringList::const_iterator it(list.begin()), |
82 | end(list.end()); |
83 | int pos; |
84 | |
85 | for(; it!=end; ++it) |
86 | if(-1!=(pos=(*it).indexOf(kde)) && pos>0 && |
87 | ('('==(*it)[pos-1] || ' '==(*it)[pos-1]) && |
88 | (*it).length()>=kde.length()+pos && |
89 | (')'==(*it)[pos+kde.length()] || ' '==(*it)[pos+kde.length()])) |
90 | { |
91 | *sel=*it; |
92 | return; |
93 | } |
94 | } |
95 | } |
96 | |
97 | |
98 | class KFileDialogBridge : public KFileDialog |
99 | { |
100 | public: |
101 | KFileDialogBridge (const KUrl &startDir, const QString &filter, QFileDialog *original_) |
102 | : KFileDialog (startDir, filter, original_), original(original_) |
103 | { |
104 | connect(this, SIGNAL(fileSelected(QString)), original, SIGNAL(currentChanged(QString))); |
105 | } |
106 | |
107 | virtual void accept() |
108 | { |
109 | kDebug(); |
110 | KFileDialog::accept(); |
111 | QMetaObject::invokeMethod(original, "accept" ); //workaround protected |
112 | } |
113 | |
114 | virtual void reject() |
115 | { |
116 | kDebug(); |
117 | KFileDialog::reject(); |
118 | QMetaObject::invokeMethod(original, "reject" ); //workaround protected |
119 | } |
120 | |
121 | QFileDialog *original; |
122 | }; |
123 | |
124 | class KColorDialogBridge : public KColorDialog |
125 | { |
126 | public: |
127 | KColorDialogBridge(QColorDialog* original_ = 0L) : KColorDialog(original_, true) , original(original_) |
128 | { |
129 | connect(this, SIGNAL(colorSelected(QColor)), original, SIGNAL(currentColorChanged(QColor))); |
130 | } |
131 | |
132 | QColorDialog *original; |
133 | |
134 | virtual void accept() |
135 | { |
136 | KColorDialog::accept(); |
137 | original->setCurrentColor(color()); |
138 | QMetaObject::invokeMethod(original, "accept" ); //workaround protected |
139 | } |
140 | |
141 | virtual void reject() |
142 | { |
143 | KColorDialog::reject(); |
144 | QMetaObject::invokeMethod(original, "reject" ); //workaround protected |
145 | } |
146 | }; |
147 | |
148 | Q_DECLARE_METATYPE(KFileDialogBridge *) |
149 | Q_DECLARE_METATYPE(KColorDialogBridge *) |
150 | |
151 | class KQGuiPlatformPlugin : public QGuiPlatformPlugin |
152 | { |
153 | Q_OBJECT |
154 | public: |
155 | KQGuiPlatformPlugin() |
156 | { |
157 | QMetaObject::invokeMethod(this, "init" , Qt::QueuedConnection); |
158 | } |
159 | |
160 | virtual QStringList keys() const { return QStringList() << QLatin1String("kde" ); } |
161 | virtual QString styleName() |
162 | { |
163 | const QString defaultStyle = KStyle::defaultStyle(); |
164 | const KConfigGroup pConfig(KGlobal::config(), "General" ); |
165 | return pConfig.readEntry("widgetStyle" , defaultStyle); |
166 | } |
167 | virtual QPalette palette() |
168 | { |
169 | return KGlobalSettings::createApplicationPalette(); |
170 | } |
171 | virtual QString systemIconThemeName() |
172 | { |
173 | return KIconTheme::current(); |
174 | } |
175 | virtual QStringList iconThemeSearchPaths() |
176 | { |
177 | return KGlobal::dirs()->resourceDirs("icon" ); |
178 | } |
179 | virtual QIcon fileSystemIcon(const QFileInfo &file) |
180 | { |
181 | return KIcon(KMimeType::findByPath(file.filePath(), 0, true)->iconName()); |
182 | } |
183 | virtual int platformHint(PlatformHint hint) |
184 | { |
185 | switch(hint) |
186 | { |
187 | case PH_ToolButtonStyle: { |
188 | KConfigGroup group(KGlobal::config(), "Toolbar style" ); |
189 | QString style = group.readEntry("ToolButtonStyle" , "TextUnderIcon" ).toLower(); |
190 | if (style == "textbesideicon" || style == "icontextright" ) |
191 | return Qt::ToolButtonTextBesideIcon; |
192 | else if (style == "textundericon" || style == "icontextbottom" ) |
193 | return Qt::ToolButtonTextUnderIcon; |
194 | else if (style == "textonly" ) |
195 | return Qt::ToolButtonTextOnly; |
196 | else |
197 | return Qt::ToolButtonIconOnly; |
198 | } |
199 | case PH_ToolBarIconSize: |
200 | return KIconLoader::global()->currentSize(KIconLoader::MainToolbar); |
201 | case PH_ItemView_ActivateItemOnSingleClick: |
202 | return KGlobalSettings::singleClick(); |
203 | default: |
204 | break; |
205 | } |
206 | return QGuiPlatformPlugin::platformHint(hint); |
207 | } |
208 | |
209 | public: // File Dialog integration |
210 | #define K_FD(QFD) KFileDialogBridge *kdefd = qvariant_cast<KFileDialogBridge *>(QFD->property("_k_bridge")) |
211 | virtual void fileDialogDelete(QFileDialog *qfd) |
212 | { |
213 | K_FD(qfd); |
214 | delete kdefd; |
215 | } |
216 | virtual bool fileDialogSetVisible(QFileDialog *qfd, bool visible) |
217 | { |
218 | K_FD(qfd); |
219 | if (!kdefd && visible) { |
220 | if(qfd->options() & QFileDialog::DontUseNativeDialog) |
221 | return false; |
222 | |
223 | kdefd = new KFileDialogBridge(KUrl::fromPath(qfd->directory().canonicalPath()), |
224 | qt2KdeFilter(qfd->nameFilters().join(";;" )), qfd); |
225 | |
226 | qfd->setProperty("_k_bridge" , QVariant::fromValue(kdefd)); |
227 | } |
228 | |
229 | if (visible) { |
230 | switch (qfd->fileMode()) { |
231 | case QFileDialog::AnyFile: |
232 | kdefd->setMode(KFile::LocalOnly | KFile::File); |
233 | break; |
234 | case QFileDialog::ExistingFile: |
235 | kdefd->setMode(KFile::LocalOnly | KFile::File | KFile::ExistingOnly); |
236 | break; |
237 | case QFileDialog::ExistingFiles: |
238 | kdefd->setMode(KFile::LocalOnly | KFile::Files | KFile::ExistingOnly); |
239 | break; |
240 | case QFileDialog::Directory: |
241 | case QFileDialog::DirectoryOnly: |
242 | kdefd->setMode(KFile::LocalOnly | KFile::Directory); |
243 | break; |
244 | } |
245 | |
246 | |
247 | kdefd->setOperationMode((qfd->acceptMode() == QFileDialog::AcceptSave) ? KFileDialog::Saving : KFileDialog::Opening); |
248 | kdefd->setCaption(qfd->windowTitle()); |
249 | kdefd->setConfirmOverwrite(qfd->confirmOverwrite()); |
250 | kdefd->setSelection(qfd->selectedFiles().value(0)); |
251 | } |
252 | kdefd->setVisible(visible); |
253 | return true; |
254 | } |
255 | virtual QDialog::DialogCode fileDialogResultCode(QFileDialog *qfd) |
256 | { |
257 | K_FD(qfd); |
258 | Q_ASSERT(kdefd); |
259 | return QDialog::DialogCode(kdefd->result()); |
260 | } |
261 | virtual void fileDialogSetDirectory(QFileDialog *qfd, const QString &directory) |
262 | { |
263 | K_FD(qfd); |
264 | kdefd->setUrl(KUrl::fromPath(directory)); |
265 | } |
266 | virtual QString fileDialogDirectory(const QFileDialog *qfd) const |
267 | { |
268 | K_FD(qfd); |
269 | Q_ASSERT(kdefd); |
270 | return kdefd->baseUrl().pathOrUrl(); |
271 | } |
272 | virtual void fileDialogSelectFile(QFileDialog *qfd, const QString &filename) |
273 | { |
274 | K_FD(qfd); |
275 | Q_ASSERT(kdefd); |
276 | kdefd->setSelection(filename); |
277 | } |
278 | virtual QStringList fileDialogSelectedFiles(const QFileDialog *qfd) const |
279 | { |
280 | K_FD(qfd); |
281 | Q_ASSERT(kdefd); |
282 | return kdefd->selectedFiles(); |
283 | } |
284 | /*virtual void fileDialogSetFilter(QFileDialog *qfd) |
285 | { |
286 | K_FD(qfd); |
287 | }*/ |
288 | virtual void fileDialogSetNameFilters(QFileDialog *qfd, const QStringList &filters) |
289 | { |
290 | K_FD(qfd); |
291 | Q_ASSERT(kdefd); |
292 | kdefd->setFilter(qt2KdeFilter(filters.join(";;" ))); |
293 | } |
294 | /*virtual void fileDialogSelectNameFilter(QFileDialog *qfd, const QString &filter) |
295 | { |
296 | K_FD(qfd); |
297 | }*/ |
298 | virtual QString fileDialogSelectedNameFilter(const QFileDialog *qfd) const |
299 | { |
300 | K_FD(qfd); |
301 | Q_ASSERT(kdefd); |
302 | QString ret; |
303 | kde2QtFilter(qfd->nameFilters().join(";;" ), kdefd->currentFilter(), &ret); |
304 | return ret; |
305 | } |
306 | public: // ColorDialog |
307 | #define K_CD(QCD) KColorDialogBridge *kdecd = qvariant_cast<KColorDialogBridge *>(QCD->property("_k_bridge")) |
308 | virtual void colorDialogDelete(QColorDialog *qcd) |
309 | { |
310 | K_CD(qcd); |
311 | delete kdecd; |
312 | |
313 | } |
314 | virtual bool colorDialogSetVisible(QColorDialog *qcd, bool visible) |
315 | { |
316 | K_CD(qcd); |
317 | if (!kdecd) { |
318 | kdecd = new KColorDialogBridge(qcd); |
319 | kdecd->setColor(qcd->currentColor()); |
320 | if (qcd->options() & QColorDialog::NoButtons) { |
321 | kdecd->setButtons(KDialog::None); |
322 | } |
323 | kdecd->setModal(qcd->isModal()); |
324 | qcd->setProperty("_k_bridge" , QVariant::fromValue(kdecd)); |
325 | } |
326 | if (visible) { |
327 | kdecd->setCaption(qcd->windowTitle()); |
328 | kdecd->setAlphaChannelEnabled(qcd->options() & QColorDialog::ShowAlphaChannel); |
329 | } |
330 | kdecd->setVisible(visible); |
331 | return true; |
332 | } |
333 | virtual void colorDialogSetCurrentColor(QColorDialog *qcd, const QColor &color) |
334 | { |
335 | K_CD(qcd); |
336 | if (kdecd) { |
337 | kdecd->setColor(color); |
338 | } |
339 | } |
340 | |
341 | private slots: |
342 | void init() |
343 | { |
344 | connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()), this, SLOT(updateToolbarIcons())); |
345 | connect(KGlobalSettings::self(), SIGNAL(toolbarAppearanceChanged(int)), this, SLOT(updateToolbarStyle())); |
346 | connect(KGlobalSettings::self(), SIGNAL(kdisplayStyleChanged()), this, SLOT(updateWidgetStyle())); |
347 | } |
348 | |
349 | void updateToolbarStyle() |
350 | { |
351 | //from gtksymbol.cpp |
352 | QWidgetList widgets = QApplication::allWidgets(); |
353 | for (int i = 0; i < widgets.size(); ++i) { |
354 | QWidget *widget = widgets.at(i); |
355 | if (qobject_cast<QToolButton*>(widget)) { |
356 | QEvent event(QEvent::StyleChange); |
357 | QApplication::sendEvent(widget, &event); |
358 | } |
359 | } |
360 | } |
361 | |
362 | void updateToolbarIcons() |
363 | { |
364 | QWidgetList widgets = QApplication::allWidgets(); |
365 | for (int i = 0; i < widgets.size(); ++i) { |
366 | QWidget *widget = widgets.at(i); |
367 | if (qobject_cast<QToolBar*>(widget) || qobject_cast<QMainWindow*>(widget)) { |
368 | QEvent event(QEvent::StyleChange); |
369 | QApplication::sendEvent(widget, &event); |
370 | } |
371 | } |
372 | } |
373 | |
374 | void updateWidgetStyle() |
375 | { |
376 | if (qApp) { |
377 | if (qApp->style()->objectName() != styleName()) { |
378 | qApp->setStyle(styleName()); |
379 | } |
380 | } |
381 | } |
382 | }; |
383 | |
384 | Q_EXPORT_PLUGIN2(KQGuiPlatformPlugin, KQGuiPlatformPlugin) |
385 | |
386 | #include "qguiplatformplugin_kde.moc" |
387 | |
388 | |