diff --git a/ArtNet/artnet_manager.py b/ArtNet/artnet_manager.py
index f5f0b41..88db6b7 100644
--- a/ArtNet/artnet_manager.py
+++ b/ArtNet/artnet_manager.py
@@ -1,6 +1,8 @@
 import shutil
 import sys
 import os
+import logging
+import datetime
 from hashlib import md5
 
 from PyQt5.QtWidgets import QApplication
@@ -14,14 +16,29 @@ from ArtNet.web.link_generator import LinkGenerator
 
 
 class ArtNetManager:
+    LOG_FOLDER = "log"
 
     def __init__(self, config_location: str = "."):
+        if not os.path.isdir(ArtNetManager.LOG_FOLDER):
+            os.mkdir(ArtNetManager.LOG_FOLDER)
+        file_name = "artnet-" + str(datetime.datetime.now().strftime("%Y-%m-%d")) + ".log"
+        logging.basicConfig(filename=os.path.join(ArtNetManager.LOG_FOLDER, file_name), encoding='utf-8',
+                            level=logging.DEBUG)
+        logFormatter = logging.Formatter(fmt="%(asctime)s.%(msecs)03d [%(threadName)-12.12s] [%(levelname)-5.5s]  "
+                                         "%(message)s",
+                                         datefmt="%Y-%m-%d %H:%M:%S")
+
+        logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
+        for handler in logging.getLogger().handlers:
+            handler.setFormatter(logFormatter)
+        logging.info("Starting ArtNet client ...")
+
         self.known_image_amount = None
         self.config = ConfigReader(config_location, "somePassword")
 
         if self.config.data["version"] != self.config.CONFIG_VERSION:
-            print("Loaded config version is unequal to expected version! {0} (current) != {1} (expected)"
-                  .format(self.config.data["version"], self.config.CONFIG_VERSION))
+            logging.warning("Loaded config version is unequal to expected version! {0} (current) != {1} (expected)"
+                            .format(self.config.data["version"], self.config.CONFIG_VERSION))
 
         self.db_connection = None
         self.__app = QApplication(sys.argv)
@@ -34,7 +51,7 @@ class ArtNetManager:
                                                                port=self.config.data["db"]["port"],
                                                                database=self.config.data["db"]["database"])
             except ValueError as e:  # db connection didn't work
-                print(e)
+                logging.error(e)
                 dialog = DBDialog()
                 prev_db_data = self.get_db_connection_details()
                 dialog.ui.user_line_edit.setText(prev_db_data["user"])
@@ -47,12 +64,13 @@ class ArtNetManager:
                 if len(db_data.keys()) == 0:
                     return
                 self.change_db_connection(host=db_data["host"], port=db_data["port"],
-                                                 user=db_data["user"], password=db_data["password"],
-                                                 database=db_data["database"])
+                                          user=db_data["user"], password=db_data["password"],
+                                          database=db_data["database"])
         self.window = Window(self)
 
-        if len(self.config.data["file_root"]) == 0 or not os.path.isdir(self.config.data["file_root"]):  # no file_root given by config or invalid
-            print("Querying for new file root due to lack of valid one ...")
+        if len(self.config.data["file_root"]) == 0 or not os.path.isdir(
+                self.config.data["file_root"]):  # no file_root given by config or invalid
+            logging.info("Querying for new file root due to lack of valid one ...")
             self.window.on_artnet_root_change_clicked()
         self.__file_reader = FileReader(self.config.data["file_root"])
 
@@ -71,7 +89,9 @@ class ArtNetManager:
 
         self.window.show()
 
-        sys.exit(self.__app.exec_())
+        status = self.__app.exec_()
+        logging.info(f"Shutting client down with status: {status}")
+        sys.exit(status)
 
     def update_all_images_list(self):
         """
@@ -93,7 +113,7 @@ class ArtNetManager:
 
         self.window.ui.imageNumberSpinBox.setMaximum(len(self.all_images))
 
-    def scrape_tags(self, file_name: str, art_ID: int, url: str=None):
+    def scrape_tags(self, file_name: str, art_ID: int, url: str = None):
         """
         Scrape the tags from the given url and return which one's are new
         :param file_name:
@@ -204,28 +224,26 @@ class ArtNetManager:
         full_art_path = self.get_root() + os.path.sep + path
 
         if delete_instead_of_move:
-            print(f"Deleting the actual file {full_art_path} is disabled for now")
-            #os.remove(full_art_path)
-            #return
+            logging.warning(f"Deleting the actual file {full_art_path} is disabled for now")
+            # os.remove(full_art_path)
+            # return
 
         trash_dst = trash_bin_folder_path + os.path.sep + path
         t_splits = trash_dst.split(os.path.sep)
         t_path = ""
-        for i in range(len(t_splits)-1):
+        for i in range(len(t_splits) - 1):
             t_path += os.path.sep + t_splits[i]
         t_path = t_path[1:]
         if not os.path.exists(t_path):
-            print(f"{t_path} did not exist and will be created!")
-            os.makedirs("."+os.path.sep+t_path)
-        print(f"Moving image {full_art_path} to {trash_dst}")
+            logging.info(f"{t_path} did not exist and will be created!")
+            os.makedirs("." + os.path.sep + t_path)
+        logging.info(f"Moving image {full_art_path} to {trash_dst}")
         shutil.move(full_art_path, trash_dst)
 
         self.update_all_images_list()
         while self.curr_image_index >= len(self.all_images):
             self.curr_image_index -= 1
 
-
-
     @DeprecationWarning
     def recalculate_hash_for_known_images(self):
         """
@@ -335,7 +353,7 @@ class ArtNetManager:
         image_db_result = self.db_connection.get_art_by_hash(
             self.get_md5_of_image(self.all_images[self.curr_image_index])
         )
-        #image_db_result = self.db_connection.get_art_by_path(self.all_images[self.curr_image_index])
+        # image_db_result = self.db_connection.get_art_by_path(self.all_images[self.curr_image_index])
         s = self.all_images[self.curr_image_index].split(os.path.sep)
         if image_db_result is not None:
             image_title = image_db_result["title"] if isinstance(image_db_result["title"], str) and \
@@ -353,18 +371,19 @@ class ArtNetManager:
             image_link = "(Unknown)"
             image_description = None
 
-        print(f"Displaying #{self.curr_image_index} \"{self.all_images[self.curr_image_index]}\"")
+        logging.info(f"Displaying #{self.curr_image_index} \"{self.all_images[self.curr_image_index]}\"")
         self.window.display_image(image_title, image_author,
                                   os.path.join(self.config.data["file_root"], self.all_images[self.curr_image_index]),
                                   self.all_images[self.curr_image_index],
                                   art_ID, image_link, file_name=s[-1], description=image_description)
-        self.window.set_tag_list([self.db_connection.get_tag_by_ID(x)[0][1].strip() for x in self.db_connection.get_art_tags_by_ID(art_ID)])
+        self.window.set_tag_list(
+            [self.db_connection.get_tag_by_ID(x)[0][1].strip() for x in self.db_connection.get_art_tags_by_ID(art_ID)])
 
         self.window.data_changed = False
         self.window.setting_up_data = False
 
     def create_db_connection(self, host: str, port: int, database: str, user: str, password: str) -> DBAdapter:
-        print(f"Changing db connection to {host}:{port} {user}@{database} ...")
+        logging.info(f"Changing db connection to {host}:{port} {user}@{database} ...")
         return DBAdapter(user=user, password=password, host=host, port=port, database=database)
 
     def get_root(self) -> str:
@@ -380,7 +399,7 @@ class ArtNetManager:
         """
         if len(path) == 0:
             exit(0)
-        print("Changing root to", path)
+        logging.info("Changing root to", path)
         self.config.data["file_root"] = path
         self.config.update_config()
         self.__file_reader = FileReader(self.config.data["file_root"])
@@ -400,5 +419,3 @@ class ArtNetManager:
         self.config.update_config()
 
         self.db_connection = self.create_db_connection(host, port, database, user, password)
-
-
diff --git a/ArtNet/db/db_adapter.py b/ArtNet/db/db_adapter.py
index b430bab..19f0d2b 100644
--- a/ArtNet/db/db_adapter.py
+++ b/ArtNet/db/db_adapter.py
@@ -1,3 +1,4 @@
+import logging
 import psycopg2
 from psycopg2.errorcodes import UNIQUE_VIOLATION
 
@@ -17,9 +18,10 @@ class DBAdapter:
 
         except psycopg2.OperationalError as e:
             raise ValueError("Invalid DB credentials!")
-        print("DB connection established to {0}:{1}/{2}".format(host, port, database))
+        logging.debug("DB connection established to {0}:{1}/{2}".format(host, port, database))
 
         if not self.check_tables():
+            logging.debug("Database schema check has failed! The expected tables have not been present.")
             raise ValueError("Invalid DB schema!")
 
     def check_tables(self) -> bool:
@@ -39,11 +41,11 @@ class DBAdapter:
                 missing.remove(table)
 
         if len(missing) > 0:
-            print("The following tables are missing from the currently connected database: {0}".format(missing))
+            logging.error("The following tables are missing from the currently connected database: {0}".format(missing))
             return False
 
         if len(unknown_tables) > 0:
-            print("The following tables are unknown and not expected inside the database: {0}".format(unknown_tables))
+            logging.error("The following tables are unknown and not expected inside the database: {0}".format(unknown_tables))
 
         return True
 
@@ -60,7 +62,7 @@ class DBAdapter:
         :param desc: image description or None for empty
         :return:
         """
-        print("Saving Image {0}:{1} authors: {2} path: {3} tags: {4} link: {5} hash:{6} desc:{7}"
+        logging.debug("Saving Image {0}:{1} authors: {2} path: {3} tags: {4} link: {5} hash:{6} desc:{7}"
               .format(ID, title, authors, path, tags, link, md5_hash, desc))
         d = {"title": title, "path": path, "id": ID, "link": link, "hash": md5_hash, "desc": desc}
         if self.get_art_by_path(path) is None:
@@ -92,8 +94,8 @@ class DBAdapter:
                 self.db_cursor.execute("INSERT INTO art_tag (art_id, tag_ID) VALUES (%(id)s, %(tag)s)", d)
             except psycopg2.Error as e:
                 if e.pgcode == UNIQUE_VIOLATION:
-                    print(e)
-                    print("Skipping Unique Violation ...")
+                    logging.debug(e)
+                    logging.info("Skipping Unique Violation ...")
                 else:
                     raise e
 
@@ -125,7 +127,7 @@ class DBAdapter:
         """
         image_data = self.get_art_by_hash(hash)
         art_ID = image_data["ID"]
-        print(f"Deleting image #{art_ID} {image_data['title']}")
+        logging.debug(f"Deleting image #{art_ID} {image_data['title']}")
         tags = self.get_art_tags_by_ID(art_ID)
         for tag_ID in tags:
             pass
@@ -174,7 +176,7 @@ class DBAdapter:
         :param link:
         :return:
         """
-        print("Saving Presence {0}:{1} Artist: {2} Link: {3}".format(name, domain, artist_ID, link))
+        logging.debug("Saving Presence {0}:{1} Artist: {2} Link: {3}".format(name, domain, artist_ID, link))
         artist = self.get_artist(artist_ID)
         if artist is None or len(artist) == 0:
             raise Exception("Unknown Artist to create/update Presence with!")
@@ -195,7 +197,7 @@ class DBAdapter:
         Remove a presence from the database
         :return:
         """
-        print("Removing Presence {0}:{1}".format(name, domain))
+        logging.debug("Removing Presence {0}:{1}".format(name, domain))
         d = {"name": name, "domain": domain}
         self.db_cursor.execute("DELETE FROM presence WHERE name = %(name)s and domain = %(domain)s", d)
         self.db.commit()
@@ -226,7 +228,7 @@ class DBAdapter:
         :param name:
         :return:
         """
-        print("Saving artist {0}:{1}".format(ID, name))
+        logging.debug("Saving artist {0}:{1}".format(ID, name))
         d = {"id": ID, "name": name}
         if ID is None:  # no ID given, auto generate it
             self.db_cursor.execute("INSERT INTO artist (name) VALUES (%(name)s)", d)
@@ -242,7 +244,7 @@ class DBAdapter:
         :param ID:
         :return:
         """
-        print("Deleting artist {0}".format(ID))
+        logging.debug("Deleting artist {0}".format(ID))
         d = {"id": ID}
         self.db_cursor.execute("DELETE FROM Artist WHERE ID = %(id)s", d)
         self.db.commit()
@@ -255,7 +257,7 @@ class DBAdapter:
         :param name:
         :return:
         """
-        print("Saving category {0}!".format(name))
+        logging.debug("Saving category {0}!".format(name))
         d = {"name": name}
         self.db_cursor.execute("INSERT INTO tag_category (name) VALUES (%(name)s)", d)
 
diff --git a/ArtNet/file/file_reader.py b/ArtNet/file/file_reader.py
index 93e5ef9..61a1185 100644
--- a/ArtNet/file/file_reader.py
+++ b/ArtNet/file/file_reader.py
@@ -37,9 +37,3 @@ class FileReader:
                 dirs.append(os.path.join(curr_dir, d))
 
         return l
-
-
-if __name__ == "__main__":
-    fr = FileReader("/home/peery/Software_Projects/ArtNet/App/Fake_Other_Artists")
-    print(fr.list_artists())
-    print(fr.get_files("AkuDrache"))
diff --git a/ArtNet/gui/picture_importer.py b/ArtNet/gui/picture_importer.py
index 55c1ab7..05e21f6 100644
--- a/ArtNet/gui/picture_importer.py
+++ b/ArtNet/gui/picture_importer.py
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
 class Ui_MainWindow(object):
     def setupUi(self, MainWindow):
         MainWindow.setObjectName("MainWindow")
-        MainWindow.resize(1239, 824)
+        MainWindow.resize(1140, 849)
         self.centralwidget = QtWidgets.QWidget(MainWindow)
         self.centralwidget.setEnabled(True)
         self.centralwidget.setObjectName("centralwidget")
@@ -173,13 +173,13 @@ class Ui_MainWindow(object):
         self.tag_layout = QtWidgets.QVBoxLayout()
         self.tag_layout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
         self.tag_layout.setObjectName("tag_layout")
-        self.label = QtWidgets.QLabel(self.right_frame)
+        self.search_tags_label = QtWidgets.QLabel(self.right_frame)
         font = QtGui.QFont()
         font.setBold(True)
         font.setWeight(75)
-        self.label.setFont(font)
-        self.label.setObjectName("label")
-        self.tag_layout.addWidget(self.label)
+        self.search_tags_label.setFont(font)
+        self.search_tags_label.setObjectName("search_tags_label")
+        self.tag_layout.addWidget(self.search_tags_label)
         self.tag_list_layout = QtWidgets.QVBoxLayout()
         self.tag_list_layout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
         self.tag_list_layout.setObjectName("tag_list_layout")
@@ -197,13 +197,13 @@ class Ui_MainWindow(object):
         self.search_result_list.setMaximumSize(QtCore.QSize(400, 16777215))
         self.search_result_list.setObjectName("search_result_list")
         self.tag_list_layout.addWidget(self.search_result_list)
-        self.label_2 = QtWidgets.QLabel(self.right_frame)
+        self.selected_tags_label = QtWidgets.QLabel(self.right_frame)
         font = QtGui.QFont()
         font.setBold(True)
         font.setWeight(75)
-        self.label_2.setFont(font)
-        self.label_2.setObjectName("label_2")
-        self.tag_list_layout.addWidget(self.label_2)
+        self.selected_tags_label.setFont(font)
+        self.selected_tags_label.setObjectName("selected_tags_label")
+        self.tag_list_layout.addWidget(self.selected_tags_label)
         self.tag_list = QtWidgets.QListView(self.right_frame)
         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
         sizePolicy.setHorizontalStretch(0)
@@ -214,14 +214,14 @@ class Ui_MainWindow(object):
         self.tag_list.setMaximumSize(QtCore.QSize(400, 16777215))
         self.tag_list.setObjectName("tag_list")
         self.tag_list_layout.addWidget(self.tag_list)
-        self.label_3 = QtWidgets.QLabel(self.right_frame)
+        self.implied_tags_list = QtWidgets.QLabel(self.right_frame)
         font = QtGui.QFont()
         font.setPointSize(9)
         font.setBold(True)
         font.setWeight(75)
-        self.label_3.setFont(font)
-        self.label_3.setObjectName("label_3")
-        self.tag_list_layout.addWidget(self.label_3)
+        self.implied_tags_list.setFont(font)
+        self.implied_tags_list.setObjectName("implied_tags_list")
+        self.tag_list_layout.addWidget(self.implied_tags_list)
         self.implied_tag_list = QtWidgets.QListView(self.right_frame)
         self.implied_tag_list.setMinimumSize(QtCore.QSize(100, 0))
         self.implied_tag_list.setMaximumSize(QtCore.QSize(400, 16777215))
@@ -263,13 +263,21 @@ class Ui_MainWindow(object):
         self.tag_button_layout.addItem(spacerItem)
         self.tag_layout.addLayout(self.tag_button_layout)
         self.horizontalLayout_3.addLayout(self.tag_layout)
+        self.topic_docker_button = QtWidgets.QToolButton(self.right_frame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.topic_docker_button.sizePolicy().hasHeightForWidth())
+        self.topic_docker_button.setSizePolicy(sizePolicy)
+        self.topic_docker_button.setObjectName("topic_docker_button")
+        self.horizontalLayout_3.addWidget(self.topic_docker_button)
         self.horizontalLayout.addWidget(self.right_frame)
         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, 1239, 30))
+        self.menuBar.setGeometry(QtCore.QRect(0, 0, 1140, 34))
         self.menuBar.setObjectName("menuBar")
         self.menuArtNet = QtWidgets.QMenu(self.menuBar)
         self.menuArtNet.setObjectName("menuArtNet")
@@ -324,14 +332,15 @@ class Ui_MainWindow(object):
         self.source_link_label.setText(_translate("MainWindow", "Link:"))
         self.description_label.setText(_translate("MainWindow", "Description:"))
         self.next_image_button.setText(_translate("MainWindow", ">"))
-        self.label.setText(_translate("MainWindow", "Search Tags"))
-        self.label_2.setText(_translate("MainWindow", "Selected Tags:"))
-        self.label_3.setText(_translate("MainWindow", "Implied Tags:"))
+        self.search_tags_label.setText(_translate("MainWindow", "Search Tags"))
+        self.selected_tags_label.setText(_translate("MainWindow", "Selected Tags:"))
+        self.implied_tags_list.setText(_translate("MainWindow", "Implied Tags:"))
         self.save_button.setText(_translate("MainWindow", "Save"))
         self.import_button.setText(_translate("MainWindow", "Import Tags"))
         self.prev_unknown_image_button.setText(_translate("MainWindow", "prev Unknown"))
         self.next_unknown_image_button.setText(_translate("MainWindow", "next Unknown"))
         self.delete_button.setText(_translate("MainWindow", "Delete"))
+        self.topic_docker_button.setText(_translate("MainWindow", ">"))
         self.menuArtNet.setTitle(_translate("MainWindow", "ArtNet"))
         self.menuTags.setTitle(_translate("MainWindow", "Tags"))
         self.menuCategory.setTitle(_translate("MainWindow", "Category"))
diff --git a/ArtNet/gui/picture_importer.ui b/ArtNet/gui/picture_importer.ui
index 7e7f3f3..43b5204 100644
--- a/ArtNet/gui/picture_importer.ui
+++ b/ArtNet/gui/picture_importer.ui
@@ -6,8 +6,8 @@
    
     0
     0
-    1239
-    824
+    1140
+    849
    
   
   
@@ -282,7 +282,7 @@
           QLayout::SetMinimumSize
          
          - 
-          
+          
            
             
              75
@@ -332,7 +332,7 @@
             
            
 
            - 
-            
+            
              
               
                75
@@ -367,7 +367,7 @@
             
            
 
            - 
-            
+            
              
               
                9
@@ -482,6 +482,19 @@
          
 
         
        
+       - 
+        
+         
+          
+           0
+           0
+          
+         
+         
+          >
+         
+        
+       
 
       
      
     
@@ -493,8 +506,8 @@
     
      0
      0
-     1239
-     30
+     1140
+     34