mcg/mcgGtk.py
2012-07-23 13:54:34 +02:00

845 lines
25 KiB
Python
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Author: coderkun <olli@coderkun.de>
from gi.repository import Gtk, Gdk, GdkPixbuf, GObject
import mcg
class MCGGtk(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="MPDCoverGrid (Gtk)")
self._mcg = mcg.MCGClient()
self._config = Configuration()
self._maximized = False
self._fullscreened = False
self._quit = False
# Box
self._main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self._main_box)
# Toolbar
self._toolbar = Toolbar()
self._main_box.pack_start(self._toolbar, False, False, 0)
# Connection Panel
self._connection_panel = ConnectionPanel(self._config)
self._main_box.pack_end(self._connection_panel, True, True, 0)
# Cover Panel
self._cover_panel = CoverPanel(self._config)
# Signals
self.connect('focus', self.focus_cb)
self.connect('key-press-event', self.key_press_cb)
self.connect('size-allocate', self.resize_cb)
self.connect('window-state-event', self.state_cb)
self.connect('delete-event', self.destroy_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_CONNECT, self.toolbar_connect_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_UPDATE, self.toolbar_update_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_PLAYPAUSE, self.toolbar_playpause_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_NEXT_SONG, self.toolbar_next_song_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_FILTER, self.toolbar_filter_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_GRID_SIZE_TEMP, self.toolbar_grid_size_temp_cb)
self._toolbar.connect_signal(Toolbar.SIGNAL_GRID_SIZE, self.toolbar_grid_size_cb)
self._cover_panel.connect_signal(CoverPanel.SIGNAL_PLAY, self.cover_panel_play_cb)
self._cover_panel.connect_signal(CoverPanel.SIGNAL_UPDATE_START, self.cover_panel_update_start_cb)
self._cover_panel.connect_signal(CoverPanel.SIGNAL_UPDATE_END, self.cover_panel_update_end_cb)
self._cover_panel.connect_signal(CoverPanel.SIGNAL_TOGGLE_FULLSCREEN, self.cover_panel_toggle_fullscreen_cb)
self._mcg.connect_signal(mcg.MCGClient.SIGNAL_CONNECT, self.mcg_connect_cb)
self._mcg.connect_signal(mcg.MCGClient.SIGNAL_STATUS, self.mcg_status_cb)
self._mcg.connect_signal(mcg.MCGClient.SIGNAL_UPDATE, self.mcg_update_cb)
self.set_hide_titlebar_when_maximized(True)
self.resize(self._config.window_width, self._config.window_height)
if self._config.window_maximized:
self.maximize()
def focus_cb(self, widget, state):
self._connect()
def resize_cb(self, widget, event):
self._save_size()
def key_press_cb(self, widget, event):
if (event.state & Gdk.ModifierType.MOD1_MASK and event.keyval == Gdk.KEY_Return) or (
self._fullscreened and event.type == Gdk.EventType.KEY_PRESS and event.keyval == Gdk.KEY_Escape):
self._toggle_fullscreen()
def state_cb(self, widget, state):
self._fullscreened = (state.new_window_state & Gdk.WindowState.FULLSCREEN > 0)
self._update_fullscreen()
self._save_state(state)
def destroy_cb(self, widget, state):
self._mcg.close()
self._config.save()
GObject.idle_add(Gtk.main_quit)
# Toolbar callbacks
def toolbar_connect_cb(self):
self._connect()
def toolbar_update_cb(self):
self._toolbar.lock()
self._mcg.update()
def toolbar_playpause_cb(self):
self._mcg.playpause()
def toolbar_next_song_cb(self):
self._mcg.next_song()
def toolbar_filter_cb(self, filter_string):
self._cover_panel.filter(filter_string)
def toolbar_grid_size_temp_cb(self, size):
self._cover_panel.set_grid_size(size)
def toolbar_grid_size_cb(self, size):
self._cover_panel.set_grid_size(size)
self._toolbar.lock()
self._mcg.update()
# Cover panel callbacks
def cover_panel_play_cb(self, album):
self._mcg.play_album(album)
def cover_panel_update_start_cb(self):
GObject.idle_add(self._toolbar.lock)
def cover_panel_update_end_cb(self):
GObject.idle_add(self._toolbar.unlock)
def cover_panel_toggle_fullscreen_cb(self, event):
if event.type == Gdk.EventType._2BUTTON_PRESS:
self._toggle_fullscreen()
# MCG callbacks
def mcg_connect_cb(self, connected, message):
if connected:
GObject.idle_add(self._connect_connected)
self._mcg.update()
self._mcg.get_status()
else:
GObject.idle_add(self._connect_disconnected)
def mcg_status_cb(self, state, album, pos):
if state == 'play':
GObject.idle_add(self._toolbar.set_pause)
elif state == 'pause' or state == 'stop':
GObject.idle_add(self._toolbar.set_play)
if album:
GObject.idle_add(self._cover_panel.set_album, album)
GObject.idle_add(self._toolbar.set_album, album, pos);
def mcg_update_cb(self, albums):
self._cover_panel.update(albums)
# Private methods
def _connect(self):
if self._mcg.is_connected():
self._mcg.disconnect()
else:
self._connection_panel.lock()
host = self._connection_panel.get_host()
port = self._connection_panel.get_port()
password = self._connection_panel.get_password()
self._mcg.connect(host, port, password)
def _connect_connected(self):
self._toolbar.connected()
self._main_box.remove(self._connection_panel)
self._main_box.pack_start(self._cover_panel, True, True, 0)
self._main_box.show_all()
def _connect_disconnected(self):
self._main_box.remove(self._cover_panel)
self._main_box.pack_start(self._connection_panel, True, True, 0)
self._main_box.show_all()
self._connection_panel.unlock()
self._toolbar.disconnected()
def _save_size(self):
if not self._maximized:
self._config.window_width = self.get_allocation().width
self._config.window_height = self.get_allocation().height
def _save_state(self, state):
self._config.window_maximized = (state.new_window_state & Gdk.WindowState.MAXIMIZED > 0)
self._maximized = (state.new_window_state & Gdk.WindowState.MAXIMIZED > 0)
def _toggle_fullscreen(self):
if not self._fullscreened:
self.fullscreen()
else:
self.unfullscreen()
def _update_fullscreen(self):
if self._fullscreened:
self._toolbar.hide()
self._cover_panel.fullscreen();
else:
self._toolbar.show()
self._cover_panel.unfullscreen();
class Toolbar(Gtk.Toolbar):
SIGNAL_CONNECT = 'connect'
SIGNAL_UPDATE = 'update'
SIGNAL_PLAYPAUSE = 'playpause'
SIGNAL_NEXT_SONG = 'next-song'
SIGNAL_FILTER = 'filter'
SIGNAL_GRID_SIZE_TEMP = 'grid-size-temp'
SIGNAL_GRID_SIZE = 'grid-size'
def __init__(self):
Gtk.Toolbar.__init__(self)
self._callbacks = {}
self.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
# Widgets
self._connection_button = Gtk.ToolButton(Gtk.STOCK_DISCONNECT)
self.add(self._connection_button)
self._update_button = Gtk.ToolButton(Gtk.STOCK_REFRESH)
self.add(self._update_button)
self.add(Gtk.SeparatorToolItem())
self._playpause_button = Gtk.ToolButton(Gtk.STOCK_MEDIA_PLAY)
self.add(self._playpause_button)
self._next_button = Gtk.ToolButton(Gtk.STOCK_MEDIA_NEXT)
self.add(self._next_button)
self.add(Gtk.SeparatorToolItem())
self._track_item = Gtk.ToolItem()
self._track_label = Gtk.Label("hi")
self._track_item.add(self._track_label)
self.add(self._track_item)
separator = Gtk.SeparatorToolItem()
separator.set_draw(False)
separator.set_expand(True)
self.add(separator)
self._filter_item = Gtk.ToolItem()
self._filter_entry = Gtk.Entry()
self._filter_item.add(self._filter_entry)
self.add(self._filter_item)
self._grid_size_item = Gtk.ToolItem()
self._grid_size_scale = Gtk.HScale()
self._grid_size_scale.set_range(100,500)
self._grid_size_scale.set_round_digits(0)
self._grid_size_scale.set_value(128)
self._grid_size_scale.set_size_request(100, -1)
self._grid_size_scale.set_draw_value(False)
self._grid_size_item.add(self._grid_size_scale)
self.add(self._grid_size_item)
# Signals
self._connection_button.connect('clicked', self._callback_with_function, self.SIGNAL_CONNECT)
self._update_button.connect('clicked', self._callback_with_function, self.SIGNAL_UPDATE)
self._playpause_button.connect('clicked', self._callback_with_function, self.SIGNAL_PLAYPAUSE)
self._next_button.connect('clicked', self._callback_with_function, self.SIGNAL_NEXT_SONG)
self._filter_entry.connect('changed', self._callback_with_function, self.SIGNAL_FILTER, self._filter_entry.get_text)
self._grid_size_scale.connect('change-value', self.grid_size_temp_cb)
self._grid_size_scale.connect('button-release-event', self.grid_size_cb)
def connect_signal(self, signal, callback):
self._callbacks[signal] = callback
def connected(self):
self._connection_button.set_stock_id(Gtk.STOCK_CONNECT)
def disconnected(self):
self._connection_button.set_stock_id(Gtk.STOCK_DISCONNECT)
def lock(self):
self.set_sensitive(False)
def unlock(self):
self.set_sensitive(True)
def set_play(self):
self._playpause_button.set_stock_id(Gtk.STOCK_MEDIA_PLAY)
def set_pause(self):
self._playpause_button.set_stock_id(Gtk.STOCK_MEDIA_PAUSE)
def lock_playpause(self):
self._playpause_button.set_stock_id(Gtk.STOCK_MEDIA_PLAY)
self._playpause_button.set_sensitive(False);
def set_album(self, album, pos):
info = "{0} {1} {2} {3}".format(album.get_tracks()[pos].get_title(), pos+1, album.get_title(), album.get_artist())
self._track_label.set_text(info)
def grid_size_temp_cb(self, widget, scroll, value):
value = round(value)
range = self._grid_size_scale.get_adjustment()
if value < range.get_lower() or value > range.get_upper():
return
self._callback(self.SIGNAL_GRID_SIZE_TEMP, value)
def grid_size_cb(self, widget, event):
value = round(self._grid_size_scale.get_value())
range = self._grid_size_scale.get_adjustment()
if value < range.get_lower() or value > range.get_upper():
return
self._callback(self.SIGNAL_GRID_SIZE, value)
def _callback(self, signal, *data):
if signal in self._callbacks:
callback = self._callbacks[signal]
callback(*data)
def _callback_with_function(self, widget, signal, data_function=None):
data = []
if data_function is not None:
data = {data_function()}
self._callback(signal, *data)
class ConnectionPanel(Gtk.Box):
def __init__(self, config):
Gtk.HBox.__init__(self)
self._callbacks = {}
self._config = config
vbox = Gtk.VBox()
self.pack_start(vbox, True, False, 0)
self._table = Gtk.Table(3, 2, False)
vbox.pack_start(self._table, True, False, 0)
# Host
host_label = Gtk.Label("Host:")
host_label.set_alignment(0, 0.5)
self._table.attach(host_label, 0, 1, 0, 1)
self._host_entry = Gtk.Entry()
self._host_entry.set_text("localhost")
self._table.attach(self._host_entry, 1, 2, 0, 1)
# Port
port_label = Gtk.Label("Port:")
port_label.set_alignment(0, 0.5)
self._table.attach(port_label, 0, 1, 1, 2)
adjustment = Gtk.Adjustment(6600, 1024, 9999, 1, 10, 10)
self._port_spinner = Gtk.SpinButton()
self._port_spinner.set_adjustment(adjustment)
self._table.attach(self._port_spinner, 1, 2, 1, 2)
# Passwort
password_label = Gtk.Label("Password:")
password_label.set_alignment(0, 0.5)
self._table.attach(password_label, 0, 1, 2, 3)
self._password_entry = Gtk.Entry()
self._password_entry.set_visibility(False)
self._table.attach(self._password_entry, 1, 2, 2, 3)
# Signals
self._host_entry.connect('focus-out-event', self._lost_focus)
self._port_spinner.connect('focus-out-event', self._lost_focus)
self._password_entry.connect('focus-out-event', self._lost_focus)
self._load_config()
def _lost_focus(self, widget, data):
self._save_config()
def _load_config(self):
self.set_host(self._config.host)
self.set_port(self._config.port)
self.set_password(self._config.password)
def _save_config(self):
self._config.host = self._host_entry.get_text()
self._config.port = self._port_spinner.get_value_as_int()
self._config.password = self._password_entry.get_text()
self._config.save()
def set_host(self, host):
self._host_entry.set_text(host)
def get_host(self):
return self._host_entry.get_text()
def set_port(self, port):
self._port_spinner.set_value(port)
def get_port(self):
return self._port_spinner.get_value_as_int()
def set_password(self, password):
if password is None:
password = ""
self._password_entry.set_text(password)
def get_password(self):
if self._password_entry.get_text() == "":
return None
else:
return self._password_entry.get_text()
def lock(self):
self._lock(False)
def unlock(self):
self._lock(True)
def _lock(self, sensitive):
self._table.set_sensitive(sensitive)
from threading import Thread
import math
class CoverPanel(Gtk.HPaned):
SIGNAL_UPDATE_START = 'update-start'
SIGNAL_UPDATE_END = 'update-end'
SIGNAL_PLAY = 'play'
SIGNAL_TOGGLE_FULLSCREEN = 'toggle-fullscreen'
def __init__(self, config):
Gtk.HPaned.__init__(self)
self._config = config
self._callbacks = {}
self._albums = []
self._cover_pixbuf = None
self._grid_pixbufs = {}
self._filter_string = ""
self._is_fullscreen = False
self._old_range = None
self._cover_background_color = None
# Image
self._cover_image = Gtk.Image()
# EventBox
self._cover_box = Gtk.EventBox()
self._cover_background_color = self._cover_box.get_style_context().get_background_color(Gtk.StateFlags.NORMAL)
self._cover_box.add(self._cover_image)
# Scroll
self._cover_scroll = Gtk.ScrolledWindow()
self._cover_scroll.add_with_viewport(self._cover_box)
self.pack1(self._cover_scroll, True, True)
# GridModel
self._cover_grid_model = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str)
self._cover_grid_model.set_sort_func(3, self.compare_albums, mcg.MCGAlbum.SORT_BY_TITLE)
self._cover_grid_model.set_sort_column_id(3, Gtk.SortType.ASCENDING)
self._cover_grid_filter = self._cover_grid_model.filter_new()
self._cover_grid_filter.set_visible_func(self.filter_visible_cb)
# GridView
self._cover_grid = Gtk.IconView(self._cover_grid_filter)
self._cover_grid.set_pixbuf_column(0)
self._cover_grid.set_text_column(-1)
self._cover_grid.set_tooltip_column(2)
self._cover_grid.set_columns(-1)
self._cover_grid.set_margin(0)
self._cover_grid.set_row_spacing(0)
self._cover_grid.set_column_spacing(0)
self._cover_grid.set_item_padding(1)
self._cover_grid.set_reorderable(False)
self._cover_grid.set_selection_mode(Gtk.SelectionMode.SINGLE)
# Scroll
self._cover_grid_scroll = Gtk.ScrolledWindow()
self._cover_grid_scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
self._cover_grid_scroll.add(self._cover_grid)
self.pack2(self._cover_grid_scroll, False, True)
# Progress Bar
self._progress_box = Gtk.VBox()
self._progress_bar = Gtk.ProgressBar()
self._progress_box.pack_start(self._progress_bar, True, False, 0)
# Context Menu
self._cover_grid_menu = Gtk.Menu()
# Infos
item_infos = Gtk.MenuItem("Infos")
item_infos.show()
self._cover_grid_menu.add(item_infos)
menu_infos = Gtk.Menu()
menu_infos.show()
item_infos.set_submenu(menu_infos)
item = Gtk.CheckMenuItem("Title")
item.connect('activate', self.cover_grid_menu_infos)
item.show()
menu_infos.add(item)
# Sorting
item_sorting = Gtk.MenuItem("Sorting")
item_sorting.show()
self._cover_grid_menu.add(item_sorting)
menu_sorting = Gtk.Menu()
menu_sorting.show()
item_sorting.set_submenu(menu_sorting)
cover_grid_menu_group_sort = None
item = Gtk.RadioMenuItem("by artist")
item.connect('activate', self.cover_grid_menu_sort, mcg.MCGAlbum.SORT_BY_ARTIST)
item.show()
menu_sorting.add(item)
cover_grid_menu_group_sort = item
item = Gtk.RadioMenuItem(group=cover_grid_menu_group_sort, label="by title")
item.set_active(True)
item.connect('activate', self.cover_grid_menu_sort, mcg.MCGAlbum.SORT_BY_TITLE)
item.show()
menu_sorting.add(item)
item = Gtk.RadioMenuItem(group=cover_grid_menu_group_sort, label="by year")
item.connect('activate', self.cover_grid_menu_sort, mcg.MCGAlbum.SORT_BY_YEAR)
item.show()
menu_sorting.add(item)
item = Gtk.SeparatorMenuItem()
item.show()
menu_sorting.add(item)
item = Gtk.RadioMenuItem("Ascending")
cover_grid_menu_group_sort_type = item
item.set_active(True)
item.connect('activate', lambda widget: self._cover_grid_model.set_sort_column_id(3, Gtk.SortType.ASCENDING))
item.show()
menu_sorting.add(item)
item = Gtk.RadioMenuItem(group=cover_grid_menu_group_sort_type, label="Descending")
item.connect('activate', lambda widget: self._cover_grid_model.set_sort_column_id(3, Gtk.SortType.DESCENDING))
item.show()
menu_sorting.add(item)
self._cover_grid_menu.show()
# Signals
self.connect('size-allocate', self.resize_pane_callback)
self._cover_scroll.connect('size-allocate', self.resize_image_callback)
self._cover_box.connect('button-press-event', self.toggle_fullscreen_cb)
self._cover_grid.connect('item-activated', self.cover_grid_click_cb)
self._cover_grid.connect('button-press-event', self.cover_grid_button_press_cb)
self.set_position(self._config.pane_position)
def connect_signal(self, signal, callback):
self._callbacks[signal] = callback
def _callback(self, signal, *args):
if signal in self._callbacks:
callback = self._callbacks[signal]
callback(*args)
def update(self, albums):
self._go = True
self._albums = albums
Thread(target=self._update, args=(albums,)).start()
def _update(self, albums):
self._callback(self.SIGNAL_UPDATE_START)
Gdk.threads_enter()
self.remove(self._cover_grid_scroll)
self._progress_bar.set_fraction(0.0)
self.pack2(self._progress_box, False)
self.show_all()
self._cover_grid.set_model(None)
self._cover_grid.freeze_child_notify()
self._cover_grid_model.clear()
Gdk.threads_leave()
i = 0
n = len(albums)
for hash in albums.keys():
album = albums[hash]
file = album.get_cover()
if file is None:
# TODO Dummy
continue
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(file, self._config.grid_item_size, self._config.grid_item_size)
if pixbuf is None:
continue
self._grid_pixbufs[album.get_hash()] = pixbuf
self._cover_grid_model.append([pixbuf, album.get_title(), GObject.markup_escape_text("\n".join([album.get_title(), album.get_artist()])), hash])
i += 1
GObject.idle_add(self._progress_bar.set_fraction, i/n)
Gdk.threads_enter()
self._cover_grid.set_model(self._cover_grid_filter)
self._cover_grid.thaw_child_notify()
self.remove(self._progress_box)
self.pack2(self._cover_grid_scroll, False)
self._dummy_pixbuf = None
self._old_range = None
Gdk.threads_leave()
self._callback(self.SIGNAL_UPDATE_END)
def set_album(self, album):
self._cover_image.set_tooltip_text(GObject.markup_escape_text("\n".join([album.get_title(), album.get_artist()])))
# Check path
url = album.get_cover()
if url is not None and url != "":
# Load image and draw it
self._cover_pixbuf = GdkPixbuf.Pixbuf.new_from_file(url)
self._resize_image()
else:
# Reset image
self._cover_pixbuf = None
self._cover_image.clear()
def set_grid_size(self, size):
self._config.grid_item_size = size
self._cover_grid.set_item_width(self._config.grid_item_size)
if self._old_range is None:
self._old_range = range(0, len(self._cover_grid_model))
old_start = self._old_range[0]
old_end = self._old_range[len(self._old_range)-1]
vis_range = self._cover_grid.get_visible_range()
(vis_start,), (vis_end,) = vis_range
vis_range = range(vis_start, vis_end+1)
self._old_range = vis_range
cur_range = range(min(vis_start, old_start), max(vis_end+1, old_end+1))
for path in cur_range:
iter = self._cover_grid_model.get_iter(path)
hash = self._cover_grid_model.get_value(iter, 3)
if path in vis_range:
pixbuf = self._grid_pixbufs[hash]
self._cover_grid_model.set_value(iter, 0, pixbuf.scale_simple(self._config.grid_item_size, self._config.grid_item_size, GdkPixbuf.InterpType.NEAREST))
vis_range = self._cover_grid.get_visible_range()
(vis_start,), (vis_end,) = vis_range
vis_range = range(vis_start, vis_end+1)
else:
pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 1, 1)
self._cover_grid_model.set_value(iter, 0, pixbuf)
self._cover_grid.set_item_width(self._config.grid_item_size)
def resize_pane_callback(self, widget, allocation):
self._config.pane_position = self.get_position()
def resize_image_callback(self, widget, allocation):
self._resize_image()
def _resize_image(self):
"""Diese Methode skaliert das geladene Bild aus dem Pixelpuffer
auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse
"""
pixbuf = self._cover_pixbuf
size = self._cover_scroll.get_allocation()
## Check pixelbuffer
if pixbuf is None:
return
# Skalierungswert für Breite und Höhe ermitteln
ratioW = float(size.width) / float(pixbuf.get_width())
ratioH = float(size.height) / float(pixbuf.get_height())
# Kleineren beider Skalierungswerte nehmen, nicht Hochskalieren
ratio = min(ratioW, ratioH)
ratio = min(ratio, 1)
# Neue Breite und Höhe berechnen
width = int(round(pixbuf.get_width()*ratio))
height = int(round(pixbuf.get_height()*ratio))
# Pixelpuffer auf Oberfläche zeichnen
self._cover_image.set_from_pixbuf(pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
def cover_grid_click_cb(self, widget, path):
path = self._cover_grid_filter.convert_path_to_child_path(path)
iter = self._cover_grid_model.get_iter(path)
self._callback(self.SIGNAL_PLAY, self._cover_grid_model.get_value(iter, 3))
def cover_grid_button_press_cb(self, widget, event):
if event.button == 3:
self._cover_grid_menu.popup(None, None, None, None, event.button, event.time)
def cover_grid_menu_sort(self, widget, criterion):
self._cover_grid_model.set_sort_func(3, self.compare_albums, criterion)
def cover_grid_menu_infos(self, widget):
if widget.get_active():
self._cover_grid.set_text_column(1)
else:
self._cover_grid.set_text_column(-1)
def filter(self, filter_string):
self._filter_string = filter_string
self._cover_grid_filter.refilter()
def filter_visible_cb(self, model, iter, data):
hash = model.get_value(iter, 3)
if hash == "":
return
album = self._albums[hash]
return album.filter(self._filter_string)
def toggle_fullscreen_cb(self, widget, event):
self._callback(self.SIGNAL_TOGGLE_FULLSCREEN, event)
def fullscreen(self):
self.remove(self._cover_grid_scroll)
self._cover_box.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1))
def unfullscreen(self):
self.pack2(self._cover_grid_scroll, False, True)
self._cover_box.override_background_color(Gtk.StateFlags.NORMAL, self._cover_background_color)
def compare_albums(self, model, row1, row2, criterion):
hash1 = model.get_value(row1, 3)
hash2 = model.get_value(row2, 3)
if hash1 == "" or hash2 == "":
return
return mcg.MCGAlbum.compare(self._albums[hash1], self._albums[hash2], criterion)
import os
import configparser
class Configuration:
CONFIG_FILE = '~/.config/mcggtk.config'
def __init__(self):
self._config = configparser.RawConfigParser()
self.host = "localhost"
self.port = 6600
self.password = ""
self.window_width = 600
self.window_height = 400
self.window_maximized = False
self.pane_position = 300
self.grid_item_size = 128
self.load()
def load(self):
if not os.path.isfile(self._get_filename()):
return
self._config.read(self._get_filename())
if self._config.has_section('connection'):
if self._config.has_option('connection', 'host'):
self.host = self._config.get('connection', 'host')
if self._config.has_option('connection', 'port'):
self.port = self._config.getint('connection', 'port')
if self._config.has_option('connection', 'password'):
self.password = self._config.get('connection', 'password')
if self._config.has_section('gui'):
if self._config.has_option('gui', 'window_width'):
self.window_width = self._config.getint('gui', 'window_width')
if self._config.has_option('gui', 'window_height'):
self.window_height = self._config.getint('gui', 'window_height')
if self._config.has_option('gui', 'window_maximized'):
self.window_maximized = self._config.getboolean('gui', 'window_maximized')
if self._config.has_option('gui', 'pane_position'):
self.pane_position = self._config.getint('gui', 'pane_position')
if self._config.has_option('gui', 'grid_item_size'):
self.grid_item_size = self._config.getint('gui', 'grid_item_size')
def save(self):
if not self._config.has_section('connection'):
self._config.add_section('connection')
self._config.set('connection', 'host', self.host)
self._config.set('connection', 'port', self.port)
self._config.remove_option('connection', 'password')
if self.password is not "":
self._config.set('connection', 'password', self.password)
if not self._config.has_section('gui'):
self._config.add_section('gui')
self._config.set('gui', 'window_width', self.window_width)
self._config.set('gui', 'window_height', self.window_height)
self._config.set('gui', 'window_maximized', self.window_maximized)
self._config.set('gui', 'pane_position', self.pane_position)
self._config.set('gui', 'grid_item_size', self.grid_item_size)
with open(self._get_filename(), 'w') as configfile:
self._config.write(configfile)
def _get_filename(self):
#return os.path.expanduser(self.CONFIG_FILE)
return 'config'
if __name__ == "__main__":
GObject.threads_init()
Gdk.threads_init()
mcgg = MCGGtk()
mcgg.show_all()
try:
Gtk.main()
except (KeyboardInterrupt, SystemExit):
pass