qt base: Adjusted codebase to the latest dev trends.

--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40142
This commit is contained in:
hsoft 2009-09-27 08:44:06 +00:00
parent 657eca1bb8
commit a508a86ce4
8 changed files with 79 additions and 324 deletions

View File

@ -9,8 +9,6 @@
import logging
import os.path as op
import sys
import traceback
from PyQt4.QtCore import Qt, QTimer, QObject, QCoreApplication, QUrl, SIGNAL
from PyQt4.QtGui import QProgressDialog, QDesktopServices, QFileDialog, QDialog, QMessageBox
@ -22,16 +20,14 @@ from hsutil.reg import RegistrationRequired
from dupeguru.app import (DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY,
JOB_DELETE)
if sys.platform == 'win32':
from .win import recycle_file
else:
logging.warning("Unsupported Platform!!!")
from qtlib.progress import Progress
from main_window import MainWindow
from directories_dialog import DirectoriesDialog
from about_box import AboutBox
from reg import Registration
from error_report_dialog import ErrorReportDialog
from . import platform
from .main_window import MainWindow
from .directories_dialog import DirectoriesDialog
from .about_box import AboutBox
from .reg import Registration
JOBID2TITLE = {
JOB_SCAN: "Scanning for duplicates",
@ -41,47 +37,6 @@ JOBID2TITLE = {
JOB_DELETE: "Sending files to the recycle bin",
}
class Progress(QProgressDialog, job.ThreadedJobPerformer):
def __init__(self, parent):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
QProgressDialog.__init__(self, '', u"Cancel", 0, 100, parent, flags)
self.setModal(True)
self.setAutoReset(False)
self.setAutoClose(False)
self._timer = QTimer()
self._jobid = ''
self.connect(self._timer, SIGNAL('timeout()'), self.updateProgress)
def updateProgress(self):
# the values might change before setValue happens
last_progress = self.last_progress
last_desc = self.last_desc
if not self._job_running or last_progress is None:
self._timer.stop()
self.close()
self.emit(SIGNAL('finished(QString)'), self._jobid)
if self._last_error is not None:
s = ''.join(traceback.format_exception(*self._last_error))
dialog = ErrorReportDialog(self.parent(), s)
dialog.exec_()
return
if self.wasCanceled():
self.job_cancelled = True
return
if last_desc:
self.setLabelText(last_desc)
self.setValue(last_progress)
def run(self, jobid, title, target, args=()):
self._jobid = jobid
self.reset()
self.setLabelText('')
self.run_threaded(target, args)
self.setWindowTitle(title)
self.show()
self._timer.start(500)
def demo_method(method):
def wrapper(self, *args, **kwargs):
try:
@ -154,7 +109,7 @@ class DupeGuru(DupeGuruBase, QObject):
#--- Override
@staticmethod
def _recycle_dupe(dupe):
recycle_file(dupe.path)
platform.recycle_file(dupe.path)
def _start_job(self, jobid, func):
title = JOBID2TITLE[jobid]

View File

@ -7,10 +7,10 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
from PyQt4.QtCore import QVariant, QModelIndex, Qt, QRect, QEvent, QPoint
from PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint
from PyQt4.QtGui import QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush
from tree_model import TreeNode, TreeModel
from qtlib.tree_model import TreeNode, TreeModel
HEADERS = ['Name', 'State']
STATES = ['Normal', 'Reference', 'Excluded']
@ -22,8 +22,7 @@ class DirectoriesDelegate(QStyledItemDelegate):
return editor
def setEditorData(self, editor, index):
value, ok = index.model().data(index, Qt.EditRole).toInt()
assert ok
value = index.model().data(index, Qt.EditRole)
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)
@ -32,7 +31,7 @@ class DirectoriesDelegate(QStyledItemDelegate):
# editor.showPopup() # this causes a weird glitch. the ugly workaround is above.
def setModelData(self, editor, model, index):
value = QVariant(editor.currentIndex())
value = editor.currentIndex()
model.setData(index, value, Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
@ -40,16 +39,15 @@ class DirectoriesDelegate(QStyledItemDelegate):
class DirectoryNode(TreeNode):
def __init__(self, parent, ref, row):
TreeNode.__init__(self, parent, row)
def __init__(self, model, parent, ref, row):
TreeNode.__init__(self, model, parent, row)
self.ref = ref
def _get_children(self):
children = []
for index, directory in enumerate(self.ref.dirs):
node = DirectoryNode(self, directory, index)
children.append(node)
return children
def _createNode(self, ref, row):
return DirectoryNode(self.model, self, ref, row)
def _getChildren(self):
return self.ref.dirs
class DirectoriesModel(TreeModel):
@ -57,33 +55,33 @@ class DirectoriesModel(TreeModel):
self._dirs = app.directories
TreeModel.__init__(self)
def _root_nodes(self):
nodes = []
for index, directory in enumerate(self._dirs):
nodes.append(DirectoryNode(None, directory, index))
return nodes
def _createNode(self, ref, row):
return DirectoryNode(self, None, ref, row)
def _getChildren(self):
return self._dirs
def columnCount(self, parent):
return 2
def data(self, index, role):
if not index.isValid():
return QVariant()
return None
node = index.internalPointer()
if role == Qt.DisplayRole:
if index.column() == 0:
return QVariant(node.ref.name)
return node.ref.name
else:
return QVariant(STATES[self._dirs.get_state(node.ref.path)])
return STATES[self._dirs.get_state(node.ref.path)]
elif role == Qt.EditRole and index.column() == 1:
return QVariant(self._dirs.get_state(node.ref.path))
return self._dirs.get_state(node.ref.path)
elif role == Qt.ForegroundRole:
state = self._dirs.get_state(node.ref.path)
if state == 1:
return QVariant(QBrush(Qt.blue))
return QBrush(Qt.blue)
elif state == 2:
return QVariant(QBrush(Qt.red))
return QVariant()
return QBrush(Qt.red)
return None
def flags(self, index):
if not index.isValid():
@ -96,15 +94,13 @@ class DirectoriesModel(TreeModel):
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal:
if role == Qt.DisplayRole and section < len(HEADERS):
return QVariant(HEADERS[section])
return QVariant()
return HEADERS[section]
return None
def setData(self, index, value, role):
if not index.isValid() or role != Qt.EditRole or index.column() != 1:
return False
node = index.internalPointer()
state, ok = value.toInt()
assert ok
self._dirs.set_state(node.ref.path, state)
self._dirs.set_state(node.ref.path, value)
return True

View File

@ -1,27 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-23
# $Id$
# Copyright 2009 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "HS" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
from PyQt4.QtCore import Qt, QUrl
from PyQt4.QtGui import QDialog, QDesktopServices
from error_report_dialog_ui import Ui_ErrorReportDialog
class ErrorReportDialog(QDialog, Ui_ErrorReportDialog):
def __init__(self, parent, error):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
QDialog.__init__(self, parent, flags)
self.setupUi(self)
self.errorTextEdit.setPlainText(error)
def accept(self):
text = self.errorTextEdit.toPlainText()
url = QUrl("mailto:support@hardcoded.net?SUBJECT=Error Report&BODY=%s" % text)
QDesktopServices.openUrl(url)
QDialog.accept(self)

View File

@ -1,117 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ErrorReportDialog</class>
<widget class="QDialog" name="ErrorReportDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>553</width>
<height>349</height>
</rect>
</property>
<property name="windowTitle">
<string>Error Report</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Something went wrong. Would you like to send the error report to Hardcoded Software?</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="errorTextEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="dontSendButton">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Don't Send</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sendButton">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Send</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>sendButton</sender>
<signal>clicked()</signal>
<receiver>ErrorReportDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>485</x>
<y>320</y>
</hint>
<hint type="destinationlabel">
<x>276</x>
<y>174</y>
</hint>
</hints>
</connection>
<connection>
<sender>dontSendButton</sender>
<signal>clicked()</signal>
<receiver>ErrorReportDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>373</x>
<y>320</y>
</hint>
<hint type="destinationlabel">
<x>276</x>
<y>174</y>
</hint>
</hints>
</connection>
</connections>
</ui>

17
base/qt/platform.py Normal file
View File

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2009-09-27
# $Id$
# Copyright 2009 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "HS" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
import logging
import sys
if sys.platform == 'win32':
from platform_win import *
else:
logging.warning("Unsupported Platform!!")

View File

@ -7,30 +7,29 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
from PyQt4.QtCore import SIGNAL, Qt, QAbstractItemModel, QVariant, QModelIndex, QRect
from PyQt4.QtCore import SIGNAL, Qt, QAbstractItemModel, QModelIndex, QRect
from PyQt4.QtGui import QBrush, QStyledItemDelegate, QFont, QTreeView, QColor
from tree_model import TreeNode, TreeModel
from qtlib.tree_model import TreeNode, TreeModel
class ResultNode(TreeNode):
def __init__(self, model, parent, row, dupe, group):
TreeNode.__init__(self, parent, row)
self.model = model
TreeNode.__init__(self, model, parent, row)
self.dupe = dupe
self.group = group
self._normalData = None
self._deltaData = None
def _get_children(self):
children = []
if self.dupe is self.group.ref:
for index, dupe in enumerate(self.group.dupes):
children.append(ResultNode(self.model, self, index, dupe, self.group))
return children
def _createNode(self, ref, row):
return ResultNode(self.model, self, row, ref, self.group)
def reset(self):
def _getChildren(self):
return self.group.dupes if self.dupe is self.group.ref else []
def invalidate(self):
self._normalData = None
self._deltaData = None
TreeNode.invalidate(self)
@property
def normalData(self):
@ -65,40 +64,41 @@ class ResultsModel(TreeModel):
self._power_marker = False
TreeModel.__init__(self)
def _root_nodes(self):
nodes = []
def _createNode(self, ref, row):
if self.power_marker:
for index, dupe in enumerate(self._results.dupes):
group = self._results.get_group_of_duplicate(dupe)
nodes.append(ResultNode(self, None, index, dupe, group))
# ref is a dupe
group = self._results.get_group_of_duplicate(ref)
return ResultNode(self, None, row, ref, group)
else:
for index, group in enumerate(self._results.groups):
nodes.append(ResultNode(self, None, index, group.ref, group))
return nodes
# ref is a group
return ResultNode(self, None, row, ref.ref, ref)
def _getChildren(self):
return self._results.dupes if self.power_marker else self._results.groups
def columnCount(self, parent):
return len(self._data.COLUMNS)
def data(self, index, role):
if not index.isValid():
return QVariant()
return None
node = index.internalPointer()
if role == Qt.DisplayRole:
data = node.deltaData if self.delta else node.normalData
return QVariant(data[index.column()])
return data[index.column()]
elif role == Qt.CheckStateRole:
if index.column() == 0 and node.dupe is not node.group.ref:
state = Qt.Checked if self._results.is_marked(node.dupe) else Qt.Unchecked
return QVariant(state)
return state
elif role == Qt.ForegroundRole:
if node.dupe is node.group.ref or node.dupe.is_ref:
return QVariant(QBrush(Qt.blue))
return QBrush(Qt.blue)
elif self.delta and index.column() in self._delta_columns:
return QVariant(QBrush(QColor(255, 142, 40))) # orange
return QBrush(QColor(255, 142, 40)) # orange
elif role == Qt.EditRole:
if index.column() == 0:
return QVariant(node.normalData[index.column()])
return QVariant()
return node.normalData[index.column()]
return None
def dupesForIndexes(self, indexes):
nodes = [index.internalPointer() for index in indexes]
@ -138,9 +138,8 @@ class ResultsModel(TreeModel):
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(self._data.COLUMNS):
return QVariant(self._data.COLUMNS[section]['display'])
return QVariant()
return self._data.COLUMNS[section]['display']
return None
def setData(self, index, value, role):
if not index.isValid():

View File

@ -1,68 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-04
# $Id$
# Copyright 2009 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "HS" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
from PyQt4.QtCore import Qt, QAbstractItemModel, QVariant, QModelIndex
class TreeNode(object):
def __init__(self, parent, row):
self.parent = parent
self.row = row
self._children = None
def _get_children(self):
raise NotImplementedError()
@property
def children(self):
if self._children is None:
self._children = self._get_children()
return self._children
class TreeModel(QAbstractItemModel):
def __init__(self):
QAbstractItemModel.__init__(self)
self._nodes = None
def _root_nodes(self):
raise NotImplementedError()
def index(self, row, column, parent):
if not self.nodes:
return QModelIndex()
if not parent.isValid():
return self.createIndex(row, column, self.nodes[row])
node = parent.internalPointer()
return self.createIndex(row, column, node.children[row])
def parent(self, index):
if not index.isValid():
return QModelIndex()
node = index.internalPointer()
if node.parent is None:
return QModelIndex()
else:
return self.createIndex(node.parent.row, 0, node.parent)
def reset(self):
self._nodes = None
QAbstractItemModel.reset(self)
def rowCount(self, parent):
if not parent.isValid():
return len(self.nodes)
node = parent.internalPointer()
return len(node.children)
@property
def nodes(self):
if self._nodes is None:
self._nodes = self._root_nodes()
return self._nodes