Theme engine using TQt for GTK+ 3.x
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tdegtk-theme.cpp 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. /* The TdeGtk Theming Engine for Gtk+.
  2. * Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free
  16. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  17. * MA 02110-1301, USA.
  18. *
  19. */
  20. // NOTE
  21. // GTK contains a number of bugs that will interfere with your overall visual experience
  22. // Those that I have reported can be accessed with this link:
  23. // https://bugzilla.gnome.org/buglist.cgi?type0-0-4=substring&emailcc1=1&emailreporter1=1&emaillongdesc1=1&field0-0-0=product&type0-0-1=substring&field0-0-1=component&field0-0-4=longdesc&emailtype1=substring&type0-0-3=substring&query_format=advanced&emailassigned_to1=1&field0-0-3=status_whiteboard&emailqa_contact1=1&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=NEEDINFO&bug_status=RESOLVED&bug_status=VERIFIED&field0-0-2=short_desc&email1=kb9vqf%40pearsoncomputing.net&type0-0-0=substring&value0-0-0=gtk%2B&type0-0-2=substring
  24. // FIXME
  25. // This style should use the TDE open/save dialogs instead of the stock Gnome GtkFileChooserDialog
  26. // This is not currently possible in GTK
  27. // See upstream GTK bug #687173
  28. #define TDEGTK_THEME_THEME_DIRECTORY_NAME "tdegtk"
  29. #define TDEGTK_THEME_CONTROL_FILE_NAME "tdegtk.css"
  30. #define RC_CACHE_VERSION TQString("1")
  31. #define DEBUG_PRINT(x) if (gtk3TQtDebug) printf(x"\n\r");
  32. #define DEBUG_PRINT_ARGS(x,y) if (gtk3TQtDebug) printf(x"\n\r",y);
  33. bool gtk3TQtEnable = false;
  34. int gtk3TQtDebug = false;
  35. bool tde_showIconsOnPushButtons = false;
  36. void initTDESettings();
  37. void writeGtkThemeControlFile(int forceRecreate);
  38. int m_scrollBarSubLineWidth = -1;
  39. bool m_scrollbarBack1 = false;
  40. bool m_scrollbarForward1 = false;
  41. bool m_scrollbarBack2 = false;
  42. bool m_scrollbarForward2 = false;
  43. extern "C" {
  44. #include <gmodule.h>
  45. #include <gtk/gtk.h>
  46. #include "tdegtk-engine.h"
  47. G_MODULE_EXPORT void theme_init(GTypeModule *module);
  48. G_MODULE_EXPORT void theme_exit(void);
  49. G_MODULE_EXPORT GtkThemingEngine* create_engine(void);
  50. G_MODULE_EXPORT void theme_init(GTypeModule *module) {
  51. tdegtk_engine_register_types(module);
  52. }
  53. G_MODULE_EXPORT void theme_exit(void) {
  54. //
  55. }
  56. }
  57. #include <stdlib.h>
  58. #include <sys/stat.h>
  59. #include <sys/types.h>
  60. #include <utility>
  61. #include <vector>
  62. #include <fstream>
  63. #include <sstream>
  64. #include <tqpainter.h>
  65. #include <tqapplication.h>
  66. #include <tqdir.h>
  67. #include <tqfile.h>
  68. #include <tqstyle.h>
  69. #include <tqslider.h>
  70. #include <tqscrollbar.h>
  71. #include <tqregexp.h>
  72. #include <tqfont.h>
  73. #include <tqpopupmenu.h>
  74. #include <kapplication.h>
  75. #include <kcmdlineargs.h>
  76. #include <kiconloader.h>
  77. #include <kaboutdata.h>
  78. #include <kicontheme.h>
  79. #include <klocale.h>
  80. #include <kconfig.h>
  81. #include <kglobal.h>
  82. #include <kglobalsettings.h>
  83. #include <gdk/gdkx.h>
  84. #include "tdegtk-widgetlookup.h"
  85. extern WidgetLookup m_widgetLookup;
  86. typedef std::pair<std::string, unsigned int> SizePair;
  87. typedef std::vector<SizePair> SizeMap;
  88. SizeMap icon_sizes;
  89. G_MODULE_EXPORT GtkThemingEngine* create_engine(void) {
  90. gtk3TQtEnable = true;
  91. gtk3TQtDebug = (getenv("GTK3_TQT_ENGINE_DEBUG") != NULL) ? 1 : 0;
  92. DEBUG_PRINT("Creating KApplication")
  93. int argc = 1;
  94. char** argv;
  95. // Supply it with fake data to keep KApplication happy
  96. argv = (char**) malloc(sizeof(char*));
  97. argv[0] = (char*) malloc(sizeof(char) * 21);
  98. strncpy(argv[0], "gtk3-tqt-application", 21);
  99. KAboutData aboutData("gtk3-tqt-engine", I18N_NOOP("gtk3-tqt-engine"), "v0.1",
  100. "GTK3 TQt theme engine", KAboutData::License_GPL,
  101. "(c) 2012, Timothy Pearson",
  102. "", 0 /* TODO: Website */, "kb9vqf@pearsoncomputing.net");
  103. KCmdLineArgs::init(argc, const_cast<char**>(argv), &aboutData);
  104. KApplication::disableAutoDcopRegistration();
  105. new KApplication(gdk_x11_get_default_xdisplay(), true, 0, 0, true);
  106. initTDESettings();
  107. // initialize icon sizes
  108. icon_sizes.push_back(std::make_pair("panel-menu", 16));
  109. icon_sizes.push_back(std::make_pair("panel", 32));
  110. icon_sizes.push_back(std::make_pair("gtk-small-toolbar", IconSize(KIcon::Toolbar)));
  111. icon_sizes.push_back(std::make_pair("gtk-large-toolbar", IconSize(KIcon::MainToolbar)));
  112. icon_sizes.push_back(std::make_pair("gtk-dnd", IconSize(KIcon::Small)));
  113. icon_sizes.push_back(std::make_pair("gtk-button", IconSize(KIcon::Small)));
  114. icon_sizes.push_back(std::make_pair("gtk-menu", IconSize(KIcon::Small)));
  115. icon_sizes.push_back(std::make_pair("gtk-dialog", IconSize(KIcon::Small)));
  116. icon_sizes.push_back(std::make_pair("", IconSize(KIcon::Small)));
  117. if (gtk3TQtDebug) {
  118. writeGtkThemeControlFile(true);
  119. }
  120. else {
  121. writeGtkThemeControlFile(false);
  122. }
  123. // Initialize hooks
  124. m_widgetLookup.initializeHooks();
  125. return GTK_THEMING_ENGINE (g_object_new (TDEGTK_TYPE_ENGINE, "name", "tdegtk", NULL));
  126. }
  127. // =========================================================================================================
  128. //
  129. // TQt3/GTK Theme Control Functions
  130. //
  131. // =========================================================================================================
  132. TQStringList tdeSearchPaths;
  133. TQString iconTheme;
  134. TQStringList iconThemeDirs;
  135. TQColor alternateBackgroundColour;
  136. int showIconsOnButtons;
  137. int toolbarStyle;
  138. TQString tdeConfigValue(const TQString& section, const TQString& name, const TQString& def) {
  139. KConfig currentConfig;
  140. currentConfig.setGroup(section);
  141. return currentConfig.readEntry(name, def);
  142. }
  143. bool tdeBoolConfigValue(const TQString& section, const TQString& name, bool def) {
  144. KConfig currentConfig;
  145. currentConfig.setGroup(section);
  146. return currentConfig.readBoolEntry(name, def);
  147. }
  148. TQString tdeFindDir(const TQString& suffix, const TQString& file1, const TQString& file2) {
  149. for ( TQStringList::Iterator it = tdeSearchPaths.begin(); it != tdeSearchPaths.end(); ++it )
  150. {
  151. if ((TQFile::exists((*it) + suffix + file1)) || (TQFile::exists((*it) + suffix + file2)))
  152. return (*it) + suffix;
  153. }
  154. return TQString();
  155. }
  156. TQString runCommand(const TQString& command) {
  157. FILE* p = popen(command.latin1(), "r");
  158. if ((p == NULL) || (p < 0))
  159. return TQString();
  160. TQString ret;
  161. while (!feof(p))
  162. {
  163. char buffer[256];
  164. int n = fread(buffer, 1, 255, p);
  165. buffer[n] = '\0';
  166. ret += buffer;
  167. }
  168. pclose(p);
  169. return ret.stripWhiteSpace();
  170. }
  171. void initTDESettings() {
  172. tdeSearchPaths.clear();
  173. TQString tdeHome = getenv("TDEHOME");
  174. TQString tdeDirs = getenv("TDEDIRS");
  175. TQString tdeDir = getenv("TDEDIR");
  176. if (!tdeHome.isEmpty()) {
  177. tdeSearchPaths.append(tdeHome);
  178. }
  179. tdeSearchPaths.append(runCommand("tde-config --localprefix"));
  180. if (!tdeDirs.isEmpty()) {
  181. tdeSearchPaths += TQStringList::split(':', tdeDirs);
  182. }
  183. if (!tdeDir.isEmpty()) {
  184. tdeSearchPaths.append(tdeDir);
  185. }
  186. tdeSearchPaths.append(runCommand("tde-config --prefix"));
  187. iconTheme = tdeConfigValue("Icons", "Theme", "crystalsvg");
  188. tde_showIconsOnPushButtons = tdeBoolConfigValue("KDE", "ShowIconsOnPushButtons", false);
  189. TQStringList back = TQStringList::split(',', tdeConfigValue("General", "alternateBackground", "238,246,255"));
  190. alternateBackgroundColour.setRgb(back[0].toInt(), back[1].toInt(), back[2].toInt());
  191. showIconsOnButtons = (tdeConfigValue("KDE", "ShowIconsOnPushButtons", "true").lower() == "true");
  192. TQString tmp = tdeConfigValue("Toolbar style", "IconText", "true").lower();
  193. if (tmp == "icononly") {
  194. toolbarStyle = 0;
  195. }
  196. else if (tmp == "icontextright") {
  197. toolbarStyle = 3;
  198. }
  199. else if (tmp == "textonly") {
  200. toolbarStyle = 1;
  201. }
  202. else if (tmp == "icontextbottom") {
  203. toolbarStyle = 2;
  204. }
  205. else {
  206. // Should never happen, but just in case we fallback to TDE's default "icononly"
  207. toolbarStyle = 0;
  208. }
  209. }
  210. void gtk3_tqt_load_resource_string(const char* css_string) {
  211. GtkCssProvider *provider;
  212. provider = gtk_css_provider_new();
  213. gtk_css_provider_load_from_data(provider, css_string, -1, NULL);
  214. GdkDisplay *display = gdk_display_get_default();
  215. GdkScreen *screen = gdk_display_get_default_screen(display);
  216. gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
  217. g_object_unref(provider);
  218. DEBUG_PRINT_ARGS("gtk3_tqt_load_resource_string(%s)", css_string)
  219. }
  220. void gtk3_tqt_reload_theme_definition_file(const char* filename) {
  221. GtkCssProvider *provider;
  222. GError *error = NULL;
  223. provider = gtk_css_provider_new();
  224. GdkDisplay *display = gdk_display_get_default();
  225. GdkScreen *screen = gdk_display_get_default_screen(display);
  226. gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
  227. if (!gtk_css_provider_load_from_path(provider, filename, &error)) {
  228. if (error) {
  229. g_printerr("[ERROR] %s: error parsing %s: %s\n", G_STRFUNC, filename, error->message);
  230. g_clear_error(&error);
  231. }
  232. else {
  233. g_printerr("[ERROR] %s: unknown failure parsing %s\n\r", G_STRFUNC, filename); fflush(stdout);
  234. }
  235. }
  236. g_object_unref(provider);
  237. }
  238. TQString tdeFontToGTKFontString(TQFont font) {
  239. TQString fontDescriptor = "font: ";
  240. fontDescriptor.append(font.family());
  241. if (font.bold()) {
  242. fontDescriptor.append(" bold");
  243. }
  244. if (font.italic()) {
  245. fontDescriptor.append(" italic");
  246. }
  247. if (font.pointSizeFloat() != -1) {
  248. fontDescriptor.append(TQString(" %1").arg(font.pointSizeFloat()));
  249. }
  250. else {
  251. fontDescriptor.append(TQString(" %1px").arg(font.pixelSize()));
  252. }
  253. return fontDescriptor;
  254. }
  255. // Thanks Martin Dvorak of metatheme
  256. TQString parse_rc_string(const TQString& defs, const TQString& pattern, bool widgetClass = true) {
  257. static int dynamic_counter = 0;
  258. ++dynamic_counter;
  259. return pattern + " {\n\t" + defs + ";\n}\n\n";
  260. }
  261. GtkIconSet* generateIconSet(const std::string& gtkIconName, const std::string& tdeIconName, TQStringList pathList) {
  262. if (tdeIconName == "NONE") {
  263. return 0L;
  264. }
  265. bool empty = true;
  266. // create iconSet
  267. GtkIconSet* iconSet = gtk_icon_set_new();
  268. // loop over iconSizes
  269. for (SizeMap::const_iterator sizeIter = icon_sizes.begin(); sizeIter != icon_sizes.end(); ++sizeIter) {
  270. // generate full icon name
  271. std::ostringstream iconFileStream;
  272. iconFileStream << sizeIter->second << "x" << sizeIter->second << "/" << tdeIconName;
  273. // loop over provided path to see if at least one icon is found
  274. for (TQStringList::const_iterator pathIter = pathList.begin(); pathIter != pathList.end(); ++pathIter) {
  275. std::string filename((*pathIter + '/' + iconFileStream.str()).latin1());
  276. if (!std::ifstream(filename.c_str())) {
  277. continue;
  278. }
  279. empty = false;
  280. GtkIconSource* iconSource(gtk_icon_source_new());
  281. // set name
  282. gtk_icon_source_set_filename(iconSource, filename.c_str());
  283. // set direction and state wildcarded
  284. gtk_icon_source_set_direction_wildcarded(iconSource, TRUE);
  285. gtk_icon_source_set_state_wildcarded(iconSource, TRUE);
  286. // set size
  287. if (sizeIter->first.empty()) {
  288. gtk_icon_source_set_size_wildcarded(iconSource, TRUE);
  289. }
  290. else {
  291. GtkIconSize size = gtk_icon_size_from_name(sizeIter->first.c_str());
  292. if (size != GTK_ICON_SIZE_INVALID) {
  293. gtk_icon_source_set_size_wildcarded(iconSource, FALSE);
  294. gtk_icon_source_set_size(iconSource, size);
  295. }
  296. }
  297. // add source to iconSet
  298. gtk_icon_set_add_source(iconSet, iconSource);
  299. break;
  300. }
  301. }
  302. // if nothing found, return;
  303. if (empty) {
  304. gtk_icon_set_unref(iconSet);
  305. return 0L;
  306. }
  307. else {
  308. return iconSet;
  309. }
  310. }
  311. void doIconMapping(const char* gtkName, const char * tdeName, GtkIconFactory* factory, TQStringList tdeIconThemeDirs) {
  312. GtkIconSet* iconSet = generateIconSet(gtkName, tdeName, tdeIconThemeDirs);
  313. if (iconSet) {
  314. gtk_icon_factory_add(factory, gtkName, iconSet);
  315. gtk_icon_set_unref(iconSet);
  316. }
  317. }
  318. TQString colorString(TQColor color) {
  319. TQString ret = "rgb(";
  320. ret += TQString::number(color.red()) + ", ";
  321. ret += TQString::number(color.green()) + ", ";
  322. ret += TQString::number(color.blue()) + ")";
  323. return ret;
  324. }
  325. void setColour(TQString name, TQString state, TQColor color, TQString widgetTypes = TQString("*")) {
  326. state = ":" + state;
  327. if (state == ":normal") {
  328. state = "";
  329. }
  330. gtk3_tqt_load_resource_string(parse_rc_string(name + ": " + colorString(color), widgetTypes + state).latin1());
  331. }
  332. static TQStringList iconInheritsDirs(const TQString& icondir) {
  333. TQFile index;
  334. index.setName(icondir + "index.theme");
  335. if( !index.open( IO_ReadOnly )) {
  336. index.setName(icondir + "index.desktop");
  337. if( !index.open( IO_ReadOnly ))
  338. return TQStringList();
  339. }
  340. char buf[1024];
  341. TQRegExp reg( "^\\s*Inherits=([^\\n]*)" );
  342. for(;;) {
  343. if( index.readLine(buf, 1023) <= 0 ) {
  344. break;
  345. }
  346. if( reg.search(buf, 0) >= 0 ) {
  347. return TQStringList::split(",", reg.cap(1));
  348. }
  349. }
  350. return TQStringList();
  351. }
  352. void addIconThemeDir(const TQString& theme) {
  353. // Try to find this theme's directory
  354. TQString icondir = tdeFindDir("/share/icons/" + theme + "/", "index.theme", "index.desktop");
  355. if(icondir.isEmpty()) {
  356. return;
  357. }
  358. if (iconThemeDirs.contains(icondir)) {
  359. return;
  360. }
  361. // Add this theme to the list
  362. iconThemeDirs.append(icondir);
  363. // Do it again for any parent themes
  364. TQStringList parents = iconInheritsDirs(icondir);
  365. for ( TQStringList::Iterator it=parents.begin() ; it!=parents.end(); ++it) {
  366. addIconThemeDir((*it).stripWhiteSpace());
  367. }
  368. }
  369. void writeGtkThemeControlFile(int forceRecreate) {
  370. if (!gtk3TQtEnable) {
  371. return;
  372. }
  373. DEBUG_PRINT("writeGtkThemeControlFile()")
  374. // Set colors
  375. // Normal
  376. setColour("color", "normal", tqApp->palette().active().text());
  377. setColour("background-color", "normal", tqApp->palette().active().background());
  378. // setColour("text", "normal", tqApp->palette().active().text());
  379. // setColour("base", "normal", tqApp->palette().active().base());
  380. // Active (on)
  381. setColour("color", "active", tqApp->palette().active().text());
  382. setColour("background-color", "active", tqApp->palette().active().background());
  383. // setColour("text", "active", tqApp->palette().active().text());
  384. // setColour("base", "active", tqApp->palette().active().base());
  385. // Mouseover
  386. setColour("color", "prelight", tqApp->palette().active().text()); // menu items - change?
  387. setColour("background-color", "prelight", tqApp->palette().active().highlight());
  388. // setColour("text", "prelight", tqApp->palette().active().text());
  389. // setColour("base", "prelight", tqApp->palette().active().base());
  390. // Selected
  391. setColour("color", "selected", tqApp->palette().active().highlightedText());
  392. setColour("background-color", "selected", tqApp->palette().active().highlight());
  393. // setColour("text", "selected", tqApp->palette().active().highlightedText());
  394. // setColour("base", "selected", tqApp->palette().active().highlight());
  395. // Disabled
  396. setColour("color", "insensitive", tqApp->palette().disabled().text());
  397. setColour("background-color", "insensitive", tqApp->palette().disabled().background());
  398. // setColour("text", "insensitive", tqApp->palette().disabled().text());
  399. // setColour("base", "insensitive", tqApp->palette().disabled().background());
  400. TQString iconSettingsString;
  401. iconSettingsString.append(TQString("gtk-menu=%1,%2").arg(IconSize(KIcon::Small)).arg(IconSize(KIcon::Small)));
  402. iconSettingsString.append(TQString(":gtk-button=%1,%2").arg(IconSize(KIcon::Small)).arg(IconSize(KIcon::Small)));
  403. iconSettingsString.append(TQString(":gtk-small-toolbar=%1,%2").arg(IconSize(KIcon::Toolbar)).arg(IconSize(KIcon::Toolbar)));
  404. iconSettingsString.append(TQString(":gtk-large-toolbar=%1,%2").arg(IconSize(KIcon::MainToolbar)).arg(IconSize(KIcon::MainToolbar)));
  405. iconSettingsString.append(TQString(":gtk-dnd=%1,%2").arg(IconSize(KIcon::Small)).arg(IconSize(KIcon::Small)));
  406. iconSettingsString.append(TQString(":gtk-dialog=%1,%2").arg(IconSize(KIcon::Small)).arg(IconSize(KIcon::Small)));
  407. // Set up global application settings
  408. GtkSettings* gtksettings = gtk_settings_get_default();
  409. GtkSettingsValue svalue;
  410. if (gtksettings) {
  411. g_object_set(gtksettings, "gtk-alternative-button-order", TRUE, NULL);
  412. g_object_set(gtksettings, "gtk-button-images", tde_showIconsOnPushButtons, NULL);
  413. g_object_set(gtksettings, "gtk-menu-popup-delay", tqApp->style().styleHint(TQStyle::SH_PopupMenu_SubMenuPopupDelay), NULL);
  414. g_object_set(gtksettings, "gtk-icon-sizes", iconSettingsString.ascii(), NULL);
  415. // Handle toolbar text display
  416. if (toolbarStyle == 3) {
  417. // This is broken by GTK bug #68700
  418. g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_BOTH_HORIZ, NULL);
  419. }
  420. else if (toolbarStyle == 2) {
  421. g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_BOTH, NULL);
  422. }
  423. else if (toolbarStyle == 1) {
  424. g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_TEXT, NULL);
  425. }
  426. else {
  427. g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_ICONS, NULL);
  428. }
  429. }
  430. // Set up icons
  431. // Build the list of icon theme directories.
  432. // This function is recursive - it gets the directories of all the inherited themes as well
  433. addIconThemeDir(iconTheme);
  434. if (!iconThemeDirs.isEmpty()) {
  435. GtkIconFactory* factory;
  436. factory = gtk_icon_factory_new();
  437. doIconMapping("gtk-about", "actions/about_kde.png", factory, iconThemeDirs);
  438. doIconMapping("gtk-add", "actions/add.png", factory, iconThemeDirs);
  439. doIconMapping("gtk-apply", "actions/apply.png", factory, iconThemeDirs);
  440. doIconMapping("gtk-bold", "actions/text_bold.png", factory, iconThemeDirs);
  441. doIconMapping("gtk-cancel", "actions/button_cancel.png", factory, iconThemeDirs);
  442. doIconMapping("gtk-cdrom", "devices/cdrom_unmount.png", factory, iconThemeDirs);
  443. doIconMapping("gtk-clear", "actions/editclear.png", factory, iconThemeDirs);
  444. doIconMapping("gtk-close", "actions/fileclose.png", factory, iconThemeDirs);
  445. doIconMapping("gtk-color-picker", "actions/colorpicker.png", factory, iconThemeDirs);
  446. doIconMapping("gtk-copy", "actions/editcopy.png", factory, iconThemeDirs);
  447. doIconMapping("gtk-convert", "actions/gtk-convert.png", factory, iconThemeDirs);
  448. doIconMapping("gtk-connect", "actions/connect_creating.png", factory, iconThemeDirs);
  449. doIconMapping("gtk-cut", "actions/editcut.png", factory, iconThemeDirs);
  450. doIconMapping("gtk-delete", "actions/editdelete.png", factory, iconThemeDirs);
  451. doIconMapping("gtk-dialog-authentication", "status/gtk-dialog-authentication", factory, iconThemeDirs);
  452. doIconMapping("gtk-dialog-error", "actions/messagebox_critical.png", factory, iconThemeDirs);
  453. doIconMapping("gtk-dialog-info", "actions/messagebox_info.png", factory, iconThemeDirs);
  454. doIconMapping("gtk-dialog-question", "actions/help.png", factory, iconThemeDirs);
  455. doIconMapping("gtk-dialog-warning", "actions/messagebox_warning.png", factory, iconThemeDirs);
  456. doIconMapping("gtk-directory", "filesystems/folder.png", factory, iconThemeDirs);
  457. doIconMapping("gtk-disconnect", "actions/connect_no.png", factory, iconThemeDirs);
  458. doIconMapping("gtk-dnd", "mimetypes/empty.png", factory, iconThemeDirs);
  459. doIconMapping("gtk-dnd-multiple", "mimetypes/kmultiple.png", factory, iconThemeDirs);
  460. doIconMapping("gtk-edit", "actions/edit.png", factory, iconThemeDirs); //2.6
  461. doIconMapping("gtk-execute", "actions/exec.png", factory, iconThemeDirs);
  462. doIconMapping("gtk-file", "mimetypes/empty.png", factory, iconThemeDirs);
  463. doIconMapping("gtk-find", "actions/find.png", factory, iconThemeDirs);
  464. doIconMapping("gtk-find-and-replace", "actions/find.png", factory, iconThemeDirs); // Is there a TDE "find and replace" icon? FIXME
  465. doIconMapping("gtk-floppy", "devices/3floppy_unmount.png", factory, iconThemeDirs);
  466. doIconMapping("gtk-fullscreen", "actions/window-fullscreen.png", factory, iconThemeDirs);
  467. doIconMapping("gtk-goto-bottom", "actions/bottom.png", factory, iconThemeDirs);
  468. doIconMapping("gtk-goto-first", "actions/start.png", factory, iconThemeDirs);
  469. doIconMapping("gtk-goto-last", "actions/finish.png", factory, iconThemeDirs);
  470. doIconMapping("gtk-goto-top", "actions/top.png", factory, iconThemeDirs);
  471. doIconMapping("gtk-go-back", "actions/back.png", factory, iconThemeDirs);
  472. doIconMapping("gtk-go-down", "actions/down.png", factory, iconThemeDirs);
  473. doIconMapping("gtk-go-forward", "actions/forward.png", factory, iconThemeDirs);
  474. doIconMapping("gtk-go-up", "actions/up.png", factory, iconThemeDirs);
  475. doIconMapping("gtk-harddisk", "devices/hdd_unmount.png", factory, iconThemeDirs);
  476. doIconMapping("gtk-help", "apps/khelpcenter.png", factory, iconThemeDirs);
  477. doIconMapping("gtk-home", "filesystems/folder_home.png", factory, iconThemeDirs);
  478. doIconMapping("gtk-indent", "actions/indent.png", factory, iconThemeDirs);
  479. doIconMapping("gtk-index", "actions/contents.png", factory, iconThemeDirs);
  480. doIconMapping("gtk-info", "actions/messagebox_info.png", factory, iconThemeDirs);
  481. doIconMapping("gtk-italic", "actions/text_italic.png", factory, iconThemeDirs);
  482. doIconMapping("gtk-jump-to", "actions/goto.png", factory, iconThemeDirs);
  483. doIconMapping("gtk-justify-center", "actions/text_center.png", factory, iconThemeDirs);
  484. doIconMapping("gtk-justify-fill", "actions/text_block.png", factory, iconThemeDirs);
  485. doIconMapping("gtk-justify-left", "actions/text_left.png", factory, iconThemeDirs);
  486. doIconMapping("gtk-justify-right", "actions/text_right.png", factory, iconThemeDirs);
  487. doIconMapping("gtk-leave-fullscreen", "actions/window-nofullscreen.png", factory, iconThemeDirs);
  488. doIconMapping("gtk-media-forward", "player-fwd.png", factory, iconThemeDirs);
  489. doIconMapping("gtk-media-next", "actions/player-end.png", factory, iconThemeDirs);
  490. doIconMapping("gtk-media-pause", "actions/player-pause.png", factory, iconThemeDirs);
  491. doIconMapping("gtk-media-previous", "actions/player-start.png", factory, iconThemeDirs);
  492. doIconMapping("gtk-media-record", "actions/gtk-media-record.png", factory, iconThemeDirs); // FIXME
  493. doIconMapping("gtk-media-rewind", "actions/player-rew.png", factory, iconThemeDirs);
  494. doIconMapping("gtk-media-stop", "actions/player-stop.png", factory, iconThemeDirs);
  495. doIconMapping("gtk-missing-image", "mimetypes/unknown.png", factory, iconThemeDirs);
  496. doIconMapping("gtk-network", "filesystems/network.png", factory, iconThemeDirs);
  497. doIconMapping("gtk-new", "actions/filenew.png", factory, iconThemeDirs);
  498. doIconMapping("gtk-no", "actions/gtk-no.png", factory, iconThemeDirs);
  499. doIconMapping("gtk-ok", "actions/button_ok.png", factory, iconThemeDirs);
  500. doIconMapping("gtk-open", "actions/fileopen.png", factory, iconThemeDirs);
  501. //doIconMapping("gtk-orientation-landscape", factory, iconThemeDirs); // FIXME
  502. //doIconMapping("gtk-orientation-portrait", factory, iconThemeDirs); // FIXME
  503. //doIconMapping("gtk-orientation-reverse-landscape", factory, iconThemeDirs); // FIXME
  504. //doIconMapping("gtk-orientation-reverse-portrait"", factory, iconThemeDirs); // FIXME
  505. doIconMapping("gtk-paste", "actions/editpaste.png", factory, iconThemeDirs);
  506. doIconMapping("gtk-preferences", "actions/configure.png", factory, iconThemeDirs);
  507. doIconMapping("gtk-print", "actions/fileprint.png", factory, iconThemeDirs);
  508. doIconMapping("gtk-print-preview", "actions/filequickprint.png", factory, iconThemeDirs);
  509. doIconMapping("gtk-properties", "actions/configure.png", factory, iconThemeDirs);
  510. doIconMapping("gtk-quit", "actions/exit.png", factory, iconThemeDirs);
  511. doIconMapping("gtk-redo", "actions/redo.png", factory, iconThemeDirs);
  512. doIconMapping("gtk-refresh", "actions/reload.png", factory, iconThemeDirs);
  513. doIconMapping("gtk-remove", "actions/remove.png", factory, iconThemeDirs);
  514. doIconMapping("gtk-revert-to-saved", "actions/revert.png", factory, iconThemeDirs);
  515. doIconMapping("gtk-save", "actions/filesave.png", factory, iconThemeDirs);
  516. doIconMapping("gtk-save-as", "actions/filesaveas.png", factory, iconThemeDirs);
  517. doIconMapping("gtk-select-all", "actions/gtk-select-all.png", factory, iconThemeDirs); // FIXME
  518. doIconMapping("gtk-select-color", "actions/colorize.png", factory, iconThemeDirs);
  519. doIconMapping("gtk-select-font", "mimetypes/font.png", factory, iconThemeDirs);
  520. //doIconMapping("gtk-sort-ascending", "??", factory, iconThemeDirs); // FIXME
  521. //doIconMapping("gtk-sort-descending", "??", factory, iconThemeDirs); // FIXME
  522. doIconMapping("gtk-spell-check", "actions/spellcheck.png", factory, iconThemeDirs);
  523. doIconMapping("gtk-stop", "actions/stop.png", factory, iconThemeDirs);
  524. doIconMapping("gtk-strikethrough", "actions/text_strike.png", factory, iconThemeDirs);
  525. doIconMapping("gtk-undelete", "actions/gtk-undelete.png", factory, iconThemeDirs); // FIXME
  526. doIconMapping("gtk-underline", "actions/text_under.png", factory, iconThemeDirs);
  527. doIconMapping("gtk-undo", "actions/undo.png", factory, iconThemeDirs);
  528. doIconMapping("gtk-unindent", "actions/unindent.png", factory, iconThemeDirs);
  529. doIconMapping("gtk-yes", "actions/button_ok.png", factory, iconThemeDirs); // Verify mapping here
  530. doIconMapping("gtk-zoom-100", "actions/viewmag1.png", factory, iconThemeDirs);
  531. doIconMapping("gtk-zoom-fit", "actions/viewmagfit.png", factory, iconThemeDirs);
  532. doIconMapping("gtk-zoom-in", "actions/viewmag+.png", factory, iconThemeDirs);
  533. doIconMapping("gtk-zoom-out", "actions/viewmag-.png", factory, iconThemeDirs);
  534. // Other icons that really should have Trinity equivalents in tdelibs
  535. doIconMapping("list-add", "actions/add.png", factory, iconThemeDirs);
  536. doIconMapping("list-remove", "actions/remove.png", factory, iconThemeDirs);
  537. doIconMapping("list-add-symbolic", "actions/add.png", factory, iconThemeDirs);
  538. doIconMapping("list-remove-symbolic", "actions/remove.png", factory, iconThemeDirs);
  539. gtk_icon_factory_add_default(factory);
  540. }
  541. // This function takes quite a long time to execute, and is run at the start of every app.
  542. // In order to speed it up, we can store the results in a file, along with the name of icon
  543. // theme and style. This file can then be regenerated when the icon theme or style change.
  544. TQDir curDir;
  545. TQString themeFilePath = TQDir::homeDirPath();
  546. curDir.setPath(themeFilePath);
  547. if (!curDir.exists()) {
  548. curDir.mkdir(themeFilePath);
  549. }
  550. themeFilePath = themeFilePath + "/.themes/";
  551. curDir.setPath(themeFilePath);
  552. if (!curDir.exists()) {
  553. curDir.mkdir(themeFilePath);
  554. }
  555. themeFilePath = themeFilePath + TQString(TDEGTK_THEME_THEME_DIRECTORY_NAME) + "/";
  556. curDir.setPath(themeFilePath);
  557. if (!curDir.exists()) {
  558. curDir.mkdir(themeFilePath);
  559. }
  560. themeFilePath = themeFilePath + "gtk-3.0/";
  561. curDir.setPath(themeFilePath);
  562. if (!curDir.exists()) {
  563. curDir.mkdir(themeFilePath);
  564. }
  565. themeFilePath = themeFilePath + TDEGTK_THEME_CONTROL_FILE_NAME;
  566. TQFile themeFile(themeFilePath);
  567. TQTextStream stream;
  568. if (!forceRecreate && themeFile.exists()) {
  569. themeFile.open(IO_ReadOnly);
  570. stream.setDevice(TQT_TQIODEVICE(&themeFile));
  571. if (stream.readLine() == "/* " + iconTheme + ", " + tqApp->style().name() + ", " + RC_CACHE_VERSION + " */") {
  572. // This cache matches the current icon theme and style
  573. themeFile.close();
  574. gtk3_tqt_reload_theme_definition_file(themeFilePath.latin1());
  575. return;
  576. }
  577. stream.unsetDevice();
  578. themeFile.close();
  579. }
  580. themeFile.open(IO_WriteOnly | IO_Truncate);
  581. stream.setDevice(TQT_TQIODEVICE(&themeFile));
  582. stream << "/* " << iconTheme << ", " << tqApp->style().name() << ", " << RC_CACHE_VERSION << " */\n\n";
  583. stream << "/* This file was generated by the Gtk TQt Theme Engine */\n";
  584. stream << "/* It will be recreated when you change your TDE icon theme or widget style */\n\n";
  585. TQScrollBar sbar(NULL);
  586. sbar.setOrientation(TQt::Horizontal);
  587. sbar.setValue(1);
  588. sbar.resize(200,25);
  589. // The following code determines how many buttons are on a scrollbar
  590. // It works by looking at each pixel of the scrollbar's area not taken up by the groove,
  591. // and asking the style which subcontrol is at that location.
  592. TQRect rect = tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, &sbar, TQStyle::SC_ScrollBarGroove);
  593. TQStyle::SubControl sc = TQStyle::SC_None;
  594. for (TQPoint pos(0,7) ; pos.x()<rect.x() ; pos.setX(pos.x()+1))
  595. {
  596. TQStyle::SubControl sc2 = tqApp->style().querySubControl(TQStyle::CC_ScrollBar, &sbar, pos);
  597. if (sc != sc2)
  598. {
  599. if (sc2 == TQStyle::SC_ScrollBarAddLine) m_scrollbarForward1 = true;
  600. if (sc2 == TQStyle::SC_ScrollBarSubLine) m_scrollbarBack1 = true;
  601. sc = sc2;
  602. }
  603. }
  604. sc = TQStyle::SC_None;
  605. for (TQPoint pos(rect.x()+rect.width(),7) ; pos.x()<200 ; pos.setX(pos.x()+1))
  606. {
  607. TQStyle::SubControl sc2 = tqApp->style().querySubControl(TQStyle::CC_ScrollBar, &sbar, pos);
  608. if (sc != sc2)
  609. {
  610. if (sc2 == TQStyle::SC_ScrollBarAddLine) m_scrollbarForward2 = true;
  611. if (sc2 == TQStyle::SC_ScrollBarSubLine) m_scrollbarBack2 = true;
  612. sc = sc2;
  613. }
  614. }
  615. // FIXME
  616. // The items in a GTK3 combobox cannot be styled, either to draw them in a custom manner or to change their height
  617. // A bug report should be filed on this issue...
  618. bool combobox_appears_as_list = (!(tqApp->style().styleHint(TQStyle::SH_ComboBox_Popup) || tqApp->style().styleHint(TQStyle::SH_GUIStyle) == TQt::MotifStyle));
  619. stream << parse_rc_string(TQString("-GtkComboBox-appears-as-list: %1px").arg(combobox_appears_as_list), "*");
  620. // FIXME
  621. // Work around problems detailed in upstream GTK bug #687677
  622. stream << parse_rc_string(TQString("-GtkComboBox-shadow-type: in"), "*");
  623. stream << parse_rc_string("-GtkComboBox-arrow-size: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ArrowSize)), "*");
  624. stream << parse_rc_string("-GtkComboBox-arrow-scaling: 0", "*");
  625. stream << parse_rc_string(TQString("-GtkScrollbar-has-backward-stepper: ") + (m_scrollbarBack1 ? "1" : "0"), "*");
  626. stream << parse_rc_string(TQString("-GtkScrollbar-has-forward-stepper: ") + (m_scrollbarForward2 ? "1" : "0"), "*");
  627. stream << parse_rc_string(TQString("-GtkScrollbar-has-secondary-forward-stepper: ") + (m_scrollbarForward1 ? "1" : "0"), "*");
  628. stream << parse_rc_string(TQString("-GtkScrollbar-has-secondary-backward-stepper: ") + (m_scrollbarBack2 ? "1" : "0"), "*");
  629. m_scrollBarSubLineWidth = tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, &sbar, TQStyle::SC_ScrollBarSubLine).width();
  630. stream << parse_rc_string("-GtkRange-stepper-size: " + TQString::number(m_scrollBarSubLineWidth), "GtkScrollbar");
  631. stream << parse_rc_string("-GtkRange-slider-width: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ScrollBarExtent)), "GtkScrollbar");
  632. stream << parse_rc_string("-GtkRange-trough-border: 0", "GtkScrollbar");
  633. stream << parse_rc_string("-GtkRange-trough-under-steppers: 1", "GtkScrollbar");
  634. stream << parse_rc_string("-GtkScrollbar-min-slider-length: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ScrollBarSliderMin)), "*");
  635. // FIXME
  636. // This is currently set to the scrollbar stepper button size, as TQt3 does not have the concept of a stepper for a TQSlider
  637. stream << parse_rc_string("-GtkRange-stepper-size: " + TQString::number(m_scrollBarSubLineWidth), "GtkScale");
  638. TQSlider slider(NULL); // To keep BlueCurve happy
  639. stream << parse_rc_string("-GtkRange-slider-width: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_SliderThickness, &slider)), "GtkScale");
  640. stream << parse_rc_string("-GtkScale-slider-length: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_SliderLength, &slider)), "*");
  641. stream << parse_rc_string("-GtkButton-child-displacement-x: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftHorizontal)), "*");
  642. stream << parse_rc_string("-GtkButton-child-displacement-y: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftVertical)), "*");
  643. stream << parse_rc_string("-GtkRange-arrow-displacement-x: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftHorizontal)), "*");
  644. stream << parse_rc_string("-GtkRange-arrow-displacement-y: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftVertical)), "*");
  645. stream << parse_rc_string("-GtkRange-arrow-displacement-x: " + TQString::number(0), "GtkScrollbar");
  646. stream << parse_rc_string("-GtkRange-arrow-displacement-y: " + TQString::number(0), "GtkScrollbar");
  647. stream << parse_rc_string("-GtkButton-default-border: 0 0 0 0", "*");
  648. stream << parse_rc_string("-GtkButton-default-outside-border: 0 0 0 0", "*");
  649. #ifdef USE_NATIVE_GTK_BUTTON_DRAWING
  650. stream << parse_rc_string("-GtkButton-inner-border: 2 2 2 2", "*");
  651. #else
  652. if (tde_showIconsOnPushButtons) {
  653. stream << parse_rc_string("-GtkButton-inner-border: 10 10 2 2", "*"); // Allow space for the icon on either side of the text
  654. }
  655. else {
  656. stream << parse_rc_string("-GtkButton-inner-border: 2 2 2 2", "*");
  657. }
  658. #endif
  659. stream << parse_rc_string("-GtkButtonBox-child_min_height: 0", "*");
  660. stream << parse_rc_string("-GtkButtonBox-child_internal_pad_x: 0", "*");
  661. stream << parse_rc_string("-GtkButtonBox-child_internal_pad_y: 0", "*");
  662. stream << parse_rc_string("-GtkRange-arrow-scaling: 1.0", "GtkScrollbar");
  663. stream << parse_rc_string("-xthickness: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_DefaultFrameWidth)), "*.GtkMenu");
  664. stream << parse_rc_string("-ythickness: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_DefaultFrameWidth)), "*.GtkMenu");
  665. stream << parse_rc_string("-xthickness: 5", "*.GtkMenu.Gtk*MenuItem");
  666. stream << parse_rc_string("-xthickness: 3", "*.GtkNotebook");
  667. stream << parse_rc_string("-ythickness: 3", "*.GtkNotebook");
  668. stream << parse_rc_string("-ythickness: 1", "*.GtkButton");
  669. stream << parse_rc_string("-color: " + colorString(TQColor(0,0,0)), "gtk-tooltips.GtkLabel", false);
  670. stream << parse_rc_string("-xthickness: 1", "*.GtkButton.*");
  671. stream << parse_rc_string("-ythickness: 1", "*.GtkButton.*");
  672. // stream << parse_rc_string("GtkTreeView::allow-rules = 0", "*");
  673. // stream << parse_rc_string("GtkTreeView::tree-line-width = 1", "*");
  674. // stream << parse_rc_string("GtkTreeView::vertical-separator = 30", "*");
  675. // //stream << parse_rc_string("GtkTreeView::odd-row-color = { 0.0, 0.0, 0.0 }", "*");
  676. stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkToolbar*GtkButton*");
  677. stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkToolbar*GtkToggleButton*");
  678. stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkNotebook*GtkButton*");
  679. stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkNotebook*GtkToggleButton*");
  680. // TQt calls them tab boxes, GTK calls them notebooks (!??!?) Either way they are a pain...
  681. //stream << parse_rc_string("-GtkNotebook-tab-overlap: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_TabBarTabOverlap)), "*");
  682. stream << parse_rc_string("-GtkNotebook-tab-overlap: 0", "*"); // Overlap is handled in the style engine itself
  683. stream << parse_rc_string("-GtkNotebook-tab-curvature: 0", "*");
  684. stream << parse_rc_string("-GtkNotebook-initial-gap: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_TabBarTabOverlap)), "*");
  685. // This sets both the radio button and check box sizes
  686. stream << parse_rc_string("-GtkCheckButton-indicator-size: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_IndicatorHeight)), "*");
  687. stream << parse_rc_string("-GtkCheckMenuItem-indicator-size: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_IndicatorHeight)), "*");
  688. // FIXME
  689. // GtkCellRendererToggle indicator-size must be set as follows, however GTK3 does not provide any means to change the default size!
  690. // See upstream GTK bug #687076
  691. //stream << parse_rc_string("-GtkCellRendererToggle-indicator-size: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_IndicatorHeight)), "*");
  692. // FIXME
  693. // GtkSpinButton widgets use ugly unthemed horizontal buttons
  694. // When GTK provides an option to switch to vertical buttons, implement theming support for them
  695. // See upstream GTK bug #687172
  696. // FIXME
  697. // There must be a way to set the selected tab offset (shift)
  698. // If not, it may be neccessary to override the GTK text drawing routines for notebooks to insert the proper shift
  699. //stream << parse_rc_string("-????: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_TabBarTabShiftHorizontal)), "*");
  700. // Expand widget padding so as to keep the prelighting out of the active widget area
  701. // FIXME
  702. // Where do these 3px values actually come from?
  703. stream << parse_rc_string("padding: " + TQString::number(3) + "px " + TQString::number(3) + "px", "GtkButton");
  704. stream << parse_rc_string("padding: " + TQString::number(3) + "px " + TQString::number(3) + "px", "GtkNotebook");
  705. stream << parse_rc_string("padding: " + TQString::number(3) + "px " + TQString::number(3) + "px", "GtkEntry");
  706. TQRect probeRect;
  707. TQRect comboBoxArrowRect;
  708. TQRect comboBoxEditFieldRect;
  709. {
  710. probeRect = TQRect(0, 0, 100, 100);
  711. TQStringList objectTypes;
  712. objectTypes.append(TQCOMBOBOX_OBJECT_NAME_STRING);
  713. TQPalette objectPalette = tqApp->palette(objectTypes);
  714. TQStyleControlElementData ceData;
  715. TQStyle::ControlElementFlags elementFlags = TQStyle::CEF_None;
  716. ceData.widgetObjectTypes = objectTypes;
  717. ceData.orientation = TQt::Horizontal;
  718. ceData.rect = probeRect;
  719. elementFlags = elementFlags | TQStyle::CEF_IsEditable;
  720. comboBoxArrowRect = tqApp->style().querySubControlMetrics(TQStyle::CC_ComboBox, ceData, elementFlags, TQStyle::SC_ComboBoxArrow);
  721. comboBoxEditFieldRect = tqApp->style().querySubControlMetrics(TQStyle::CC_ComboBox, ceData, elementFlags, TQStyle::SC_ComboBoxEditField);
  722. }
  723. // The padding is specified in a highly unusual format:
  724. // top_width, right_width, bottom_width, left_width
  725. // Compare that to the more typical format of:
  726. // left, top, right, bottom
  727. stream << parse_rc_string("padding: " + TQString::number(comboBoxEditFieldRect.y()-probeRect.y()) + "px " + TQString::number(probeRect.right()-comboBoxEditFieldRect.right()-comboBoxArrowRect.width()) + "px " + TQString::number(probeRect.bottom()-comboBoxEditFieldRect.bottom()) + "px " + TQString::number(comboBoxEditFieldRect.x()-probeRect.x()) + "px", "GtkComboBox>GtkEntry");
  728. // Set header sizes
  729. stream << parse_rc_string("padding: " + TQString::number(0) + "px " + TQString::number(0) + "px", "GtkTreeView>*>GtkButton");
  730. stream << parse_rc_string("border-width: " + TQString::number(0) + "px " + TQString::number(0) + "px", "GtkTreeView>*>GtkButton");
  731. stream << parse_rc_string("padding: " + TQString::number(0) + "px " + TQString::number(0) + "px", "GtkList>*>GtkButton");
  732. stream << parse_rc_string("border-width: " + TQString::number(0) + "px " + TQString::number(0) + "px", "GtkList>*>GtkButton");
  733. // Ensure group boxes are not cut off by their labels
  734. // FIXME
  735. // Where do these 2px values actually come from?
  736. stream << parse_rc_string("padding: " + TQString::number(2) + "px " + TQString::number(2) + "px", "GtkFrame");
  737. // Separators appear to be hardcoded to 1px high in TQt3
  738. // Anything else will cause a silent drawing failure!
  739. stream << parse_rc_string("-GtkWidget-separator-height: " + TQString::number(1), "*");
  740. stream << parse_rc_string("-GtkWidget-separator-width: " + TQString::number(1), "*");
  741. stream << parse_rc_string("-GtkWidget-wide-separators: 1", "*");
  742. // Set treeview cell size
  743. stream << parse_rc_string("-GtkTreeView-vertical-separator: 0", "*");
  744. // FIXME
  745. // GTK3 does not currently support drawing GtkTextView backgrounds through the style engine
  746. // Therefore, the best we can currently do is to set the background to the correct TQt3 color, which is obviously suboptimal as the TQt3 background drawing methods are never called!
  747. // Even the recommended CSS style properties do not appear to work!
  748. // See upstream GTK bug #687363
  749. {
  750. TQStringList objectTypes;
  751. objectTypes.append(TQTEXTEDIT_OBJECT_NAME_STRING);
  752. TQPalette objectPalette = tqApp->palette(objectTypes);
  753. // stream << parse_rc_string("background-color: " + colorString(objectPalette.color(TQPalette::Active, TQColorGroup::Base)), "GtkTextView");
  754. // stream << parse_rc_string("background-color: " + colorString(objectPalette.color(TQPalette::Disabled, TQColorGroup::Base)), "GtkTextView:insensitive");
  755. setColour("color", "normal", objectPalette.color(TQPalette::Active, TQColorGroup::Foreground), "GtkTextView");
  756. setColour("color", "insensitive", objectPalette.color(TQPalette::Disabled, TQColorGroup::Foreground), "GtkTextView");
  757. setColour("background-color", "normal", objectPalette.color(TQPalette::Active, TQColorGroup::Base), "GtkTextView");
  758. setColour("background-color", "insensitive", objectPalette.color(TQPalette::Disabled, TQColorGroup::Base), "GtkTextView");
  759. }
  760. // Handle menu metrics
  761. int tdeStandardMenuItemHeight;
  762. int tdeSeparatorMenuItemHeight;
  763. int tdeMenuFrameWidth;
  764. {
  765. TQStringList objectTypes;
  766. objectTypes.append(TQPOPUPMENU_OBJECT_NAME_STRING);
  767. TQPalette objectPalette = tqApp->palette(objectTypes);
  768. TQStyleControlElementData ceData;
  769. TQStyle::ControlElementFlags elementFlags = TQStyle::CEF_None;
  770. ceData.widgetObjectTypes = objectTypes;
  771. ceData.orientation = TQt::Horizontal;
  772. TQMenuItem tqt3MenuItem;
  773. tqt3MenuItem.setSeparator(false);
  774. tdeStandardMenuItemHeight = TQPopupMenu::menuItemHeight(&tqt3MenuItem, tqApp->fontMetrics());
  775. tqt3MenuItem.setSeparator(true);
  776. tdeSeparatorMenuItemHeight = TQPopupMenu::menuItemHeight(&tqt3MenuItem, tqApp->fontMetrics());
  777. TQSize sz;
  778. ceData.rect = TQRect(0, 0, 0, tdeStandardMenuItemHeight);
  779. sz = tqApp->style().sizeFromContents(TQStyle::CT_PopupMenuItem, ceData, elementFlags, TQSize(0, tdeStandardMenuItemHeight), TQStyleOption(&tqt3MenuItem));
  780. sz = sz.expandedTo(TQSize(0, sz.height()));
  781. tdeStandardMenuItemHeight = sz.height();
  782. ceData.rect = TQRect(0, 0, 0, tdeSeparatorMenuItemHeight);
  783. sz = tqApp->style().sizeFromContents(TQStyle::CT_PopupMenuItem, ceData, elementFlags, TQSize(0, tdeSeparatorMenuItemHeight), TQStyleOption(&tqt3MenuItem));
  784. sz = sz.expandedTo(TQSize(0, sz.height()));
  785. tdeSeparatorMenuItemHeight = sz.height();
  786. tdeMenuFrameWidth = tqApp->style().pixelMetric(TQStyle::PM_DefaultFrameWidth, ceData, elementFlags);
  787. }
  788. stream << parse_rc_string("-GtkWidget-separator-height: " + TQString::number(tdeSeparatorMenuItemHeight), "GtkMenuItem");
  789. stream << parse_rc_string("-GtkWidget-separator-width: " + TQString::number(tdeSeparatorMenuItemHeight), "GtkMenuItem");
  790. stream << parse_rc_string("-GtkWidget-wide-separators: 1", "GtkMenuItem");
  791. stream << parse_rc_string("padding: " + TQString::number(tdeMenuFrameWidth) + "px " + TQString::number(tdeMenuFrameWidth) + "px " + TQString::number(tdeMenuFrameWidth) + "px " + TQString::number(tdeMenuFrameWidth) + "px", "GtkMenu");
  792. // FIXME
  793. // GTK does not seem to support inserting actual space between the items in a menu bar; instead it insists on expanding the size of the menu items themselves (GtkMenuBar>GtkMenuItem padding:)
  794. // This is rather jarring visually; if a way is found to work around this GTK bug the menu bar item spacing should be fixed ASAP!
  795. // stream << parse_rc_string("padding: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_)), "GtkMenuBar");
  796. stream << parse_rc_string("padding: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_MenuBarFrameWidth)) + "px " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_MenuBarItemSpacing)*0.75) + "px", "GtkMenuBar>GtkMenuItem");
  797. stream << parse_rc_string("padding: " + TQString::number((tdeStandardMenuItemHeight-tqApp->style().pixelMetric(TQStyle::PM_IndicatorHeight))/2) + "px " + TQString::number(0) + "px", "GtkMenu>GtkMenuItem");
  798. stream << parse_rc_string("padding: " + TQString::number(0) + "px " + TQString::number(0) + "px", "GtkMenu>GtkMenuSpacerItem");
  799. // stream << parse_rc_string("padding: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_)), "GtkMenu>GtkSeparatorMenuItem");
  800. // Set up fonts
  801. TQFont generalFont = KGlobalSettings::generalFont();
  802. TQFont toolBarFont = KGlobalSettings::toolBarFont();
  803. TQFont menuFont = KGlobalSettings::menuFont();
  804. // TQFont windowTitleFont = KGlobalSettings::windowTitleFont();
  805. // TQFont taskbarFont = KGlobalSettings::taskbarFont();
  806. stream << parse_rc_string(tdeFontToGTKFontString(generalFont), "*");
  807. stream << parse_rc_string(tdeFontToGTKFontString(toolBarFont), "*GtkToolbar*GtkButton*");
  808. stream << parse_rc_string(tdeFontToGTKFontString(menuFont), "*.GtkMenu");
  809. themeFile.close();
  810. if (!gtk3TQtDebug) {
  811. gtk3_tqt_reload_theme_definition_file(themeFilePath.latin1());
  812. }
  813. }
  814. // =========================================================================================================