diff --git a/__main__.py b/__main__.py
index e881f87..e116172 100755
--- a/__main__.py
+++ b/__main__.py
@@ -230,6 +230,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# Use maptosource() here to get the view_model
# indices selected in the listView
# Implement this for the tableview
+ # The same process can be used to mirror selection
selected_books = self.listView.selectedIndexes()
if selected_books:
@@ -603,8 +604,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.format_contentView()
def show_settings(self):
- # TODO
- # The hiding of the settings dialog should uncheck the settings show action
if not self.settings_dialog.isVisible():
self.settings_dialog.show()
else:
diff --git a/database.py b/database.py
index 9907a26..aff1616 100644
--- a/database.py
+++ b/database.py
@@ -38,11 +38,10 @@ class DatabaseFunctions:
name = i[1]
tags = i[2]
- # TODO
- # Get insert or replace working
-
- sql_command = ("INSERT OR REPLACE INTO directories (Path,Name,Tags) VALUES (?, ?, ?)")
- self.database.execute(sql_command, [path, name, tags])
+ sql_command = (
+ "INSERT OR REPLACE INTO directories (ID, Path, Name, Tags)\
+ VALUES ((SELECT ID FROM directories WHERE Path = ?), ?, ?, ?)")
+ self.database.execute(sql_command, [path, path, name, tags])
self.database.commit()
self.close_database()
diff --git a/models.py b/models.py
index b263f27..535a204 100644
--- a/models.py
+++ b/models.py
@@ -91,6 +91,21 @@ class MostExcellentTableModel(QtCore.QAbstractTableModel):
# These are standard select but don't edit values
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
+ def setData(self, index, value, role=QtCore.Qt.EditRole):
+ # We don't need to connect this to dataChanged since the underlying
+ # table model (not the proxy model) is the one that's being updated
+
+ # Database tags for files should not be updated each time
+ # a new folder gets added or deleted from the directory
+ # This will be done @ runtime
+ # Individually set file tags will be preserved
+ # Duplicate file tags will be removed
+
+ row = index.row()
+ col = index.column()
+ self.display_data[row][col] = value
+ return True
+
class TableProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent=None):
diff --git a/resources/raw/settings.ui b/resources/raw/settings.ui
index cf4b6f6..198f5fa 100644
--- a/resources/raw/settings.ui
+++ b/resources/raw/settings.ui
@@ -82,13 +82,6 @@
- -
-
-
- Refresh
-
-
-
@@ -135,16 +128,23 @@
-
-
-
+
- About
+ OK
-
-
+
- OK
+ Cancel
+
+
+
+ -
+
+
+ About
diff --git a/resources/settingswindow.py b/resources/settingswindow.py
index 886295f..de34349 100644
--- a/resources/settingswindow.py
+++ b/resources/settingswindow.py
@@ -45,9 +45,6 @@ class Ui_Dialog(object):
self.removeButton = QtWidgets.QPushButton(self.groupBox_2)
self.removeButton.setObjectName("removeButton")
self.horizontalLayout.addWidget(self.removeButton)
- self.refreshButton = QtWidgets.QPushButton(self.groupBox_2)
- self.refreshButton.setObjectName("refreshButton")
- self.horizontalLayout.addWidget(self.refreshButton)
self.gridLayout_2.addLayout(self.horizontalLayout, 1, 0, 1, 1)
self.verticalLayout_2.addWidget(self.groupBox_2)
self.groupBox = QtWidgets.QGroupBox(Dialog)
@@ -71,12 +68,15 @@ class Ui_Dialog(object):
self.gridLayout.addLayout(self.horizontalLayout_3, 0, 0, 1, 1)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
- self.aboutButton = QtWidgets.QPushButton(self.groupBox)
- self.aboutButton.setObjectName("aboutButton")
- self.horizontalLayout_2.addWidget(self.aboutButton)
self.okButton = QtWidgets.QPushButton(self.groupBox)
self.okButton.setObjectName("okButton")
self.horizontalLayout_2.addWidget(self.okButton)
+ self.cancelButton = QtWidgets.QPushButton(self.groupBox)
+ self.cancelButton.setObjectName("cancelButton")
+ self.horizontalLayout_2.addWidget(self.cancelButton)
+ self.aboutButton = QtWidgets.QPushButton(self.groupBox)
+ self.aboutButton.setObjectName("aboutButton")
+ self.horizontalLayout_2.addWidget(self.aboutButton)
self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)
self.verticalLayout_2.addWidget(self.groupBox)
self.gridLayout_3.addLayout(self.verticalLayout_2, 0, 0, 1, 1)
@@ -91,12 +91,12 @@ class Ui_Dialog(object):
self.tableFilterEdit.setPlaceholderText(_translate("Dialog", "Search for Paths, Names, Tags..."))
self.addButton.setText(_translate("Dialog", "Add"))
self.removeButton.setText(_translate("Dialog", "Remove"))
- self.refreshButton.setText(_translate("Dialog", "Refresh"))
self.groupBox.setTitle(_translate("Dialog", "Startup"))
self.checkBox.setText(_translate("Dialog", "Auto add files"))
self.fileRemember.setText(_translate("Dialog", "Remember open files"))
self.checkBox_2.setText(_translate("Dialog", "Show Library"))
self.checkBox_3.setText(_translate("Dialog", "Cover Shadows"))
- self.aboutButton.setText(_translate("Dialog", "About"))
self.okButton.setText(_translate("Dialog", "OK"))
+ self.cancelButton.setText(_translate("Dialog", "Cancel"))
+ self.aboutButton.setText(_translate("Dialog", "About"))
diff --git a/settings.py b/settings.py
index 28fad8b..4bda41c 100644
--- a/settings.py
+++ b/settings.py
@@ -124,6 +124,7 @@ class Settings:
self.settings.endGroup()
self.settings.beginGroup('settingsWindow')
- self.settings.setValue('windowSize', self.parent_window.settings_dialog.window_size)
- self.settings.setValue('windowPosition', self.parent_window.settings_dialog.window_position)
- self.settings.setValue('tableHeaders', self.parent_window.settings_dialog.table_headers)
+ these_settings = self.parent_window.settings_dialog_settings
+ self.settings.setValue('windowSize', these_settings['size'])
+ self.settings.setValue('windowPosition', these_settings['position'])
+ self.settings.setValue('tableHeaders', these_settings['headers'])
diff --git a/settingsdialog.py b/settingsdialog.py
index b0b5e60..c5dec87 100644
--- a/settingsdialog.py
+++ b/settingsdialog.py
@@ -12,28 +12,33 @@ from threaded import BackGroundBookSearch, BackGroundBookAddition
class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
+ # TODO
+ # Deletion from table
+ # Cancel behavior
+ # Update database on table model update
+
def __init__(self, parent_window):
super(SettingsUI, self).__init__()
self.setupUi(self)
- # These are just for declarative purposes
- self.window_size = None
- self.window_position = None
- self.table_headers = []
-
self.last_open_directory = None
self.parent_window = parent_window
self.database_path = self.parent_window.database_path
+
self.resize(self.parent_window.settings_dialog_settings['size'])
self.move(self.parent_window.settings_dialog_settings['position'])
self.table_model = None
+ self.old_table_model = None
self.table_proxy_model = None
+ self.paths = None
self.thread = None
self.tableFilterEdit.textChanged.connect(self.update_table_proxy_model)
self.addButton.clicked.connect(self.add_directories)
+ self.cancelButton.clicked.connect(self.cancel_pressed)
+ self.okButton.clicked.connect(self.ok_pressed)
self.generate_table()
header_sizes = self.parent_window.settings_dialog_settings['headers']
@@ -45,27 +50,26 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
QtWidgets.QHeaderView.Interactive)
self.tableView.horizontalHeader().setHighlightSections(False)
self.tableView.horizontalHeader().setStretchLastSection(True)
-
# self.tableView.horizontalHeader().setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch)
- # self.database_data = collections.OrderedDict()
- # self.database_modification = False
-
def generate_table(self):
# Fetch all directories in the database
- paths = database.DatabaseFunctions(
+ self.paths = database.DatabaseFunctions(
self.database_path).fetch_data(
('Path', 'Name', 'Tags'),
'directories',
{'Path': ''},
'LIKE')
- if not paths:
+ if not self.paths:
print('Database returned no paths for settings...')
+ else:
+ # Convert to a list because tuples, well, they're tuples
+ self.paths = [list(i) for i in self.paths]
table_header = ['Path', 'Name', 'Tags']
self.table_model = MostExcellentTableModel(
- table_header, paths, None)
+ table_header, self.paths, None)
self.create_table_proxy_model()
@@ -86,52 +90,67 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.tableFilterEdit.text())
def add_directories(self):
- add_directory = QtWidgets.QFileDialog.getExistingDirectory(
- self, 'Select Directory', self.last_open_directory,
- QtWidgets.QFileDialog.ShowDirsOnly)
-
- data_pair = [[add_directory, None, None]]
- database.DatabaseFunctions(self.database_path).set_library_paths(data_pair)
-
- self.generate_table()
-
# Directories will be added recursively
- # Sub directory addition is allowed in that files will not
+ # Sub directory addition is not allowed
+ # In case it is to be allowed eventually, files will not
# be duplicated. However, any additional tags will get
# added to file tags
- # Database tags for files should not be updated each time
- # a new folder gets added or deleted from the directory
- # This will be done @ runtime
- # Individually set file tags will be preserved
- # Duplicate file tags will be removed
+ add_directory = QtWidgets.QFileDialog.getExistingDirectory(
+ self, 'Select Directory', self.last_open_directory,
+ QtWidgets.QFileDialog.ShowDirsOnly)
+ add_directory = os.path.realpath(add_directory)
- # Whatever code you write to recurse through directories will
- # have to go into the threaded module
+ # TODO
+ # Account for a parent folder getting added after a subfolder
+ # Currently this does the inverse only
+ for i in self.paths:
+ already_present = os.path.realpath(i[0])
+ if already_present == add_directory or already_present in add_directory:
+ QtWidgets.QMessageBox.critical(
+ self,
+ 'Error',
+ 'Duplicate or sub folder: ' + already_present + ' ',
+ QtWidgets.QMessageBox.Ok)
+ return
+
+ # Set default name for the directory
+ directory_name = os.path.basename(add_directory).title()
+ data_pair = [[add_directory, directory_name, None]]
+ database.DatabaseFunctions(self.database_path).set_library_paths(data_pair)
+ self.generate_table()
+
+ def ok_pressed(self):
# Traverse directories looking for files
-
- def parse_all(self, directories):
- add_directory = None
- self.thread = BackGroundBookSearch(self, add_directory)
+ self.thread = BackGroundBookSearch(self, self.table_model.display_data)
self.thread.finished.connect(self.do_something)
self.thread.start()
def do_something(self):
print('Book search completed')
- def closeEvent(self, event):
- self.no_more_settings()
- event.accept()
+ def cancel_pressed(self):
+ self.hide()
+
+ # TODO
+ # Implement cancel by restoring the table model to an older version
+ # def showEvent(self, event):
+ # event.accept()
def hideEvent(self, event):
self.no_more_settings()
event.accept()
def no_more_settings(self):
+ self.table_model = self.old_table_model
self.parent_window.libraryToolBar.settingsButton.setChecked(False)
- self.window_size = self.size()
- self.window_position = self.pos()
- self.table_headers = []
+ self.resizeEvent()
+
+ def resizeEvent(self, event=None):
+ self.parent_window.settings_dialog_settings['size'] = self.size()
+ self.parent_window.settings_dialog_settings['position'] = self.pos()
+ table_headers = []
for i in range(2):
- self.table_headers.append(self.tableView.horizontalHeader().sectionSize(i))
+ table_headers.append(self.tableView.horizontalHeader().sectionSize(i))
+ self.parent_window.settings_dialog_settings['headers'] = table_headers
diff --git a/sorter.py b/sorter.py
index 3e5c512..c3ccdc4 100644
--- a/sorter.py
+++ b/sorter.py
@@ -2,7 +2,6 @@
# TODO
# See if you want to include a hash of the book's name and author
-# Overwrite book if deleted and then re-added
import io
import os
@@ -65,6 +64,10 @@ class BookSorter:
self.progress_emitter.connect_to_progressbar()
def database_hashes(self):
+ # TODO
+ # Overwrite book if deleted and then re-added
+ # Also fetch the path of the file here
+
all_hashes = database.DatabaseFunctions(
self.database_path).fetch_data(
('Hash',),
diff --git a/threaded.py b/threaded.py
index d01d69a..334eedc 100644
--- a/threaded.py
+++ b/threaded.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import os
+from multiprocessing.dummy import Pool
from PyQt5 import QtCore
import sorter
@@ -42,16 +43,39 @@ class BackGroundBookAddition(QtCore.QThread):
class BackGroundBookSearch(QtCore.QThread):
- def __init__(self, parent_window, root_directory, parent=None):
+ def __init__(self, parent_window, data_list, parent=None):
super(BackGroundBookSearch, self).__init__(parent)
self.parent_window = parent_window
- self.root_directory = root_directory
- self.valid_files = []
+ self.data_list = data_list
+ self.valid_files = [] # A tuple should get added to this containing the
+ # file path and the folder name / tags
def run(self):
- for directory, subdir, files in os.walk(self.root_directory):
- for filename in files:
- if os.path.splitext(filename)[1][1:] in sorter.available_parsers:
- self.valid_files.append(os.path.join(directory, filename))
- print(self.valid_files)
+ def traverse_directory(incoming_data):
+ root_directory = incoming_data[0]
+ folder_name = incoming_data[1]
+ folder_tags = incoming_data[2]
+
+ for directory, subdir, files in os.walk(root_directory):
+ for filename in files:
+ if os.path.splitext(filename)[1][1:] in sorter.available_parsers:
+ self.valid_files.append(
+ (os.path.join(directory, filename), folder_name, folder_tags))
+
+ def initiate_threads():
+ _pool = Pool(5)
+ _pool.map(traverse_directory, self.data_list)
+ _pool.close()
+ _pool.join()
+
+ initiate_threads()
+
+ # TODO
+ # Change existing sorter module functionality to handle
+ # preset tags
+ # Change database to accomodate User Tags, Folder Name, Folder Tags
+
+ # self.valid_files will now be added to the database
+ # and models will be rebuilt accordingly
+ # Coming soon to a commit near you