Exemplo n.º 1
0
 def _exec(self):
     """Spawns the process, and returns its stdout.
     (NOTE: separate function to make python2.4 exception syntax happy)
     """
     try:
         # Cannot spawn processes with PythonW/Win32 unless stdin and
         # stderr are redirected to a pipe as well.
         self._proc = subprocess.Popen(
             self._args,
             stdout=subprocess.PIPE,
             stdin=subprocess.PIPE,
             stderr=subprocess.PIPE,
             startupinfo=self._startupinfo(),
         )
         return self._proc.stdout
     except Exception, ex:
         cmd = len(self._args) > 0 and self._args[0] or "<invalid>"
         log.info(
             (
                 _('! Error spawning process "%(command)s": %(error)s.')
                 + u" "
                 + _('"%(command)s" must be on your system PATH to be found.')
             )
             % {"command": unicode(cmd, errors="replace"), "error": unicode(str(ex), errors="replace")}
         )
         return None
Exemplo n.º 2
0
    def _upgrade_database(self, from_version, to_version):
        """ Performs sequential upgrades to the database, bringing
        it from C{from_version} to C{to_version}. If C{from_version}
        is -1, the database structure will simply be re-created at the
        current version. """

        if from_version == -1:
            self._create_tables()
            return

        if from_version != to_version:
            upgrades = range(from_version, to_version)
            log.info(_("Upgrading library database version from %(from)d to %(to)d."),
                { "from" : from_version, "to" : to_version })

            if 0 in upgrades:
                # Upgrade from Comix database structure to DB version 1
                # (Added table 'info')
                self._create_table_info()

            if 1 in upgrades:
                # Upgrade to database structure version 2.
                # (Added table 'watchlist' for storing auto-add directories)
                self._create_table_watchlist()

            self._con.execute('''update info set value = ? where key = 'version' ''',
                              (str(_LibraryBackend.DB_VERSION),))
Exemplo n.º 3
0
    def _upgrade_database(self, from_version, to_version):
        """ Performs sequential upgrades to the database, bringing
        it from C{from_version} to C{to_version}. If C{from_version}
        is -1, the database structure will simply be re-created at the
        current version. """

        if from_version == -1:
            self._create_tables()
            return

        if from_version != to_version:
            upgrades = range(from_version, to_version)
            log.info(
                _("Upgrading library database version from %(from)d to %(to)d."),
                {"from": from_version, "to": to_version},
            )

            if 0 in upgrades:
                # Upgrade from Comix database structure to DB version 1
                # (Added table 'info')
                self._create_table_info()

            if 1 in upgrades:
                # Upgrade to database structure version 2.
                # (Added table 'watchlist' for storing auto-add directories)
                self._create_table_watchlist()

            if 2 in upgrades:
                # Changed 'added' field in 'book' from date to datetime.
                self._con.execute("""alter table book rename to book_old""")
                self._create_table_book()
                self._con.execute(
                    """insert into book
                    (id, name, path, pages, format, size, added)
                    select id, name, path, pages, format, size, datetime(added)
                    from book_old"""
                )
                self._con.execute("""drop table book_old""")

            if 3 in upgrades:
                # Added field 'recursive' to table 'watchlist'
                self._con.execute("""alter table watchlist rename to watchlist_old""")
                self._create_table_watchlist()
                self._con.execute(
                    """insert into watchlist
                    (path, collection, recursive)
                    select path, collection, 0 from watchlist_old"""
                )
                self._con.execute("""drop table watchlist_old""")

            if 4 in upgrades:
                # Added table 'recent' to store recently viewed book information and
                # create a collection (-2, Recent)
                self._create_table_recent()
                lastread = last_read_page.LastReadPage(self)
                lastread.migrate_database_to_library(COLLECTION_RECENT)

            self._con.execute(
                """update info set value = ? where key = 'version' """, (str(_LibraryBackend.DB_VERSION),)
            )
Exemplo n.º 4
0
 def is_available():
     global _pdf_possible
     if _pdf_possible is None:
         proc = process.Process(['mudraw'])
         fd = proc.spawn()
         if fd is not None:
             fd.close()
             proc.wait()
             _pdf_possible = True
         else:
             log.info('MuPDF not available.')
             _pdf_possible = False
     return _pdf_possible
Exemplo n.º 5
0
 def is_available():
     global _pdf_possible
     if _pdf_possible is not None:
         return _pdf_possible
     global _mutool_exec, _mudraw_exec, _mudraw_trace_args
     mutool = process.find_executable((u"mutool",))
     _pdf_possible = False
     version = None
     if mutool is None:
         log.debug("mutool executable not found")
     else:
         _mutool_exec = [mutool]
         # Find MuPDF version; assume 1.6 version since
         # the '-v' switch is only supported from 1.7 onward...
         version = "1.6"
         proc = process.popen([mutool, "-v"], stdout=process.NULL, stderr=process.PIPE)
         try:
             output = proc.stderr.read()
             if output.startswith("mutool version "):
                 version = output[15:].rstrip()
         finally:
             proc.stderr.close()
             proc.wait()
         version = LooseVersion(version)
         if version >= LooseVersion("1.8"):
             # Mutool executable with draw support.
             _mudraw_exec = [mutool, "draw"]
             _mudraw_trace_args = ["-F", "trace"]
             _pdf_possible = True
         else:
             # Separate mudraw executable.
             mudraw = process.find_executable((u"mudraw",))
             if mudraw is None:
                 log.debug("mudraw executable not found")
             else:
                 _mudraw_exec = [mudraw]
                 if version >= LooseVersion("1.7"):
                     _mudraw_trace_args = ["-F", "trace"]
                 else:
                     _mudraw_trace_args = ["-x"]
                 _pdf_possible = True
     if _pdf_possible:
         log.info("Using MuPDF version: %s", version)
         log.debug("mutool: %s", " ".join(_mutool_exec))
         log.debug("mudraw: %s", " ".join(_mudraw_exec))
         log.debug("mudraw trace arguments: %s", " ".join(_mudraw_trace_args))
     else:
         log.info("MuPDF not available.")
     return _pdf_possible
Exemplo n.º 6
0
 def _exec(self, stdin, stderr):
     """Spawns the process, and returns its stdout.
     (NOTE: separate function to make python2.4 exception syntax happy)
     """
     try:
         self._proc = subprocess.Popen(self._args, stdout=subprocess.PIPE,
                 stdin=stdin, stderr=stderr,
                 startupinfo=self._startupinfo())
         return self._proc.stdout
     except Exception, ex:
         cmd = len(self._args) > 0 and self._args[0] or "<invalid>"
         log.info((
             _('! Error spawning process "%(command)s": %(error)s.')
             + u' '
             + _('"%(command)s" must be on your system PATH to be found.')) %
             { 'command' : unicode(cmd, errors='replace'),
               'error' : unicode(str(ex), errors='replace')})
         return None
Exemplo n.º 7
0
    def read_fileinfo_file(self):
        '''Read last loaded file info from disk.'''

        fileinfo = None

        if os.path.isfile(constants.FILEINFO_JSON_PATH):
            try:
                with open(constants.FILEINFO_JSON_PATH,
                          mode='rt',
                          encoding='utf8') as config:
                    fileinfo = json.load(config)
            except Exception as ex:
                log.error(_('! Corrupt preferences file "%s", deleting...'),
                          constants.FILEINFO_JSON_PATH)
                log.info('Error was: %s', ex)
                os.remove(constants.FILEINFO_JSON_PATH)

        return fileinfo
Exemplo n.º 8
0
    def read_fileinfo_file(self):
        """Read last loaded file info from disk."""

        fileinfo = None

        if os.path.isfile(constants.FILEINFO_PICKLE_PATH):
            config = None
            try:
                config = open(constants.FILEINFO_PICKLE_PATH, 'rb')

                fileinfo = cPickle.load(config)

                config.close()

            except Exception, ex:
                log.error(_('! Corrupt preferences file "%s", deleting...'),
                        constants.FILEINFO_PICKLE_PATH )
                log.info(u'Error was: %s', ex)
                if config is not None:
                    config.close()
                os.remove(constants.FILEINFO_PICKLE_PATH)
Exemplo n.º 9
0
    def read_fileinfo_file(self):
        """Read last loaded file info from disk."""

        fileinfo = None

        if os.path.isfile(constants.FILEINFO_PICKLE_PATH):
            config = None
            try:
                config = open(constants.FILEINFO_PICKLE_PATH, 'rb')

                fileinfo = cPickle.load(config)

                config.close()

            except Exception, ex:
                log.error(_('! Corrupt preferences file "%s", deleting...'),
                          constants.FILEINFO_PICKLE_PATH)
                log.info(u'Error was: %s', ex)
                if config is not None:
                    config.close()
                os.remove(constants.FILEINFO_PICKLE_PATH)
Exemplo n.º 10
0
    def _upgrade_database(self, from_version, to_version):
        ''' Performs sequential upgrades to the database, bringing
        it from C{from_version} to C{to_version}. If C{from_version}
        is -1, the database structure will simply be re-created at the
        current version. '''

        if from_version < 5:
            self._create_tables()
            return

        if from_version != to_version:
            upgrades = range(from_version, to_version)
            log.info(
                _('Upgrading library database version from %(from)d to %(to)d.'
                  ), {
                      'from': from_version,
                      'to': to_version
                  })

            if 5 in upgrades:
                # Changed all 'string' columns into 'text' columns
                self._con.execute('''alter table book rename to book_old''')
                self._create_table_book()
                self._con.execute('''insert into book
                    (id, name, path, pages, format, size, added)
                    select id, name, path, pages, format, size, added from book_old'''
                                  )
                self._con.execute('''drop table book_old''')

                self._con.execute(
                    '''alter table collection rename to collection_old''')
                self._create_table_collection()
                self._con.execute('''insert into collection
                    (id, name, supercollection)
                    select id, name, supercollection from collection_old''')
                self._con.execute('''drop table collection_old''')

            self._con.execute(
                '''update info set value = ? where key = 'version' ''',
                (str(_LibraryBackend.DB_VERSION), ))
Exemplo n.º 11
0
def get_archive_handler(path, type=None):
    """ Returns a fitting extractor handler for the archive passed
    in <path> (with optional mime type <type>. Returns None if no matching
    extractor was found.
    """
    if type is None:
        type = archive_mime_type(path)

    if type == constants.ZIP:
        return zip.ZipArchive(path)
    elif type == constants.ZIP_EXTERNAL and zip_external.ZipExecArchive.is_available():
        return zip_external.ZipExecArchive(path)
    elif type == constants.ZIP_EXTERNAL and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for unsupported zip archives.')
        return sevenzip.SevenZipArchive(path)
    elif type in (constants.TAR, constants.GZIP, constants.BZIP2):
        return tar.TarArchive(path)
    elif type == constants.RAR and rar.RarArchive.is_available():
        return rar.RarArchive(path)
    elif type == constants.RAR and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for RAR archives.')
        return sevenzip.SevenZipArchive(path)
    elif type == constants.SEVENZIP and sevenzip.SevenZipArchive.is_available():
        return sevenzip.SevenZipArchive(path)
    elif type == constants.LHA and lha.LhaArchive.is_available():
        return lha.LhaArchive(path)
    elif type == constants.LHA and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for LHA archives.')
        return sevenzip.SevenZipArchive(path)
    elif type == constants.PDF and pdf.PdfArchive.is_available():
        return pdf.PdfArchive(path)
    else:
        return None
Exemplo n.º 12
0
    def _upgrade_database(self, from_version, to_version):
        """ Performs sequential upgrades to the database, bringing
        it from C{from_version} to C{to_version}. If C{from_version}
        is -1, the database structure will simply be re-created at the
        current version. """

        if from_version == -1:
            self._create_tables()
            return

        if from_version != to_version:
            upgrades = range(from_version, to_version)
            log.info(_("Upgrading library database version from %(from)d to %(to)d."),
                { "from" : from_version, "to" : to_version })

            if 0 in upgrades:
                # Upgrade from Comix database structure to DB version 1
                # (Added table 'info')
                self._create_table_info()

            if 1 in upgrades:
                # Upgrade to database structure version 2.
                # (Added table 'watchlist' for storing auto-add directories)
                self._create_table_watchlist()

            if 2 in upgrades:
                # Changed 'added' field in 'book' from date to datetime.
                self._con.execute('''alter table book rename to book_old''')
                self._create_table_book()
                self._con.execute('''insert into book
                    (id, name, path, pages, format, size, added)
                    select id, name, path, pages, format, size, datetime(added)
                    from book_old''')
                self._con.execute('''drop table book_old''')


            self._con.execute('''update info set value = ? where key = 'version' ''',
                              (str(_LibraryBackend.DB_VERSION),))
Exemplo n.º 13
0
def get_archive_handler(path):
    """ Returns a fitting extractor handler for the archive passed
    in <path>. Returns None if no matching extractor was found. """
    mime = archive_mime_type(path)

    if mime == constants.ZIP:
        return zip.ZipArchive(path)
    elif mime in (constants.TAR, constants.GZIP, constants.BZIP2):
        return tar.TarArchive(path)
    elif mime == constants.RAR and rar.RarArchive.is_available():
        return rar.RarArchive(path)
    elif mime == constants.RAR and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for RAR archives.')
        return sevenzip.SevenZipArchive(path)
    elif mime == constants.SEVENZIP and sevenzip.SevenZipArchive.is_available():
        return sevenzip.SevenZipArchive(path)
    elif mime == constants.LHA and lha.LhaArchive.is_available():
        return lha.LhaArchive(path)
    elif mime == constants.LHA and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for LHA archives.')
        return sevenzip.SevenZipArchive(path)
    else:
        return None
Exemplo n.º 14
0
def get_archive_handler(path):
    """ Returns a fitting extractor handler for the archive passed
    in <path>. Returns None if no matching extractor was found. """
    mime = archive_mime_type(path)

    if mime == constants.ZIP:
        return zip.ZipArchive(path)
    elif mime in (constants.TAR, constants.GZIP, constants.BZIP2):
        return tar.TarArchive(path)
    elif mime == constants.RAR and rar.RarArchive.is_available():
        return rar.RarArchive(path)
    elif mime == constants.RAR and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for RAR archives.')
        return sevenzip.SevenZipArchive(path)
    elif mime == constants.SEVENZIP and sevenzip.SevenZipArchive.is_available():
        return sevenzip.SevenZipArchive(path)
    elif mime == constants.LHA and lha.LhaArchive.is_available():
        return lha.LhaArchive(path)
    elif mime == constants.LHA and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for LHA archives.')
        return sevenzip.SevenZipArchive(path)
    else:
        return None
Exemplo n.º 15
0
def get_archive_handler(path, type=None):
    """ Returns a fitting extractor handler for the archive passed
    in <path> (with optional mime type <type>. Returns None if no matching
    extractor was found.
    """
    if type is None:
        type = archive_mime_type(path)

    if type == constants.ZIP:
        return zip.ZipArchive(path)
    elif type == constants.ZIP_EXTERNAL and zip_external.ZipExecArchive.is_available(
    ):
        return zip_external.ZipExecArchive(path)
    elif type == constants.ZIP_EXTERNAL and sevenzip.SevenZipArchive.is_available(
    ):
        log.info('Using Sevenzip for unsupported zip archives.')
        return sevenzip.SevenZipArchive(path)
    elif type in (constants.TAR, constants.GZIP, constants.BZIP2):
        return tar.TarArchive(path)
    elif type == constants.RAR and rar.RarArchive.is_available():
        return rar.RarArchive(path)
    elif type == constants.RAR and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for RAR archives.')
        return sevenzip.SevenZipArchive(path)
    elif type == constants.SEVENZIP and sevenzip.SevenZipArchive.is_available(
    ):
        return sevenzip.SevenZipArchive(path)
    elif type == constants.LHA and lha.LhaArchive.is_available():
        return lha.LhaArchive(path)
    elif type == constants.LHA and sevenzip.SevenZipArchive.is_available():
        log.info('Using Sevenzip for LHA archives.')
        return sevenzip.SevenZipArchive(path)
    elif type == constants.PDF and pdf.PdfArchive.is_available():
        return pdf.PdfArchive(path)
    else:
        return None
Exemplo n.º 16
0
from mcomix.preferences import prefs
from mcomix import constants
from mcomix import log


if sys.platform == 'win32':
    # Works around GTK's slowness on Win32 by using PIL
    # for loading instead and converting it afterwards.
    # NOTE: Using False here should work fine for Windows, too.
    USE_PIL = False
else:
    USE_PIL = False

log.info('Using %s for loading images (versions: %s [%s], GDK [%s])',
         'PIL' if USE_PIL else 'GDK',
         PIL_VERSION[0], PIL_VERSION[1],
         # Unfortunately gdk_pixbuf_version is not exported,
         # so show the GTK+ version instead.
         'GTK+ ' + '.'.join(map(str, gtk.gtk_version)))


def rotate_pixbuf(src, rotation):
    rotation %= 360
    if 0 == rotation:
        return src
    if 90 == rotation:
        return src.rotate_simple(gtk.gdk.PIXBUF_ROTATE_CLOCKWISE)
    if 180 == rotation:
        return src.rotate_simple(gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN)
    if 270 == rotation:
        return src.rotate_simple(gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
    raise ValueError("unsupported rotation: %s" % rotation)
Exemplo n.º 17
0
try:
    from PIL import PILLOW_VERSION
    PIL_VERSION = ('Pillow', PILLOW_VERSION)
except ImportError:
    from PIL import VERSION as PIL_VERSION
    PIL_VERSION = ('PIL', PIL_VERSION)
from cStringIO import StringIO

from mcomix.preferences import prefs
from mcomix import constants
from mcomix import log
from mcomix import tools


# Unfortunately gdk_pixbuf_version is not exported, so show the GTK+ version instead.
log.info('GDK version: %s', 'GTK+ ' + '.'.join(map(str, gtk.gtk_version)))
log.info('PIL version: %s [%s]', PIL_VERSION[0], PIL_VERSION[1])


# Fallback pixbuf for missing images.
MISSING_IMAGE_ICON = None

_missing_icon_dialog = gtk.Dialog()
_missing_icon_pixbuf = _missing_icon_dialog.render_icon(
        gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR)
MISSING_IMAGE_ICON = _missing_icon_pixbuf
assert MISSING_IMAGE_ICON

GTK_GDK_COLOR_BLACK = gtk.gdk.color_parse('black')
GTK_GDK_COLOR_WHITE = gtk.gdk.color_parse('white')
Exemplo n.º 18
0
    def _upgrade_database(self, from_version, to_version):
        """ Performs sequential upgrades to the database, bringing
        it from C{from_version} to C{to_version}. If C{from_version}
        is -1, the database structure will simply be re-created at the
        current version. """

        if from_version == -1:
            self._create_tables()
            return

        if from_version != to_version:
            upgrades = range(from_version, to_version)
            log.info(
                _("Upgrading library database version from %(from)d to %(to)d."
                  ), {
                      "from": from_version,
                      "to": to_version
                  })

            if 0 in upgrades:
                # Upgrade from Comix database structure to DB version 1
                # (Added table 'info')
                self._create_table_info()

            if 1 in upgrades:
                # Upgrade to database structure version 2.
                # (Added table 'watchlist' for storing auto-add directories)
                self._create_table_watchlist()

            if 2 in upgrades:
                # Changed 'added' field in 'book' from date to datetime.
                self._con.execute('''alter table book rename to book_old''')
                self._create_table_book()
                self._con.execute('''insert into book
                    (id, name, path, pages, format, size, added)
                    select id, name, path, pages, format, size, datetime(added)
                    from book_old''')
                self._con.execute('''drop table book_old''')

            if 3 in upgrades:
                # Added field 'recursive' to table 'watchlist'
                self._con.execute(
                    '''alter table watchlist rename to watchlist_old''')
                self._create_table_watchlist()
                self._con.execute('''insert into watchlist
                    (path, collection, recursive)
                    select path, collection, 0 from watchlist_old''')
                self._con.execute('''drop table watchlist_old''')

            if 4 in upgrades:
                # Added table 'recent' to store recently viewed book information and
                # create a collection (-2, Recent)
                self._create_table_recent()
                lastread = last_read_page.LastReadPage(self)
                lastread.migrate_database_to_library(COLLECTION_RECENT)

            if 5 in upgrades:
                # Changed all 'string' columns into 'text' columns
                self._con.execute('''alter table book rename to book_old''')
                self._create_table_book()
                self._con.execute('''insert into book
                    (id, name, path, pages, format, size, added)
                    select id, name, path, pages, format, size, added from book_old'''
                                  )
                self._con.execute('''drop table book_old''')

                self._con.execute(
                    '''alter table collection rename to collection_old''')
                self._create_table_collection()
                self._con.execute('''insert into collection
                    (id, name, supercollection)
                    select id, name, supercollection from collection_old''')
                self._con.execute('''drop table collection_old''')

            self._con.execute(
                '''update info set value = ? where key = 'version' ''',
                (str(_LibraryBackend.DB_VERSION), ))
Exemplo n.º 19
0
def run():
    '''Run the program.'''

    # Load configuration and setup localisation.
    preferences.read_preferences_file()
    from mcomix import i18n
    i18n.install_gettext()

    # Retrieve and parse command line arguments.
    args = parse_arguments()

    if args.version:
        print_version()

    # First things first: set the log level.
    log.setLevel(log.levels[args.loglevel])

    # Check Python version
    try:
        assert sys.version_info[:3] >= constants.REQUIRED_PYTHON_VERSION

    except AssertionError:
        log.error(_('You don\'t have the required version of the Python installed.'))
        log.error(_('Installed Python version is: %s') % '.'.join(str(n) for n in sys.version_info))
        log.error(_('Required Python version is: %s or higher') % '.'.join(str(n) for n in constants.REQUIRED_PYTHON_VERSION))
        wait_and_exit()

    # Check for PyGTK and PIL dependencies.
    try:
        from gi import version_info as gi_version_info
        if gi_version_info < (3, 30, 0):
            log.error(_('You do not have the required versions of PyGObject installed.'))
            wait_and_exit()

        from gi import require_version

        require_version('PangoCairo', '1.0')
        require_version('Gtk', '3.0')
        require_version('Gdk', '3.0')

        from gi.repository import Gdk, GdkPixbuf, Gtk, GLib

        if (Gtk.get_major_version(), Gtk.get_minor_version()) < (3, 24):
            log.error(_('You do not have the required versions of GTK+ 3 gir bindings installed.'))
            wait_and_exit()

    except ValueError:
        log.error(_('You do not have the required versions of GTK+ 3.0 installed.'))
        wait_and_exit()

    except ImportError:
        log.error(_('No version of GObject was found on your system.'))
        log.error(_('This error might be caused by missing GTK+ libraries.'))
        wait_and_exit()

    try:
        import PIL
        assert [int(n) for n in PIL.__version__.split('.')[:3]] >= [int(n) for n in constants.REQUIRED_PIL_VERSION.split('.')]

    except AttributeError:
        log.error(_('You don\'t have the required version of the Pillow installed.'))
        log.error(_('Required Pillow version is: %s or higher') % constants.REQUIRED_PIL_VERSION)
        wait_and_exit()

    except ValueError:
        log.error(_('Unrecognized Pillow version: %s') % PIL.__version__)
        log.error(_('Required Pillow version is: %s or higher') % constants.REQUIRED_PIL_VERSION)
        wait_and_exit()

    except ImportError:
        log.error(_('Pillow %s or higher is required.') % constants.REQUIRED_PIL_VERSION)
        log.error(_('No version of the Pillow was found on your system.'))
        wait_and_exit()

    except AssertionError:
        log.error(_('You don\'t have the required version of the Pillow installed.'))
        log.error(_('Installed PIL version is: %s') % PIL.__version__)
        log.error(_('Required Pillow version is: %s or higher') % constants.REQUIRED_PIL_VERSION)
        wait_and_exit()

    log.info('Image loaders: Pillow [%s], GDK [%s])',
             PIL.__version__,GdkPixbuf.PIXBUF_VERSION)

    if not os.path.exists(constants.DATA_DIR):
        os.makedirs(constants.DATA_DIR, 0o700)

    if not os.path.exists(constants.CONFIG_DIR):
        os.makedirs(constants.CONFIG_DIR, 0o700)

    from mcomix import icons
    icons.load_icons()

    open_path = args.path or None
    open_page = 1

    if isinstance(open_path, list):
        n = 0
        while n<len(open_path):
            p = os.path.join(constants.STARTDIR, open_path[n])
            p = os.path.normpath(p)
            if not os.path.exists(p):
                log.error(_('{} not exists.').format(p))
                open_path.pop(n)
                continue
            open_path[n] = p
            n += 1
        if not open_path:
            open_path = None

    if not open_path and preferences.prefs['auto load last file'] \
       and preferences.prefs['path to last file'] \
       and os.path.isfile(preferences.prefs['path to last file']):
        open_path = preferences.prefs['path to last file']
        open_page = preferences.prefs['page of last file']

    # Some languages require a RTL layout
    if preferences.prefs['language'] in ('he', 'fa'):
        Gtk.Widget.set_default_direction(Gtk.TextDirection.RTL)

    Gdk.set_program_class(constants.APPNAME)

    settings = Gtk.Settings.get_default()
    # Enable icons for menu items.
    settings.props.gtk_menu_images = True

    from mcomix import main
    window = main.MainWindow(fullscreen = args.fullscreen, is_slideshow = args.slideshow,
                             show_library = args.library, manga_mode = args.manga,
                             double_page = args.doublepage, zoom_mode = args.zoommode,
                             open_path = open_path, open_page = open_page)
    main.set_main_window(window)

    if 'win32' != sys.platform:
        # Add a SIGCHLD handler to reap zombie processes.
        def on_sigchld(signum, frame):
            try:
                os.waitpid(-1, os.WNOHANG)
            except OSError:
                pass
        signal.signal(signal.SIGCHLD, on_sigchld)

    for sig in (signal.SIGINT, signal.SIGTERM):
        signal.signal(sig, lambda signum, stack: GLib.idle_add(window.terminate_program))
    try:
        Gtk.main()
    except KeyboardInterrupt: # Will not always work because of threading.
        window.terminate_program()
Exemplo n.º 20
0
from mcomix.preferences import prefs
from mcomix import constants
from mcomix import log


if sys.platform == 'win32':
    # Works around GTK's slowness on Win32 by using PIL
    # for loading instead and converting it afterwards.
    # NOTE: Using False here should work fine for Windows, too.
    USE_PIL = False
else:
    USE_PIL = False

log.info('Using %s for loading images (versions: %s [%s], GDK [%s])',
         'PIL' if USE_PIL else 'GDK',
         PIL_VERSION[0], PIL_VERSION[1],
         # Unfortunately gdk_pixbuf_version is not exported,
         # so show the GTK+ version instead.
         'GTK+ ' + '.'.join(map(str, gtk.gtk_version)))


# Fallback pixbuf for missing images.
MISSING_IMAGE_ICON = None

_missing_icon_dialog = gtk.Dialog()
_missing_icon_pixbuf = _missing_icon_dialog.render_icon(
        gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR)
MISSING_IMAGE_ICON = _missing_icon_pixbuf
assert MISSING_IMAGE_ICON

GTK_GDK_COLOR_BLACK = gtk.gdk.color_parse('black')
GTK_GDK_COLOR_WHITE = gtk.gdk.color_parse('white')
Exemplo n.º 21
0
from PIL import ImageOps
from PIL.JpegImagePlugin import _getexif
try:
    from PIL import PILLOW_VERSION
    PIL_VERSION = ('Pillow', PILLOW_VERSION)
except ImportError:
    from PIL import VERSION as PIL_VERSION
    PIL_VERSION = ('PIL', PIL_VERSION)
from io import BytesIO
from functools import reduce

from mcomix.preferences import prefs
from mcomix import constants
from mcomix import log

log.info('Using %s for loading images (versions: PIL [%s], GDK [%s])',
         PIL_VERSION[0], PIL_VERSION[1], GdkPixbuf.PIXBUF_VERSION)

# Fallback pixbuf for missing images.
MISSING_IMAGE_ICON = None

_missing_icon_dialog = Gtk.Dialog()
_missing_icon_pixbuf = _missing_icon_dialog.render_icon(
    Gtk.STOCK_MISSING_IMAGE, Gtk.IconSize.LARGE_TOOLBAR)
MISSING_IMAGE_ICON = _missing_icon_pixbuf
assert MISSING_IMAGE_ICON

GTK_GDK_COLOR_BLACK = Gdk.color_parse('black')
GTK_GDK_COLOR_WHITE = Gdk.color_parse('white')


def rotate_pixbuf(src, rotation):