Use TreeView and a custom model to display data.

This commit is contained in:
Bastian Kleineidam 2010-11-06 07:04:35 +01:00
parent 885ce223a4
commit 7b6f0e78ca
4 changed files with 189 additions and 92 deletions

View file

@ -28,6 +28,7 @@ from .options import LinkCheckerOptions
from .checker import CheckerThread
from .contextmenu import ContextMenu
from .editor import EditorWindow
from .urlmodel import UrlItem, UrlItemModel
from .. import configuration, checker, director, add_intern_pattern, \
strformat, fileutil
from ..containers import enum
@ -82,8 +83,7 @@ class LinkCheckerMain (QtGui.QMainWindow, Ui_MainWindow):
self.editor = EditorWindow(parent=self)
# Note: we can't use QT assistant here because of the .exe packaging
self.assistant = HelpWindow(self, self.get_qhcpath())
# setup this widget
self.init_treewidget()
self.init_treeview()
self.read_settings()
self.connect_widgets()
self.init_config()
@ -120,13 +120,16 @@ class LinkCheckerMain (QtGui.QMainWindow, Ui_MainWindow):
self.connect(self.checker, QtCore.SIGNAL("terminated()"), self.set_status_idle)
self.connect(self.checker, QtCore.SIGNAL("log_url(PyQt_PyObject)"), self.log_url)
def init_treewidget (self):
self.treeWidget.setColumnHidden(0, True)
self.treeWidget.setColumnWidth(1, 200)
self.treeWidget.setColumnWidth(2, 200)
self.treeWidget.setColumnWidth(3, 150)
self.treeWidget.setSortingEnabled(True)
self.treeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
def init_treeview (self):
self.model = UrlItemModel()
self.treeView.setModel(self.model)
self.treeView.setColumnHidden(0, True)
self.treeView.setColumnWidth(1, 200)
self.treeView.setColumnWidth(2, 200)
self.treeView.setColumnWidth(3, 150)
#self.setForeground(4, QtGui.QBrush(url_item.color))
self.treeView.setSortingEnabled(True)
self.treeView.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.num = 0
def get_status (self):
@ -211,7 +214,7 @@ Version 2 or later.</p>
def check (self):
"""Check given URL."""
self.controlButton.setEnabled(False)
self.treeWidget.clear()
self.model.clear()
self.set_config()
aggregate = director.get_aggregate(self.config)
url = unicode(self.urlinput.text()).strip()
@ -263,44 +266,16 @@ Version 2 or later.</p>
def log_url (self, url_data):
"""Add URL data to tree widget."""
num = u"%09d" % self.num
if url_data.parent_url:
parent = unicode(url_data.parent_url) + \
(_(", line %d") % url_data.line) + \
(_(", col %d") % url_data.column)
else:
parent = u""
url = unicode(url_data.url)
name = url_data.name
if url_data.valid:
if url_data.warnings:
color = QtCore.Qt.darkYellow
else:
color = QtCore.Qt.darkGreen
result = u"Valid"
else:
color = QtCore.Qt.darkRed
result = u"Error"
if url_data.result:
result += u": %s" % url_data.result
item = QtGui.QTreeWidgetItem((num, parent, url, name, result))
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
item.setForeground(4, QtGui.QBrush(color))
item.setToolTip(2, url)
item.setToolTip(3, name)
if url_data.warnings:
text = u"\n".join(url_data.warnings)
item.setToolTip(4, strformat.wrap(text, 60))
self.treeWidget.addTopLevelItem(item)
self.model.addUrlItem(UrlItem(url_data, self.num))
self.num += 1
def on_treeWidget_itemDoubleClicked (self, item, column):
def on_treeView_itemDoubleClicked (self, item, column):
"""View property page."""
pass # XXX todo
def on_treeWidget_customContextMenuRequested (self, point):
def on_treeView_customContextMenuRequested (self, point):
"""Show item context menu."""
item = self.treeWidget.itemAt(point)
item = self.treeView.itemAt(point)
if item is not None:
self.contextmenu.enableFromItem(item)
self.contextmenu.popup(QtGui.QCursor.pos())
@ -308,7 +283,7 @@ Version 2 or later.</p>
@QtCore.pyqtSignature("")
def on_actionViewOnline_triggered (self):
"""View item URL online."""
item = self.treeWidget.currentItem()
item = self.treeView.currentItem()
if item is not None:
url = str(item.text(2))
webbrowser.open(url)
@ -316,7 +291,7 @@ Version 2 or later.</p>
@QtCore.pyqtSignature("")
def on_actionViewParentOnline_triggered (self):
"""View item parent URL online."""
item = self.treeWidget.currentItem()
item = self.treeView.currentItem()
if item is not None:
parenturl, line, col = get_parent_url(str(item.text(1)))
webbrowser.open(parenturl)
@ -324,7 +299,7 @@ Version 2 or later.</p>
@QtCore.pyqtSignature("")
def on_actionViewParentSource_triggered (self):
"""View item parent URL source in local text editor (read-only)."""
item = self.treeWidget.currentItem()
item = self.treeView.currentItem()
if item is not None:
# XXX simplify this once a proper model is stored
parenturl, line, col = get_parent_url(str(item.text(1)))
@ -348,7 +323,7 @@ Version 2 or later.</p>
@QtCore.pyqtSignature("")
def on_actionCopyToClipboard_triggered (self):
"""Copy item URL to clipboard."""
item = self.treeWidget.currentItem()
item = self.treeView.currentItem()
if item is not None:
url = str(item.text(2))
clipboard = QtGui.QApplication.clipboard()

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'ui/main.ui'
#
# Created: Thu Oct 14 21:04:29 2010
# Created: Sat Nov 6 07:03:42 2010
# by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!
@ -50,16 +50,16 @@ class Ui_MainWindow(object):
self.controlButton.setObjectName("controlButton")
self.horizontalLayout_3.addWidget(self.controlButton)
self.gridLayout.addLayout(self.horizontalLayout_3, 0, 1, 1, 1)
self.treeWidget = QtGui.QTreeWidget(self.centralwidget)
self.treeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.treeWidget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.treeWidget.setAlternatingRowColors(True)
self.treeWidget.setUniformRowHeights(True)
self.treeWidget.setItemsExpandable(False)
self.treeWidget.setAllColumnsShowFocus(True)
self.treeWidget.setExpandsOnDoubleClick(False)
self.treeWidget.setObjectName("treeWidget")
self.gridLayout.addWidget(self.treeWidget, 1, 0, 1, 2)
self.treeView = QtGui.QTreeView(self.centralwidget)
self.treeView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.treeView.setAlternatingRowColors(True)
self.treeView.setUniformRowHeights(True)
self.treeView.setItemsExpandable(False)
self.treeView.setSortingEnabled(True)
self.treeView.setAllColumnsShowFocus(True)
self.treeView.setExpandsOnDoubleClick(False)
self.treeView.setObjectName("treeView")
self.gridLayout.addWidget(self.treeView, 1, 0, 1, 2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 638, 21))
@ -115,12 +115,6 @@ class Ui_MainWindow(object):
self.label.setText(_("URL"))
self.controlButton.setToolTip(_("Start checking the given URL."))
self.controlButton.setText(_("Start"))
self.treeWidget.setSortingEnabled(True)
self.treeWidget.headerItem().setText(0, _("#"))
self.treeWidget.headerItem().setText(1, _("Parent"))
self.treeWidget.headerItem().setText(2, _("Url"))
self.treeWidget.headerItem().setText(3, _("Name"))
self.treeWidget.headerItem().setText(4, _("Result"))
self.menuLinkChecka.setTitle(_("File"))
self.menuEdit.setTitle(_("Edit"))
self.menuHelp.setTitle(_("Help"))

View file

@ -82,10 +82,7 @@
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeWidget" name="treeWidget">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<widget class="QTreeView" name="treeView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
@ -107,31 +104,6 @@
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>#</string>
</property>
</column>
<column>
<property name="text">
<string>Parent</string>
</property>
</column>
<column>
<property name="text">
<string>Url</string>
</property>
</column>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Result</string>
</property>
</column>
</widget>
</item>
</layout>

156
linkcheck/gui/urlmodel.py Normal file
View file

@ -0,0 +1,156 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010 Bastian Kleineidam
#
# 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.
#
# 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. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore
from .. import strformat
Headers = [u"#", _(u"Parent"), _(u"URL"), _(u"Name"), _(u"Result")]
EmptyHeader = QtCore.QVariant()
class UrlItem (object):
"""URL item model storing info to be displayed."""
def __init__ (self, url_data, number):
# store plain data
self.id = number
self.url = url_data.url
self.base_url = url_data.base_url
self.name = url_data.name
self.parent_url = url_data.parent_url
self.base_ref = url_data.base_ref
self.dltime = url_data.dltime
self.dlsize = url_data.dlsize
self.checktime = url_data.checktime
self.info = url_data.info[:]
self.warnings = url_data.warnings[:]
self.valid = url_data.value
self.result = url_data.result
self.line = url_data.line
self.column = url_data.column
# format display and tooltips
self.init_display()
self.init_tooltips()
def init_display (self):
# Parent URL
if self.parent_url:
parent = unicode(self.parent_url) + \
(_(", line %d") % self.line) + \
(_(", col %d") % self.column)
else:
parent = u""
# Result
if self.valid:
if self.warnings:
self.color = QtCore.Qt.darkYellow
else:
self.color = QtCore.Qt.darkGreen
result = u"Valid"
else:
self.color = QtCore.Qt.darkRed
result = u"Error"
if self.result:
result += u": %s" % self.result
self.display.append(result)
self.display = [
# ID
u"%09d" % self.number,
# Parent URL
parent,
# URL
unicode(self.url),
# Name
self.name,
# Result
result,
]
def init_tooltips (self):
# Result
if self.warnings:
result = strformat.wrap(u"\n".join(self.warnings), 60)
else:
result = u""
self.tooltips = [
# ID
u"",
# Parent URL
u"",
# URL
unicode(self.url),
# Name
self.name,
# Result
result,
]
class UrlItemModel(QtCore.QAbstractItemModel):
def __init__ (self, parent=None):
super(UrlItemModel, self).__init__(parent)
# list of UrlItem objects
self.urls = []
def rowCount (self, parent=QtCore.QModelIndex()):
return len(self.urls)
def columnCount (self, parent=QtCore.QModelIndex()):
return len(Headers)
def parent (self, child=QtCore.QModelIndex()):
return QtCore.QModelIndex()
def index (self, row, column, parent=QtCore.QModelIndex()):
return self.createIndex(row, column)
def data (self, index, role=QtCore.Qt.DisplayRole):
V = QtCore.QVariant
if not index.isValid or \
not (0 <= index.row() < len(self.urls)):
return V()
urlitem = self.data[index.row()]
column = index.column()
if role == QtCore.Qt.DisplayRole:
return V(urlitem.display[column])
elif role == QtCore.Qt.ToolTipRole:
return V(urlitem.tooltips[column])
elif role == QtCore.Qt.TextColorRole and column == 4:
return V(urlitem.color)
else:
return V()
def headerData (self, section, orientation, role):
if orientation == QtCore.Qt.Horizontal and \
role == QtCore.Qt.DisplayRole:
return Headers[section]
return EmptyHeader
def flags (self, index):
if not index.isValid():
return 0
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def clear (self):
self.beginResetModel()
self.urls = []
self.endResetModel()
def addUrlItem (self, urlitem):
self.urls.append(urlitem)
return self.insertRows(self.rowCount())