Implement file drag drop

This commit is contained in:
BasioMeusPuga
2018-05-13 18:16:17 -04:00
parent ffaace2eaa
commit ffcf07414f
4 changed files with 180 additions and 194 deletions

View File

@@ -34,7 +34,7 @@ from PyQt5 import QtWidgets, QtGui, QtCore
from lector import database
from lector import sorter
from lector.toolbars import LibraryToolBar, BookToolBar
from lector.widgets import Tab
from lector.widgets import Tab, DragDropListView, DragDropTableView
from lector.delegates import LibraryDelegate
from lector.threaded import BackGroundTabUpdate, BackGroundBookAddition, BackGroundBookDeletion
from lector.library import Library
@@ -62,6 +62,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# Initialize translation function
self._translate = QtCore.QCoreApplication.translate
# Create library widgets
self.listView = DragDropListView(self, self.listPage)
self.gridLayout_4.addWidget(self.listView, 0, 0, 1, 1)
self.tableView = DragDropTableView(self, self.tablePage)
self.gridLayout_3.addWidget(self.tableView, 0, 0, 1, 1)
# Empty variables that will be infested soon
self.settings = {}
self.thread = None # Background Thread
@@ -318,24 +325,104 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
my_args = cl_parser.positionalArguments()
if my_args:
file_list = [QtCore.QFileInfo(i).absoluteFilePath() for i in my_args]
books = sorter.BookSorter(
file_list,
('addition', 'manual'),
self.database_path,
self.settings['auto_tags'],
self.temp_dir.path())
self.process_post_hoc_files(file_list, True)
parsed_books = books.initiate_threads()
if not parsed_books:
return
def process_post_hoc_files(self, file_list, open_files_after_processing):
# Takes care of both dragged and dropped files
# As well as files sent as command line arguments
books = sorter.BookSorter(
file_list,
('addition', 'manual'),
self.database_path,
self.settings['auto_tags'],
self.temp_dir.path())
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
self.lib_ref.generate_model('addition', parsed_books, True)
parsed_books = books.initiate_threads()
if not parsed_books:
return
file_dict = {QtCore.QFileInfo(i).absoluteFilePath(): None for i in my_args}
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
self.lib_ref.generate_model('addition', parsed_books, True)
file_dict = {i: None for i in file_list}
if open_files_after_processing:
self.open_files(file_dict)
self.move_on()
self.move_on()
def open_files(self, path_hash_dictionary):
# file_paths is expected to be a dictionary
# This allows for threading file opening
# Which should speed up multiple file opening
# especially @ application start
file_paths = [i for i in path_hash_dictionary]
for filename in path_hash_dictionary.items():
file_md5 = filename[1]
if not file_md5:
try:
with open(filename[0], 'rb') as current_book:
first_bytes = current_book.read(1024 * 32) # First 32KB of the file
file_md5 = hashlib.md5(first_bytes).hexdigest()
except FileNotFoundError:
return
# Remove any already open files
# Set focus to last file in case only one is open
for i in range(1, self.tabWidget.count()):
tab_metadata = self.tabWidget.widget(i).metadata
if tab_metadata['hash'] == file_md5:
file_paths.remove(filename[0])
if not file_paths:
self.tabWidget.setCurrentIndex(i)
return
if not file_paths:
return
def finishing_touches():
self.profile_functions.format_contentView()
self.start_culling_timer()
print('Attempting to open: ' + ', '.join(file_paths))
contents = sorter.BookSorter(
file_paths,
('reading', None),
self.database_path,
True,
self.temp_dir.path()).initiate_threads()
# TODO
# Notification feedback in case all books return nothing
if not contents:
return
for i in contents:
# New tabs are created here
# Initial position adjustment is carried out by the tab itself
file_data = contents[i]
Tab(file_data, self)
if self.settings['last_open_tab'] == 'library':
self.tabWidget.setCurrentIndex(0)
self.listView.setFocus()
self.settings['last_open_tab'] = None
return
for i in range(1, self.tabWidget.count()):
this_path = self.tabWidget.widget(i).metadata['path']
if self.settings['last_open_tab'] == this_path:
self.tabWidget.setCurrentIndex(i)
self.settings['last_open_tab'] = None
finishing_touches()
return
self.tabWidget.setCurrentIndex(self.tabWidget.count() - 1)
finishing_touches()
def start_culling_timer(self):
if self.settings['perform_culling']:
@@ -626,80 +713,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.open_files(path)
def open_files(self, path_hash_dictionary):
# file_paths is expected to be a dictionary
# This allows for threading file opening
# Which should speed up multiple file opening
# especially @ application start
file_paths = [i for i in path_hash_dictionary]
for filename in path_hash_dictionary.items():
file_md5 = filename[1]
if not file_md5:
try:
with open(filename[0], 'rb') as current_book:
first_bytes = current_book.read(1024 * 32) # First 32KB of the file
file_md5 = hashlib.md5(first_bytes).hexdigest()
except FileNotFoundError:
return
# Remove any already open files
# Set focus to last file in case only one is open
for i in range(1, self.tabWidget.count()):
tab_metadata = self.tabWidget.widget(i).metadata
if tab_metadata['hash'] == file_md5:
file_paths.remove(filename[0])
if not file_paths:
self.tabWidget.setCurrentIndex(i)
return
if not file_paths:
return
def finishing_touches():
self.profile_functions.format_contentView()
self.start_culling_timer()
print('Attempting to open: ' + ', '.join(file_paths))
contents = sorter.BookSorter(
file_paths,
('reading', None),
self.database_path,
True,
self.temp_dir.path()).initiate_threads()
# TODO
# Notification feedback in case all books return nothing
if not contents:
return
for i in contents:
# New tabs are created here
# Initial position adjustment is carried out by the tab itself
file_data = contents[i]
Tab(file_data, self)
if self.settings['last_open_tab'] == 'library':
self.tabWidget.setCurrentIndex(0)
self.listView.setFocus()
self.settings['last_open_tab'] = None
return
for i in range(1, self.tabWidget.count()):
this_path = self.tabWidget.widget(i).metadata['path']
if self.settings['last_open_tab'] == this_path:
self.tabWidget.setCurrentIndex(i)
self.settings['last_open_tab'] = None
finishing_touches()
return
self.tabWidget.setCurrentIndex(self.tabWidget.count() - 1)
finishing_touches()
def statusbar_visibility(self):
if self.sender() == self.libraryToolBar.searchBar:
if self.libraryToolBar.searchBar.text() == '':

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'raw/main.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
@@ -35,20 +35,6 @@ class Ui_MainWindow(object):
self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
self.gridLayout_4.setSpacing(0)
self.gridLayout_4.setObjectName("gridLayout_4")
self.listView = QtWidgets.QListView(self.listPage)
self.listView.setFrameShape(QtWidgets.QFrame.NoFrame)
self.listView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.listView.setProperty("showDropIndicator", False)
self.listView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.listView.setMovement(QtWidgets.QListView.Static)
self.listView.setProperty("isWrapping", True)
self.listView.setResizeMode(QtWidgets.QListView.Fixed)
self.listView.setLayoutMode(QtWidgets.QListView.SinglePass)
self.listView.setViewMode(QtWidgets.QListView.IconMode)
self.listView.setUniformItemSizes(True)
self.listView.setWordWrap(True)
self.listView.setObjectName("listView")
self.gridLayout_4.addWidget(self.listView, 0, 0, 1, 1)
self.stackedWidget.addWidget(self.listPage)
self.tablePage = QtWidgets.QWidget()
self.tablePage.setObjectName("tablePage")
@@ -56,20 +42,6 @@ class Ui_MainWindow(object):
self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
self.gridLayout_3.setSpacing(0)
self.gridLayout_3.setObjectName("gridLayout_3")
self.tableView = QtWidgets.QTableView(self.tablePage)
self.tableView.setFrameShape(QtWidgets.QFrame.Box)
self.tableView.setFrameShadow(QtWidgets.QFrame.Plain)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.tableView.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed|QtWidgets.QAbstractItemView.SelectedClicked)
self.tableView.setAlternatingRowColors(True)
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableView.setGridStyle(QtCore.Qt.NoPen)
self.tableView.setSortingEnabled(True)
self.tableView.setWordWrap(False)
self.tableView.setObjectName("tableView")
self.tableView.horizontalHeader().setVisible(True)
self.tableView.verticalHeader().setVisible(False)
self.gridLayout_3.addWidget(self.tableView, 0, 0, 1, 1)
self.stackedWidget.addWidget(self.tablePage)
self.gridLayout_2.addWidget(self.stackedWidget, 0, 0, 1, 1)
self.tabWidget.addTab(self.tab, "")

View File

@@ -55,46 +55,6 @@
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QListView" name="listView">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="movement">
<enum>QListView::Static</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
<property name="resizeMode">
<enum>QListView::Fixed</enum>
</property>
<property name="layoutMode">
<enum>QListView::SinglePass</enum>
</property>
<property name="spacing">
<number>0</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tablePage">
@@ -114,43 +74,6 @@
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QTableView" name="tableView">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@@ -666,3 +666,81 @@ class PliantQGraphicsScene(QtWidgets.QGraphicsScene):
self.parent.load_cover(cover_pixmap, True)
self.parent.show()
class DragDropListView(QtWidgets.QListView):
# This is the library listview
def __init__(self, main_window, parent):
super(DragDropListView, self).__init__(parent)
self.main_window = main_window
self.setAcceptDrops(True)
self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.setResizeMode(QtWidgets.QListView.Fixed)
self.setLayoutMode(QtWidgets.QListView.SinglePass)
self.setViewMode(QtWidgets.QListView.IconMode)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setProperty("showDropIndicator", False)
self.setProperty("isWrapping", True)
self.setFrameShape(QtWidgets.QFrame.NoFrame)
self.setUniformItemSizes(True)
self.setWordWrap(True)
self.setObjectName("listView")
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.acceptProposedAction()
else:
super(DragDropListView, self).dragEnterEvent(event)
def dragMoveEvent(self, event):
super(DragDropListView, self).dragMoveEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
file_list = [url.path() for url in event.mimeData().urls()]
self.main_window.process_post_hoc_files(file_list, False)
event.acceptProposedAction()
else:
super(DragDropListView, self).dropEvent(event)
class DragDropTableView(QtWidgets.QTableView):
# This is the library tableview
def __init__(self, main_window, parent):
super(DragDropTableView, self).__init__(parent)
self.main_window = main_window
self.setAcceptDrops(True)
self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.setFrameShape(QtWidgets.QFrame.Box)
self.setFrameShadow(QtWidgets.QFrame.Plain)
self.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.setEditTriggers(
QtWidgets.QAbstractItemView.DoubleClicked |
QtWidgets.QAbstractItemView.EditKeyPressed |
QtWidgets.QAbstractItemView.SelectedClicked)
self.setAlternatingRowColors(True)
self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.setGridStyle(QtCore.Qt.NoPen)
self.setSortingEnabled(True)
self.setWordWrap(False)
self.setObjectName("tableView")
self.horizontalHeader().setVisible(True)
self.verticalHeader().setVisible(False)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.acceptProposedAction()
else:
super(DragDropTableView, self).dragEnterEvent(event)
def dragMoveEvent(self, event):
super(DragDropTableView, self).dragMoveEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
file_list = [url.path() for url in event.mimeData().urls()]
self.main_window.process_post_hoc_files(file_list, False)
event.acceptProposedAction()
else:
super(DragDropTableView, self).dropEvent(event)