Update readme and structure
This commit is contained in:
182
mediainfosama/file_cmds.py
Normal file
182
mediainfosama/file_cmds.py
Normal file
@ -0,0 +1,182 @@
|
||||
import os, subprocess, json
|
||||
from shlex import quote
|
||||
|
||||
class FileCmds:
|
||||
def __init__(self, file_path):
|
||||
super().__init__()
|
||||
self.file_path = file_path
|
||||
self.track_count = self.track_count()
|
||||
self.basic_info = self.generate_basic()
|
||||
self.advanced_info = self.generate_advanced()
|
||||
self.tabs_list = self.generate_tabs_list()
|
||||
self.tabs_content = self.generate_tabs_content()
|
||||
|
||||
|
||||
def execute_bash(self, cmd):
|
||||
'''
|
||||
Execute a bash command
|
||||
|
||||
:type cmd: str
|
||||
:return: str
|
||||
'''
|
||||
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
|
||||
output, error = process.communicate()
|
||||
return output
|
||||
|
||||
|
||||
def file_exist(self):
|
||||
'''
|
||||
Check if the file exists
|
||||
|
||||
:rtype: bool
|
||||
'''
|
||||
if os.path.exists(self.file_path):
|
||||
return True
|
||||
else:
|
||||
print("The file doesn't exist")
|
||||
return False
|
||||
|
||||
|
||||
def media_inform(self, inform):
|
||||
'''
|
||||
Execute mediainfo --Inform
|
||||
|
||||
:type inform: str
|
||||
:rtype: str
|
||||
'''
|
||||
bash_command = f"mediainfo --Inform={quote(inform)} {quote(self.file_path)}"
|
||||
output = self.execute_bash(bash_command).decode('utf-8')
|
||||
return output
|
||||
|
||||
|
||||
def track_count(self):
|
||||
'''
|
||||
Return the number of track of each type
|
||||
|
||||
:rtype: dict[str,int]
|
||||
'''
|
||||
track_types = [
|
||||
"Video",
|
||||
"Audio",
|
||||
"Text",
|
||||
"Image",
|
||||
"Menu",
|
||||
]
|
||||
|
||||
output = {}
|
||||
|
||||
for track_type in track_types:
|
||||
count = self.media_inform(f"General;%{track_type}Count%").replace('\n', '')
|
||||
if not count:
|
||||
count = 0
|
||||
output[track_type] = int(count)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def generate_basic(self):
|
||||
'''
|
||||
Return the basic tab
|
||||
|
||||
:rtype: string
|
||||
'''
|
||||
inform_general = r"General;G: %Format%, %FileSize_String%, %Duration_String%, %BitRate_String%\n"
|
||||
inform_video = r"Video;V: %Format%, %Format_Profile%, %StreamSize_String%, %Width%x%Height%, %FrameRate% FPS, %BitRate_String%\n"
|
||||
inform_audio = r"Audio;A: %Language_String%, %Format%, %StreamSize_String%, %BitRate_String%, %Channel(s)_String%, %SamplingRate_String%\n"
|
||||
inform_text = r"Text;T: %Language_String%, %Format%\n"
|
||||
|
||||
informs = [inform_general]
|
||||
|
||||
if not self.track_count["Video"] == 0:
|
||||
informs.append(inform_video)
|
||||
|
||||
if not self.track_count["Audio"] == 0:
|
||||
informs.append(inform_audio)
|
||||
|
||||
if not self.track_count["Text"] == 0:
|
||||
informs.append(inform_text)
|
||||
|
||||
output = ""
|
||||
|
||||
for inform in informs:
|
||||
output += self.media_inform(inform)
|
||||
|
||||
if not self.track_count["Menu"] == 0:
|
||||
output += "M: Menu\n\n"
|
||||
|
||||
output += "\n"
|
||||
output += self.execute_bash(f"mediainfo {quote(self.file_path)}").decode('utf-8')
|
||||
return(output)
|
||||
|
||||
|
||||
def generate_advanced(self):
|
||||
'''
|
||||
Return the advanced tab
|
||||
|
||||
:rtype: string
|
||||
'''
|
||||
output = self.execute_bash(f"mediainfo --Full {quote(self.file_path)}").decode('utf-8')
|
||||
return output
|
||||
|
||||
|
||||
def generate_tabs_list(self):
|
||||
'''
|
||||
Return the list of item for the QListWidget
|
||||
|
||||
:rtype: list
|
||||
'''
|
||||
tab_str = ""
|
||||
tabs = ["Basic", "Advanced"]
|
||||
inform_general = r"General;General (%Format%)\n"
|
||||
|
||||
informs = [inform_general]
|
||||
|
||||
if self.track_count["Video"] == 1:
|
||||
inform_video = r'Video;Video (%Format%)\n'
|
||||
informs.append(inform_video)
|
||||
elif self.track_count["Video"] > 1:
|
||||
inform_video = r'Video;Video #%StreamKindPos% (%Format%)\n'
|
||||
informs.append(inform_video)
|
||||
|
||||
if self.track_count["Audio"] == 1:
|
||||
inform_audio = r'Audio;Audio (%Format%)\n'
|
||||
informs.append(inform_audio)
|
||||
elif self.track_count["Audio"] > 1:
|
||||
inform_audio = r'Audio;Audio #%StreamKindPos% (%Format%)\n'
|
||||
informs.append(inform_audio)
|
||||
|
||||
if self.track_count["Text"] == 1:
|
||||
inform_text = r'Text;Text (%Format%)\n'
|
||||
informs.append(inform_text)
|
||||
elif self.track_count["Text"] > 1:
|
||||
inform_text = r'Text;Text #%StreamKindPos% (%Format%)\n'
|
||||
informs.append(inform_text)
|
||||
|
||||
for inform in informs:
|
||||
tab_str += self.media_inform(inform)
|
||||
|
||||
if not self.track_count["Menu"] == 0:
|
||||
tab_str += "Menu"
|
||||
|
||||
tabs.extend(list(filter(None, tab_str.split("\n"))))
|
||||
return tabs
|
||||
|
||||
|
||||
def generate_tabs_content(self):
|
||||
'''
|
||||
Return the content of the tabs
|
||||
|
||||
:rtype: dict[str:str]
|
||||
'''
|
||||
track_list = self.advanced_info.split("\n\n")
|
||||
del track_list[-1]
|
||||
|
||||
tabs = {}
|
||||
tabs["Basic"] = self.basic_info
|
||||
tabs["Advanced"] = self.advanced_info
|
||||
|
||||
|
||||
for i in range(len(track_list)):
|
||||
tabs.update({self.tabs_list[i+2]: track_list[i]})
|
||||
|
||||
return tabs
|
11
mediainfosama/main.py
Normal file
11
mediainfosama/main.py
Normal file
@ -0,0 +1,11 @@
|
||||
import sys
|
||||
|
||||
from PySide6 import QtWidgets
|
||||
from main_window import MainWindow
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
|
||||
app.exec()
|
105
mediainfosama/main_window.py
Normal file
105
mediainfosama/main_window.py
Normal file
@ -0,0 +1,105 @@
|
||||
from PySide6.QtWidgets import QWidget
|
||||
from PySide6.QtCore import QSize
|
||||
from PySide6.QtGui import QTextCharFormat, QTextCursor, QColor
|
||||
from ui_main_window import Ui_MainWindow
|
||||
from file_cmds import FileCmds
|
||||
|
||||
|
||||
class MainWindow(QWidget, Ui_MainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self.window_title = "mediaInfoSama"
|
||||
self.setWindowTitle(self.window_title)
|
||||
self.setAcceptDrops(True)
|
||||
self.setupConnections()
|
||||
|
||||
self.splitter.setStretchFactor(0, False)
|
||||
self.splitter.setStretchFactor(1, True)
|
||||
|
||||
|
||||
def setupConnections(self):
|
||||
self.tracks_list_widget.itemSelectionChanged.connect(self.popuplate_content)
|
||||
self.search_line_edit.textChanged.connect(self.search)
|
||||
|
||||
|
||||
def dragEnterEvent(self, event):
|
||||
event.accept()
|
||||
|
||||
|
||||
def dragMoveEvent(self, event):
|
||||
event.accept()
|
||||
|
||||
|
||||
def dropEvent(self, event):
|
||||
self.file_path = event.mimeData().urls()[0].toLocalFile()
|
||||
self.file_cmds = FileCmds(self.file_path)
|
||||
|
||||
if self.file_cmds.file_exist() == False:
|
||||
return
|
||||
|
||||
self.setWindowTitle(f"{self.file_path} - {self.window_title}")
|
||||
self.populate_tabs()
|
||||
self.tracks_list_widget.item(0).setSelected(True)
|
||||
|
||||
|
||||
def populate_tabs(self):
|
||||
self.tracks_list_widget.clear()
|
||||
self.tracks_list_widget.addItems(self.file_cmds.tabs_list)
|
||||
|
||||
for i in range(self.tracks_list_widget.count()):
|
||||
item = self.tracks_list_widget.item(i)
|
||||
height = self.tracks_list_widget.sizeHintForRow(0)
|
||||
item.setSizeHint(QSize(0, height+5))
|
||||
|
||||
|
||||
def popuplate_content(self):
|
||||
item_selected = self.tracks_list_widget.selectedItems()
|
||||
if item_selected:
|
||||
self.content = self.file_cmds.tabs_content[item_selected[0].text()]
|
||||
self.detail_text_edit.setPlainText(self.content)
|
||||
self.search()
|
||||
|
||||
|
||||
def search(self):
|
||||
to_search = self.search_line_edit.text()
|
||||
|
||||
if not to_search:
|
||||
self.detail_text_edit.setPlainText(self.content)
|
||||
return
|
||||
|
||||
content_list = self.content.split("\n")
|
||||
|
||||
searched_content = []
|
||||
|
||||
for line in content_list:
|
||||
if to_search.lower() in line.lower():
|
||||
searched_content.append(line)
|
||||
# elif line == "" and not searched_content[-1] == "":
|
||||
elif line == "":
|
||||
if searched_content and not searched_content[-1] == "":
|
||||
searched_content.append(line)
|
||||
|
||||
searched_content = "\n".join(searched_content)
|
||||
self.detail_text_edit.setPlainText(searched_content)
|
||||
|
||||
def add_selection():
|
||||
sel = self.detail_text_edit.ExtraSelection()
|
||||
sel.cursor = cursor
|
||||
sel.format = fmt
|
||||
selections.append(sel)
|
||||
|
||||
selections = []
|
||||
doc = self.detail_text_edit.document()
|
||||
fmt = QTextCharFormat()
|
||||
fmt.setBackground(QColor(0,128,0))
|
||||
cursor = QTextCursor()
|
||||
while True:
|
||||
cursor = doc.find(to_search, cursor)
|
||||
if cursor.isNull() or cursor.atEnd():
|
||||
if cursor.atEnd():
|
||||
if cursor.selectedText() == to_search:
|
||||
add_selection()
|
||||
break
|
||||
add_selection()
|
||||
self.detail_text_edit.setExtraSelections(selections)
|
83
mediainfosama/ui_main_window.py
Normal file
83
mediainfosama/ui_main_window.py
Normal file
@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'main_window_dark.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.4.1
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
|
||||
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
||||
QMetaObject, QObject, QPoint, QRect,
|
||||
QSize, QTime, QUrl, Qt)
|
||||
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QFont, QFontDatabase, QGradient, QIcon,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QApplication, QFrame, QLineEdit, QListWidget,
|
||||
QListWidgetItem, QSizePolicy, QSplitter, QTextEdit,
|
||||
QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
if not MainWindow.objectName():
|
||||
MainWindow.setObjectName(u"MainWindow")
|
||||
MainWindow.resize(1214, 888)
|
||||
MainWindow.setStyleSheet(u"background-color: rgb(42, 42, 42);\n"
|
||||
"font: 11pt \"UbuntuMono NF\";\n"
|
||||
"selection-background-color: rgb(105, 105, 105);\n"
|
||||
"color: rgb(230, 230, 230);")
|
||||
self.verticalLayout_2 = QVBoxLayout(MainWindow)
|
||||
self.verticalLayout_2.setSpacing(0)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.splitter = QSplitter(MainWindow)
|
||||
self.splitter.setObjectName(u"splitter")
|
||||
self.splitter.setStyleSheet(u"background-color: rgb(48, 98, 148);\n"
|
||||
"background-color: rgb(105, 105, 105);")
|
||||
self.splitter.setFrameShadow(QFrame.Plain)
|
||||
self.splitter.setOrientation(Qt.Horizontal)
|
||||
self.splitter.setHandleWidth(2)
|
||||
self.layoutWidget = QWidget(self.splitter)
|
||||
self.layoutWidget.setObjectName(u"layoutWidget")
|
||||
self.verticalLayout = QVBoxLayout(self.layoutWidget)
|
||||
self.verticalLayout.setSpacing(2)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.search_line_edit = QLineEdit(self.layoutWidget)
|
||||
self.search_line_edit.setObjectName(u"search_line_edit")
|
||||
self.search_line_edit.setStyleSheet(u"background-color: rgb(42, 42, 42);")
|
||||
self.search_line_edit.setFrame(False)
|
||||
|
||||
self.verticalLayout.addWidget(self.search_line_edit)
|
||||
|
||||
self.tracks_list_widget = QListWidget(self.layoutWidget)
|
||||
self.tracks_list_widget.setObjectName(u"tracks_list_widget")
|
||||
self.tracks_list_widget.setStyleSheet(u"background-color: rgb(42, 42, 42);")
|
||||
self.tracks_list_widget.setFrameShape(QFrame.NoFrame)
|
||||
|
||||
self.verticalLayout.addWidget(self.tracks_list_widget)
|
||||
|
||||
self.splitter.addWidget(self.layoutWidget)
|
||||
self.detail_text_edit = QTextEdit(self.splitter)
|
||||
self.detail_text_edit.setObjectName(u"detail_text_edit")
|
||||
self.detail_text_edit.setStyleSheet(u"background-color: rgb(42, 42, 42);")
|
||||
self.detail_text_edit.setFrameShape(QFrame.NoFrame)
|
||||
self.detail_text_edit.setReadOnly(True)
|
||||
self.splitter.addWidget(self.detail_text_edit)
|
||||
|
||||
self.verticalLayout_2.addWidget(self.splitter)
|
||||
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
|
||||
QMetaObject.connectSlotsByName(MainWindow)
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Form", None))
|
||||
self.search_line_edit.setText("")
|
||||
self.search_line_edit.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Search...", None))
|
||||
# retranslateUi
|
||||
|
Reference in New Issue
Block a user