4
\$\begingroup\$

In my first attempt, I have tried to load images from disk and load it to a QTableView using QAbstractTableModel. I'd like a general code review of this code.

import sys
import os
from PyQt4 import QtGui, QtCore
class MyListModel(QtCore.QAbstractTableModel): 
 def __init__(self, datain, col, thumbRes, parent=None): 
 """ datain: a list where each item is a row
 """
 self._thumbRes = thumbRes
 QtCore.QAbstractListModel.__init__(self, parent) 
 self._listdata = datain
 self._col = col
 self.pixmap_cache = {}
 def colData(self, section, orientation, role):
 if role == QtCore.Qt.DisplayRole:
 return None
 def headerData(self, section, orientation, role):
 if role == QtCore.Qt.DisplayRole:
 if orientation in [QtCore.Qt.Vertical, QtCore.Qt.Horizontal]:
 return None
 def rowCount(self, parent=QtCore.QModelIndex()): 
 return len(self._listdata) 
 def columnCount(self, parent):
 return self._col
 def data(self, index, role):
 if role == QtCore.Qt.SizeHintRole:
 return QtCore.QSize(*self._thumbRes)
 if role == QtCore.Qt.TextAlignmentRole:
 return QtCore.Qt.AlignCenter
 if role == QtCore.Qt.EditRole:
 row = index.row()
 column = index.column()
 try:
 fileName = os.path.split(self._listdata[row][column])[-1]
 except IndexError:
 return
 return fileName
 if role == QtCore.Qt.ToolTipRole:
 row = index.row()
 column = index.column()
 try:
 self.selectonChanged(row,column)
 fileName = os.path.split(self._listdata[row][column])[-1]
 except IndexError:
 return
 return QtCore.QString(fileName)
 if index.isValid() and role == QtCore.Qt.DecorationRole:
 row = index.row()
 column = index.column()
 try:
 value = self._listdata[row][column]
 except IndexError:
 return
 pixmap = None
 # value is image path as key
 if self.pixmap_cache.has_key(value) == False:
 pixmap=self.generatePixmap(value)
 self.pixmap_cache[value] = pixmap
 else:
 pixmap = self.pixmap_cache[value]
 return QtGui.QImage(pixmap).scaled(self._thumbRes[0],self._thumbRes[1], 
 QtCore.Qt.KeepAspectRatio)
 if index.isValid() and role == QtCore.Qt.DisplayRole:
 row = index.row()
 column = index.column()
 try:
 value = self._listdata[row][column]
 fileName = os.path.split(value)[-1]
 except IndexError:
 return
 return os.path.splitext(fileName)[0]
 def generatePixmap(self, value):
 pixmap=QtGui.QPixmap()
 pixmap.load(value)
 return pixmap
 def flags(self, index):
 return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
 def setData(self, index, value, role=QtCore.Qt.EditRole):
 if role == QtCore.Qt.EditRole:
 row = index.row()
 column = index.column()
 try:
 newName = os.path.join(str(os.path.split(self._listdata[row][column])[0]), str(value.toString()))
 except IndexError:
 return
 self.__renameFile(self._listdata[row][column], newName)
 self._listdata[row][column] = newName
 self.dataChanged.emit(index, index)
 return True
 return False
 def selectonChanged(self, row, column):
 # TODO Image scale
 pass
 def __renameFile(self, fileToRename, newName):
 try:
 os.rename(str(fileToRename), newName)
 except Exception, err:
 print err
class MyTableView(QtGui.QTableView):
 """docstring for MyTableView"""
 def __init__(self):
 super(MyTableView, self).__init__()
 self.setWindowFlags(QtCore.Qt.Widget | QtCore.Qt.FramelessWindowHint | QtCore.Qt.X11BypassWindowManagerHint)
 sw = QtGui.QDesktopWidget().screenGeometry(self).width()
 sh = QtGui.QDesktopWidget().screenGeometry(self).height()
 self.setGeometry(0,0,sw,sh)
 self.showFullScreen()
 thumbWidth = 300
 thumbheight = 420
 col = sw/thumbWidth 
 self.setColumnWidth(thumbWidth, thumbheight)
 crntDir = "/Users/UserName/Pictures/"
 # create table
 list_data = []
 philes = os.listdir(crntDir)
 for phile in philes:
 if phile.endswith(".png") or phile.endswith("jpg"):
 list_data.append(os.path.join(crntDir, phile))
 _twoDLst = convertToTwoDList(list_data, col)
 lm = MyListModel(_twoDLst, col, (thumbWidth, thumbheight), self)
 self.setShowGrid(False)
 self.setWordWrap(True)
 self.setModel(lm)
 self.resizeColumnsToContents()
 self.resizeRowsToContents()
 def keyPressEvent(self, keyevent):
 """ Capture key to exit, next image, previous image,
 on Escape , Key Right and key left respectively.
 """
 event = keyevent.key()
 if event == QtCore.Qt.Key_Escape:
 self.close()
def convertToTwoDList(l, n): 
 return [l[i:i+n] for i in range(0, len(l), n)]
if __name__ == '__main__':
 app = QtGui.QApplication(sys.argv)
 window = MyTableView()
 window.show()
 window.raise_()
 sys.exit(app.exec_())
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 7, 2013 at 10:29
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

Abstract Model

There are a few improvements I could see in your table model class:

  1. In data() you could use elif for all of the if-statements past the first. This will save the need to evaluate each if-condition after the first condition that was found to be True
  2. Use key in dict notation. You have this line in your data() method:

    if self.pixmap_cache.has_key(value) == False:
    

    This can be written simpler and more Pythonic-ly as:

    if not value in self.pixmap_cache:
    
  3. In setData() you caste the result from os.path.split() to a str. This is not necessary as os.path.split() returns a tuple containing strings.

  4. Finally, in your selectionChanged() function, raise a NotImplementedError instead of passing. Just in case.

Table

  1. In your __init__() function, you set the current directory. You have hard-coded some basic user information. Instead, use the function os.path.expanduser. This will expand ~ into the current user's information.

    crntDir = os.path.expanduser('~/Pictures/')
    
  2. In your for-loop checking for file extensions, you simply check for phile.endswith('jpg'). This will match anything that ends with jpg, including directories. Add the period and it will be fixed.

  3. There is no need to store MyListModel in a variable. Just go ahead and declare it in self.setModel().

General Comments

  1. In your convertToTwoDList function, make your variable names more descriptive. They are very ambiguous at the moment.
  2. Look over the PEP8 style guide. It will help your code look more Pythonic. A few examples:
    use_underscores in variable names instead of camelCase. Keep consistent spacing throughout your code. Overall it looks very good, however there are times where you have double-blank lines in-between methods.
answered May 17, 2014 at 1:19
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.