#!/usr/bin/python3

import glob, os, math, sys, fileinput, time, subprocess
from collections import namedtuple

from PyQt5.QtCore import QAbstractTableModel, Qt, QSize
from PyQt5.QtGui import QImage, QPixmap, QIcon
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableView, QStyledItemDelegate, QDesktopWidget, QMessageBox

# Create a custom namedtuple class to hold our data.
preview = namedtuple("preview", "id title image")
IDESKFILE = os.path.join(os.path.expanduser("~/"), ".ideskrc")
NUMBER_OF_COLUMNS = 2
CELL_PADDING = 20 # all sides

IDESKDEFAULT = """table Config
  FontName: sans
  FontSize: 11
  FontColor: #FFFFFF
  ToolTip.FontSize: 16
  ToolTip.FontName: sans
  ToolTip.ForeColor: #dddddd
  ToolTip.BackColor: #999999
  ToolTip.CaptionOnHover: false
  ToolTip.CaptionPlacement: Right
  Locked: false
  Transparency: 100
  Shadow: true
  ShadowColor: #000000
  ShadowX: 1
  ShadowY: 1 
  Bold: true
  ClickDelay: 300
  IconSnap: true
  SnapWidth: 10
  SnapHeight: 10
  SnapOrigin: BottomRight
  SnapShadow: false
  SnapShadowTrans: 200
  CaptionOnHover: false
  CaptionPlacement: bottom
  FillStyle: fillinvert
  Background.Delay: 0
  Background.File: /usr/share/wallpapers/wood_desktop.jpg
  Background.Mode: Scale
  Background.Color: #000000
end

table Actions
  Lock: control right doubleClk
  Reload: middle doubleClk
  Drag: left hold
  EndDrag: left singleClk
  Execute[0]: left doubleClk
  Execute[1]: right doubleClk
end
"""

class PreviewDelegate(QStyledItemDelegate):
    
    def paint(self, painter, option, index):
        # data is our preview object
        data = index.model().data(index, Qt.DisplayRole)
        if data is None:
            return
            
        width = option.rect.width() - CELL_PADDING * 2
        height = option.rect.height() - CELL_PADDING * 2

        # option.rect holds the area we are painting on the widget (our table cell)
        # scale our pixmap to fit
        scaled = data.image.scaled(
            width,
            height,
            aspectRatioMode=Qt.KeepAspectRatio,
        )
        # Position in the middle of the area.
        x = int(CELL_PADDING + (width - scaled.width()) / 2)
        y = int(CELL_PADDING + (height - scaled.height()) / 2)
        
        painter.drawImage(option.rect.x() + x, option.rect.y() + y, scaled)
        
    def sizeHint(self, option, index):
        # All items the same size.
        return QSize(300, 200)


class PreviewModel(QAbstractTableModel):
    def __init__(self, todos=None):
        super().__init__()
        # .data holds our data for display, as a list of Preview objects.
        self.previews = []

    def data(self, index, role):
        try:
            data = self.previews[index.row() * 2 + index.column() ]
        except IndexError:
            # Incomplete last row.
            return
            
        if role == Qt.DisplayRole:
            return data   # Pass the data to our delegate to draw.
           
        if role == Qt.ToolTipRole:
            return data.title

    def columnCount(self, index):
        return NUMBER_OF_COLUMNS

    def rowCount(self, index):
        n_items = len(self.previews)
        return math.ceil(n_items / NUMBER_OF_COLUMNS)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(620,300)
        self.view = QTableView()
        self.view.horizontalHeader().hide()
        self.view.verticalHeader().hide()
        self.view.setGridStyle(Qt.NoPen)
        
        delegate = PreviewDelegate()
        self.view.setItemDelegate(delegate)
        self.model = PreviewModel()
        self.view.setModel(self.model)
        
        self.setCentralWidget(self.view)

        # Add images.
        for n, fn in enumerate(glob.glob("/usr/share/wallpapers/*.jpg") + glob.glob("/usr/share/wallpapers/*.jxl")):
            image = QImage(fn)
            item = preview(n, fn, image)
            self.model.previews.append(item)
        self.model.layoutChanged.emit()
        
        self.view.resizeRowsToContents()
        self.view.resizeColumnsToContents()
        self.view.doubleClicked.connect(self.slotDoubleClicked)

    def slotDoubleClicked(self, item):
        #print(item.column())
        index = self.view.selectionModel().currentIndex()
        imgData = self.view.model().data(index,Qt.DisplayRole)
        x = (str(imgData)).split("\'")
        imgURL = (x[1])
        self.makeChange(imgURL)


    def makeChange(self, imgPath):	
        wall_string = '  Background.File: ' + imgPath + "\n"
        if not os.path.exists(IDESKFILE):
            try:
                fileDef = open( IDESKFILE, 'w' )
                fileDef.write( IDESKDEFAULT )
                fileDef.close()
            except:
                sys.stderr.write("Cannot write idesk configuration file to your home directory.")
                raise SystemExit

        whole = ""
        for line in fileinput.input([IDESKFILE], inplace=True):
            if line.strip().startswith('Background.File:'):
                 line = wall_string
            whole = whole + line
        nfile = open(IDESKFILE, "w")
        nfile.write(whole)
        nfile.close()
        
        self.statusBar().showMessage("Background image has be set to:\n" + os.path.basename(imgPath))
        os.system('killall -9 idesk')
        os.system('idesk 2>/dev/null &')


    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            sys.exit()


app = QApplication(sys.argv)
window = MainWindow()
window.setWindowIcon(QIcon('/usr/share/pixmaps/wallpaper.png'))
window.setWindowTitle("Set Desktop Background")
window.resize(620,500)
window.setMaximumWidth(620)
qtRectangle = window.frameGeometry()
centerPoint = QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
window.move(qtRectangle.topLeft())
window.statusBar().showMessage("Double-Click an image to set as your desktop background.")
window.show()
app.exec_()
