...
 
Commits (8)
......@@ -4,6 +4,7 @@ V 0.18.0:
- Is now more opinionated, removed options for renaming schemes
- Added CLI tools for adding multi-episodes and excludes
- Implemented toktokkie-supercut tool
- Implemented manga, light novel and visual novel support
V 0.17.0:
- Added verification mechanisms
- Added unit tests for metadata and verification
......
"""LICENSE
Copyright 2015 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import os
import argparse
from colorama import Fore, Style
from puffotter.init import cli_start, argparse_add_verbosity
from toktokkie import Directory, sentry_dsn
from toktokkie.exceptions import MissingMetadata, InvalidMetadata
from toktokkie.metadata.Manga import Manga
from toktokkie.metadata.components.enums import MediaType, MangaIdType
from manga_dl.scrapers.mangadex import MangaDexScraper
def main(args: argparse.Namespace):
"""
The main function of this script
:param args: The command line arguments
:return: None
"""
scraper = MangaDexScraper()
for path in args.directories:
try:
directory = Directory(path)
print(directory.metadata.name)
metadata = directory.metadata # type: Manga
if metadata.media_type() != MediaType.MANGA:
print("Not a manga directory: {}".format(path))
continue
mangadex_id = metadata.ids.get(MangaIdType.MANGADEX)
if mangadex_id is None or len(mangadex_id) == 0:
print("No mangadex ID for {}".format(path))
continue
chapters = scraper.load_chapters(None, mangadex_id[0])
main_chapters = []
special_chapters = []
for chapter in chapters:
if "." in chapter.chapter_number:
special_chapters.append(chapter)
else:
try:
int(chapter.chapter_number)
main_chapters.append(chapter)
except ValueError:
special_chapters.append(chapter)
current_latest = len(os.listdir(metadata.main_path))
main_chapters = list(filter(
lambda x: int(x.chapter_number) > current_latest,
main_chapters
))
if not args.dry_run:
directory.rename(noconfirm=True)
maxchar = max(metadata.name)
downloaded = []
for c in main_chapters:
if c.chapter_number in downloaded:
continue
downloaded.append(c.chapter_number)
name = "{}{} - Chapter {}.cbz".format(
maxchar,
metadata.name,
c.chapter_number.zfill(len(str(current_latest)))
)
dest = os.path.join(metadata.main_path, name)
if not args.dry_run:
print("Downloading Chapter {}".format(c))
c.download(dest)
else:
print("{}Found chapter: {}{}".format(
Fore.LIGHTYELLOW_EX,
c,
Style.RESET_ALL
))
if not args.dry_run:
directory.rename(noconfirm=True)
except MissingMetadata:
print("{} has no metadata file.".format(path))
except InvalidMetadata:
print("{}'s metadata is invalid.".format(path))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("directories", nargs="+",
help="The directories to update. "
"Files and directories that do not contain any "
"valid metadata configuration will be ignored.")
parser.add_argument("--dry-run", action="store_true",
help="Does not download or rename anything")
argparse_add_verbosity(parser)
cli_start(
main, parser, "Thanks for using toktokkie!", "toktokkie", sentry_dsn
)
#!/usr/bin/env python
"""LICENSE
Copyright 2015 Hermann Krumrey <hermann@krumreyh.com>
......@@ -20,41 +18,45 @@ along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import argparse
from toktokkie import Directory
from toktokkie.exceptions import MissingMetadata, InvalidMetadata
from puffotter.init import cli_start, argparse_add_verbosity
from toktokkie import sentry_dsn
from toktokkie.scripts import toktokkie_commands
def main():
def main(args: argparse.Namespace):
"""
The toktokkie-rename main method
The main function of this script
:param args: The command line arguments
:return: None
"""
parser = argparse.ArgumentParser()
parser.add_argument("directories", nargs="+",
help="The directories to rename. "
"Files and directories that do not contain any "
"valid metadata configuration will be ignored.")
parser.add_argument("--noconfirm", action="store_true",
help="Skips the user confirmation step")
args = parser.parse_args()
for command_cls in toktokkie_commands:
if command_cls.name() == args.command:
command = command_cls(args)
command.execute()
directories = args.directories
for path in directories:
def define_parser() -> argparse.ArgumentParser:
"""
:return: The command line parser for this script
"""
parser = argparse.ArgumentParser()
argparse_add_verbosity(parser)
command_parser = parser.add_subparsers(required=True, dest="command")
for command_cls in toktokkie_commands:
subparser = command_parser.add_parser(command_cls.name())
argparse_add_verbosity(subparser)
command_cls.prepare_parser(subparser)
try:
directory = Directory(path)
directory.rename(args.noconfirm)
except ValueError:
print("Renaming of " + path + "failed")
except MissingMetadata:
print("{} has no metadata file.".format(path))
except InvalidMetadata:
print("{}'s metadata is invalid.".format(path))
return parser
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("Thanks for using toktokkie!")
cli_start(
main,
define_parser(),
"Thanks for using toktokkie!",
"toktokkie",
sentry_dsn
)
#!/bin/env python
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie-gui. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import os
from subprocess import check_output
qt_designer_dir = os.path.join("toktokkie", "gui", "qt_designer")
pyuic_dir = os.path.join("toktokkie", "gui", "pyuic")
for design in os.listdir(qt_designer_dir):
if design.endswith(".ui"):
design_file = os.path.join(qt_designer_dir, design)
result_file = os.path.join(pyuic_dir, design.replace(".ui", ".py"))
generated = check_output(["pyuic5", design_file])
with open(result_file, "wb") as f:
f.write(generated)
......@@ -49,6 +49,9 @@ if __name__ == "__main__":
"puffotter",
"manga-dl"
],
extras_require={
"gui": ["PyQt5"]
},
test_suite='nose.collector',
tests_require=['nose'],
include_package_data=True,
......
......@@ -19,8 +19,8 @@ along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
from toktokkie.check.Checker import Checker
from toktokkie.metadata.BookSeries import BookSeries
from toktokkie.metadata.components.enums import BookIdType
from anime_list_apis.models.attributes.Id import IdType
from toktokkie.metadata.components.enums import IdType
from anime_list_apis.models.attributes.Id import IdType as AnimeListIdType
class BookSeriesChecker(Checker):
......@@ -45,7 +45,7 @@ class BookSeriesChecker(Checker):
"""
metadata = self.metadata # type: BookSeries
manga_list = self.config["anilist_manga_list"]
anilist_id = metadata.ids.get(BookIdType.ANILIST, [None])[0]
anilist_id = metadata.ids.get(IdType.ANILIST, [None])[0]
if anilist_id is None:
return self.error("No Anilist ID")
......@@ -53,7 +53,7 @@ class BookSeriesChecker(Checker):
anilist_id = int(anilist_id)
manga = None
for entry in manga_list:
if entry.id.get(IdType.ANILIST) == anilist_id:
if entry.id.get(AnimeListIdType.ANILIST) == anilist_id:
manga = entry
break
......
......@@ -23,10 +23,10 @@ import requests
from typing import Optional
from toktokkie.check.Checker import Checker
from toktokkie.metadata.Manga import Manga
from toktokkie.metadata.components.enums import MangaIdType
from toktokkie.metadata.components.enums import IdType
from anime_list_apis.api.AnilistApi import AnilistApi
from anime_list_apis.models.MediaListEntry import MangaListEntry
from anime_list_apis.models.attributes.Id import IdType
from anime_list_apis.models.attributes.Id import IdType as AnimeListIdType
class MangaChecker(Checker):
......@@ -75,11 +75,11 @@ class MangaChecker(Checker):
local_chaptercount = len(os.listdir(metadata.main_path))
try:
anilist_id = int(metadata.ids.get(MangaIdType.ANILIST)[0])
anilist_id = int(metadata.ids.get(IdType.ANILIST)[0])
list_entry = None
for entry in anilist_entries: # type: MangaListEntry
if entry.id.get(IdType.ANILIST) == anilist_id:
if entry.id.get(AnimeListIdType.ANILIST) == anilist_id:
list_entry = entry
break
......
......@@ -26,9 +26,9 @@ from toktokkie.check.Checker import Checker
from toktokkie.renaming.Renamer import Renamer
from toktokkie.renaming.RenameOperation import RenameOperation
from toktokkie.metadata.TvSeries import TvSeries
from toktokkie.metadata.components.enums import TvIdType
from toktokkie.metadata.components.enums import IdType
from anime_list_apis.api.AnilistApi import AnilistApi
from anime_list_apis.models.attributes.Id import IdType
from anime_list_apis.models.attributes.Id import IdType as AnimeListIdType
from anime_list_apis.models.attributes.MediaType import MediaType
from anime_list_apis.models.attributes.ConsumingStatus import ConsumingStatus
from anime_list_apis.models.attributes.ReleasingStatus import ReleasingStatus
......@@ -248,7 +248,7 @@ class TvSeriesChecker(Checker):
user_list = self.config["anilist_anime_list"]
completed_ids = list(
map(
lambda x: int(x.id.get(IdType.ANILIST)),
lambda x: int(x.id.get(AnimeListIdType.ANILIST)),
filter(
lambda x: x.consuming_status == ConsumingStatus.COMPLETED,
user_list
......@@ -260,13 +260,13 @@ class TvSeriesChecker(Checker):
for season in metadata.seasons:
mal_ids = None
if TvIdType.MYANIMELIST not in season.ids:
if IdType.MYANIMELIST not in season.ids:
valid = \
self.error("No myanimelist ID for {}".format(season.name))
else:
mal_ids = season.ids[TvIdType.MYANIMELIST]
mal_ids = season.ids[IdType.MYANIMELIST]
if TvIdType.ANILIST not in season.ids:
if IdType.ANILIST not in season.ids:
valid = self.error("No anilist ID for {}".format(season.name))
......@@ -291,11 +291,11 @@ class TvSeriesChecker(Checker):
if resp == "y":
ids = season.ids
ids[TvIdType.ANILIST] = anilist_ids
ids[IdType.ANILIST] = anilist_ids
season.ids = ids
self.metadata.write()
ids = season.ids.get(TvIdType.ANILIST, [])
ids = season.ids.get(IdType.ANILIST, [])
for _id in ids:
if int(_id) not in completed_ids:
data = api.get_anime_data(int(_id))
......@@ -321,10 +321,10 @@ class TvSeriesChecker(Checker):
metadata = self.metadata # type: TvSeries
ignores = {}
excluded = metadata.excludes.get(TvIdType.TVDB, {})
multis = metadata.multi_episodes.get(TvIdType.TVDB, {})
excluded = metadata.excludes.get(IdType.TVDB, {})
multis = metadata.multi_episodes.get(IdType.TVDB, {})
start_overrides = \
metadata.season_start_overrides.get(TvIdType.TVDB, {})
metadata.season_start_overrides.get(IdType.TVDB, {})
# Add excluded episodes directly
for season, episodes in excluded.items():
......@@ -359,7 +359,7 @@ class TvSeriesChecker(Checker):
:return: The generated name
"""
metadata = self.metadata # type: TvSeries
multis = metadata.multi_episodes.get(TvIdType.TVDB, {})
multis = metadata.multi_episodes.get(IdType.TVDB, {})
series_name = metadata.name
if series_name_override is not None:
......
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import os
import json
import time
from threading import Thread
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QTreeWidgetItem, QWidget
from toktokkie import Directory
from toktokkie.exceptions import MissingMetadata, InvalidMetadata
from toktokkie.metadata.components.enums import MediaType
from toktokkie.gui.pyuic.main import Ui_MainWindow
from toktokkie.gui.widgets.BookWidget import BookWidget
from toktokkie.gui.widgets.MovieWidget import MovieWidget
from toktokkie.gui.widgets.TvSeriesWidget import TvSeriesWidget
from toktokkie.gui.widgets.TvSeasonWidget import TvSeasonWidget
class MainWindow(QMainWindow, Ui_MainWindow):
"""
The Main Window of the application
"""
def __init__(self):
"""
Initializes the main window
"""
start = time.time()
super().__init__(None)
self.setupUi(self)
self.config_dir = os.path.join(
os.path.expanduser("~"), ".config/toktokkie"
)
self.config_file = os.path.join(self.config_dir, "config.json")
with open(self.config_file, "r") as f:
self.config = json.load(f)
self._initialize_actions()
self.media = {}
self.reload()
self.media_widgets = {
MediaType.TV_SERIES: TvSeriesWidget(self),
MediaType.MOVIE: MovieWidget(self),
MediaType.BOOK: BookWidget(self),
MediaType.BOOK_SERIES: BookWidget(self),
"tv_season": TvSeasonWidget(self),
"default": QWidget(self)
}
for _, widget in self.media_widgets.items():
self.widget_stack.addWidget(widget)
end = time.time()
print("Startup Time: {}".format(end-start))
def reload(self):
"""
Refreshes the data shown
:return: None
"""
self._reload_directories()
self._display_directories_in_tree()
def write_config(self):
"""
Writes the config file to disk
:return:
"""
with open(self.config_file, "w") as f:
json.dump(
self.config,
f,
sort_keys=True,
indent=4,
separators=(",", ": ")
)
def _initialize_actions(self):
"""
Initilizes any actions that can be taken
:return: None
"""
self.media_tree.currentItemChanged.connect(self._display_media)
self.add_directories_option.triggered.connect(self._open_add_dialog)
self.remove_directories_option.triggered.connect(
self._open_remove_dialog
)
def _open_add_dialog(self):
"""
Opens a dialog window that allows the user to add a new directory
:return: None
"""
directory = QFileDialog.getExistingDirectory(self, "Browse")
if directory:
self.config["media_directories"].append(directory)
self.write_config()
self._reload_directories()
self._display_directories_in_tree()
def _open_remove_dialog(self):
"""
Opens a dialog window that allows the user to remove a previously added
directory
:return: None
"""
pass
# RemoveDirectoryDialog(self).show()
def _reload_directories(self):
"""
Reloads the metadata from the directories specified in the config file
:return: None
"""
start = time.time()
self.media = {}
for media_type in MediaType:
self.media[media_type] = []
for media_directory in self.config["media_directories"]:
if not os.path.isdir(media_directory):
continue
for subdir in os.listdir(media_directory):
try:
media = Directory(os.path.join(media_directory, subdir))
except (MissingMetadata, InvalidMetadata):
continue
self.media[media.metadata.media_type()].append(media)
for media_type in self.media:
self.media[media_type].sort(key=lambda x: x.metadata.name)
end = time.time()
print("Loaded directories in {}".format(end - start))
def _display_directories_in_tree(self):
"""
Displays the media items' names in the tree
:return: None
"""
self.media_tree.clear()
for media_type, media_directories in self.media.items():
widget = QTreeWidgetItem([media_type.value])
for media_directory in media_directories:
metadata = media_directory.metadata
icon = metadata.get_icon_file("main")
subwidget = QTreeWidgetItem([metadata.name])
if icon is not None:
Thread(target=lambda: subwidget.setIcon(0, QIcon(icon)))\
.start()
if metadata.media_type() == MediaType.TV_SERIES:
for season in metadata.seasons:
season_widget = QTreeWidgetItem([season.name])
subwidget.addChild(season_widget)
widget.addChild(subwidget)
self.media_tree.addTopLevelItem(widget)
def _display_media(self, tree_item: QTreeWidgetItem):
"""
Displays a media item
:param tree_item: The tree item that got selected
:return: None
"""
if tree_item is None or tree_item.parent() is None:
self.widget_stack.setCurrentWidget(self.media_widgets["default"])
return
depth = 0
depth_check = tree_item
while depth_check.parent() is not None:
depth += 1
depth_check = depth_check.parent()
if depth == 1:
series_widget = tree_item
elif depth == 2:
series_widget = tree_item.parent()
else:
return
media_type = MediaType(series_widget.parent().data(0, 0))
index = series_widget.parent().indexOfChild(series_widget)
metadata = self.media[media_type][index].metadata
if depth == 1:
widget = self.media_widgets[media_type]
widget.set_metadata(metadata)
self.widget_stack.setCurrentWidget(widget)
elif depth == 2:
if metadata.media_type() == MediaType.TV_SERIES:
season = tree_item.data(0, 0)
widget = self.media_widgets["tv_season"]
widget.set_metadata(metadata, season)
self.widget_stack.setCurrentWidget(widget)
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
from PyQt5.QtWidgets import QDialog, QMainWindow, QListWidgetItem
from toktokkie.gui.pyuic.remove_directory_dialog import \
Ui_RemoveDirectoryDialog
class RemoveDirectoryDialog(QDialog, Ui_RemoveDirectoryDialog):
"""
Class that models a dialog that allows a user to remove a directory
from the config file
"""
def __init__(self, parent: QMainWindow):
"""
Initializes the widget
:param parent: The parent window
"""
super().__init__(parent)
self.setupUi(self)
self.remove_button.clicked.connect(self.remove_selected)
media_dirs = self.parent().config["media_directories"]
for path in media_dirs:
self.directory_list.addItem(QListWidgetItem(path))
def remove_selected(self):
"""
Removes the selected directories from the config and
closes the dialog afterwards
:return: None
"""
selected = self.directory_list.selectedItems()
for item in selected:
self.parent().config["media_directories"].remove(item.text())
self.parent().write_config()
self.parent().reload()
self.close()
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'toktokkie/gui/qt_designer/book_widget.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_BookWidget(object):
def setupUi(self, BookWidget):
BookWidget.setObjectName("BookWidget")
BookWidget.resize(661, 369)
self.gridLayout = QtWidgets.QGridLayout(BookWidget)
self.gridLayout.setObjectName("gridLayout")
self.name = QtWidgets.QLabel(BookWidget)
font = QtGui.QFont()
font.setPointSize(24)
self.name.setFont(font)
self.name.setAlignment(QtCore.Qt.AlignCenter)
self.name.setObjectName("name")
self.gridLayout.addWidget(self.name, 1, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 2, 0, 1, 1)
self.open_directory_button = QtWidgets.QPushButton(BookWidget)
self.open_directory_button.setObjectName("open_directory_button")
self.gridLayout.addWidget(self.open_directory_button, 5, 0, 1, 1)
self.icon_label = QtWidgets.QLabel(BookWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.icon_label.sizePolicy().hasHeightForWidth())
self.icon_label.setSizePolicy(sizePolicy)
self.icon_label.setMinimumSize(QtCore.QSize(256, 256))
self.icon_label.setMaximumSize(QtCore.QSize(256, 256))
self.icon_label.setText("")
self.icon_label.setPixmap(QtGui.QPixmap("../../../../../Downloads/pokemon_folder_icon_by_mikromike-d8mldi8.png"))
self.icon_label.setScaledContents(True)
self.icon_label.setAlignment(QtCore.Qt.AlignCenter)
self.icon_label.setObjectName("icon_label")
self.gridLayout.addWidget(self.icon_label, 3, 0, 1, 1)
self.frame = QtWidgets.QFrame(BookWidget)
self.frame.setEnabled(True)
self.frame.setMaximumSize(QtCore.QSize(500, 16777215))
self.frame.setFrameShape(QtWidgets.QFrame.Box)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.frame_2 = QtWidgets.QFrame(self.frame)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_2)
self.gridLayout_3.setObjectName("gridLayout_3")
self.gridLayout_2.addWidget(self.frame_2, 4, 0, 1, 4)
self.tags_edit = QtWidgets.QLineEdit(self.frame)
self.tags_edit.setText("")
self.tags_edit.setObjectName("tags_edit")
self.gridLayout_2.addWidget(self.tags_edit, 1, 1, 1, 3)
self.isbn_url_button = QtWidgets.QPushButton(self.frame)
self.isbn_url_button.setObjectName("isbn_url_button")
self.gridLayout_2.addWidget(self.isbn_url_button, 2, 3, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_2.addItem(spacerItem1, 3, 0, 1, 1)
self.confirm_changes_button = QtWidgets.QPushButton(self.frame)
self.confirm_changes_button.setObjectName("confirm_changes_button")
self.gridLayout_2.addWidget(self.confirm_changes_button, 5, 1, 1, 1)
self.isbn_edit = QtWidgets.QLineEdit(self.frame)
self.isbn_edit.setText("")
self.isbn_edit.setObjectName("isbn_edit")
self.gridLayout_2.addWidget(self.isbn_edit, 2, 1, 1, 2)
self.label_2 = QtWidgets.QLabel(self.frame)
self.label_2.setFrameShape(QtWidgets.QFrame.Box)
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
self.label_4 = QtWidgets.QLabel(self.frame)
self.label_4.setFrameShape(QtWidgets.QFrame.Box)
self.label_4.setAlignment(QtCore.Qt.AlignCenter)
self.label_4.setObjectName("label_4")
self.gridLayout_2.addWidget(self.label_4, 0, 0, 1, 1)
self.label_3 = QtWidgets.QLabel(self.frame)
self.label_3.setFrameShape(QtWidgets.QFrame.Box)
self.label_3.setAlignment(QtCore.Qt.AlignCenter)
self.label_3.setObjectName("label_3")
self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1)
self.media_type_label = QtWidgets.QLabel(self.frame)
self.media_type_label.setAlignment(QtCore.Qt.AlignCenter)
self.media_type_label.setObjectName("media_type_label")
self.gridLayout_2.addWidget(self.media_type_label, 0, 1, 1, 3)
self.gridLayout.addWidget(self.frame, 0, 1, 7, 1)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 4, 0, 1, 1)
self.retranslateUi(BookWidget)
QtCore.QMetaObject.connectSlotsByName(BookWidget)
BookWidget.setTabOrder(self.tags_edit, self.isbn_edit)
BookWidget.setTabOrder(self.isbn_edit, self.isbn_url_button)
BookWidget.setTabOrder(self.isbn_url_button, self.confirm_changes_button)
def retranslateUi(self, BookWidget):
_translate = QtCore.QCoreApplication.translate
BookWidget.setWindowTitle(_translate("BookWidget", "Form"))
self.name.setText(_translate("BookWidget", "Name"))
self.open_directory_button.setText(_translate("BookWidget", "Open Directory"))
self.isbn_url_button.setText(_translate("BookWidget", "Go"))
self.confirm_changes_button.setText(_translate("BookWidget", "Confirm Changes"))
self.label_2.setText(_translate("BookWidget", "ISBN"))
self.label_4.setText(_translate("BookWidget", "Media Type"))
self.label_3.setText(_translate("BookWidget", "Tags"))
self.media_type_label.setText(_translate("BookWidget", "Media Type"))
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'toktokkie/gui/qt_designer/main.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(972, 525)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.splitter = QtWidgets.QSplitter(self.centralwidget)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.media_tree = QtWidgets.QTreeWidget(self.splitter)
self.media_tree.setMinimumSize(QtCore.QSize(200, 0))
self.media_tree.setMaximumSize(QtCore.QSize(16777215, 16777215))
self.media_tree.setObjectName("media_tree")
self.widget_stack = QtWidgets.QStackedWidget(self.splitter)
self.widget_stack.setMinimumSize(QtCore.QSize(750, 0))
self.widget_stack.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.widget_stack.setFrameShadow(QtWidgets.QFrame.Raised)
self.widget_stack.setObjectName("widget_stack")
self.stackedWidgetPage1 = QtWidgets.QWidget()
self.stackedWidgetPage1.setObjectName("stackedWidgetPage1")
self.widget_stack.addWidget(self.stackedWidgetPage1)
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 972, 24))
self.menuBar.setObjectName("menuBar")
self.menuAdd_Directories = QtWidgets.QMenu(self.menuBar)
self.menuAdd_Directories.setObjectName("menuAdd_Directories")
MainWindow.setMenuBar(self.menuBar)
self.add_directories_option = QtWidgets.QAction(MainWindow)
self.add_directories_option.setObjectName("add_directories_option")
self.remove_directories_option = QtWidgets.QAction(MainWindow)
self.remove_directories_option.setObjectName("remove_directories_option")
self.menuAdd_Directories.addAction(self.add_directories_option)
self.menuAdd_Directories.addAction(self.remove_directories_option)
self.menuBar.addAction(self.menuAdd_Directories.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "toktokkie"))
self.media_tree.headerItem().setText(0, _translate("MainWindow", "Media"))
self.menuAdd_Directories.setTitle(_translate("MainWindow", "File"))
self.add_directories_option.setText(_translate("MainWindow", "Add directories"))
self.remove_directories_option.setText(_translate("MainWindow", "Remove directories"))
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'toktokkie/gui/qt_designer/movie_widget.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MovieWidget(object):
def setupUi(self, MovieWidget):
MovieWidget.setObjectName("MovieWidget")
MovieWidget.resize(661, 369)
self.gridLayout = QtWidgets.QGridLayout(MovieWidget)
self.gridLayout.setObjectName("gridLayout")
self.name = QtWidgets.QLabel(MovieWidget)
font = QtGui.QFont()
font.setPointSize(24)
self.name.setFont(font)
self.name.setAlignment(QtCore.Qt.AlignCenter)
self.name.setObjectName("name")
self.gridLayout.addWidget(self.name, 1, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 2, 0, 1, 1)
self.open_directory_button = QtWidgets.QPushButton(MovieWidget)
self.open_directory_button.setObjectName("open_directory_button")
self.gridLayout.addWidget(self.open_directory_button, 5, 0, 1, 1)
self.icon_label = QtWidgets.QLabel(MovieWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.icon_label.sizePolicy().hasHeightForWidth())
self.icon_label.setSizePolicy(sizePolicy)
self.icon_label.setMinimumSize(QtCore.QSize(256, 256))
self.icon_label.setMaximumSize(QtCore.QSize(256, 256))
self.icon_label.setText("")
self.icon_label.setPixmap(QtGui.QPixmap("../../../../../Downloads/pokemon_folder_icon_by_mikromike-d8mldi8.png"))
self.icon_label.setScaledContents(True)
self.icon_label.setAlignment(QtCore.Qt.AlignCenter)
self.icon_label.setObjectName("icon_label")
self.gridLayout.addWidget(self.icon_label, 3, 0, 1, 1)
self.frame = QtWidgets.QFrame(MovieWidget)
self.frame.setEnabled(True)
self.frame.setMaximumSize(QtCore.QSize(500, 16777215))
self.frame.setFrameShape(QtWidgets.QFrame.Box)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.frame_2 = QtWidgets.QFrame(self.frame)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_2)
self.gridLayout_3.setObjectName("gridLayout_3")
self.gridLayout_2.addWidget(self.frame_2, 4, 0, 1, 4)
self.tags_edit = QtWidgets.QLineEdit(self.frame)
self.tags_edit.setText("")
self.tags_edit.setObjectName("tags_edit")
self.gridLayout_2.addWidget(self.tags_edit, 1, 1, 1, 3)
self.imdb_url_button = QtWidgets.QPushButton(self.frame)
self.imdb_url_button.setObjectName("imdb_url_button")
self.gridLayout_2.addWidget(self.imdb_url_button, 2, 3, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_2.addItem(spacerItem1, 3, 0, 1, 1)
self.confirm_changes_button = QtWidgets.QPushButton(self.frame)
self.confirm_changes_button.setObjectName("confirm_changes_button")
self.gridLayout_2.addWidget(self.confirm_changes_button, 5, 1, 1, 1)
self.imdb_id_edit = QtWidgets.QLineEdit(self.frame)
self.imdb_id_edit.setText("")
self.imdb_id_edit.setObjectName("imdb_id_edit")
self.gridLayout_2.addWidget(self.imdb_id_edit, 2, 1, 1, 2)
self.label_2 = QtWidgets.QLabel(self.frame)
self.label_2.setFrameShape(QtWidgets.QFrame.Box)
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
self.label_4 = QtWidgets.QLabel(self.frame)
self.label_4.setFrameShape(QtWidgets.QFrame.Box)
self.label_4.setAlignment(QtCore.Qt.AlignCenter)
self.label_4.setObjectName("label_4")
self.gridLayout_2.addWidget(self.label_4, 0, 0, 1, 1)
self.label_3 = QtWidgets.QLabel(self.frame)
self.label_3.setFrameShape(QtWidgets.QFrame.Box)
self.label_3.setAlignment(QtCore.Qt.AlignCenter)
self.label_3.setObjectName("label_3")
self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1)
self.media_type_label = QtWidgets.QLabel(self.frame)
self.media_type_label.setAlignment(QtCore.Qt.AlignCenter)
self.media_type_label.setObjectName("media_type_label")
self.gridLayout_2.addWidget(self.media_type_label, 0, 1, 1, 3)
self.gridLayout.addWidget(self.frame, 0, 1, 7, 1)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 4, 0, 1, 1)
self.retranslateUi(MovieWidget)
QtCore.QMetaObject.connectSlotsByName(MovieWidget)
MovieWidget.setTabOrder(self.tags_edit, self.imdb_id_edit)
MovieWidget.setTabOrder(self.imdb_id_edit, self.imdb_url_button)
MovieWidget.setTabOrder(self.imdb_url_button, self.confirm_changes_button)
def retranslateUi(self, MovieWidget):
_translate = QtCore.QCoreApplication.translate
MovieWidget.setWindowTitle(_translate("MovieWidget", "Form"))
self.name.setText(_translate("MovieWidget", "Name"))
self.open_directory_button.setText(_translate("MovieWidget", "Open Directory"))
self.imdb_url_button.setText(_translate("MovieWidget", "Go"))
self.confirm_changes_button.setText(_translate("MovieWidget", "Confirm Changes"))
self.label_2.setText(_translate("MovieWidget", "IMDB.com"))
self.label_4.setText(_translate("MovieWidget", "Media Type"))
self.label_3.setText(_translate("MovieWidget", "Tags"))
self.media_type_label.setText(_translate("MovieWidget", "Movie"))
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'toktokkie/gui/qt_designer/tv_season_widget.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_TvSeasonWidget(object):
def setupUi(self, TvSeasonWidget):
TvSeasonWidget.setObjectName("TvSeasonWidget")
TvSeasonWidget.resize(661, 369)
self.gridLayout = QtWidgets.QGridLayout(TvSeasonWidget)
self.gridLayout.setObjectName("gridLayout")
self.name = QtWidgets.QLabel(TvSeasonWidget)
font = QtGui.QFont()
font.setPointSize(24)
self.name.setFont(font)
self.name.setAlignment(QtCore.Qt.AlignCenter)
self.name.setObjectName("name")
self.gridLayout.addWidget(self.name, 1, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 2, 0, 1, 1)
self.open_directory_button = QtWidgets.QPushButton(TvSeasonWidget)
self.open_directory_button.setObjectName("open_directory_button")
self.gridLayout.addWidget(self.open_directory_button, 5, 0, 1, 1)
self.icon_label = QtWidgets.QLabel(TvSeasonWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.icon_label.sizePolicy().hasHeightForWidth())
self.icon_label.setSizePolicy(sizePolicy)
self.icon_label.setMinimumSize(QtCore.QSize(256, 256))
self.icon_label.setMaximumSize(QtCore.QSize(256, 256))
self.icon_label.setText("")
self.icon_label.setPixmap(QtGui.QPixmap("../../../../metadata/Breaking Bad/.meta/icons/main.png"))
self.icon_label.setScaledContents(True)
self.icon_label.setAlignment(QtCore.Qt.AlignCenter)
self.icon_label.setObjectName("icon_label")
self.gridLayout.addWidget(self.icon_label, 3, 0, 1, 1)
self.frame = QtWidgets.QFrame(TvSeasonWidget)
self.frame.setEnabled(True)
self.frame.setMaximumSize(QtCore.QSize(500, 16777215))
self.frame.setFrameShape(QtWidgets.QFrame.Box)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.tvdb_id_edit = QtWidgets.QLineEdit(self.frame)
self.tvdb_id_edit.setText("")
self.tvdb_id_edit.setObjectName("tvdb_id_edit")
self.gridLayout_2.addWidget(self.tvdb_id_edit, 1, 1, 1, 2)
self.frame_2 = QtWidgets.QFrame(self.frame)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_2)
self.gridLayout_3.setObjectName("gridLayout_3")
self.amount_of_episodes_label = QtWidgets.QLabel(self.frame_2)
self.amount_of_episodes_label.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.amount_of_episodes_label.setText("")
self.amount_of_episodes_label.setAlignment(QtCore.Qt.AlignCenter)
self.amount_of_episodes_label.setObjectName("amount_of_episodes_label")
self.gridLayout_3.addWidget(self.amount_of_episodes_label, 1, 1, 1, 1)
self.label_12 = QtWidgets.QLabel(self.frame_2)
self.label_12.setFrameShape(QtWidgets.QFrame.WinPanel)
self.label_12.setAlignment(QtCore.Qt.AlignCenter)
self.label_12.setObjectName("label_12")
self.gridLayout_3.addWidget(self.label_12, 1, 0, 1, 1)
self.episode_list = QtWidgets.QListWidget(self.frame_2)
self.episode_list.setObjectName("episode_list")
self.gridLayout_3.addWidget(self.episode_list, 2, 0, 1, 2)
self.gridLayout_2.addWidget(self.frame_2, 3, 0, 1, 4)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_2.addItem(spacerItem1, 2, 0, 1, 1)
self.confirm_changes_button = QtWidgets.QPushButton(self.frame)
self.confirm_changes_button.setObjectName("confirm_changes_button")
self.gridLayout_2.addWidget(self.confirm_changes_button, 4, 1, 1, 1)
self.tvdb_url_button = QtWidgets.QPushButton(self.frame)
self.tvdb_url_button.setObjectName("tvdb_url_button")
self.gridLayout_2.addWidget(self.tvdb_url_button, 1, 3, 1, 1)
self.label_2 = QtWidgets.QLabel(self.frame)
self.label_2.setFrameShape(QtWidgets.QFrame.Box)
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 1, 0, 1, 1)
self.season_name = QtWidgets.QLabel(self.frame)
self.season_name.setAlignment(QtCore.Qt.AlignCenter)
self.season_name.setObjectName("season_name")
self.gridLayout_2.addWidget(self.season_name, 0, 0, 1, 4)
self.gridLayout.addWidget(self.frame, 0, 1, 7, 1)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 4, 0, 1, 1)
self.retranslateUi(TvSeasonWidget)
QtCore.QMetaObject.connectSlotsByName(TvSeasonWidget)
TvSeasonWidget.setTabOrder(self.tvdb_id_edit, self.tvdb_url_button)
TvSeasonWidget.setTabOrder(self.tvdb_url_button, self.confirm_changes_button)
def retranslateUi(self, TvSeasonWidget):
_translate = QtCore.QCoreApplication.translate
TvSeasonWidget.setWindowTitle(_translate("TvSeasonWidget", "Form"))
self.name.setText(_translate("TvSeasonWidget", "Name"))
self.open_directory_button.setText(_translate("TvSeasonWidget", "Open Directory"))
self.label_12.setText(_translate("TvSeasonWidget", "Amount of Episodes"))
self.confirm_changes_button.setText(_translate("TvSeasonWidget", "Confirm Changes"))
self.tvdb_url_button.setText(_translate("TvSeasonWidget", "Go"))
self.label_2.setText(_translate("TvSeasonWidget", "TheTVDB.com"))
self.season_name.setText(_translate("TvSeasonWidget", "Season Name"))
This diff is collapsed.
"""LICENSE
Copyright 2019 Hermann Krumrey <hermann@krumreyh.com>
This file is part of toktokkie.
toktokkie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
toktokkie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BookWidget</class>
<widget class="QWidget" name="BookWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>661</width>
<height>369</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="name">
<property name="font">
<font>
<pointsize>24</pointsize>
</font>
</property>
<property name="text">
<string>Name</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="open_directory_button">
<property name="text">
<string>Open Directory</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="icon_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>../../../../../Downloads/pokemon_folder_icon_by_mikromike-d8mldi8.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="7">
<widget class="QFrame" name="frame">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="0" colspan="4">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3"/>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="tags_edit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="isbn_url_button">
<property name="text">
<string>Go</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="confirm_changes_button">
<property name="text">
<string>Confirm Changes</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="isbn_edit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string>ISBN</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string>Media Type</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string>Tags</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLabel" name="media_type_label">
<property name="text">
<string>Media Type</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>
<tabstop>tags_edit</tabstop>
<tabstop>isbn_edit</tabstop>
<tabstop>isbn_url_button</tabstop>
<tabstop>confirm_changes_button</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>972</width>
<height>525</height>
</rect>
</property>
<property name="windowTitle">
<string>toktokkie</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeWidget" name="media_tree">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<column>
<property name="text">
<string>Media</string>
</property>
</column>
</widget>
<widget class="QStackedWidget" name="widget_stack">
<property name="minimumSize">
<size>
<width>750</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QWidget" name="stackedWidgetPage1"/>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>972</width>
<height>24</height>