fluxstyle_gui 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #!/usr/bin/env python2
  2. # Copyright 2005,2006 Michael Rice
  3. # errr@errr-online.com
  4. """ fluxStyle
  5. fluxStyle is a graphical style-manager for the fluxbox
  6. window manager. Orignal version written by Michael Rice.
  7. Many special thanks to Zan a.k.a. Lauri Peltonen for GUI
  8. Improvements & Bug Stomping.
  9. Released under GPL v2.
  10. TODO
  11. - somehow support older styles and not put folders in the list
  12. like folders that dont have anything to do with a style.
  13. - fix any bugs that may still be there and unseen..
  14. - add tray icon support (this is started will be done soon)
  15. """
  16. import os
  17. from os.path import isfile, expanduser, isdir
  18. import gtk
  19. import gtk.glade
  20. from fluxstyle import find_styles, parse_config
  21. from fluxstyle import error_message
  22. GLADEFILE="/usr/share/fluxstyle/glade/main.glade"
  23. N_IMAGE="/usr/share/fluxstyle/images/none.jpg"
  24. #GLADEFILE = "./glade/main.glade"
  25. #N_IMAGE = "./images/none.jpg"
  26. class StyleChange:
  27. """Class wrapper for changing styles in fluxbox"""
  28. location = ""
  29. @staticmethod
  30. def main():
  31. gtk.main()
  32. def __init__(self):
  33. """The main fluxStyle window will show"""
  34. windowname = "window1"
  35. self.wTree = gtk.glade.XML(GLADEFILE, windowname)
  36. self.treeview1 = self.wTree.get_widget("treeview1")
  37. self.view_menu = self.wTree.get_widget("view1_menu")
  38. self.__fill_view_menu__(self.view_menu)
  39. handler = {
  40. "on_apply_style_clicked": self.__apply_style_clicked__,
  41. "on_quit_clicked": gtk.main_quit,
  42. "on_add_style_clicked": self.__add_style_clicked__,
  43. "on_remove_style_clicked": self.__remove_style_clicked__,
  44. "on_quit1_activate": gtk.main_quit,
  45. "on_about1_activate": self.__about1_activate__,
  46. "on_window1_destroy": gtk.main_quit,
  47. "on_default1_activate": self.__fill_combolist__
  48. }
  49. self.wTree.signal_autoconnect(handler)
  50. #Preparing the treeview here
  51. self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str)
  52. self.treeview1.set_model(self.liststore)
  53. renderer = gtk.CellRendererText()
  54. imagerenderer = gtk.CellRendererPixbuf()
  55. imagerenderer.set_property('ypad', 10)
  56. imagerenderer.set_property('xpad', 5)
  57. column1 = gtk.TreeViewColumn("Preview", imagerenderer, pixbuf=0)
  58. column1.set_resizable(True)
  59. column2 = gtk.TreeViewColumn("Name", renderer, text=1)
  60. column2.set_resizable(True)
  61. self.treeview1.append_column(column1)
  62. self.treeview1.append_column(column2)
  63. #Fill it (Clear + fill)
  64. self.__fill_combolist__(self.treeview1, loc="default")
  65. return
  66. # Call backs begin here
  67. # fill combo list
  68. def __fill_combolist__(self, widget, loc="default"):
  69. """Fill the combo list with styles test to see if there is a
  70. ~/.fluxbox/styles if there isnt then make it and move on."""
  71. self.location = expanduser(loc)
  72. if self.location == "default":
  73. self.location = expanduser("~/.fluxbox/styles")
  74. try:
  75. dir = os.listdir(self.location)
  76. dir.sort()
  77. self.liststore.clear()
  78. for styles in dir:
  79. self.liststore.append((
  80. self.__get_preview__(styles),
  81. styles,
  82. ))
  83. except OSError:
  84. dir_ = expanduser("~/.fluxbox/styles")
  85. os.makedirs(dir_, mode=0700)
  86. message = """You did not have a default style folder. One has
  87. been created for you. The list will remain empty until you
  88. install a style which you can do by clicking the add button.
  89. """
  90. error_message.info_message(message)
  91. else:
  92. try:
  93. dir_ = os.listdir(self.location)
  94. dir_.sort()
  95. self.liststore.clear()
  96. for styles in dir_:
  97. self.liststore.append((self.__get_preview__(styles),
  98. styles,))
  99. except OSError:
  100. m = """You have an invalid location in your ~/.fluxStyle.rc
  101. file. It is possible that you have a syntax error. Please exit
  102. fluxStlye and fix the error in this file and try again.
  103. """
  104. error_message.info_message(m)
  105. # get the preview image for view
  106. def __get_preview__(self, stylename):
  107. """Get the preview image from: location + /styleName/preview.jpg"""
  108. self.location = expanduser(self.location)
  109. image = gtk.Image()
  110. if isdir(self.location + "/" + stylename):
  111. if isfile(self.location+"/"+stylename+"/preview.jpg"):
  112. image.set_from_file(self.location+"/" +stylename+"/preview.jpg")
  113. else:
  114. image.set_from_file(N_IMAGE)
  115. return image.get_pixbuf()
  116. def __fill_view_menu__(self, widget):
  117. if parse_config.check4_config() == 2:
  118. message = """First run detected. A default config has been created
  119. for you. You should edit this config to control the location of
  120. styles shown in the preview window. The config file is located in
  121. ~/.fluxStyle.rc"""
  122. error_message.info_message(message)
  123. elif parse_config.check4_config() == 3:
  124. message = """You do not have the config file ~/.fluxStyle.rc and
  125. you do not have write access to your $HOME directory."""
  126. error_message.info_message(message)
  127. elif parse_config.check4_config():
  128. ops = parse_config.parse_file(expanduser("~/.fluxStyle.rc"))
  129. l = []
  130. if ops != False:
  131. count = 1
  132. view = self.view_menu
  133. for k,v in ops.iteritems():
  134. if k == "STYLES_DIRS":
  135. for x in v:
  136. l.append(x.strip().split(','))
  137. for i in l:
  138. if len(i) <= 1:
  139. name = "_"+str(count)+" %s"%(" Extra Styles")
  140. menuitem = gtk.MenuItem(name + str(count))
  141. menuitem.connect("activate",
  142. self.__fill_combolist__,
  143. i[0])
  144. view.add(menuitem)
  145. count += 1
  146. else:
  147. name = "_%s"%(i[0])
  148. menuitem = gtk.MenuItem(name)
  149. menuitem.connect("activate",
  150. self.__fill_combolist__,
  151. i[1])
  152. view.add(menuitem)
  153. view.show_all()
  154. # Set style
  155. def __apply_style_clicked__(self,widget):
  156. """Used to apply new styles"""
  157. style = self.__get_selected_style__()
  158. if style:
  159. find_styles.set_style(style,self.location)
  160. # Add style
  161. def __add_style_clicked__(self,widget):
  162. """Install a new style, multiple styles can be installed at once."""
  163. dialog = gtk.FileChooserDialog("Choose file to install",
  164. None,gtk.FILE_CHOOSER_ACTION_OPEN,
  165. (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
  166. gtk.STOCK_OPEN, gtk.RESPONSE_OK))
  167. dialog.set_default_response(gtk.RESPONSE_OK)
  168. filter = gtk.FileFilter()
  169. filter.set_name("Fluxbox Styles")
  170. filter.add_mime_type("tar/gz")
  171. filter.add_mime_type("tar/bz2")
  172. filter.add_pattern("*.tar.gz")
  173. filter.add_pattern("*.tar.bz2")
  174. filter.add_pattern("*.tgz")
  175. dialog.add_filter(filter)
  176. dialog.set_select_multiple(True)
  177. response = dialog.run()
  178. if response == gtk.RESPONSE_OK:
  179. find_styles.install_style(dialog.get_filenames())
  180. self.__fill_combolist__(self)
  181. dialog.destroy()
  182. if response == gtk.RESPONSE_CANCEL:
  183. dialog.destroy()
  184. # remove style
  185. def __remove_style_clicked__(self,widget):
  186. """Remove selected style"""
  187. style = self.__get_selected_style__()
  188. if style == False:
  189. m = "You must select a style to remove first"
  190. error_message.info_message(m)
  191. else:
  192. message = gtk.MessageDialog(None,
  193. gtk.DIALOG_MODAL,
  194. gtk.MESSAGE_INFO,
  195. gtk.BUTTONS_NONE,
  196. "Are you sure you want to delete {0}?".format(style))
  197. message.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
  198. message.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CLOSE)
  199. response = message.run()
  200. message.hide()
  201. if response == gtk.RESPONSE_OK:
  202. if find_styles.remove_style(style,self.location) != False:
  203. message.destroy()
  204. self.__fill_combolist__(self,self.location)
  205. else:
  206. say = """You do not have access to remove this style Please
  207. contact your system admin for help removing this style.
  208. """
  209. message = gtk.MessageDialog(None,
  210. gtk.DIALOG_MODAL,
  211. gtk.MESSAGE_INFO,
  212. gtk.BUTTONS_NONE,
  213. say)
  214. message.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
  215. response = message.run()
  216. message.hide()
  217. if response == gtk.RESPONSE_CLOSE:
  218. message.destroy()
  219. if response == gtk.RESPONSE_CLOSE:
  220. message.destroy()
  221. def __get_selected_style__(self):
  222. """Getting the selected style"""
  223. selection = self.treeview1.get_selection()
  224. (model, iter) = selection.get_selected()
  225. if model and iter:
  226. return model.get_value(iter, 1)
  227. else:
  228. return False
  229. def __close_about__(self,widget,event):
  230. """close about dialog"""
  231. if event == gtk.RESPONSE_CANCEL:
  232. self.aboutdialog.destroy()
  233. def __about1_activate__(self,widget):
  234. """Activate the help button with the about dialog,
  235. use generic if pygtk < 2.5.9
  236. """
  237. if gtk.pygtk_version < (2,5,90):
  238. message = """Update your pygtk version for more features.
  239. Version 2.6.0 or newer is reccomended.
  240. """
  241. error_message.info_message(message)
  242. else:
  243. windowname2="aboutdialog1"
  244. self.wTree2=gtk.glade.XML (GLADEFILE,windowname2)
  245. handler = { "on_aboutdialog1_response":self.__close_about__}
  246. self.wTree2.signal_autoconnect(handler)
  247. self.aboutdialog = self.wTree2.get_widget("aboutdialog1")
  248. if __name__ == "__main__":
  249. style = StyleChange()
  250. style.main()