Difference between revisions of "Avdump GUI"

From AniDB
Jump to navigation Jump to search
 
(28 intermediate revisions by the same user not shown)
Line 13: Line 13:
 
==Changelog==
 
==Changelog==
 
<pre>
 
<pre>
  v2.00 - 03.06.2011
+
  v2.42 - 08.01.2019 *available as auto update*
  Avdump2 Build 4260 added
+
  * Avdump2 Build 7080 added
rewrote the whole lot and simplified it
 
  
  v1.07 - 06.04.2008
+
  v2.41 - 05.01.2019 *available as auto update*
  Avdump 0.34 added
+
  * show error message about too long paths
fixed a bug with the bufferfield not allowing 16 buffer while that being the default
+
  * fallback to cp437 in case shell encoding fails which i guess should work?
  made option o default when no profile exists
 
  
  v1.06 - 12.02.2008
+
  v2.40 - 03.01.2019 *available as auto update*
  Avdump 0.33 added
+
  * Avdump2 Build 7070 added
 +
* show errors in filelist if we encounter one while processing a file instead of endless retrying
  
  v1.05 - 13.11.2007
+
  v2.33 - 09.11.2016 *available as auto update*
  thx to rar for fixing dumping of files with characters in non local codepage
+
  * new icon
 +
* progressbar and status not updating
  
  v1.04 - 10.11.2007
+
  v2.32 - 09.11.2016 *available as auto update*
  fix for not being able to dump files with Japanese characters in the filename
+
  * options not being stored on initial start
Avdump 0.32 added and changes implemented
 
  
  v1.03 - 13.05.2007
+
  v2.31 - 09.11.2016 *available as auto update*
  added the console again
+
  * fixed drag and drop
fix for log, export and done paths with spaces
 
added parents for the dialogues so they die with the program and can't stay open any more
 
option 9 added (experimental mp3 hashing for ostdb)
 
 
v1.02 - 13.05.2007
 
added error and warning dialogue boxes to prevent a couple problems
 
added some exception handling for a few fields
 
 
v1.01 - 12.05.2007
 
killed a nasty bug with trailing \ in the scanpath
 
 
v1.00 - 12.05.2007
 
Initial release
 
</pre>
 
  
==Source==
+
v2.30 - 03.11.2016 *available as auto update*
This GUI was coded purely in python using pyqt for the framework.
+
* ported from python 2.7 to 3.4
 +
* path/filename encoding woes fixed(?)
 +
* export option removed and made implicit to be always enabled
  
===avdump2gui.pyw===
+
v2.20 - 18.08.2015 *available as auto update*
<pre style="font-size: 60%;">
+
  * Avdump2 Build 6714 added
import sys, os, platform, subprocessw, ConfigParser, string, unicodedata
+
* dependencies updated
  
from time import time
+
v2.19 - 11.11.2012 *available as msi installer & auto update*
 +
* Avdump2 Build 6525 added
 +
* recompiled with updated dependencies which may or may not fix some issues or cause new ones
  
# Import Qt modules
+
v2.18 - 31.07.2012 *available as auto update*
from PyQt4 import QtCore, QtGui
+
* Avdump2 Build 5290 added
  
# Import the compiled UI module
+
v2.17 - 21.09.2011 *available as auto update*
from gui import Ui_MainWindow
+
* filename encoding issue fixed
  
# Create a class for our main window
+
v2.15 - 13.09.2011
class Main(QtGui.QMainWindow):
+
* Avdump2 Build 5028 added
    def __init__(self):
+
* text fix (Optionen instead of Options. watch out for da evil germanz ja)
        QtGui.QMainWindow.__init__(self)
+
* can now drop files into the table to process
        self._ui = Ui_MainWindow()
+
* speed improvement when adding lots of files at once (really only noticeable > 500)
        self._ui.setupUi(self)
+
* potentially fixing some issue with the last filehash not being shown in the export box
        self._filelist = {}
 
        self._paths = {}
 
        self._done_files = []
 
        self._worker = None
 
        self._export_filename = 'exports/export_' + str(int(time())) + '.txt'
 
        self._allowed_extensions = ('avi', 'mpg', 'mpeg', 'ts', 'm2ts', 'rm', 'rmvb', 'asf', 'wmv', 'mov', 'qt', 'ogm',
 
                                  'mp4', 'mkv', 'swf', 'flv', 'ogv', 'webm', 'mk3d', 'srt', 'sub', 'ssa', 'smi', 'idx', 'ass',
 
                                  'txt', 'mks', 'lrc', 'rt', 'tmp', 'js', 'pjs', 'tts', 'xss', 'mp3', 'aac', 'ac3', 'dts', 'wav',
 
                                  'flac', 'wma', 'mka', 'ra', 'ogg', 'm4a', 'dtshd', 'thd', 'rar', 'zip', 'ace', '7z', 'smil')
 
  
        tmp = []
+
v2.14 - 11.09.2011
        for ext in self._allowed_extensions:
+
* Avdump2 Build 5000 added
            tmp.append('*.' + ext)
 
  
        self._allowed_extensions_str = "; ".join(tmp)
+
v2.13 - 06.09.2011
 +
* Avdump2 Build 4991 added
 +
* fixes to be compatible to the new Avdump2 CLI
  
        self._ui.datatable.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+
v2.12 - 05.09.2011 *pulled*
        self._ui.datatable.setColumnWidth(0, 90)
+
* Avdump2 Build 4964 added
        self._ui.datatable.setColumnWidth(1, 250)
 
        self._ui.datatable.setColumnWidth(2, 40)
 
  
        self.connect(self._ui.files_button, QtCore.SIGNAL("clicked()"), self._slotFile)
+
v2.11 - 01.07.2011
        self.connect(self._ui.folder_button, QtCore.SIGNAL("clicked()"), self._slotFolder)
+
* trying to scan files without having provided a username/password -> BOOM (trying to kill the subprocess without it running)
        self.connect(self._ui.start_button, QtCore.SIGNAL("clicked()"), self._run)
+
* removing already scanned files form the list and readding them will process them again even if "done" is set
        self.connect(self._ui.stop_button, QtCore.SIGNAL("clicked()"), self._stop)
+
  (from frontend at least. avdump itself would ignore them. this would leave a couple "new" entries in the list)
        self.connect(QtGui.QAction(self), QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
 
  
        self._enable_elements()
+
v2.10 - 01.07.2011
        self._read_config()
+
* Avdump2 Build 4334 added
        self._read_done()
+
* Autoupdater implemented
 +
* last scanned dir stored in config
 +
* window size stored in config (unless it's maximized)
 +
* use stderr to catch errors instead of stdout
 +
* lots of rewriting
  
#################################################
+
v2.02 - 09.06.2011
#                                              #
+
* Avdump2 Build 4320 added
#                GUI FUNCTIONS                #
+
* ditched subprocess module in favour of qprocess
#                                              #
+
* peek into console output and notice the user when an error happened (outdated version or wrong password/username)
#################################################
 
  
    def _disable_elements(self):
+
v2.01 - 06.06.2011
        self._ui.username.setDisabled(True)
+
* various nasty bugs removed
        self._ui.apikey.setDisabled(True)
+
* windows can be enlarged on demand
        self._ui.files_button.setDisabled(True)
 
        self._ui.folder_button.setDisabled(True)
 
        self._ui.done.setDisabled(True)
 
        self._ui.exp.setDisabled(True)
 
        self._ui.start_button.setDisabled(True)
 
        self._ui.stop_button.setEnabled(True)
 
  
    def _enable_elements(self):
+
v2.00 - 03.06.2011
        self._ui.username.setEnabled(True)
+
* Avdump2 Build 4260 added
        self._ui.apikey.setEnabled(True)
+
* rewrote the whole lot and simplified it
        self._ui.files_button.setEnabled(True)
 
        self._ui.folder_button.setEnabled(True)
 
        self._ui.done.setEnabled(True)
 
        self._ui.exp.setEnabled(True)
 
        self._ui.start_button.setEnabled(True)
 
        self._ui.stop_button.setDisabled(True)
 
  
    def _output_export(self):
+
v1.07 - 06.04.2008
        self._ui.ed2k_export.setText("".join(file(self._export_filename).readlines()))
+
* Avdump 0.34 added
 +
* fixed a bug with the bufferfield not allowing 16 buffer while that being the default
 +
* made option o default when no profile exists
  
    def _calculate_progress(self):
+
v1.06 - 12.02.2008
        if self._ui.datatable.rowCount() == 0:
+
* Avdump 0.33 added
            return 0
 
  
        done = 0
+
v1.05 - 13.11.2007
        for i in range(self._ui.datatable.rowCount()):
+
* thx to rar for fixing dumping of files with characters in non local codepage
            if unicode(self._ui.datatable.item(i,2).text()) == 'done':
 
                done += 1
 
  
        return done*100/self._ui.datatable.rowCount()
+
v1.04 - 10.11.2007
 +
* fix for not being able to dump files with Japanese characters in the filename
 +
* Avdump 0.32 added and changes implemented
  
#################################################
+
v1.03 - 13.05.2007
#                                              #
+
* added the console again
#                EVENT HANDLER                #
+
* fix for log, export and done paths with spaces
#                                              #
+
* added parents for the dialogues so they die with the program and can't stay open any more
#################################################
+
* option 9 added (experimental mp3 hashing for ostdb)
    def _closeEvent(self,event):
+
        self._stop()
+
v1.02 - 13.05.2007
        self._write_config()
+
  * added error and warning dialogue boxes to prevent a couple problems
        event.accept()
+
* added some exception handling for a few fields
 
+
    def _done(self, path):
+
  v1.01 - 12.05.2007
        i = self._paths[path]
+
  * killed a nasty bug with trailing \ in the scanpath
        item = QtGui.QTableWidgetItem('done')
+
        self._ui.datatable.setItem(i, 2, item)
+
v1.00 - 12.05.2007
        if self._ui.exp.isChecked():
+
  * Initial release
            self._output_export()
 
        self._ui.progressBar.setValue(self._calculate_progress())
 
 
 
    def _finished(self):
 
        self._paths = {}
 
        self._ui.progressBar.setValue(self._calculate_progress())
 
        self._worker = None
 
        self._enable_elements()
 
        if self._ui.exp.isChecked():
 
            self._output_export()
 
 
 
    def _stop(self):
 
        if self._worker is not None:
 
            self._worker.stop()
 
            self._output_export()
 
            self._enable_elements()
 
 
 
    def _slotFile(self):
 
        files = QtGui.QFileDialog.getOpenFileNames(self, 'File select', os.getcwd(), self._allowed_extensions_str)
 
        for path in files:
 
            self._add_file(unicode(path))
 
 
 
    def _slotFolder(self):
 
        path = unicode(QtGui.QFileDialog.getExistingDirectory(self, "Select Directory"))
 
        if path != '':
 
            for root, dir, files in os.walk(path):
 
                for filename in files:
 
                    self._add_file(os.path.join(root, filename))
 
 
 
    def _add_file(self, fileloc):
 
        if len(fileloc) == 0:
 
            return
 
        elif unicodedata.normalize('NFKC', fileloc) in self._done_files:
 
            return
 
 
 
        no = self._ui.datatable.rowCount()
 
 
 
        if platform.system().lower() == 'windows':
 
            fileloc = fileloc.replace("/", "\\")
 
            filepath, filename = fileloc.rsplit("\\", 1)
 
        else:
 
            filepath, filename = fileloc.rsplit("/", 1)
 
 
 
        tmp, ext = filename.rsplit('.', 1)
 
        if ext not in self._allowed_extensions:
 
            return
 
 
 
        if fileloc not in self._filelist.keys():
 
            self._filelist[fileloc] = 1
 
            self._ui.datatable.insertRow(no)
 
 
 
            item = QtGui.QTableWidgetItem(filepath)
 
            self._ui.datatable.setItem(no, 0, item)
 
 
 
            item = QtGui.QTableWidgetItem(filename)
 
            self._ui.datatable.setItem(no, 1, item)
 
 
 
            item = QtGui.QTableWidgetItem('new')
 
            self._ui.datatable.setItem(no, 2, item)
 
            self._ui.progressBar.setValue(self._calculate_progress())
 
 
 
    def _run(self):
 
        username = unicode(self._ui.username.text())
 
        apikey  = unicode(self._ui.apikey.text())
 
 
 
        if self._ui.datatable.rowCount() == 0:
 
            QtGui.QMessageBox.information(self, "Error!", "No files to scan in list.", QtGui.QMessageBox.Ok)
 
            return
 
        elif not os.path.exists('avdump2cl.exe'):
 
            QtGui.QMessageBox.information(self, "Error!", "Avdump2cl.exe not found.", QtGui.QMessageBox.Ok)
 
            return
 
        elif len(username) == 0 or len(apikey) == 0:
 
            QtGui.QMessageBox.information(self, "Error!", "No username and/or api-key specified!", QtGui.QMessageBox.Ok)
 
            return
 
 
 
        paths    = []
 
        for i in range(self._ui.datatable.rowCount()):
 
            if unicode(self._ui.datatable.item(i,2).text()) == 'new':
 
                path = os.path.join(unicode(self._ui.datatable.item(i,0).text()), unicode(self._ui.datatable.item(i,1).text()))
 
                paths.append(path)
 
                self._paths[path] = i
 
 
 
        if len(paths) > 0:
 
            self._ui.progressBar.setValue(self._calculate_progress())
 
            self._disable_elements()
 
            done    = ''
 
            if self._ui.done.isChecked() is True:
 
                done = '-done:done.txt'
 
 
 
            exp      = ''
 
            if self._ui.exp.isChecked() is True:
 
                if not os.path.exists('exports'):
 
                    os.mkdir('exports')
 
                exp = '-exp:' + self._export_filename
 
               
 
            self._worker = avdump_worker(username, apikey, done, exp, paths)
 
            self.connect(self._worker, QtCore.SIGNAL("done"), self._done)
 
            self.connect(self._worker, QtCore.SIGNAL("finished"), self._finished)
 
            self._worker.start()         
 
 
 
#################################################
 
#                                              #
 
#              CONFIG READ/WRITE              #
 
#                                              #
 
#################################################
 
    def _read_config(self):
 
        if os.path.exists('options.ini'):
 
            config = ConfigParser.ConfigParser()
 
            config.read('options.ini')
 
            self._ui.username.setText(config.get('DEFAULT', 'username'))
 
            self._ui.apikey.setText(config.get('DEFAULT', 'apikey'))
 
            if config.get('DEFAULT', 'done') == '1':
 
                self._ui.done.setChecked(True)
 
            else:
 
                self._ui.done.setChecked(False)
 
 
 
            if config.get('DEFAULT', 'exp') == '1':
 
                self._ui.exp.setChecked(True)
 
            else:
 
                self._ui.exp.setChecked(False)
 
 
 
    def _write_config(self):
 
        config = ConfigParser.ConfigParser()
 
        config.set("DEFAULT", "username", str(self._ui.username.text()))
 
        config.set("DEFAULT", "apikey", str(self._ui.apikey.text()))
 
        if self._ui.done.isChecked():
 
            config.set("DEFAULT", "done", 1)
 
        else:
 
            config.set("DEFAULT", "done", 0)
 
        if self._ui.exp.isChecked():
 
            config.set("DEFAULT", "exp", 1)
 
        else:
 
            config.set("DEFAULT", "exp", 0)
 
        config.write(file("options.ini", "w"))
 
 
 
    def _read_done(self):
 
        if os.path.exists("done.txt"):
 
            for line in file("done.txt"):
 
                self._done_files.append(unicodedata.normalize('NFKC', line.decode("utf8").strip()))
 
 
 
class avdump_worker(QtCore.QThread):
 
    def __init__(self, username, apikey, done, exp, paths):
 
        QtCore.QThread.__init__(self, parent=None)
 
        self._username    = username
 
        self._apikey      = apikey
 
        self._done        = done
 
        self._exp        = exp
 
        self._paths      = paths
 
        self._was_stopped = False
 
        self._avdump      = None
 
 
 
    def stop(self):
 
        self._was_stopped = True
 
        self._avdump.terminate()
 
 
 
    def run(self):
 
        for path in self._paths:
 
            if self._was_stopped is True:
 
                break
 
            self._avdump = subprocessw.Popen((u'avdump2cl.exe -ac:%s:%s %s %s "%s"') %(self._username, self._apikey, self._done, self._exp, path))
 
            self._avdump.communicate()
 
            if self._was_stopped is False:
 
                self.emit(QtCore.SIGNAL('done'), path)
 
 
 
        if self._was_stopped is False:
 
            self.emit(QtCore.SIGNAL('finished'))
 
 
 
def main():
 
    app = QtGui.QApplication(sys.argv)
 
    window=Main()
 
    window.show()
 
    sys.exit(app.exec_())
 
 
 
if __name__ == "__main__":
 
    main()
 
</pre>
 
 
 
===gui.py===
 
<pre style="font-size: 60%;">
 
# -*- coding: utf-8 -*-
 
 
 
# Form implementation generated from reading ui file 'C:\Python27\Lib\site-packages\PyQt4\avdump.ui'
 
#
 
# Created: Fri Jun 03 11:19:16 2011
 
#      by: PyQt4 UI code generator 4.8.1
 
#
 
# WARNING! All changes made in this file will be lost!
 
 
 
from PyQt4 import QtCore, QtGui
 
 
 
try:
 
    _fromUtf8 = QtCore.QString.fromUtf8
 
except AttributeError:
 
    _fromUtf8 = lambda s: s
 
 
 
class Ui_MainWindow(object):
 
    def setupUi(self, MainWindow):
 
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
 
        MainWindow.resize(600, 400)
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
 
        MainWindow.setSizePolicy(sizePolicy)
 
        MainWindow.setMinimumSize(QtCore.QSize(600, 400))
 
        MainWindow.setMaximumSize(QtCore.QSize(600, 400))
 
        self.main = QtGui.QWidget(MainWindow)
 
        self.main.setObjectName(_fromUtf8("main"))
 
        self.username_box = QtGui.QGroupBox(self.main)
 
        self.username_box.setGeometry(QtCore.QRect(430, 10, 165, 51))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.username_box.sizePolicy().hasHeightForWidth())
 
        self.username_box.setSizePolicy(sizePolicy)
 
        self.username_box.setObjectName(_fromUtf8("username_box"))
 
        self.username = QtGui.QLineEdit(self.username_box)
 
        self.username.setGeometry(QtCore.QRect(10, 20, 145, 20))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.username.sizePolicy().hasHeightForWidth())
 
        self.username.setSizePolicy(sizePolicy)
 
        self.username.setObjectName(_fromUtf8("username"))
 
        self.api_box = QtGui.QGroupBox(self.main)
 
        self.api_box.setGeometry(QtCore.QRect(430, 60, 165, 51))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.api_box.sizePolicy().hasHeightForWidth())
 
        self.api_box.setSizePolicy(sizePolicy)
 
        self.api_box.setObjectName(_fromUtf8("api_box"))
 
        self.apikey = QtGui.QLineEdit(self.api_box)
 
        self.apikey.setGeometry(QtCore.QRect(10, 20, 145, 20))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.apikey.sizePolicy().hasHeightForWidth())
 
        self.apikey.setSizePolicy(sizePolicy)
 
        self.apikey.setObjectName(_fromUtf8("apikey"))
 
        self.progressBar = QtGui.QProgressBar(self.main)
 
        self.progressBar.setGeometry(QtCore.QRect(5, 230, 421, 23))
 
        self.progressBar.setProperty(_fromUtf8("value"), 0)
 
        self.progressBar.setObjectName(_fromUtf8("progressBar"))
 
        self.start_button = QtGui.QPushButton(self.main)
 
        self.start_button.setGeometry(QtCore.QRect(430, 230, 80, 23))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.start_button.sizePolicy().hasHeightForWidth())
 
        self.start_button.setSizePolicy(sizePolicy)
 
        self.start_button.setObjectName(_fromUtf8("start_button"))
 
        self.options_box = QtGui.QGroupBox(self.main)
 
        self.options_box.setGeometry(QtCore.QRect(430, 110, 165, 61))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.options_box.sizePolicy().hasHeightForWidth())
 
        self.options_box.setSizePolicy(sizePolicy)
 
        self.options_box.setObjectName(_fromUtf8("options_box"))
 
        self.exp = QtGui.QCheckBox(self.options_box)
 
        self.exp.setGeometry(QtCore.QRect(10, 20, 141, 16))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.exp.sizePolicy().hasHeightForWidth())
 
        self.exp.setSizePolicy(sizePolicy)
 
        self.exp.setChecked(True)
 
        self.exp.setObjectName(_fromUtf8("exp"))
 
        self.done = QtGui.QCheckBox(self.options_box)
 
        self.done.setGeometry(QtCore.QRect(10, 40, 141, 16))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.done.sizePolicy().hasHeightForWidth())
 
        self.done.setSizePolicy(sizePolicy)
 
        self.done.setChecked(True)
 
        self.done.setObjectName(_fromUtf8("done"))
 
        self.scapth_box = QtGui.QGroupBox(self.main)
 
        self.scapth_box.setGeometry(QtCore.QRect(430, 170, 165, 51))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.scapth_box.sizePolicy().hasHeightForWidth())
 
        self.scapth_box.setSizePolicy(sizePolicy)
 
        self.scapth_box.setObjectName(_fromUtf8("scapth_box"))
 
        self.files_button = QtGui.QPushButton(self.scapth_box)
 
        self.files_button.setGeometry(QtCore.QRect(10, 20, 72, 23))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.files_button.sizePolicy().hasHeightForWidth())
 
        self.files_button.setSizePolicy(sizePolicy)
 
        self.files_button.setObjectName(_fromUtf8("files_button"))
 
        self.folder_button = QtGui.QPushButton(self.scapth_box)
 
        self.folder_button.setGeometry(QtCore.QRect(85, 20, 72, 23))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.folder_button.sizePolicy().hasHeightForWidth())
 
        self.folder_button.setSizePolicy(sizePolicy)
 
        self.folder_button.setObjectName(_fromUtf8("folder_button"))
 
        self.datatable = QtGui.QTableWidget(self.main)
 
        self.datatable.setGeometry(QtCore.QRect(5, 10, 421, 211))
 
        self.datatable.setObjectName(_fromUtf8("datatable"))
 
        self.datatable.setColumnCount(3)
 
        self.datatable.setRowCount(0)
 
        item = QtGui.QTableWidgetItem()
 
        self.datatable.setHorizontalHeaderItem(0, item)
 
        item = QtGui.QTableWidgetItem()
 
        self.datatable.setHorizontalHeaderItem(1, item)
 
        item = QtGui.QTableWidgetItem()
 
        self.datatable.setHorizontalHeaderItem(2, item)
 
        self.stop_button = QtGui.QPushButton(self.main)
 
        self.stop_button.setGeometry(QtCore.QRect(515, 230, 80, 23))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.stop_button.sizePolicy().hasHeightForWidth())
 
        self.stop_button.setSizePolicy(sizePolicy)
 
        self.stop_button.setObjectName(_fromUtf8("stop_button"))
 
        self.groupBox = QtGui.QGroupBox(self.main)
 
        self.groupBox.setGeometry(QtCore.QRect(5, 259, 591, 135))
 
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
 
        sizePolicy.setHorizontalStretch(0)
 
        sizePolicy.setVerticalStretch(0)
 
        sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
 
        self.groupBox.setSizePolicy(sizePolicy)
 
        self.groupBox.setObjectName(_fromUtf8("groupBox"))
 
        self.ed2k_export = QtGui.QTextBrowser(self.groupBox)
 
        self.ed2k_export.setGeometry(QtCore.QRect(7, 17, 577, 111))
 
        self.ed2k_export.setObjectName(_fromUtf8("ed2k_export"))
 
        MainWindow.setCentralWidget(self.main)
 
 
 
        self.retranslateUi(MainWindow)
 
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
 
 
 
    def retranslateUi(self, MainWindow):
 
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "Avdump2", None, QtGui.QApplication.UnicodeUTF8))
 
        self.username_box.setTitle(QtGui.QApplication.translate("MainWindow", "Username", None, QtGui.QApplication.UnicodeUTF8))
 
        self.api_box.setTitle(QtGui.QApplication.translate("MainWindow", "Api-key", None, QtGui.QApplication.UnicodeUTF8))
 
        self.start_button.setText(QtGui.QApplication.translate("MainWindow", "Start", None, QtGui.QApplication.UnicodeUTF8))
 
        self.options_box.setTitle(QtGui.QApplication.translate("MainWindow", "Optionen", None, QtGui.QApplication.UnicodeUTF8))
 
        self.exp.setText(QtGui.QApplication.translate("MainWindow", "export ed2k links", None, QtGui.QApplication.UnicodeUTF8))
 
        self.done.setText(QtGui.QApplication.translate("MainWindow", "ignore already scanned", None, QtGui.QApplication.UnicodeUTF8))
 
        self.scapth_box.setTitle(QtGui.QApplication.translate("MainWindow", "Files/Folder to process", None, QtGui.QApplication.UnicodeUTF8))
 
        self.files_button.setText(QtGui.QApplication.translate("MainWindow", "Files", None, QtGui.QApplication.UnicodeUTF8))
 
        self.folder_button.setText(QtGui.QApplication.translate("MainWindow", "Folder", None, QtGui.QApplication.UnicodeUTF8))
 
        self.datatable.horizontalHeaderItem(0).setText(QtGui.QApplication.translate("MainWindow", "path", None, QtGui.QApplication.UnicodeUTF8))
 
        self.datatable.horizontalHeaderItem(1).setText(QtGui.QApplication.translate("MainWindow", "filename", None, QtGui.QApplication.UnicodeUTF8))
 
        self.datatable.horizontalHeaderItem(2).setText(QtGui.QApplication.translate("MainWindow", "status", None, QtGui.QApplication.UnicodeUTF8))
 
        self.stop_button.setText(QtGui.QApplication.translate("MainWindow", "Stop", None, QtGui.QApplication.UnicodeUTF8))
 
        self.groupBox.setTitle(QtGui.QApplication.translate("MainWindow", "ED2k-Export", None, QtGui.QApplication.UnicodeUTF8))
 
</pre>
 
 
 
===Wrapper module for subprocess by rar===
 
<pre style="font-size: 60%;">
 
import subprocess
 
from subprocess import call, PIPE, STDOUT, list2cmdline, mswindows
 
import ctypes
 
import ctypes.wintypes
 
CreateProcessW = ctypes.windll.kernel32.CreateProcessW
 
CloseHandle = ctypes.windll.kernel32.CloseHandle
 
 
 
__all__ = ["Popen", "PIPE", "STDOUT", "call"]
 
 
 
class STARTUPINFOW(ctypes.Structure):
 
_fields_ = (("cb", ctypes.wintypes.DWORD), # should init to 17*4 maybe?
 
("lpReserved", ctypes.wintypes.LPWSTR),
 
("lpDesktop", ctypes.wintypes.LPWSTR),
 
("lpTitle", ctypes.wintypes.LPWSTR),
 
("dwX", ctypes.wintypes.DWORD),
 
("dwY", ctypes.wintypes.DWORD),
 
("dwXSize", ctypes.wintypes.DWORD),
 
("dwYSize", ctypes.wintypes.DWORD),
 
("dwXCountChars", ctypes.wintypes.DWORD),
 
("dwYCountChars", ctypes.wintypes.DWORD),
 
("dwFillAttribute", ctypes.wintypes.DWORD),
 
("dwFlags", ctypes.wintypes.DWORD),
 
("wShowWindow", ctypes.wintypes.WORD),
 
("cbReserved2", ctypes.wintypes.WORD),
 
("lpReserved2", ctypes.wintypes.LPSTR), # actually LPBYTE
 
("hStdInput", ctypes.wintypes.HANDLE),
 
("hStdOutput", ctypes.wintypes.HANDLE),
 
("hStdError", ctypes.wintypes.HANDLE))
 
 
 
class PROCESS_INFORMATION(ctypes.Structure):
 
_fields_ = (("hProcess", ctypes.wintypes.HANDLE),
 
("hThread", ctypes.wintypes.HANDLE),
 
("dwProcessId", ctypes.wintypes.DWORD),
 
("dwThreadId", ctypes.wintypes.DWORD))
 
 
 
if mswindows:
 
class Popen(subprocess.Popen):
 
def _execute_child(self, args, executable, preexec_fn, close_fds,
 
cwd, env, universal_newlines,
 
startupinfo, creationflags, shell,
 
p2cread, p2cwrite,
 
c2pread, c2pwrite,
 
errread, errwrite):
 
 
 
if not isinstance(args, basestring):
 
args = list2cmdline(args)
 
 
if not isinstance(args, unicode):
 
subprocess.Popen._execute_child(self, args, executable,
 
preexec_fn, close_fds, cwd, env, universal_newlines,
 
startupinfo, creationflags, shell, p2cread, p2cwrite,
 
c2pread, c2pwrite, errread, errwrite)
 
return
 
 
 
if startupinfo == None:
 
startupinfo = STARTUPINFOW()
 
startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
 
startupinfo.wShowWindow = subprocess._subprocess.SW_HIDE
 
else:
 
raise NotImplementedError("Can't pass startup stuff")
 
 
if not None in (p2cread, c2pwrite, errwrite):
 
raise NotImplementedError("Can't pass file object bits")
 
 
 
if shell:
 
raise NotImplementedError("Can't pick your own shell for unicode args")
 
 
margs = ctypes.create_unicode_buffer(args)
 
processinfo = PROCESS_INFORMATION()
 
 
 
CreateProcessW(executable, margs,
 
None, None,
 
1,
 
creationflags,
 
env, cwd,
 
ctypes.byref(startupinfo), ctypes.byref(processinfo))
 
 
hp, ht, pid, tid = (processinfo.hProcess, processinfo.hThread,
 
processinfo.dwProcessId, processinfo.dwThreadId)
 
 
# can't wrap this as a _subprocess_handle so scuppered, need sp_handle_new()
 
self._handle = hp
 
self.pid = pid
 
CloseHandle(ht) # ht.Close()
 
else:
 
Popen = subprocess.Popen
 
 
</pre>
 
</pre>
  
 +
[[Category:Features]]
 +
[[Category:AniDB Clients]]
 
[[Category:Avdump]]
 
[[Category:Avdump]]
 +
[[Category:Development]]

Latest revision as of 15:02, 27 September 2019

Introduction

Note You have to set an API key in your profile before auto-creqing with Avdump GUI.

A simple GUI for Avdump2 is available for CLI skeptics. The GUI package includes the most recent version of Avdump2 as well.

Screenshot of the AVDump2 GUI

Usage

  1. Download the GUI here (portable).
  2. Set your AniDB user name and API password in the options menu.
    1. API password is set on your user settings page: http://anidb.net/perl-bin/animedb.pl?show=profile
    2. Under the "Account" tab, create a UDP API key; it can be anything you want. It is used for Avdump2 to connect to AniDB.
  3. Save the options.
  4. Select what you want to scan from the main menu; files or folders.
  5. Select the stuff you want to scan (... Button) (you can select multiple files at once).
  6. Click Start.

For further Assistance join IRC:anidb and bug Der Idiot.

For Vista and Windows 7 permission issues on installation:

  • Create a blank .bat file.
  • Insert this text into it and modify it to your situation:
    "C:\Windows\System32\msiExec.exe" -i "C:\Directory\Where\Located\avdump-gui.msi"
  • Right click and run the .bat file as administrator.

Changelog

 v2.42 - 08.01.2019 *available as auto update*
 * Avdump2 Build 7080 added

 v2.41 - 05.01.2019 *available as auto update*
 * show error message about too long paths
 * fallback to cp437 in case shell encoding fails which i guess should work?

 v2.40 - 03.01.2019 *available as auto update*
 * Avdump2 Build 7070 added
 * show errors in filelist if we encounter one while processing a file instead of endless retrying

 v2.33 - 09.11.2016 *available as auto update*
 * new icon
 * progressbar and status not updating

 v2.32 - 09.11.2016 *available as auto update*
 * options not being stored on initial start

 v2.31 - 09.11.2016 *available as auto update*
 * fixed drag and drop

 v2.30 - 03.11.2016 *available as auto update*
 * ported from python 2.7 to 3.4
 * path/filename encoding woes fixed(?)
 * export option removed and made implicit to be always enabled

 v2.20 - 18.08.2015 *available as auto update*
 * Avdump2 Build 6714 added
 * dependencies updated

 v2.19 - 11.11.2012 *available as msi installer & auto update*
 * Avdump2 Build 6525 added
 * recompiled with updated dependencies which may or may not fix some issues or cause new ones

 v2.18 - 31.07.2012 *available as auto update*
 * Avdump2 Build 5290 added

 v2.17 - 21.09.2011 *available as auto update*
 * filename encoding issue fixed

 v2.15 - 13.09.2011
 * Avdump2 Build 5028 added
 * text fix (Optionen instead of Options. watch out for da evil germanz ja)
 * can now drop files into the table to process
 * speed improvement when adding lots of files at once (really only noticeable > 500)
 * potentially fixing some issue with the last filehash not being shown in the export box

 v2.14 - 11.09.2011
 * Avdump2 Build 5000 added

 v2.13 - 06.09.2011
 * Avdump2 Build 4991 added
 * fixes to be compatible to the new Avdump2 CLI

 v2.12 - 05.09.2011 *pulled*
 * Avdump2 Build 4964 added

 v2.11 - 01.07.2011
 * trying to scan files without having provided a username/password -> BOOM (trying to kill the subprocess without it running)
 * removing already scanned files form the list and readding them will process them again even if "done" is set
   (from frontend at least. avdump itself would ignore them. this would leave a couple "new" entries in the list)

 v2.10 - 01.07.2011
 * Avdump2 Build 4334 added
 * Autoupdater implemented
 * last scanned dir stored in config
 * window size stored in config (unless it's maximized)
 * use stderr to catch errors instead of stdout
 * lots of rewriting

 v2.02 - 09.06.2011
 * Avdump2 Build 4320 added
 * ditched subprocess module in favour of qprocess
 * peek into console output and notice the user when an error happened (outdated version or wrong password/username)

 v2.01 - 06.06.2011
 * various nasty bugs removed
 * windows can be enlarged on demand

 v2.00 - 03.06.2011
 * Avdump2 Build 4260 added
 * rewrote the whole lot and simplified it

 v1.07 - 06.04.2008
 * Avdump 0.34 added
 * fixed a bug with the bufferfield not allowing 16 buffer while that being the default
 * made option o default when no profile exists

 v1.06 - 12.02.2008
 * Avdump 0.33 added

 v1.05 - 13.11.2007
 * thx to rar for fixing dumping of files with characters in non local codepage

 v1.04 - 10.11.2007
 * fix for not being able to dump files with Japanese characters in the filename
 * Avdump 0.32 added and changes implemented

 v1.03 - 13.05.2007
 * added the console again
 * fix for log, export and done paths with spaces
 * added parents for the dialogues so they die with the program and can't stay open any more
 * option 9 added (experimental mp3 hashing for ostdb)
 
 v1.02 - 13.05.2007
 * added error and warning dialogue boxes to prevent a couple problems
 * added some exception handling for a few fields
 
 v1.01 - 12.05.2007
 * killed a nasty bug with trailing \ in the scanpath
 
 v1.00 - 12.05.2007
 * Initial release