mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-03-10 13:44:37 +00:00
The directories dialog is now the main window. There's probably many glitches left to fix due to that change, but the basic functionalities are there.
--HG-- rename : qt/base/main_window.py => qt/base/result_window.py rename : qt/pe/main_window.py => qt/pe/result_window.py
This commit is contained in:
parent
30eb26af7d
commit
d51f5184d7
133
qt/base/app.py
133
qt/base/app.py
@ -6,14 +6,12 @@
|
|||||||
# 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/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import os.path as op
|
import os.path as op
|
||||||
|
|
||||||
from PyQt4.QtCore import QTimer, QObject, QCoreApplication, QUrl, SIGNAL, pyqtSignal
|
from PyQt4.QtCore import QTimer, QObject, QCoreApplication, QUrl, QProcess, SIGNAL, pyqtSignal
|
||||||
from PyQt4.QtGui import QDesktopServices, QFileDialog, QDialog, QMessageBox
|
from PyQt4.QtGui import QDesktopServices, QFileDialog, QDialog, QMessageBox, QApplication
|
||||||
|
|
||||||
from jobprogress import job
|
from jobprogress import job
|
||||||
from jobprogress.qt import Progress
|
from jobprogress.qt import Progress
|
||||||
@ -21,13 +19,14 @@ from jobprogress.qt import Progress
|
|||||||
from core.app import DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, JOB_DELETE
|
from core.app import DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, JOB_DELETE
|
||||||
|
|
||||||
from qtlib.about_box import AboutBox
|
from qtlib.about_box import AboutBox
|
||||||
|
from qtlib.recent import Recent
|
||||||
from qtlib.reg import Registration
|
from qtlib.reg import Registration
|
||||||
|
|
||||||
from . import platform
|
from . import platform
|
||||||
|
from .result_window import ResultWindow
|
||||||
from .main_window import MainWindow
|
|
||||||
from .directories_dialog import DirectoriesDialog
|
from .directories_dialog import DirectoriesDialog
|
||||||
from .problem_dialog import ProblemDialog
|
from .problem_dialog import ProblemDialog
|
||||||
|
from .util import createActions
|
||||||
|
|
||||||
JOBID2TITLE = {
|
JOBID2TITLE = {
|
||||||
JOB_SCAN: "Scanning for duplicates",
|
JOB_SCAN: "Scanning for duplicates",
|
||||||
@ -54,16 +53,20 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
|
|
||||||
#--- Private
|
#--- Private
|
||||||
def _setup(self):
|
def _setup(self):
|
||||||
|
self._setupActions()
|
||||||
self.prefs = self._create_preferences()
|
self.prefs = self._create_preferences()
|
||||||
self.prefs.load()
|
self.prefs.load()
|
||||||
self._update_options()
|
self._update_options()
|
||||||
self.main_window = self._create_main_window()
|
self.resultWindow = self._create_result_window()
|
||||||
self._progress = Progress(self.main_window)
|
self._progress = Progress(self.resultWindow)
|
||||||
self.directories_dialog = DirectoriesDialog(self.main_window, self)
|
self.directories_dialog = DirectoriesDialog(self.resultWindow, self)
|
||||||
self.details_dialog = self._create_details_dialog(self.main_window)
|
self.details_dialog = self._create_details_dialog(self.resultWindow)
|
||||||
self.problemDialog = ProblemDialog(parent=self.main_window, app=self)
|
self.problemDialog = ProblemDialog(parent=self.resultWindow, app=self)
|
||||||
self.preferences_dialog = self._create_preferences_dialog(self.main_window)
|
self.preferences_dialog = self._create_preferences_dialog(self.resultWindow)
|
||||||
self.about_box = AboutBox(self.main_window, self)
|
self.about_box = AboutBox(self.resultWindow, self)
|
||||||
|
|
||||||
|
self.recentResults = Recent(self, self.directories_dialog.menuLoadRecent, 'recentResults')
|
||||||
|
self.recentResults.mustOpenItem.connect(self.load_from)
|
||||||
|
|
||||||
self.reg = Registration(self)
|
self.reg = Registration(self)
|
||||||
self.set_registration(self.prefs.registration_code, self.prefs.registration_email)
|
self.set_registration(self.prefs.registration_code, self.prefs.registration_email)
|
||||||
@ -73,19 +76,30 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
# In some circumstances, the nag is hidden by other window, which may make the user think
|
# In some circumstances, the nag is hidden by other window, which may make the user think
|
||||||
# that the application haven't launched.
|
# that the application haven't launched.
|
||||||
QTimer.singleShot(0, self.reg.show_nag)
|
QTimer.singleShot(0, self.reg.show_nag)
|
||||||
if self.prefs.mainWindowIsMaximized:
|
self.directories_dialog.show()
|
||||||
self.main_window.showMaximized()
|
|
||||||
else:
|
|
||||||
self.main_window.show()
|
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate)
|
self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate)
|
||||||
self.connect(self._progress, SIGNAL('finished(QString)'), self.job_finished)
|
self.connect(self._progress, SIGNAL('finished(QString)'), self.job_finished)
|
||||||
|
|
||||||
|
def _setupActions(self):
|
||||||
|
# Setup actions that are common to both the directory dialog and the results window.
|
||||||
|
# (name, shortcut, icon, desc, func)
|
||||||
|
ACTIONS = [
|
||||||
|
('actionQuit', 'Ctrl+Q', '', "Quit", self.quitTriggered),
|
||||||
|
('actionPreferences', 'Ctrl+5', 'preferences', "Preferences", self.preferencesTriggered),
|
||||||
|
('actionShowHelp', 'F1', '', "dupeGuru Help", self.showHelpTriggered),
|
||||||
|
('actionAbout', '', '', "About dupeGuru", self.showAboutBoxTriggered),
|
||||||
|
('actionRegister', '', '', "Register dupeGuru", self.registerTriggered),
|
||||||
|
('actionCheckForUpdate', '', '', "Check for Update", self.checkForUpdateTriggered),
|
||||||
|
('actionOpenDebugLog', '', '', "Open Debug Log", self.openDebugLogTriggered),
|
||||||
|
]
|
||||||
|
createActions(ACTIONS, self)
|
||||||
|
|
||||||
def _setup_as_registered(self):
|
def _setup_as_registered(self):
|
||||||
self.prefs.registration_code = self.registration_code
|
self.prefs.registration_code = self.registration_code
|
||||||
self.prefs.registration_email = self.registration_email
|
self.prefs.registration_email = self.registration_email
|
||||||
self.main_window.actionRegister.setVisible(False)
|
self.actionRegister.setVisible(False)
|
||||||
self.about_box.registerButton.hide()
|
self.about_box.registerButton.hide()
|
||||||
self.about_box.registeredEmailLabel.setText(self.prefs.registration_email)
|
self.about_box.registeredEmailLabel.setText(self.prefs.registration_email)
|
||||||
|
|
||||||
@ -99,8 +113,8 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
def _create_details_dialog(self, parent):
|
def _create_details_dialog(self, parent):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def _create_main_window(self):
|
def _create_result_window(self):
|
||||||
return MainWindow(app=self)
|
return ResultWindow(app=self)
|
||||||
|
|
||||||
def _create_preferences(self):
|
def _create_preferences(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@ -126,7 +140,7 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
self._progress.run(jobid, title, func, args=args)
|
self._progress.run(jobid, title, func, args=args)
|
||||||
except job.JobInProgressError:
|
except job.JobInProgressError:
|
||||||
msg = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."
|
msg = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."
|
||||||
QMessageBox.information(self.main_window, 'Action in progress', msg)
|
QMessageBox.information(self.resultWindow, 'Action in progress', msg)
|
||||||
|
|
||||||
def add_selected_to_ignore_list(self):
|
def add_selected_to_ignore_list(self):
|
||||||
dupes = self.without_ref(self.selected_dupes)
|
dupes = self.without_ref(self.selected_dupes)
|
||||||
@ -134,14 +148,14 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
return
|
return
|
||||||
title = "Add to Ignore List"
|
title = "Add to Ignore List"
|
||||||
msg = "All selected {0} matches are going to be ignored in all subsequent scans. Continue?".format(len(dupes))
|
msg = "All selected {0} matches are going to be ignored in all subsequent scans. Continue?".format(len(dupes))
|
||||||
if self.main_window._confirm(title, msg):
|
if self.confirm(title, msg):
|
||||||
DupeGuruBase.add_selected_to_ignore_list(self)
|
DupeGuruBase.add_selected_to_ignore_list(self)
|
||||||
|
|
||||||
def copy_or_move_marked(self, copy):
|
def copy_or_move_marked(self, copy):
|
||||||
opname = 'copy' if copy else 'move'
|
opname = 'copy' if copy else 'move'
|
||||||
title = "Select a directory to {0} marked files to".format(opname)
|
title = "Select a directory to {0} marked files to".format(opname)
|
||||||
flags = QFileDialog.ShowDirsOnly
|
flags = QFileDialog.ShowDirsOnly
|
||||||
destination = str(QFileDialog.getExistingDirectory(self.main_window, title, '', flags))
|
destination = str(QFileDialog.getExistingDirectory(self.resultWindow, title, '', flags))
|
||||||
if not destination:
|
if not destination:
|
||||||
return
|
return
|
||||||
recreate_path = self.prefs.destination_type
|
recreate_path = self.prefs.destination_type
|
||||||
@ -153,46 +167,32 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
return
|
return
|
||||||
title = "Remove duplicates"
|
title = "Remove duplicates"
|
||||||
msg = "You are about to remove {0} files from results. Continue?".format(len(dupes))
|
msg = "You are about to remove {0} files from results. Continue?".format(len(dupes))
|
||||||
if self.main_window._confirm(title, msg):
|
if self.confirm(title, msg):
|
||||||
DupeGuruBase.remove_selected(self)
|
DupeGuruBase.remove_selected(self)
|
||||||
|
|
||||||
#--- Public
|
#--- Public
|
||||||
def askForRegCode(self):
|
def askForRegCode(self):
|
||||||
self.reg.ask_for_code()
|
self.reg.ask_for_code()
|
||||||
|
|
||||||
|
def confirm(self, title, msg, default_button=QMessageBox.Yes):
|
||||||
|
active = QApplication.activeWindow()
|
||||||
|
buttons = QMessageBox.Yes | QMessageBox.No
|
||||||
|
answer = QMessageBox.question(active, title, msg, buttons, default_button)
|
||||||
|
return answer == QMessageBox.Yes
|
||||||
|
|
||||||
def invokeCustomCommand(self):
|
def invokeCustomCommand(self):
|
||||||
cmd = self.prefs.custom_command
|
cmd = self.prefs.custom_command
|
||||||
if cmd:
|
if cmd:
|
||||||
self.invoke_command(cmd)
|
self.invoke_command(cmd)
|
||||||
else:
|
else:
|
||||||
msg = "You have no custom command set up. Please, set it up in your preferences."
|
msg = "You have no custom command set up. Please, set it up in your preferences."
|
||||||
QMessageBox.warning(self.main_window, 'Custom Command', msg)
|
QMessageBox.warning(self.resultWindow, 'Custom Command', msg)
|
||||||
|
|
||||||
def openDebugLog(self):
|
|
||||||
debugLogPath = op.join(self.appdata, 'debug.log')
|
|
||||||
self._open_path(debugLogPath)
|
|
||||||
|
|
||||||
def show_about_box(self):
|
|
||||||
self.about_box.show()
|
|
||||||
|
|
||||||
def show_details(self):
|
def show_details(self):
|
||||||
self.details_dialog.show()
|
self.details_dialog.show()
|
||||||
|
|
||||||
def show_directories(self):
|
def showResultsWindow(self):
|
||||||
self.directories_dialog.show()
|
self.resultWindow.show()
|
||||||
|
|
||||||
def show_help(self):
|
|
||||||
base_path = platform.HELP_PATH.format(self.EDITION)
|
|
||||||
url = QUrl.fromLocalFile(op.abspath(op.join(base_path, 'index.html')))
|
|
||||||
QDesktopServices.openUrl(url)
|
|
||||||
|
|
||||||
def show_preferences(self):
|
|
||||||
self.preferences_dialog.load()
|
|
||||||
result = self.preferences_dialog.exec_()
|
|
||||||
if result == QDialog.Accepted:
|
|
||||||
self.preferences_dialog.save()
|
|
||||||
self.prefs.save()
|
|
||||||
self._update_options()
|
|
||||||
|
|
||||||
#--- Signals
|
#--- Signals
|
||||||
willSavePrefs = pyqtSignal()
|
willSavePrefs = pyqtSignal()
|
||||||
@ -203,6 +203,9 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
self.prefs.save()
|
self.prefs.save()
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
def checkForUpdateTriggered(self):
|
||||||
|
QProcess.execute('updater.exe', ['/checknow'])
|
||||||
|
|
||||||
def job_finished(self, jobid):
|
def job_finished(self, jobid):
|
||||||
self._job_completed(jobid)
|
self._job_completed(jobid)
|
||||||
if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE):
|
if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE):
|
||||||
@ -210,10 +213,40 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
self.problemDialog.show()
|
self.problemDialog.show()
|
||||||
else:
|
else:
|
||||||
msg = "All files were processed successfully."
|
msg = "All files were processed successfully."
|
||||||
QMessageBox.information(self.main_window, 'Operation Complete', msg)
|
QMessageBox.information(self.resultWindow, 'Operation Complete', msg)
|
||||||
elif jobid == JOB_SCAN:
|
elif jobid == JOB_SCAN:
|
||||||
if not self.results.groups:
|
if not self.results.groups:
|
||||||
title = "Scanning complete"
|
title = "Scan complete"
|
||||||
msg = "No duplicates found."
|
msg = "No duplicates found."
|
||||||
QMessageBox.information(self.main_window, title, msg)
|
QMessageBox.information(self.resultWindow, title, msg)
|
||||||
|
else:
|
||||||
|
self.showResultsWindow()
|
||||||
|
elif jobid == JOB_LOAD:
|
||||||
|
self.showResultsWindow()
|
||||||
|
|
||||||
|
def openDebugLogTriggered(self):
|
||||||
|
debugLogPath = op.join(self.appdata, 'debug.log')
|
||||||
|
self._open_path(debugLogPath)
|
||||||
|
|
||||||
|
def preferencesTriggered(self):
|
||||||
|
self.preferences_dialog.load()
|
||||||
|
result = self.preferences_dialog.exec_()
|
||||||
|
if result == QDialog.Accepted:
|
||||||
|
self.preferences_dialog.save()
|
||||||
|
self.prefs.save()
|
||||||
|
self._update_options()
|
||||||
|
|
||||||
|
def quitTriggered(self):
|
||||||
|
self.directories_dialog.close()
|
||||||
|
|
||||||
|
def registerTriggered(self):
|
||||||
|
self.reg.ask_for_code()
|
||||||
|
|
||||||
|
def showAboutBoxTriggered(self):
|
||||||
|
self.about_box.show()
|
||||||
|
|
||||||
|
def showHelpTriggered(self):
|
||||||
|
base_path = platform.HELP_PATH.format(self.EDITION)
|
||||||
|
url = QUrl.fromLocalFile(op.abspath(op.join(base_path, 'index.html')))
|
||||||
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
|
@ -6,17 +6,20 @@
|
|||||||
# 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/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
from PyQt4.QtCore import SIGNAL, Qt, QSize
|
from PyQt4.QtCore import QSize, QRect
|
||||||
from PyQt4.QtGui import (QDialog, QFileDialog, QHeaderView, QVBoxLayout, QHBoxLayout, QTreeView,
|
from PyQt4.QtGui import (QWidget, QFileDialog, QHeaderView, QVBoxLayout, QHBoxLayout, QTreeView,
|
||||||
QAbstractItemView, QSpacerItem, QSizePolicy, QPushButton, QApplication)
|
QAbstractItemView, QSpacerItem, QSizePolicy, QPushButton, QApplication, QMessageBox, QMainWindow,
|
||||||
|
QMenuBar, QMenu)
|
||||||
|
|
||||||
|
from core.app import NoScannableFileError
|
||||||
|
|
||||||
from . import platform
|
from . import platform
|
||||||
from .directories_model import DirectoriesModel, DirectoriesDelegate
|
from .directories_model import DirectoriesModel, DirectoriesDelegate
|
||||||
|
from .util import createActions
|
||||||
|
|
||||||
class DirectoriesDialog(QDialog):
|
class DirectoriesDialog(QMainWindow):
|
||||||
def __init__(self, parent, app):
|
def __init__(self, parent, app):
|
||||||
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
|
QMainWindow.__init__(self, None)
|
||||||
QDialog.__init__(self, parent, flags)
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.lastAddedFolder = platform.INITIAL_FOLDER_IN_DIALOGS
|
self.lastAddedFolder = platform.INITIAL_FOLDER_IN_DIALOGS
|
||||||
self.directoriesModel = DirectoriesModel(self.app)
|
self.directoriesModel = DirectoriesModel(self.app)
|
||||||
@ -24,21 +27,61 @@ class DirectoriesDialog(QDialog):
|
|||||||
self._setupUi()
|
self._setupUi()
|
||||||
self._updateRemoveButton()
|
self._updateRemoveButton()
|
||||||
|
|
||||||
self.connect(self.doneButton, SIGNAL('clicked()'), self.doneButtonClicked)
|
self.scanButton.clicked.connect(self.scanButtonClicked)
|
||||||
self.connect(self.addButton, SIGNAL('clicked()'), self.addButtonClicked)
|
self.addButton.clicked.connect(self.addButtonClicked)
|
||||||
self.connect(self.removeButton, SIGNAL('clicked()'), self.removeButtonClicked)
|
self.removeButton.clicked.connect(self.removeButtonClicked)
|
||||||
self.connect(self.treeView.selectionModel(), SIGNAL('selectionChanged(QItemSelection,QItemSelection)'), self.selectionChanged)
|
self.treeView.selectionModel().selectionChanged.connect(self.selectionChanged)
|
||||||
self.app.willSavePrefs.connect(self.appWillSavePrefs)
|
self.app.willSavePrefs.connect(self.appWillSavePrefs)
|
||||||
|
|
||||||
|
def _setupActions(self):
|
||||||
|
# (name, shortcut, icon, desc, func)
|
||||||
|
ACTIONS = [
|
||||||
|
('actionLoadResults', 'Ctrl+L', '', "Load Results...", self.loadResultsTriggered),
|
||||||
|
('actionShowResultsWindow', '', '', "Results Window", self.app.showResultsWindow),
|
||||||
|
]
|
||||||
|
createActions(ACTIONS, self)
|
||||||
|
|
||||||
|
def _setupMenu(self):
|
||||||
|
self.menubar = QMenuBar(self)
|
||||||
|
self.menubar.setGeometry(QRect(0, 0, 42, 22))
|
||||||
|
self.menuFile = QMenu(self.menubar)
|
||||||
|
self.menuFile.setTitle("File")
|
||||||
|
self.menuView = QMenu(self.menubar)
|
||||||
|
self.menuView.setTitle("View")
|
||||||
|
self.menuHelp = QMenu(self.menubar)
|
||||||
|
self.menuHelp.setTitle("Help")
|
||||||
|
self.menuLoadRecent = QMenu(self.menuFile)
|
||||||
|
self.menuLoadRecent.setTitle("Load Recent Results")
|
||||||
|
self.setMenuBar(self.menubar)
|
||||||
|
|
||||||
|
self.menuFile.addAction(self.actionLoadResults)
|
||||||
|
self.menuFile.addAction(self.menuLoadRecent.menuAction())
|
||||||
|
self.menuFile.addSeparator()
|
||||||
|
self.menuFile.addAction(self.app.actionQuit)
|
||||||
|
self.menuView.addAction(self.app.actionPreferences)
|
||||||
|
self.menuView.addAction(self.actionShowResultsWindow)
|
||||||
|
self.menuHelp.addAction(self.app.actionShowHelp)
|
||||||
|
self.menuHelp.addAction(self.app.actionRegister)
|
||||||
|
self.menuHelp.addAction(self.app.actionCheckForUpdate)
|
||||||
|
self.menuHelp.addAction(self.app.actionOpenDebugLog)
|
||||||
|
self.menuHelp.addAction(self.app.actionAbout)
|
||||||
|
|
||||||
|
self.menubar.addAction(self.menuFile.menuAction())
|
||||||
|
self.menubar.addAction(self.menuView.menuAction())
|
||||||
|
self.menubar.addAction(self.menuHelp.menuAction())
|
||||||
|
|
||||||
def _setupUi(self):
|
def _setupUi(self):
|
||||||
self.setWindowTitle("Directories")
|
self.setWindowTitle(self.app.NAME)
|
||||||
self.resize(420, 338)
|
self.resize(420, 338)
|
||||||
self.verticalLayout = QVBoxLayout(self)
|
self.centralwidget = QWidget(self)
|
||||||
self.treeView = QTreeView(self)
|
self.verticalLayout = QVBoxLayout(self.centralwidget)
|
||||||
|
self.treeView = QTreeView(self.centralwidget)
|
||||||
self.treeView.setItemDelegate(self.directoriesDelegate)
|
self.treeView.setItemDelegate(self.directoriesDelegate)
|
||||||
self.treeView.setModel(self.directoriesModel)
|
self.treeView.setModel(self.directoriesModel)
|
||||||
self.treeView.setAcceptDrops(True)
|
self.treeView.setAcceptDrops(True)
|
||||||
self.treeView.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed|QAbstractItemView.SelectedClicked)
|
triggers = QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed\
|
||||||
|
|QAbstractItemView.SelectedClicked
|
||||||
|
self.treeView.setEditTriggers(triggers)
|
||||||
self.treeView.setDragDropOverwriteMode(True)
|
self.treeView.setDragDropOverwriteMode(True)
|
||||||
self.treeView.setDragDropMode(QAbstractItemView.DropOnly)
|
self.treeView.setDragDropMode(QAbstractItemView.DropOnly)
|
||||||
self.treeView.setUniformRowHeights(True)
|
self.treeView.setUniformRowHeights(True)
|
||||||
@ -51,31 +94,35 @@ class DirectoriesDialog(QDialog):
|
|||||||
self.horizontalLayout = QHBoxLayout()
|
self.horizontalLayout = QHBoxLayout()
|
||||||
spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||||
self.horizontalLayout.addItem(spacerItem)
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
self.removeButton = QPushButton(self)
|
self.removeButton = QPushButton(self.centralwidget)
|
||||||
self.removeButton.setText("Remove")
|
self.removeButton.setText("Remove")
|
||||||
self.removeButton.setShortcut("Del")
|
self.removeButton.setShortcut("Del")
|
||||||
self.removeButton.setMinimumSize(QSize(91, 0))
|
self.removeButton.setMinimumSize(QSize(91, 0))
|
||||||
self.removeButton.setMaximumSize(QSize(16777215, 32))
|
self.removeButton.setMaximumSize(QSize(16777215, 32))
|
||||||
self.horizontalLayout.addWidget(self.removeButton)
|
self.horizontalLayout.addWidget(self.removeButton)
|
||||||
self.addButton = QPushButton(self)
|
self.addButton = QPushButton(self.centralwidget)
|
||||||
self.addButton.setText("Add")
|
self.addButton.setText("Add")
|
||||||
self.addButton.setMinimumSize(QSize(91, 0))
|
self.addButton.setMinimumSize(QSize(91, 0))
|
||||||
self.addButton.setMaximumSize(QSize(16777215, 32))
|
self.addButton.setMaximumSize(QSize(16777215, 32))
|
||||||
self.horizontalLayout.addWidget(self.addButton)
|
self.horizontalLayout.addWidget(self.addButton)
|
||||||
spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
|
spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
|
||||||
self.horizontalLayout.addItem(spacerItem1)
|
self.horizontalLayout.addItem(spacerItem1)
|
||||||
self.doneButton = QPushButton(self)
|
self.scanButton = QPushButton(self.centralwidget)
|
||||||
self.doneButton.setText("Done")
|
self.scanButton.setText("Scan")
|
||||||
sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.doneButton.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.scanButton.sizePolicy().hasHeightForWidth())
|
||||||
self.doneButton.setSizePolicy(sizePolicy)
|
self.scanButton.setSizePolicy(sizePolicy)
|
||||||
self.doneButton.setMinimumSize(QSize(91, 0))
|
self.scanButton.setMinimumSize(QSize(91, 0))
|
||||||
self.doneButton.setMaximumSize(QSize(16777215, 32))
|
self.scanButton.setMaximumSize(QSize(16777215, 32))
|
||||||
self.doneButton.setDefault(True)
|
self.scanButton.setDefault(True)
|
||||||
self.horizontalLayout.addWidget(self.doneButton)
|
self.horizontalLayout.addWidget(self.scanButton)
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
|
self.setCentralWidget(self.centralwidget)
|
||||||
|
|
||||||
|
self._setupActions()
|
||||||
|
self._setupMenu()
|
||||||
|
|
||||||
if self.app.prefs.directoriesWindowRect is not None:
|
if self.app.prefs.directoriesWindowRect is not None:
|
||||||
self.setGeometry(self.app.prefs.directoriesWindowRect)
|
self.setGeometry(self.app.prefs.directoriesWindowRect)
|
||||||
@ -90,6 +137,17 @@ class DirectoriesDialog(QDialog):
|
|||||||
node = index.internalPointer()
|
node = index.internalPointer()
|
||||||
# label = 'Remove' if node.parent is None else 'Exclude'
|
# label = 'Remove' if node.parent is None else 'Exclude'
|
||||||
|
|
||||||
|
#--- QWidget overrides
|
||||||
|
def closeEvent(self, event):
|
||||||
|
event.accept()
|
||||||
|
if self.app.results.is_modified:
|
||||||
|
title = "Unsaved results"
|
||||||
|
msg = "You have unsaved results, do you really want to quit?"
|
||||||
|
if not self.app.confirm(title, msg):
|
||||||
|
event.ignore()
|
||||||
|
if event.isAccepted():
|
||||||
|
QApplication.quit()
|
||||||
|
|
||||||
#--- Events
|
#--- Events
|
||||||
def addButtonClicked(self):
|
def addButtonClicked(self):
|
||||||
title = "Select a directory to add to the scanning list"
|
title = "Select a directory to add to the scanning list"
|
||||||
@ -103,8 +161,13 @@ class DirectoriesDialog(QDialog):
|
|||||||
def appWillSavePrefs(self):
|
def appWillSavePrefs(self):
|
||||||
self.app.prefs.directoriesWindowRect = self.geometry()
|
self.app.prefs.directoriesWindowRect = self.geometry()
|
||||||
|
|
||||||
def doneButtonClicked(self):
|
def loadResultsTriggered(self):
|
||||||
self.hide()
|
title = "Select a results file to load"
|
||||||
|
files = "dupeGuru Results (*.dupeguru)"
|
||||||
|
destination = QFileDialog.getOpenFileName(self, title, '', files)
|
||||||
|
if destination:
|
||||||
|
self.app.load_from(destination)
|
||||||
|
self.app.recentResults.insertItem(destination)
|
||||||
|
|
||||||
def removeButtonClicked(self):
|
def removeButtonClicked(self):
|
||||||
indexes = self.treeView.selectedIndexes()
|
indexes = self.treeView.selectedIndexes()
|
||||||
@ -116,6 +179,18 @@ class DirectoriesDialog(QDialog):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
self.app.remove_directory(row)
|
self.app.remove_directory(row)
|
||||||
|
|
||||||
|
def scanButtonClicked(self):
|
||||||
|
title = "Start a new scan"
|
||||||
|
if len(self.app.results.groups) > 0:
|
||||||
|
msg = "Are you sure you want to start a new duplicate scan?"
|
||||||
|
if not self.app.confirm(title, msg):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
self.app.start_scanning()
|
||||||
|
except NoScannableFileError:
|
||||||
|
msg = "The selected directories contain no scannable file."
|
||||||
|
QMessageBox.warning(self, title, msg)
|
||||||
|
|
||||||
def selectionChanged(self, selected, deselected):
|
def selectionChanged(self, selected, deselected):
|
||||||
self._updateRemoveButton()
|
self._updateRemoveButton()
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ class Preferences(PreferencesBase):
|
|||||||
self.columns_width[index] = width
|
self.columns_width[index] = width
|
||||||
self.columns_visible = get('ColumnsVisible', self.columns_visible)
|
self.columns_visible = get('ColumnsVisible', self.columns_visible)
|
||||||
|
|
||||||
self.mainWindowIsMaximized = get('MainWindowIsMaximized', self.mainWindowIsMaximized)
|
self.resultWindowIsMaximized = get('ResultWindowIsMaximized', self.resultWindowIsMaximized)
|
||||||
self.mainWindowRect = self.get_rect('MainWindowRect', self.mainWindowRect)
|
self.resultWindowRect = self.get_rect('ResultWindowRect', self.resultWindowRect)
|
||||||
self.detailsWindowRect = self.get_rect('DetailsWindowRect', self.detailsWindowRect)
|
self.detailsWindowRect = self.get_rect('DetailsWindowRect', self.detailsWindowRect)
|
||||||
self.directoriesWindowRect = self.get_rect('DirectoriesWindowRect', self.directoriesWindowRect)
|
self.directoriesWindowRect = self.get_rect('DirectoriesWindowRect', self.directoriesWindowRect)
|
||||||
self.recentResults = get('RecentResults', self.recentResults)
|
self.recentResults = get('RecentResults', self.recentResults)
|
||||||
@ -59,8 +59,8 @@ class Preferences(PreferencesBase):
|
|||||||
self.destination_type = 1
|
self.destination_type = 1
|
||||||
self.custom_command = ''
|
self.custom_command = ''
|
||||||
|
|
||||||
self.mainWindowIsMaximized = False
|
self.resultWindowIsMaximized = False
|
||||||
self.mainWindowRect = None
|
self.resultWindowRect = None
|
||||||
self.detailsWindowRect = None
|
self.detailsWindowRect = None
|
||||||
self.directoriesWindowRect = None
|
self.directoriesWindowRect = None
|
||||||
self.recentResults = []
|
self.recentResults = []
|
||||||
@ -89,8 +89,8 @@ class Preferences(PreferencesBase):
|
|||||||
set_('ColumnsWidth', self.columns_width)
|
set_('ColumnsWidth', self.columns_width)
|
||||||
set_('ColumnsVisible', self.columns_visible)
|
set_('ColumnsVisible', self.columns_visible)
|
||||||
|
|
||||||
set_('MainWindowIsMaximized', self.mainWindowIsMaximized)
|
set_('ResultWindowIsMaximized', self.resultWindowIsMaximized)
|
||||||
self.set_rect('MainWindowRect', self.mainWindowRect)
|
self.set_rect('ResultWindowRect', self.resultWindowRect)
|
||||||
self.set_rect('DetailsWindowRect', self.detailsWindowRect)
|
self.set_rect('DetailsWindowRect', self.detailsWindowRect)
|
||||||
self.set_rect('DirectoriesWindowRect', self.directoriesWindowRect)
|
self.set_rect('DirectoriesWindowRect', self.directoriesWindowRect)
|
||||||
set_('RecentResults', self.recentResults)
|
set_('RecentResults', self.recentResults)
|
||||||
|
@ -8,21 +8,18 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt, QCoreApplication, QProcess, SIGNAL, QUrl, QRect
|
from PyQt4.QtCore import Qt, SIGNAL, QUrl, QRect
|
||||||
from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QToolButton, QLabel, QHeaderView,
|
from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QLabel, QHeaderView, QMessageBox,
|
||||||
QMessageBox, QInputDialog, QLineEdit, QDesktopServices, QFileDialog, QAction, QMenuBar,
|
QInputDialog, QLineEdit, QDesktopServices, QFileDialog, QMenuBar, QWidget, QVBoxLayout,
|
||||||
QToolBar, QWidget, QVBoxLayout, QAbstractItemView, QStatusBar)
|
QAbstractItemView, QStatusBar)
|
||||||
|
|
||||||
from hscommon.util import nonone
|
from hscommon.util import nonone
|
||||||
from qtlib.recent import Recent
|
|
||||||
|
|
||||||
from core.app import NoScannableFileError
|
|
||||||
|
|
||||||
from . import dg_rc
|
|
||||||
from .results_model import ResultsModel, ResultsView
|
from .results_model import ResultsModel, ResultsView
|
||||||
from .stats_label import StatsLabel
|
from .stats_label import StatsLabel
|
||||||
|
from .util import createActions
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class ResultWindow(QMainWindow):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
QMainWindow.__init__(self, None)
|
QMainWindow.__init__(self, None)
|
||||||
self.app = app
|
self.app = app
|
||||||
@ -41,11 +38,8 @@ class MainWindow(QMainWindow):
|
|||||||
def _setupActions(self):
|
def _setupActions(self):
|
||||||
# (name, shortcut, icon, desc, func)
|
# (name, shortcut, icon, desc, func)
|
||||||
ACTIONS = [
|
ACTIONS = [
|
||||||
('actionScan', 'Ctrl+T', self.app.LOGO_NAME, "Start Scan", self.scanTriggered),
|
|
||||||
('actionDirectories', 'Ctrl+4', 'folder', "Directories", self.directoriesTriggered),
|
|
||||||
('actionDetails', 'Ctrl+3', 'details', "Details", self.detailsTriggered),
|
('actionDetails', 'Ctrl+3', 'details', "Details", self.detailsTriggered),
|
||||||
('actionActions', '', 'actions', "Actions", self.actionsTriggered),
|
('actionActions', '', 'actions', "Actions", self.actionsTriggered),
|
||||||
('actionPreferences', 'Ctrl+5', 'preferences', "Preferences", self.preferencesTriggered),
|
|
||||||
('actionDelta', 'Ctrl+2', 'delta', "Delta Values", self.deltaTriggered),
|
('actionDelta', 'Ctrl+2', 'delta', "Delta Values", self.deltaTriggered),
|
||||||
('actionPowerMarker', 'Ctrl+1', 'power_marker', "Power Marker", self.powerMarkerTriggered),
|
('actionPowerMarker', 'Ctrl+1', 'power_marker', "Power Marker", self.powerMarkerTriggered),
|
||||||
('actionDeleteMarked', 'Ctrl+D', '', "Send Marked to Recycle Bin", self.deleteTriggered),
|
('actionDeleteMarked', 'Ctrl+D', '', "Send Marked to Recycle Bin", self.deleteTriggered),
|
||||||
@ -64,28 +58,13 @@ class MainWindow(QMainWindow):
|
|||||||
('actionInvertMarking', 'Ctrl+Alt+A', '', "Invert Marking", self.markInvertTriggered),
|
('actionInvertMarking', 'Ctrl+Alt+A', '', "Invert Marking", self.markInvertTriggered),
|
||||||
('actionMarkSelected', '', '', "Mark Selected", self.markSelectedTriggered),
|
('actionMarkSelected', '', '', "Mark Selected", self.markSelectedTriggered),
|
||||||
('actionClearIgnoreList', '', '', "Clear Ignore List", self.clearIgnoreListTriggered),
|
('actionClearIgnoreList', '', '', "Clear Ignore List", self.clearIgnoreListTriggered),
|
||||||
('actionQuit', 'Ctrl+Q', '', "Quit", self.close),
|
|
||||||
('actionApplyFilter', 'Ctrl+F', '', "Apply Filter", self.applyFilterTriggered),
|
('actionApplyFilter', 'Ctrl+F', '', "Apply Filter", self.applyFilterTriggered),
|
||||||
('actionCancelFilter', 'Ctrl+Shift+F', '', "Cancel Filter", self.cancelFilterTriggered),
|
('actionCancelFilter', 'Ctrl+Shift+F', '', "Cancel Filter", self.cancelFilterTriggered),
|
||||||
('actionShowHelp', 'F1', '', "dupeGuru Help", self.showHelpTriggered),
|
|
||||||
('actionAbout', '', '', "About dupeGuru", self.aboutTriggered),
|
|
||||||
('actionRegister', '', '', "Register dupeGuru", self.registerTrigerred),
|
|
||||||
('actionCheckForUpdate', '', '', "Check for Update", self.checkForUpdateTriggered),
|
|
||||||
('actionExport', '', '', "Export To HTML", self.exportTriggered),
|
('actionExport', '', '', "Export To HTML", self.exportTriggered),
|
||||||
('actionLoadResults', 'Ctrl+L', '', "Load Results...", self.loadResultsTriggered),
|
|
||||||
('actionSaveResults', 'Ctrl+S', '', "Save Results...", self.saveResultsTriggered),
|
('actionSaveResults', 'Ctrl+S', '', "Save Results...", self.saveResultsTriggered),
|
||||||
('actionOpenDebugLog', '', '', "Open Debug Log", self.openDebugLogTriggered),
|
|
||||||
('actionInvokeCustomCommand', 'Ctrl+I', '', "Invoke Custom Command", self.app.invokeCustomCommand),
|
('actionInvokeCustomCommand', 'Ctrl+I', '', "Invoke Custom Command", self.app.invokeCustomCommand),
|
||||||
]
|
]
|
||||||
for name, shortcut, icon, desc, func in ACTIONS:
|
createActions(ACTIONS, self)
|
||||||
action = QAction(self)
|
|
||||||
if icon:
|
|
||||||
action.setIcon(QIcon(QPixmap(':/' + icon)))
|
|
||||||
if shortcut:
|
|
||||||
action.setShortcut(shortcut)
|
|
||||||
action.setText(desc)
|
|
||||||
action.triggered.connect(func)
|
|
||||||
setattr(self, name, action)
|
|
||||||
self.actionDelta.setCheckable(True)
|
self.actionDelta.setCheckable(True)
|
||||||
self.actionPowerMarker.setCheckable(True)
|
self.actionPowerMarker.setCheckable(True)
|
||||||
|
|
||||||
@ -100,14 +79,10 @@ class MainWindow(QMainWindow):
|
|||||||
self.menuActions.setTitle("Actions")
|
self.menuActions.setTitle("Actions")
|
||||||
self.menuColumns = QMenu(self.menubar)
|
self.menuColumns = QMenu(self.menubar)
|
||||||
self.menuColumns.setTitle("Columns")
|
self.menuColumns.setTitle("Columns")
|
||||||
self.menuModes = QMenu(self.menubar)
|
self.menuView = QMenu(self.menubar)
|
||||||
self.menuModes.setTitle("Modes")
|
self.menuView.setTitle("View")
|
||||||
self.menuWindow = QMenu(self.menubar)
|
|
||||||
self.menuWindow.setTitle("Windows")
|
|
||||||
self.menuHelp = QMenu(self.menubar)
|
self.menuHelp = QMenu(self.menubar)
|
||||||
self.menuHelp.setTitle("Help")
|
self.menuHelp.setTitle("Help")
|
||||||
self.menuLoadRecent = QMenu(self.menuFile)
|
|
||||||
self.menuLoadRecent.setTitle("Load Recent Results")
|
|
||||||
self.setMenuBar(self.menubar)
|
self.setMenuBar(self.menubar)
|
||||||
|
|
||||||
self.menuActions.addAction(self.actionDeleteMarked)
|
self.menuActions.addAction(self.actionDeleteMarked)
|
||||||
@ -131,32 +106,27 @@ class MainWindow(QMainWindow):
|
|||||||
self.menuMark.addAction(self.actionMarkNone)
|
self.menuMark.addAction(self.actionMarkNone)
|
||||||
self.menuMark.addAction(self.actionInvertMarking)
|
self.menuMark.addAction(self.actionInvertMarking)
|
||||||
self.menuMark.addAction(self.actionMarkSelected)
|
self.menuMark.addAction(self.actionMarkSelected)
|
||||||
self.menuModes.addAction(self.actionPowerMarker)
|
self.menuView.addAction(self.actionPowerMarker)
|
||||||
self.menuModes.addAction(self.actionDelta)
|
self.menuView.addAction(self.actionDelta)
|
||||||
self.menuWindow.addAction(self.actionDetails)
|
self.menuView.addSeparator()
|
||||||
self.menuWindow.addAction(self.actionDirectories)
|
self.menuView.addAction(self.actionDetails)
|
||||||
self.menuWindow.addAction(self.actionPreferences)
|
self.menuView.addAction(self.app.actionPreferences)
|
||||||
self.menuHelp.addAction(self.actionShowHelp)
|
self.menuHelp.addAction(self.app.actionShowHelp)
|
||||||
self.menuHelp.addAction(self.actionRegister)
|
self.menuHelp.addAction(self.app.actionRegister)
|
||||||
self.menuHelp.addAction(self.actionCheckForUpdate)
|
self.menuHelp.addAction(self.app.actionCheckForUpdate)
|
||||||
self.menuHelp.addAction(self.actionOpenDebugLog)
|
self.menuHelp.addAction(self.app.actionOpenDebugLog)
|
||||||
self.menuHelp.addAction(self.actionAbout)
|
self.menuHelp.addAction(self.app.actionAbout)
|
||||||
self.menuFile.addAction(self.actionScan)
|
|
||||||
self.menuFile.addSeparator()
|
|
||||||
self.menuFile.addAction(self.actionLoadResults)
|
|
||||||
self.menuFile.addAction(self.menuLoadRecent.menuAction())
|
|
||||||
self.menuFile.addAction(self.actionSaveResults)
|
self.menuFile.addAction(self.actionSaveResults)
|
||||||
self.menuFile.addAction(self.actionExport)
|
self.menuFile.addAction(self.actionExport)
|
||||||
self.menuFile.addAction(self.actionClearIgnoreList)
|
self.menuFile.addAction(self.actionClearIgnoreList)
|
||||||
self.menuFile.addSeparator()
|
self.menuFile.addSeparator()
|
||||||
self.menuFile.addAction(self.actionQuit)
|
self.menuFile.addAction(self.app.actionQuit)
|
||||||
|
|
||||||
self.menubar.addAction(self.menuFile.menuAction())
|
self.menubar.addAction(self.menuFile.menuAction())
|
||||||
self.menubar.addAction(self.menuMark.menuAction())
|
self.menubar.addAction(self.menuMark.menuAction())
|
||||||
self.menubar.addAction(self.menuActions.menuAction())
|
self.menubar.addAction(self.menuActions.menuAction())
|
||||||
self.menubar.addAction(self.menuColumns.menuAction())
|
self.menubar.addAction(self.menuColumns.menuAction())
|
||||||
self.menubar.addAction(self.menuModes.menuAction())
|
self.menubar.addAction(self.menuView.menuAction())
|
||||||
self.menubar.addAction(self.menuWindow.menuAction())
|
|
||||||
self.menubar.addAction(self.menuHelp.menuAction())
|
self.menubar.addAction(self.menuHelp.menuAction())
|
||||||
|
|
||||||
# Columns menu
|
# Columns menu
|
||||||
@ -190,27 +160,8 @@ class MainWindow(QMainWindow):
|
|||||||
actionMenu.addAction(self.actionRenameSelected)
|
actionMenu.addAction(self.actionRenameSelected)
|
||||||
self.actionActions.setMenu(actionMenu)
|
self.actionActions.setMenu(actionMenu)
|
||||||
|
|
||||||
def _setupToolbar(self):
|
|
||||||
self.toolBar = QToolBar(self)
|
|
||||||
self.toolBar.setMovable(False)
|
|
||||||
self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
|
||||||
self.toolBar.setFloatable(False)
|
|
||||||
self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.toolBar)
|
|
||||||
|
|
||||||
self.toolBar.addAction(self.actionScan)
|
|
||||||
button = QToolButton(self.toolBar)
|
|
||||||
button.setDefaultAction(self.actionActions.menu().menuAction())
|
|
||||||
button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
|
||||||
self.actionsButton = button
|
|
||||||
self.toolBar.addWidget(button)
|
|
||||||
self.toolBar.addAction(self.actionDirectories)
|
|
||||||
self.toolBar.addAction(self.actionDetails)
|
|
||||||
self.toolBar.addAction(self.actionPreferences)
|
|
||||||
self.toolBar.addAction(self.actionDelta)
|
|
||||||
self.toolBar.addAction(self.actionPowerMarker)
|
|
||||||
|
|
||||||
def _setupUi(self):
|
def _setupUi(self):
|
||||||
self.setWindowTitle(QCoreApplication.instance().applicationName())
|
self.setWindowTitle("dupeGuru Results")
|
||||||
self.resize(630, 514)
|
self.resize(630, 514)
|
||||||
self.centralwidget = QWidget(self)
|
self.centralwidget = QWidget(self)
|
||||||
self.verticalLayout_2 = QVBoxLayout(self.centralwidget)
|
self.verticalLayout_2 = QVBoxLayout(self.centralwidget)
|
||||||
@ -230,17 +181,16 @@ class MainWindow(QMainWindow):
|
|||||||
self.setCentralWidget(self.centralwidget)
|
self.setCentralWidget(self.centralwidget)
|
||||||
self._setupActions()
|
self._setupActions()
|
||||||
self._setupMenu()
|
self._setupMenu()
|
||||||
self._setupToolbar()
|
|
||||||
self.recentResults = Recent(self.app, self.menuLoadRecent, 'recentResults')
|
|
||||||
self.recentResults.mustOpenItem.connect(self.app.load_from)
|
|
||||||
self.statusbar = QStatusBar(self)
|
self.statusbar = QStatusBar(self)
|
||||||
self.statusbar.setSizeGripEnabled(True)
|
self.statusbar.setSizeGripEnabled(True)
|
||||||
self.setStatusBar(self.statusbar)
|
self.setStatusBar(self.statusbar)
|
||||||
self.statusLabel = QLabel(self)
|
self.statusLabel = QLabel(self)
|
||||||
self.statusbar.addPermanentWidget(self.statusLabel, 1)
|
self.statusbar.addPermanentWidget(self.statusLabel, 1)
|
||||||
|
|
||||||
if self.app.prefs.mainWindowRect is not None and not self.app.prefs.mainWindowIsMaximized:
|
if self.app.prefs.resultWindowIsMaximized:
|
||||||
self.setGeometry(self.app.prefs.mainWindowRect)
|
self.setWindowState(self.windowState() | Qt.WindowMaximized)
|
||||||
|
if self.app.prefs.resultWindowRect is not None and not self.app.prefs.resultWindowIsMaximized:
|
||||||
|
self.setGeometry(self.app.prefs.resultWindowRect)
|
||||||
|
|
||||||
# Platform-specific setup
|
# Platform-specific setup
|
||||||
if sys.platform == 'linux2':
|
if sys.platform == 'linux2':
|
||||||
@ -249,11 +199,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.actionHardlinkMarked.setVisible(False)
|
self.actionHardlinkMarked.setVisible(False)
|
||||||
|
|
||||||
#--- Private
|
#--- Private
|
||||||
def _confirm(self, title, msg, default_button=QMessageBox.Yes):
|
|
||||||
buttons = QMessageBox.Yes | QMessageBox.No
|
|
||||||
answer = QMessageBox.question(self, title, msg, buttons, default_button)
|
|
||||||
return answer == QMessageBox.Yes
|
|
||||||
|
|
||||||
def _load_columns(self):
|
def _load_columns(self):
|
||||||
h = self.resultsView.horizontalHeader()
|
h = self.resultsView.horizontalHeader()
|
||||||
h.setResizeMode(QHeaderView.Interactive)
|
h.setResizeMode(QHeaderView.Interactive)
|
||||||
@ -270,19 +215,7 @@ class MainWindow(QMainWindow):
|
|||||||
colid = action.column_index
|
colid = action.column_index
|
||||||
action.setChecked(not h.isSectionHidden(colid))
|
action.setChecked(not h.isSectionHidden(colid))
|
||||||
|
|
||||||
#--- QWidget overrides
|
|
||||||
def closeEvent(self, event):
|
|
||||||
event.accept()
|
|
||||||
if self.app.results.is_modified:
|
|
||||||
title = "Unsaved results"
|
|
||||||
msg = "You have unsaved results, do you really want to quit?"
|
|
||||||
if not self._confirm(title, msg):
|
|
||||||
event.ignore()
|
|
||||||
|
|
||||||
#--- Actions
|
#--- Actions
|
||||||
def aboutTriggered(self):
|
|
||||||
self.app.show_about_box()
|
|
||||||
|
|
||||||
def actionsTriggered(self):
|
def actionsTriggered(self):
|
||||||
self.actionsButton.showMenu()
|
self.actionsButton.showMenu()
|
||||||
|
|
||||||
@ -303,9 +236,6 @@ class MainWindow(QMainWindow):
|
|||||||
def cancelFilterTriggered(self):
|
def cancelFilterTriggered(self):
|
||||||
self.app.apply_filter('')
|
self.app.apply_filter('')
|
||||||
|
|
||||||
def checkForUpdateTriggered(self):
|
|
||||||
QProcess.execute('updater.exe', ['/checknow'])
|
|
||||||
|
|
||||||
def clearIgnoreListTriggered(self):
|
def clearIgnoreListTriggered(self):
|
||||||
title = "Clear Ignore List"
|
title = "Clear Ignore List"
|
||||||
count = len(self.app.scanner.ignore_list)
|
count = len(self.app.scanner.ignore_list)
|
||||||
@ -313,7 +243,7 @@ class MainWindow(QMainWindow):
|
|||||||
QMessageBox.information(self, title, "Nothing to clear.")
|
QMessageBox.information(self, title, "Nothing to clear.")
|
||||||
return
|
return
|
||||||
msg = "Do you really want to remove all {0} items from the ignore list?".format(count)
|
msg = "Do you really want to remove all {0} items from the ignore list?".format(count)
|
||||||
if self._confirm(title, msg, QMessageBox.No):
|
if self.app.confirm(title, msg, QMessageBox.No):
|
||||||
self.app.scanner.ignore_list.Clear()
|
self.app.scanner.ignore_list.Clear()
|
||||||
QMessageBox.information(self, title, "Ignore list cleared.")
|
QMessageBox.information(self, title, "Ignore list cleared.")
|
||||||
|
|
||||||
@ -326,7 +256,7 @@ class MainWindow(QMainWindow):
|
|||||||
return
|
return
|
||||||
title = "Delete duplicates"
|
title = "Delete duplicates"
|
||||||
msg = "You are about to send {0} files to the recycle bin. Continue?".format(count)
|
msg = "You are about to send {0} files to the recycle bin. Continue?".format(count)
|
||||||
if self._confirm(title, msg):
|
if self.app.confirm(title, msg):
|
||||||
self.app.delete_marked()
|
self.app.delete_marked()
|
||||||
|
|
||||||
def deltaTriggered(self):
|
def deltaTriggered(self):
|
||||||
@ -335,9 +265,6 @@ class MainWindow(QMainWindow):
|
|||||||
def detailsTriggered(self):
|
def detailsTriggered(self):
|
||||||
self.app.show_details()
|
self.app.show_details()
|
||||||
|
|
||||||
def directoriesTriggered(self):
|
|
||||||
self.app.show_directories()
|
|
||||||
|
|
||||||
def exportTriggered(self):
|
def exportTriggered(self):
|
||||||
h = self.resultsView.horizontalHeader()
|
h = self.resultsView.horizontalHeader()
|
||||||
column_ids = []
|
column_ids = []
|
||||||
@ -354,17 +281,9 @@ class MainWindow(QMainWindow):
|
|||||||
return
|
return
|
||||||
title = "Delete and hardlink duplicates"
|
title = "Delete and hardlink duplicates"
|
||||||
msg = "You are about to send {0} files to the trash and hardlink them afterwards. Continue?".format(count)
|
msg = "You are about to send {0} files to the trash and hardlink them afterwards. Continue?".format(count)
|
||||||
if self._confirm(title, msg):
|
if self.app.confirm(title, msg):
|
||||||
self.app.delete_marked(replace_with_hardlinks=True)
|
self.app.delete_marked(replace_with_hardlinks=True)
|
||||||
|
|
||||||
def loadResultsTriggered(self):
|
|
||||||
title = "Select a results file to load"
|
|
||||||
files = "dupeGuru Results (*.dupeguru)"
|
|
||||||
destination = QFileDialog.getOpenFileName(self, title, '', files)
|
|
||||||
if destination:
|
|
||||||
self.app.load_from(destination)
|
|
||||||
self.recentResults.insertItem(destination)
|
|
||||||
|
|
||||||
def makeReferenceTriggered(self):
|
def makeReferenceTriggered(self):
|
||||||
self.app.make_selected_reference()
|
self.app.make_selected_reference()
|
||||||
|
|
||||||
@ -383,9 +302,6 @@ class MainWindow(QMainWindow):
|
|||||||
def moveTriggered(self):
|
def moveTriggered(self):
|
||||||
self.app.copy_or_move_marked(False)
|
self.app.copy_or_move_marked(False)
|
||||||
|
|
||||||
def openDebugLogTriggered(self):
|
|
||||||
self.app.openDebugLog()
|
|
||||||
|
|
||||||
def openTriggered(self):
|
def openTriggered(self):
|
||||||
self.app.open_selected()
|
self.app.open_selected()
|
||||||
|
|
||||||
@ -395,16 +311,13 @@ class MainWindow(QMainWindow):
|
|||||||
def preferencesTriggered(self):
|
def preferencesTriggered(self):
|
||||||
self.app.show_preferences()
|
self.app.show_preferences()
|
||||||
|
|
||||||
def registerTrigerred(self):
|
|
||||||
self.app.reg.ask_for_code()
|
|
||||||
|
|
||||||
def removeMarkedTriggered(self):
|
def removeMarkedTriggered(self):
|
||||||
count = self.app.results.mark_count
|
count = self.app.results.mark_count
|
||||||
if not count:
|
if not count:
|
||||||
return
|
return
|
||||||
title = "Remove duplicates"
|
title = "Remove duplicates"
|
||||||
msg = "You are about to remove {0} files from results. Continue?".format(count)
|
msg = "You are about to remove {0} files from results. Continue?".format(count)
|
||||||
if self._confirm(title, msg):
|
if self.app.confirm(title, msg):
|
||||||
self.app.remove_marked()
|
self.app.remove_marked()
|
||||||
|
|
||||||
def removeSelectedTriggered(self):
|
def removeSelectedTriggered(self):
|
||||||
@ -422,23 +335,7 @@ class MainWindow(QMainWindow):
|
|||||||
destination = QFileDialog.getSaveFileName(self, title, '', files)
|
destination = QFileDialog.getSaveFileName(self, title, '', files)
|
||||||
if destination:
|
if destination:
|
||||||
self.app.save_as(destination)
|
self.app.save_as(destination)
|
||||||
self.recentResults.insertItem(destination)
|
self.app.recentResults.insertItem(destination)
|
||||||
|
|
||||||
def scanTriggered(self):
|
|
||||||
title = "Start a new scan"
|
|
||||||
if len(self.app.results.groups) > 0:
|
|
||||||
msg = "Are you sure you want to start a new duplicate scan?"
|
|
||||||
if not self._confirm(title, msg):
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
self.app.start_scanning()
|
|
||||||
except NoScannableFileError:
|
|
||||||
msg = "The selected directories contain no scannable file."
|
|
||||||
QMessageBox.warning(self, title, msg)
|
|
||||||
self.app.show_directories()
|
|
||||||
|
|
||||||
def showHelpTriggered(self):
|
|
||||||
self.app.show_help()
|
|
||||||
|
|
||||||
#--- Events
|
#--- Events
|
||||||
def appWillSavePrefs(self):
|
def appWillSavePrefs(self):
|
||||||
@ -451,8 +348,8 @@ class MainWindow(QMainWindow):
|
|||||||
visible.append(not h.isSectionHidden(i))
|
visible.append(not h.isSectionHidden(i))
|
||||||
prefs.columns_width = widths
|
prefs.columns_width = widths
|
||||||
prefs.columns_visible = visible
|
prefs.columns_visible = visible
|
||||||
prefs.mainWindowIsMaximized = self.isMaximized()
|
prefs.resultWindowIsMaximized = self.isMaximized()
|
||||||
prefs.mainWindowRect = self.geometry()
|
prefs.resultWindowRect = self.geometry()
|
||||||
|
|
||||||
def columnToggled(self, action):
|
def columnToggled(self, action):
|
||||||
colid = action.column_index
|
colid = action.column_index
|
21
qt/base/util.py
Normal file
21
qt/base/util.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Created By: Virgil Dupras
|
||||||
|
# Created On: 2011-01-15
|
||||||
|
# Copyright 2011 Hardcoded Software (http://www.hardcoded.net)
|
||||||
|
#
|
||||||
|
# This software is licensed under the "BSD" 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/bsd_license
|
||||||
|
|
||||||
|
from PyQt4.QtGui import QPixmap, QIcon, QAction
|
||||||
|
|
||||||
|
def createActions(actions, target):
|
||||||
|
# actions = [(name, shortcut, icon, desc, func)]
|
||||||
|
for name, shortcut, icon, desc, func in actions:
|
||||||
|
action = QAction(target)
|
||||||
|
if icon:
|
||||||
|
action.setIcon(QIcon(QPixmap(':/' + icon)))
|
||||||
|
if shortcut:
|
||||||
|
action.setShortcut(shortcut)
|
||||||
|
action.setText(desc)
|
||||||
|
action.triggered.connect(func)
|
||||||
|
setattr(target, name, action)
|
@ -20,7 +20,7 @@ from core_pe.scanner import ScannerPE
|
|||||||
from ..base.app import DupeGuru as DupeGuruBase
|
from ..base.app import DupeGuru as DupeGuruBase
|
||||||
from .block import getblocks
|
from .block import getblocks
|
||||||
from .details_dialog import DetailsDialog
|
from .details_dialog import DetailsDialog
|
||||||
from .main_window import MainWindow
|
from .result_window import ResultWindow
|
||||||
from .preferences import Preferences
|
from .preferences import Preferences
|
||||||
from .preferences_dialog import PreferencesDialog
|
from .preferences_dialog import PreferencesDialog
|
||||||
|
|
||||||
@ -79,8 +79,8 @@ class DupeGuru(DupeGuruBase):
|
|||||||
def _create_details_dialog(self, parent):
|
def _create_details_dialog(self, parent):
|
||||||
return DetailsDialog(parent, self)
|
return DetailsDialog(parent, self)
|
||||||
|
|
||||||
def _create_main_window(self):
|
def _create_result_window(self):
|
||||||
return MainWindow(app=self)
|
return ResultWindow(app=self)
|
||||||
|
|
||||||
def _create_preferences(self):
|
def _create_preferences(self):
|
||||||
return Preferences()
|
return Preferences()
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
from PyQt4.QtCore import SIGNAL
|
from PyQt4.QtCore import SIGNAL
|
||||||
from PyQt4.QtGui import QMessageBox, QAction
|
from PyQt4.QtGui import QMessageBox, QAction
|
||||||
|
|
||||||
from ..base.main_window import MainWindow as MainWindowBase
|
from ..base.result_window import ResultWindow as ResultWindowBase
|
||||||
|
|
||||||
class MainWindow(MainWindowBase):
|
class ResultWindow(ResultWindowBase):
|
||||||
def _setupUi(self):
|
def _setupUi(self):
|
||||||
MainWindowBase._setupUi(self)
|
ResultWindowBase._setupUi(self)
|
||||||
self.actionClearPictureCache = QAction("Clear Picture Cache", self)
|
self.actionClearPictureCache = QAction("Clear Picture Cache", self)
|
||||||
self.menuFile.insertAction(self.actionClearIgnoreList, self.actionClearPictureCache)
|
self.menuFile.insertAction(self.actionClearIgnoreList, self.actionClearPictureCache)
|
||||||
self.connect(self.actionClearPictureCache, SIGNAL("triggered()"), self.clearPictureCacheTriggered)
|
self.connect(self.actionClearPictureCache, SIGNAL("triggered()"), self.clearPictureCacheTriggered)
|
||||||
@ -21,7 +21,7 @@ class MainWindow(MainWindowBase):
|
|||||||
def clearPictureCacheTriggered(self):
|
def clearPictureCacheTriggered(self):
|
||||||
title = "Clear Picture Cache"
|
title = "Clear Picture Cache"
|
||||||
msg = "Do you really want to remove all your cached picture analysis?"
|
msg = "Do you really want to remove all your cached picture analysis?"
|
||||||
if self._confirm(title, msg, QMessageBox.No):
|
if self.app.confirm(title, msg, QMessageBox.No):
|
||||||
self.app.scanner.clear_picture_cache()
|
self.app.scanner.clear_picture_cache()
|
||||||
QMessageBox.information(self, title, "Picture cache cleared.")
|
QMessageBox.information(self, title, "Picture cache cleared.")
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user