1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2025-03-10 05:34:36 +00:00

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 logging
import os.path as op import os.path as op
import sys
import traceback
from PyQt4.QtCore import Qt, QTimer, QObject, QCoreApplication, QUrl, SIGNAL from PyQt4.QtCore import Qt, QTimer, QObject, QCoreApplication, QUrl, SIGNAL
from PyQt4.QtGui import QProgressDialog, QDesktopServices, QFileDialog, QDialog, QMessageBox 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, from dupeguru.app import (DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY,
JOB_DELETE) JOB_DELETE)
if sys.platform == 'win32': from qtlib.progress import Progress
from .win import recycle_file
else:
logging.warning("Unsupported Platform!!!")
from main_window import MainWindow from . import platform
from directories_dialog import DirectoriesDialog
from about_box import AboutBox from .main_window import MainWindow
from reg import Registration from .directories_dialog import DirectoriesDialog
from error_report_dialog import ErrorReportDialog from .about_box import AboutBox
from .reg import Registration
JOBID2TITLE = { JOBID2TITLE = {
JOB_SCAN: "Scanning for duplicates", JOB_SCAN: "Scanning for duplicates",
@ -41,47 +37,6 @@ JOBID2TITLE = {
JOB_DELETE: "Sending files to the recycle bin", 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 demo_method(method):
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
try: try:
@ -154,7 +109,7 @@ class DupeGuru(DupeGuruBase, QObject):
#--- Override #--- Override
@staticmethod @staticmethod
def _recycle_dupe(dupe): def _recycle_dupe(dupe):
recycle_file(dupe.path) platform.recycle_file(dupe.path)
def _start_job(self, jobid, func): def _start_job(self, jobid, func):
title = JOBID2TITLE[jobid] title = JOBID2TITLE[jobid]

View File

@ -7,10 +7,10 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # 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 PyQt4.QtGui import QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush
from tree_model import TreeNode, TreeModel from qtlib.tree_model import TreeNode, TreeModel
HEADERS = ['Name', 'State'] HEADERS = ['Name', 'State']
STATES = ['Normal', 'Reference', 'Excluded'] STATES = ['Normal', 'Reference', 'Excluded']
@ -22,8 +22,7 @@ class DirectoriesDelegate(QStyledItemDelegate):
return editor return editor
def setEditorData(self, editor, index): def setEditorData(self, editor, index):
value, ok = index.model().data(index, Qt.EditRole).toInt() value = index.model().data(index, Qt.EditRole)
assert ok
editor.setCurrentIndex(value); editor.setCurrentIndex(value);
press = QMouseEvent(QEvent.MouseButtonPress, QPoint(0, 0), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) 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) 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. # editor.showPopup() # this causes a weird glitch. the ugly workaround is above.
def setModelData(self, editor, model, index): def setModelData(self, editor, model, index):
value = QVariant(editor.currentIndex()) value = editor.currentIndex()
model.setData(index, value, Qt.EditRole) model.setData(index, value, Qt.EditRole)
def updateEditorGeometry(self, editor, option, index): def updateEditorGeometry(self, editor, option, index):
@ -40,16 +39,15 @@ class DirectoriesDelegate(QStyledItemDelegate):
class DirectoryNode(TreeNode): class DirectoryNode(TreeNode):
def __init__(self, parent, ref, row): def __init__(self, model, parent, ref, row):
TreeNode.__init__(self, parent, row) TreeNode.__init__(self, model, parent, row)
self.ref = ref self.ref = ref
def _get_children(self): def _createNode(self, ref, row):
children = [] return DirectoryNode(self.model, self, ref, row)
for index, directory in enumerate(self.ref.dirs):
node = DirectoryNode(self, directory, index) def _getChildren(self):
children.append(node) return self.ref.dirs
return children
class DirectoriesModel(TreeModel): class DirectoriesModel(TreeModel):
@ -57,33 +55,33 @@ class DirectoriesModel(TreeModel):
self._dirs = app.directories self._dirs = app.directories
TreeModel.__init__(self) TreeModel.__init__(self)
def _root_nodes(self): def _createNode(self, ref, row):
nodes = [] return DirectoryNode(self, None, ref, row)
for index, directory in enumerate(self._dirs):
nodes.append(DirectoryNode(None, directory, index)) def _getChildren(self):
return nodes return self._dirs
def columnCount(self, parent): def columnCount(self, parent):
return 2 return 2
def data(self, index, role): def data(self, index, role):
if not index.isValid(): if not index.isValid():
return QVariant() return None
node = index.internalPointer() node = index.internalPointer()
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
if index.column() == 0: if index.column() == 0:
return QVariant(node.ref.name) return node.ref.name
else: 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: 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: elif role == Qt.ForegroundRole:
state = self._dirs.get_state(node.ref.path) state = self._dirs.get_state(node.ref.path)
if state == 1: if state == 1:
return QVariant(QBrush(Qt.blue)) return QBrush(Qt.blue)
elif state == 2: elif state == 2:
return QVariant(QBrush(Qt.red)) return QBrush(Qt.red)
return QVariant() return None
def flags(self, index): def flags(self, index):
if not index.isValid(): if not index.isValid():
@ -96,15 +94,13 @@ class DirectoriesModel(TreeModel):
def headerData(self, section, orientation, role): def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal: if orientation == Qt.Horizontal:
if role == Qt.DisplayRole and section < len(HEADERS): if role == Qt.DisplayRole and section < len(HEADERS):
return QVariant(HEADERS[section]) return HEADERS[section]
return QVariant() return None
def setData(self, index, value, role): def setData(self, index, value, role):
if not index.isValid() or role != Qt.EditRole or index.column() != 1: if not index.isValid() or role != Qt.EditRole or index.column() != 1:
return False return False
node = index.internalPointer() node = index.internalPointer()
state, ok = value.toInt() self._dirs.set_state(node.ref.path, value)
assert ok
self._dirs.set_state(node.ref.path, state)
return True 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 # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # 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 PyQt4.QtGui import QBrush, QStyledItemDelegate, QFont, QTreeView, QColor
from tree_model import TreeNode, TreeModel from qtlib.tree_model import TreeNode, TreeModel
class ResultNode(TreeNode): class ResultNode(TreeNode):
def __init__(self, model, parent, row, dupe, group): def __init__(self, model, parent, row, dupe, group):
TreeNode.__init__(self, parent, row) TreeNode.__init__(self, model, parent, row)
self.model = model
self.dupe = dupe self.dupe = dupe
self.group = group self.group = group
self._normalData = None self._normalData = None
self._deltaData = None self._deltaData = None
def _get_children(self): def _createNode(self, ref, row):
children = [] return ResultNode(self.model, self, row, ref, self.group)
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 reset(self): def _getChildren(self):
return self.group.dupes if self.dupe is self.group.ref else []
def invalidate(self):
self._normalData = None self._normalData = None
self._deltaData = None self._deltaData = None
TreeNode.invalidate(self)
@property @property
def normalData(self): def normalData(self):
@ -65,40 +64,41 @@ class ResultsModel(TreeModel):
self._power_marker = False self._power_marker = False
TreeModel.__init__(self) TreeModel.__init__(self)
def _root_nodes(self): def _createNode(self, ref, row):
nodes = []
if self.power_marker: if self.power_marker:
for index, dupe in enumerate(self._results.dupes): # ref is a dupe
group = self._results.get_group_of_duplicate(dupe) group = self._results.get_group_of_duplicate(ref)
nodes.append(ResultNode(self, None, index, dupe, group)) return ResultNode(self, None, row, ref, group)
else: else:
for index, group in enumerate(self._results.groups): # ref is a group
nodes.append(ResultNode(self, None, index, group.ref, group)) return ResultNode(self, None, row, ref.ref, ref)
return nodes
def _getChildren(self):
return self._results.dupes if self.power_marker else self._results.groups
def columnCount(self, parent): def columnCount(self, parent):
return len(self._data.COLUMNS) return len(self._data.COLUMNS)
def data(self, index, role): def data(self, index, role):
if not index.isValid(): if not index.isValid():
return QVariant() return None
node = index.internalPointer() node = index.internalPointer()
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
data = node.deltaData if self.delta else node.normalData data = node.deltaData if self.delta else node.normalData
return QVariant(data[index.column()]) return data[index.column()]
elif role == Qt.CheckStateRole: elif role == Qt.CheckStateRole:
if index.column() == 0 and node.dupe is not node.group.ref: 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 state = Qt.Checked if self._results.is_marked(node.dupe) else Qt.Unchecked
return QVariant(state) return state
elif role == Qt.ForegroundRole: elif role == Qt.ForegroundRole:
if node.dupe is node.group.ref or node.dupe.is_ref: 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: 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: elif role == Qt.EditRole:
if index.column() == 0: if index.column() == 0:
return QVariant(node.normalData[index.column()]) return node.normalData[index.column()]
return QVariant() return None
def dupesForIndexes(self, indexes): def dupesForIndexes(self, indexes):
nodes = [index.internalPointer() for index in indexes] nodes = [index.internalPointer() for index in indexes]
@ -138,9 +138,8 @@ class ResultsModel(TreeModel):
def headerData(self, section, orientation, role): def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(self._data.COLUMNS): if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(self._data.COLUMNS):
return QVariant(self._data.COLUMNS[section]['display']) return self._data.COLUMNS[section]['display']
return None
return QVariant()
def setData(self, index, value, role): def setData(self, index, value, role):
if not index.isValid(): 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