# -*- coding: utf-8 -*-
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 autoindent syntax=python
# -*- Mode: Python; py-indent-offset: 4 -*-
"""
Ojuba Control Center
Copyright © 2009, Ojuba Team <core@ojuba.org>

        Released under terms of Waqf Public License.
        This program is free software; you can redistribute it and/or modify
        it under the terms of the latest version Waqf Public License as
        published by Ojuba.org.

        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

        The Latest version of the license can be found on
        "http://waqf.ojuba.org/license"
"""

#import pty
#import signal
#import os
#import re
#import time
from gi.repository import Gtk
from subprocess import Popen, PIPE
from OjubaControlCenter.pluginsClass import PluginsClass
from OjubaControlCenter.widgets import run_in_bg
from OjubaControlCenter.widgets import LaunchOrInstall, sure, info, error

## NOTE: these global vars is loader validators
category = 'hw'
caption = _('Fallback X procedures:')
description = ''
priority = 11

class occPlugin(PluginsClass):
    xorgconf_t="""
# generated by Ojuba Control Center
Section "ServerLayout"
        Identifier         "Default Layout"
        Screen            0    "Screen0" 0 0
        InputDevice        "Keyboard0" "CoreKeyboard"
EndSection

Section "Files"
        ModulePath            "/usr/lib/xorg/modules/extensions/nvidia"
        ModulePath            "/usr/lib/xorg/modules/extensions/catalyst"
        ModulePath            "/usr/lib/xorg/modules"
EndSection

Section "ServerFlags"
        Option                 "AIGLX" "%(aiglx)s"
        Option                 "Xinerama" "0"
EndSection

Section "InputDevice"
        # generated from default
        Identifier         "Keyboard0"
        Driver                 "keyboard"
EndSection

Section "Device"
        Identifier         "Device0"
        Driver                 "%(driver)s"
EndSection

Section "Monitor"
        Identifier         "Monitor0"
        VendorName         "Unknown"
        ModelName            "Generic"
        HorizSync             30.0 - 97.0
        VertRefresh         50.0 - 180.0
        Option                 "DPMS"
EndSection

Section "Screen"
        Identifier         "Screen0"
        Device                 "Device0"
        Monitor                "Monitor0"
        DefaultDepth        24
        Option                 "TwinView" "0"
        Option                 "TwinViewXineramaInfoOrder" "CRT-0"
        #Option                 "metamodes" "1280x1024_85 +0+0; 1280x1024 +0+0"
        Option                 "metamodes" "%(modes)s"
        SubSection         "Display"
                Depth             24
        EndSubSection
EndSection

Section "Extensions"
        Option                 "Composite" "%(compiz)s"
EndSection
"""
    generic_drivers='fbdev, vesa'
    drivers=(
        ('10de','nvidia','nvidia, nouveau, nv'),
        ('1002','radeonhd','fglrx, radeonhd, ati'),
        ('8086','intel', 'intel, i740'),
        ('1106','openchrome','openchrome, s3, s3virge, savage'), # via
        ('5333','openchrome','openchrome, s3, s3virge, savage'), # s3
        ('1039','sis', 'sis')
    )
    def __init__(self,ccw):
        PluginsClass.__init__(self, ccw, caption, category, priority)
        self.__lspci=None
        vb=Gtk.VBox(False,2)
        self.add(vb)
        hb=Gtk.HBox(False,2)
        vb.pack_start(hb,True,True,2)
        l=Gtk.Label()
        l.set_markup(_("""This is an advanced tool that should <b>NOT</b> be used in normal cases.
If you tried other tools and it fails you may use this tool."""))
        hb.pack_start(l,False,False,2)
        hb=Gtk.HBox(False,2)
        vb.pack_start(hb,False,False,2)
        self.advanced=Gtk.Expander()
        self.advanced.set_label(_("Show Advanced options"))
        hb.pack_start(self.advanced,False,False,2)
        vbe=Gtk.VBox(False,2)
        self.advanced.add(vbe)
        
        f=Gtk.Frame()
        f.set_label(_('initrd generation'))
        vbe.pack_start(f,False,False,2)
        vb=Gtk.VBox(False,2)
        f.add(vb)
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        l=Gtk.Label(_("""initrd file could contain old modules that conflict some proprietary drivers.
You may want to generate a new initrd file."""))
        hb.pack_start(l,False,False,2)
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        b=Gtk.Button(_("Generate initrd"))
        b.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_EXECUTE, Gtk.IconSize.BUTTON))
        b.connect('clicked', self.mkinitrd)
        hb.pack_start(b,False,False,2)
        
        f=Gtk.Frame()
        f.set_label(_('Xorg.conf creation tool'))
        vbe.pack_start(f,False,False,2)
        vb=Gtk.VBox(False,2)
        f.add(vb)
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        l=Gtk.Label(_("""Xorg.conf is the file that controls X server which is the base of the graphical environment.
This tool will overwrite xorg.conf with a new one that is not based on your working one."""))
        hb.pack_start(l,False,False,2)
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        hb.pack_start(Gtk.Label(_('Driver:')),False,False,2)
        self.driver=Gtk.Entry()
        d,tip=self.default_driver()
        self.driver.set_text(d)
        self.driver.set_tooltip_text(_('usually a single lower case word like: %s') % tip)
        hb.pack_start(self.driver,False,False,2)
        
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        self.compiz=Gtk.CheckButton(_("Enable Composite extension"))
        self.compiz.set_active(True)
        self.compiz.set_tooltip_text(_('This extention is needed by special effects but could case problems in rare cases.'))
        hb.pack_start(self.compiz,False,False,2)
        self.aiglx=Gtk.CheckButton(_("Enable AIGLX"))
        self.aiglx.set_active(True)
        self.aiglx.set_tooltip_text(_('Enable Accelerated indirect rendering.'))
        hb.pack_start(self.aiglx,False,False,2)
        
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        hb.pack_start(Gtk.Label(_('Vertical Refresh Rate:')),False,False,2)
        self.auto_vref=Gtk.CheckButton(_('auto'))
        self.auto_vref.set_active(True)
        hb.pack_start(self.auto_vref,False,False,2)
        self.m_vref=Gtk.CheckButton(_('manual:'))
        self.m_vref.set_active(True)
        hb.pack_start(self.m_vref,False,False,2)
        self.vref=Gtk.SpinButton()
        self.vref.set_tooltip_text(_('a value of 85Hz would be nicer on your eyes, lower values like 60Hz would work with LCD or old CRT monitors.'))
        self.vref.set_adjustment(Gtk.Adjustment(85, 50, 120, 5, 0, 0))
        hb.pack_start(self.vref,False,False,2)
        self.m_vref.connect('toggled', lambda b: self.vref.set_sensitive(self.m_vref.get_active()))

        self.res=[]
        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        hb.pack_start(Gtk.Label(_('HD Resolutions:')),False,False,2)
        for i in ['1920×1080', '1280x1024', '1280×720']:
            self.res.append(Gtk.CheckButton(i))
            hb.pack_start(self.res[-1],False,False,2)

        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        hb.pack_start(Gtk.Label(_('LCD Wide Resolutions:')),False,False,2)
        for i in ['2560x1600', '1920x1200', '1680x1050', '1440x900', '1280x800']:
            self.res.append(Gtk.CheckButton(i))
            hb.pack_start(self.res[-1],False,False,2)


        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        hb.pack_start(Gtk.Label(_('Normal Resolutions:')),False,False,2)
        res=['1600x1200', '1280x960', '1024x768', '800x600', '640x400', '320x240', '320x200']

        for n,i in enumerate(res):
            c=Gtk.CheckButton(i)
            self.res.append(c)
            if n>1: c.set_active(True)
            hb.pack_start(c,False,False,2)

        hb=Gtk.HBox(False,2); vb.pack_start(hb,False,False,2)
        b=Gtk.Button(stock=Gtk.STOCK_SAVE)
        b.connect('clicked', self.save)
        hb.pack_start(b,False,False,2)
        b=Gtk.Button(_('Delete xorg.conf'))
        b.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_DELETE, Gtk.IconSize.BUTTON))
        b.set_tooltip_text(_('This will make X use default settings.'))
        b.connect('clicked', self.delete)
        hb.pack_start(b,False,False,2)

    def delete(self, b):
        if not sure(_('Do you like to remove xorg.conf file to use default settings?'), self.ccw): return
        s=self.ccw.mechanism('run', 'system', 'rm /etc/X11/xorg.conf')
        if s == 'NotAuth': return
        if s=='0': info(_('Done. Changes will take effect when you login next time.'), self.ccw)
        else: error(_('unexpected return code, possible an error had occurred.'), self.ccw); return

    def __lspci_n(self):
        if self.__lspci: return self.__lspci
        p1 = Popen(["lspci","-n"], stdout=PIPE)
        self.__lspci=filter(lambda j: len(j)>=3, map(lambda i: i.split(' ',3),p1.communicate()[0].lower().splitlines()))
        return self.__lspci

    def __vga_pciid(self):
        return map(lambda i: i[2].split(':'),filter(lambda j: j[1]=='0300:', self.__lspci_n()))

    def is_vga_by(self, pid):
        l=filter(lambda i: i[0]==pid,self.__vga_pciid())
        if not l: return False
        return True

    def default_driver(self):
        for pid,df,l in self.drivers:
            if self.is_vga_by(pid): return df, l+", "+self.generic_drivers
        return 'vesa', self.generic_drivers

    def modestr(self, modes):
        if self.m_vref.get_active():
            v=int(self.vref.get_value())
            if self.auto_vref.get_active():
                return '; '.join(map(lambda m: "%s_%d +0+0; %s +0+0" % (m,v,m), modes))
            else:
                return '; '.join(map(lambda m: "%s_%d +0+0" % (m,v), modes))
        return '; '.join(map(lambda m: "%s +0+0" % (m), modes))

    def save(self, b):
        v={}
        modes=map(lambda m: m.get_child().get_text(), filter(lambda r: r.get_active() ,self.res))
        v['modes']=self.modestr(modes)
        v['driver']=self.driver.get_text().strip()
        v['compiz']=('Disable','Enable')[self.compiz.get_active()]
        v['aiglx']=('off','on')[self.aiglx.get_active()]
        if ' ' in v['driver'] or '\t' in v['driver']: error(_('driver should be one word')); return
        if v['driver'].lower()!=v['driver']: error(_('driver should be lower case'), self.ccw); return
        if not sure(_('Are you sure you want to overwrite your currently working xorg.conf file and generate a new one ?'), self.ccw): return
        xorgconf=self.xorgconf_t % v
        s=self.ccw.mechanism('vga', 'saveXorgConf', xorgconf)
        if s == 'NotAuth': return
        if s=='0': info(_('Done. Changes will take effect when you login next time.'), self.ccw)
        else: error(_('unexpected return code, possible an error had occurred.'), self.ccw); return
        self.mkinitrd(b)

    def mkinitrd(self, b):
        if not sure(_('Some proprietary require rebuild initrd.\nWould you like to do that?'), self.ccw): return
        s=self.ccw.mechanism('run', 'system','mkinitrd -f --allow-missing /boot/initrd-`uname -r`.img `uname -r`')
        if s == 'NotAuth': return
        if s=='0': info(_('Done. Changes will take effect when you reboot.'), self.ccw)
        else: error(_('unexpected return code, possible an error had occurred.'), self.ccw); return

