#!/usr/bin/python
# -*- coding: UTF-8 -*-
###########################################################################
# displayconfig.py - description                                          #
# ------------------------------                                          #
# begin     : Fri Mar 02 2007                                             #
# copyright : (C) 2007 Canonical
# email     : michael.vogt@ubuntu.com                                     #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 2 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
###########################################################################

import string
import os
import select
import sys
import csv
import time
import signal
import shutil

import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
import gobject
from displayconfiggtk.SimpleGladeApp import SimpleGladeApp


from displayconfig.displayconfigcommon import _findXorgConfig, testX
from displayconfig.displayconfigabstraction import *

from gettext import gettext as _


class DisplayConfig(SimpleGladeApp):

    def __init__(self, gladefile):
        SimpleGladeApp.__init__(self, gladefile)
        
        self.xconfigpath = _findXorgConfig()
        SetDataFileDir("/usr/share/displayconfig-gtk/")

        self.xsetup = XSetup(self.xconfigpath)
        self._populateMonitorDialog()
        self._populateGfxcardDialog()
        self._syncGUI()
        
    def _populateMonitorDialog(self):
        self.monitordb = monitordb = GetMonitorModelDB()
        tree = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("", renderer, text=0)
        self.treeview_monitors.append_column(column)
        self.treeview_monitors.set_model(tree)
        toplevel_iter = tree.append(None)
        tree.set(toplevel_iter, 0, _("Manufactures"))
        vendors = monitordb.vendordb.keys()
        vendors.sort()
        for vendor in vendors:
            monitorkeys = self.monitordb.vendordb[vendor].keys()
            tree_iter = tree.append(toplevel_iter)
            tree.set(tree_iter,
                     0, vendor,
                     1, None)
            for monitorkey in monitorkeys:
                it = tree.append(tree_iter)
                tree.set(it,
                         0, monitorkey,
                         1, self.monitordb.vendordb[vendor][monitorkey])
        toplevel_iter = tree.append(None)
        tree.set(toplevel_iter, 0, _("Generic"))
        generics = monitordb.genericdb.keys()
        generics.sort()
        for generic in generics:
            tree_iter = tree.append(toplevel_iter)
            tree.set(tree_iter,
                     0, generic,
                     1, monitordb.genericdb[generic])
        customs = monitordb.getCustomMonitors().keys()
        customs.sort()
        for custom in customs:
            tree_iter = tree.append(None)
            tree.set(tree_iter,
                     0, custom,
                     1, monitordb.getCustomMonitors()[custom])
        self.treeview_monitors.set_cursor(tree.get_path(tree_iter))
    def on_treeview_monitors_cursor_changed(self, treeview):
        model = treeview.get_model()
        cursor_path = treeview.get_cursor()[0]
        mon = model[cursor_path][1]
        if mon is not None:
            self.label_hrange.set_text(mon.getVerticalSync())
            self.label_vrange.set_text(mon.getHorizontalSync())
    def on_treeview_gfxcards_cursor_changed(self, treeview):
        model = treeview.get_model()
        cursor_path = treeview.get_cursor()[0]
        card = model[cursor_path][1]
        self.radiobutton_driver_proprietary.set_active(False)
        self.radiobutton_driver_proprietary.set_sensitive(False)
        if card is not None:
            s = card.getProprietaryDriver()
            self.radiobutton_driver_proprietary.set_sensitive(s is not None)

    def _populateGfxcardDialog(self):
        self.gfxcarddb = gfxcarddb = GfxCardModelDB()
        tree = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("", renderer, text=0)
        self.treeview_gfxcards.append_column(column)
        self.treeview_gfxcards.set_model(tree)
        toplevel_iter = tree.append(None)
        tree.set(toplevel_iter, 0, _("Manufactures"))
        # Add the GfxCards under the Manufacturer item.
        vendors = gfxcarddb.vendordb.keys()
        vendors.sort()
        for vendor in vendors:
            cardkeys = self.gfxcarddb.vendordb[vendor].keys()
            tree_iter = tree.append(toplevel_iter)
            tree.set(tree_iter,
                     0, vendor,
                     1, None)
            for cardkey in cardkeys:
                it = tree.append(tree_iter)
                tree.set(it,
                         0, cardkey,
                         1, self.gfxcarddb.vendordb[vendor][cardkey])
        toplevel_iter = tree.append(None)
        tree.set(toplevel_iter, 0, _("Drivers"))
        # Add the GfxCard _drivers_ under the Drivers item
        drivers = gfxcarddb.driverdb.keys()
        drivers.sort()
        for driver in drivers:
            tree_iter = tree.append(toplevel_iter)
            tree.set(tree_iter,
                     0, driver,
                     1, gfxcarddb.driverdb[driver])
    def _syncGUI(self):
        self.vbox_cards.foreach(lambda w: self.vbox_cards.remove(w))
        for gfxcard in self.xsetup.getGfxCards():
            xml = gtk.glade.XML(self.glade_path, "window_fake")
            card = gfxcard.getGfxCardModel()
            if card is not None:
                xml.get_widget("label_card").set_text(card.getName())
                # FIXME: getDriver() and getProprietaryDriver() sometimes
                #        return None
                if gfxcard.isProprietaryDriver():
                    xml.get_widget("label_driver").set_text(card.getProprietaryDriver())
                else:
                    xml.get_widget("label_driver").set_text(card.getDriver())
                xml.get_widget("button_card_configure").connect("clicked", self.on_button_card_configure_clicked, gfxcard)
            for i in range(len(gfxcard.getScreens())):
                monitor_name = _("unknown")
                screen = gfxcard.getScreens()[i]
                if screen.getMonitorModel() is not None:
                    monitor_name = screen.getMonitorModel().getName()
                if screen.getMonitorAspect()==ModeLine.ASPECT_16_9:
                    monitor_name += _(" (widescreen)")
                xml.get_widget("label_monitor%i" % i).set_text(monitor_name)
                xml.get_widget("label_monitor%i" % i).show()
                xml.get_widget("label_cap_monitor%i" % i).show()
                xml.get_widget("button_monitor_configure%i" % i).show()
                xml.get_widget("button_monitor_configure%i" % i).connect("clicked", self.on_button_monitor_configure_clicked, gfxcard, i)
            bin = gtk.Alignment()
            xml.get_widget("label_card_frame").set_markup("<b>%s</b>" % card.getName())
            bin.show()
            self.vbox_cards.pack_start(bin)
            xml.get_widget("frame_card").reparent(bin)
    def _select_in_treeview(self, treeview, key, col):
        def find(model, path, iter):
            if model[path][col] == key:
                treeview.expand_to_path(path)
                treeview.scroll_to_cell(path)
                treeview.set_cursor(path)
                return True
            return False
        model = treeview.get_model()
        model.foreach(find)
    def on_button_monitor_configure_clicked(self, widget, gfxcard, screen_index):
        screen = gfxcard.getScreens()[screen_index]
        self._select_in_treeview(self.treeview_monitors, screen.getMonitorModel(), 1)
        res = self.dialog_monitor.run()
        self.dialog_monitor.hide()
        if res == gtk.RESPONSE_OK:
            model = self.treeview_monitors.get_model()
            cursor_path = self.treeview_monitors.get_cursor()[0]
            mon = model[cursor_path][1]
            if mon is not None:
                # FIXME: support multiple screens 
                screen.setMonitorModel(mon)
                self._syncGUI()
    def on_button_card_configure_clicked(self, widget, gfxcard):
        self._select_in_treeview(self.treeview_gfxcards,
                                 gfxcard.getGfxCardModel().name, 0)
        self.radiobutton_driver_proprietary.set_active(gfxcard.isProprietaryDriver())
        res = self.dialog_gfxcard.run()
        self.dialog_gfxcard.hide()
        if res == gtk.RESPONSE_OK:
            model = self.treeview_gfxcards.get_model()        
            cursor_path = self.treeview_gfxcards.get_cursor()[0]
            card = model[cursor_path][1]
            if card is not None:
                #print card
                gfxcard.setGfxCardModel(card)
                gfxcard.setProprietaryDriver(self.radiobutton_driver_proprietary.get_active())
                self._syncGUI()
        
    def on_button_close_clicked(self, widget):
        gtk.main_quit()
    def on_button_apply_clicked(self, widget):
        self.apply_changes()
        gtk.main_quit()
    def on_button_test_config_clicked(self, widget):
        print "on_button_test_config_clicked()"
        (res, msg) = testX(self.xsetup,"/usr/share/displayconfig-gtk/servertestdialog-gtk")
        print res
        print msg
        if (res == False):
            dia = gtk.MessageDialog(parent=self.window_main,
                                    type=gtk.MESSAGE_INFO,
                                    buttons=gtk.BUTTONS_CLOSE,
                                    message_format=_("X server failed"))
            dia.format_secondary_text(_("The configuration was not successful"))
            dia.run()
            dia.destroy()
            
    def apply_changes(self):
        print "applying changes"
        # Backup up the current config file.
        i = 1
        while os.path.exists("%s.%i" % (self.xconfigpath,i)):
            i += 1
        shutil.copyfile(self.xconfigpath,"%s.%i" % (self.xconfigpath,i))
        # Write out the new config
        tmpfilename = self.xconfigpath + ".tmp"
        self.xsetup.writeXorgConfig(tmpfilename)
        os.rename(tmpfilename, self.xconfigpath)


if __name__ == "__main__":

    isroot = os.getuid()==0
    
    d = DisplayConfig("/usr/share/displayconfig-gtk/displayconfig.glade")
    d.run()

    sys.exit(0)

    
