2009-06-01 09:55:11 +00:00
|
|
|
# Created By: Virgil Dupras
|
|
|
|
# Created On: 2009-04-25
|
2010-01-01 20:11:34 +00:00
|
|
|
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
|
2009-08-05 08:59:46 +00:00
|
|
|
#
|
2010-09-30 10:17:41 +00:00
|
|
|
# This software is licensed under the "BSD" License as described in the "LICENSE" file,
|
2009-08-05 08:59:46 +00:00
|
|
|
# which should be included with this package. The terms are also available at
|
2010-09-30 10:17:41 +00:00
|
|
|
# http://www.hardcoded.net/licenses/bsd_license
|
2009-06-01 09:55:11 +00:00
|
|
|
|
2010-08-11 14:39:06 +00:00
|
|
|
import urllib.parse
|
2009-10-29 12:02:49 +00:00
|
|
|
|
|
|
|
from PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint, QUrl
|
2009-12-15 14:09:13 +00:00
|
|
|
from PyQt4.QtGui import (QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush, QStyle,
|
|
|
|
QStyleOptionComboBox, QStyleOptionViewItemV4)
|
2009-06-01 09:55:11 +00:00
|
|
|
|
2010-02-07 15:00:58 +00:00
|
|
|
from qtlib.tree_model import RefNode, TreeModel
|
|
|
|
|
|
|
|
from core.gui.directory_tree import DirectoryTree
|
2009-06-01 09:55:11 +00:00
|
|
|
|
|
|
|
HEADERS = ['Name', 'State']
|
|
|
|
STATES = ['Normal', 'Reference', 'Excluded']
|
|
|
|
|
|
|
|
class DirectoriesDelegate(QStyledItemDelegate):
|
|
|
|
def createEditor(self, parent, option, index):
|
|
|
|
editor = QComboBox(parent);
|
|
|
|
editor.addItems(STATES)
|
|
|
|
return editor
|
|
|
|
|
2009-12-15 14:09:13 +00:00
|
|
|
def paint(self, painter, option, index):
|
|
|
|
self.initStyleOption(option, index)
|
|
|
|
# No idea why, but this cast is required if we want to have access to the V4 valuess
|
|
|
|
option = QStyleOptionViewItemV4(option)
|
|
|
|
if (index.column() == 1) and (option.state & QStyle.State_Selected):
|
|
|
|
cboption = QStyleOptionComboBox()
|
|
|
|
cboption.rect = option.rect
|
|
|
|
# On OS X (with Qt4.6.0), adding State_Enabled to the flags causes the whole drawing to
|
|
|
|
# fail (draw nothing), but it's an OS X only glitch. On Windows, it works alright.
|
|
|
|
cboption.state |= QStyle.State_Enabled
|
|
|
|
QApplication.style().drawComplexControl(QStyle.CC_ComboBox, cboption, painter)
|
|
|
|
painter.setBrush(option.palette.text())
|
|
|
|
rect = QRect(option.rect)
|
|
|
|
rect.setLeft(rect.left()+4)
|
|
|
|
painter.drawText(rect, Qt.AlignLeft, option.text)
|
|
|
|
else:
|
|
|
|
QStyledItemDelegate.paint(self, painter, option, index)
|
|
|
|
|
2009-06-01 09:55:11 +00:00
|
|
|
def setEditorData(self, editor, index):
|
2009-09-27 08:44:06 +00:00
|
|
|
value = index.model().data(index, Qt.EditRole)
|
2009-06-01 09:55:11 +00:00
|
|
|
editor.setCurrentIndex(value);
|
|
|
|
press = QMouseEvent(QEvent.MouseButtonPress, QPoint(0, 0), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
|
|
|
|
release = QMouseEvent(QEvent.MouseButtonRelease, QPoint(0, 0), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
|
|
|
|
QApplication.sendEvent(editor, press)
|
|
|
|
QApplication.sendEvent(editor, release)
|
|
|
|
# editor.showPopup() # this causes a weird glitch. the ugly workaround is above.
|
|
|
|
|
|
|
|
def setModelData(self, editor, model, index):
|
2009-09-27 08:44:06 +00:00
|
|
|
value = editor.currentIndex()
|
2009-06-01 09:55:11 +00:00
|
|
|
model.setData(index, value, Qt.EditRole)
|
|
|
|
|
|
|
|
def updateEditorGeometry(self, editor, option, index):
|
|
|
|
editor.setGeometry(option.rect)
|
|
|
|
|
|
|
|
|
|
|
|
class DirectoriesModel(TreeModel):
|
|
|
|
def __init__(self, app):
|
|
|
|
TreeModel.__init__(self)
|
2010-02-07 15:00:58 +00:00
|
|
|
self.model = DirectoryTree(self, app)
|
2010-02-12 14:39:29 +00:00
|
|
|
self.model.connect()
|
2009-06-01 09:55:11 +00:00
|
|
|
|
2009-09-27 08:44:06 +00:00
|
|
|
def _createNode(self, ref, row):
|
2010-02-07 15:00:58 +00:00
|
|
|
return RefNode(self, None, ref, row)
|
2009-09-27 08:44:06 +00:00
|
|
|
|
|
|
|
def _getChildren(self):
|
2010-02-07 15:00:58 +00:00
|
|
|
return list(self.model)
|
2009-06-01 09:55:11 +00:00
|
|
|
|
|
|
|
def columnCount(self, parent):
|
|
|
|
return 2
|
|
|
|
|
|
|
|
def data(self, index, role):
|
|
|
|
if not index.isValid():
|
2009-09-27 08:44:06 +00:00
|
|
|
return None
|
2009-06-01 09:55:11 +00:00
|
|
|
node = index.internalPointer()
|
2010-02-07 15:00:58 +00:00
|
|
|
ref = node.ref
|
2009-06-01 09:55:11 +00:00
|
|
|
if role == Qt.DisplayRole:
|
|
|
|
if index.column() == 0:
|
2010-02-07 15:00:58 +00:00
|
|
|
return ref.name
|
2009-06-01 09:55:11 +00:00
|
|
|
else:
|
2010-02-07 15:00:58 +00:00
|
|
|
return STATES[ref.state]
|
2009-06-01 09:55:11 +00:00
|
|
|
elif role == Qt.EditRole and index.column() == 1:
|
2010-02-07 15:00:58 +00:00
|
|
|
return ref.state
|
2009-06-01 09:55:11 +00:00
|
|
|
elif role == Qt.ForegroundRole:
|
2010-02-07 15:00:58 +00:00
|
|
|
state = ref.state
|
2009-06-01 09:55:11 +00:00
|
|
|
if state == 1:
|
2009-09-27 08:44:06 +00:00
|
|
|
return QBrush(Qt.blue)
|
2009-06-01 09:55:11 +00:00
|
|
|
elif state == 2:
|
2009-09-27 08:44:06 +00:00
|
|
|
return QBrush(Qt.red)
|
|
|
|
return None
|
2009-06-01 09:55:11 +00:00
|
|
|
|
2009-10-29 12:02:49 +00:00
|
|
|
def dropMimeData(self, mimeData, action, row, column, parentIndex):
|
2010-09-25 13:34:42 +00:00
|
|
|
# the data in mimeData is urlencoded **in utf-8**!!! What we do is to decode, the mime data
|
|
|
|
# with 'ascii', which works since it's urlencoded. Then, we pass that to urllib.
|
2009-10-29 12:02:49 +00:00
|
|
|
if not mimeData.hasFormat('text/uri-list'):
|
|
|
|
return False
|
2010-09-25 13:34:42 +00:00
|
|
|
data = bytes(mimeData.data('text/uri-list')).decode('ascii')
|
2010-08-11 14:39:06 +00:00
|
|
|
unquoted = urllib.parse.unquote(data)
|
2010-09-25 13:34:42 +00:00
|
|
|
urls = unquoted.split('\r\n')
|
2010-08-11 14:39:06 +00:00
|
|
|
paths = [str(QUrl(url).toLocalFile()) for url in urls if url]
|
2009-10-29 12:02:49 +00:00
|
|
|
for path in paths:
|
2010-02-07 15:00:58 +00:00
|
|
|
self.model.add_directory(path)
|
2009-10-29 12:02:49 +00:00
|
|
|
self.reset()
|
|
|
|
return True
|
|
|
|
|
2009-06-01 09:55:11 +00:00
|
|
|
def flags(self, index):
|
|
|
|
if not index.isValid():
|
2009-10-29 12:02:49 +00:00
|
|
|
return Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
|
|
|
|
result = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDropEnabled
|
2009-06-01 09:55:11 +00:00
|
|
|
if index.column() == 1:
|
|
|
|
result |= Qt.ItemIsEditable
|
|
|
|
return result
|
|
|
|
|
|
|
|
def headerData(self, section, orientation, role):
|
|
|
|
if orientation == Qt.Horizontal:
|
|
|
|
if role == Qt.DisplayRole and section < len(HEADERS):
|
2009-09-27 08:44:06 +00:00
|
|
|
return HEADERS[section]
|
|
|
|
return None
|
2009-06-01 09:55:11 +00:00
|
|
|
|
2009-10-29 12:02:49 +00:00
|
|
|
def mimeTypes(self):
|
|
|
|
return ['text/uri-list']
|
|
|
|
|
2009-06-01 09:55:11 +00:00
|
|
|
def setData(self, index, value, role):
|
|
|
|
if not index.isValid() or role != Qt.EditRole or index.column() != 1:
|
|
|
|
return False
|
|
|
|
node = index.internalPointer()
|
2010-02-07 15:00:58 +00:00
|
|
|
ref = node.ref
|
|
|
|
ref.state = value
|
2009-06-01 09:55:11 +00:00
|
|
|
return True
|
|
|
|
|
2009-10-29 12:02:49 +00:00
|
|
|
def supportedDropActions(self):
|
|
|
|
# Normally, the correct action should be ActionLink, but the drop doesn't work. It doesn't
|
|
|
|
# work with ActionMove either. So screw that, and accept anything.
|
|
|
|
return Qt.ActionMask
|
|
|
|
|
2010-02-07 15:00:58 +00:00
|
|
|
#--- model --> view
|
|
|
|
def refresh(self):
|
|
|
|
self.reset()
|
|
|
|
|