Beispiel #1
0
class Gallery:

    def __init__(self, config, root_path):
        self.config = config
        self.root_path = root_path
        self.source_image_path = os.path.join(root_path, "source_images")
        self.source_video_path = os.path.join(root_path, "source_videos")
        self.theme_name = config.get("gallery", "theme")
        self.themes_path = os.path.join(root_path, "themes")
        self.theme_path = os.path.join(self.themes_path, self.theme_name)

        if not os.path.exists(self.theme_path):
            raise Exception("theme '%s' not found " % self.theme_name)

        themeconfigpath = os.path.join(self.theme_path, "config.txt")

        if not os.path.exists(themeconfigpath):
            raise Exception("couldn't find theme config.txt")

        self.config.read(themeconfigpath)

        self.templates_path = os.path.join(self.theme_path, "templates")

        self.template_path = os.path.join(root_path, "templates")
        self.output_path = os.path.join(root_path, "output")

        self.small_size = self.config.get("gallery",
                                          "small_image_size").split(",")
        self.large_size = self.config.get("gallery",
                                          "large_image_size").split(",")

        self.video_size = self.config.get("gallery",
                                          "video_max_size").split(",")

        self.configure_templates()
        self.discover_plugins()

    def discover_plugins(self):
        self.plugin_manager = PluginManager()
        self.plugin_manager.discover_plugins(
            os.path.join(self.root_path, "plugins"))

    def configure_templates(self):
        self.tempEnv = Environment(
            loader=FileSystemLoader(self.templates_path))

    def get_template(self, templateName):
        return self.tempEnv.get_template(templateName)

    def generate(self):
        images = self.discover_images()

        videos = self.process_videos()

        print videos

        images = self.generate_images(images)

        # plugin call point - pre page generation, with images as
        # arguments (to provide extra context for pages)
        extra_context = self.plugin_manager.prePageGeneration(
            self.config,
            self.source_image_path,
            self.source_video_path,
            images,
            videos)

        self.generate_pages(images, videos, extra_context)
        self.copy_static_content()

    def upload(self):
        # plugin call point, generation complete - upload
        self.plugin_manager.upload(self.config, self.output_path)

        # plugin call point, generation complete - notify
        self.plugin_manager.notify(self.config, self.output_path)

    def copy_static_content(self):
        static_path = os.path.join(self.theme_path, "static")
        static_output_path = os.path.join(self.output_path, "static")
        if os.path.exists(static_output_path):
            shutil.rmtree(static_output_path)
        shutil.copytree(static_path, static_output_path)

    def discover_images(self):
        images = []
        for filename in os.listdir(self.source_image_path):
            if filename.lower().find(".jpg") != -1:
                image = MediaObject(
                    source_path=os.path.join(
                        self.source_image_path,
                        filename),
                    filename=filename,
                    output_path=self.output_path)
                image.target_small_size = self.small_size
                image.target_large_size = self.large_size
                images.append(image)

        print "%s images found" % len(images)
        return images

    def process_videos(self):
        videos = []
        vp = videoprocessing.VideoProcessor()

        for filename in os.listdir(self.source_video_path):
            video = MediaObject(type=MediaObject.TYPE_VIDEO,
                                filename=filename,
                                source_path=os.path.join(
                                    self.source_video_path, filename),
                                output_path=self.output_path)

            videos.append(video)

            if video.transcoded:
                # copy already transcoded video
                target_path = os.path.join(self.output_path, video.filename)
                print "copying m4v video: %s" % video.source_path
                shutil.copy(video.source_path, target_path)
            else:
                # transcode the others
                target_filename = video.filename[
                    :video.filename.find(".")] + ".m4v"
                video.filename = target_filename
                target_path = os.path.join(self.output_path, target_filename)

                print "transcoding %s to %s" % (video.source_path, target_path)
                params = vp.getSizeAndDuration(video.source_path)
                vp.trancodeRawVideo(
                    video.source_path, target_path, params, self.video_size)

            video.thumb_path = vp.getScreencap(
                video.source_path, self.output_path)
            video.thumb_filename = os.path.split(video.thumb_path)[1]

            # get dimensions and duration
            params = vp.getSizeAndDuration(
                os.path.join(self.output_path, video.filename))
            video.width = params.get('width', None)
            video.height = params.get('height', None)
            video.hours = params.get('hours', None)
            video.minutes = params.get('minutes', None)
            video.seconds = params.get('seconds', None)
            video.title = filename

        return videos

    def generate_pages(self, images, videos, extra_context):
        try:
            themeMode = self.config.get("theme", "THEME_MODE")
        except ConfigParser.NoOptionError:
            themeMode = 'static'

        # merge video and photo records
        media = []
        media.extend(videos)
        media.extend(images)
        for mediaobject in media:
            if mediaobject.type == MediaObject.TYPE_PHOTO:
                mediaobject.page = "view_photo_%s.html" % mediaobject.id
            elif mediaobject.type == MediaObject.TYPE_VIDEO:
                mediaobject.page = "view_video_%s.html" % mediaobject.id

        if themeMode == 'ajax':
            return self.generate_ajax_pages(media, extra_context)
        elif themeMode == 'static':
            return self.generate_plain_pages(media, extra_context)
        else:
            raise Exception("unknown mode in theme")

    def generate_ajax_pages(self, media, extra_context):

        page_context = {
            'root_url': self.config.get("gallery", "ROOT_URL"),
            'imagecount': len(media),
            'media': media,
            'gallerytitle': self.config.get("gallery", "title"),
        }

        page_context.update(extra_context)

        self.render_page("index.html", "index.html", page_context)

        # create video embed pages
        for mediaitem in media:
            if mediaitem.type == MediaObject.TYPE_VIDEO:
                local_page_context = {
                    'video': mediaitem,
                    'root_url': self.config.get("gallery", "ROOT_URL"),
                }
                self.render_page("embedvideo.html", "embed_%s.html" %
                                mediaitem.filename, local_page_context)

        self.render_static_pages(page_context)

    def generate_plain_pages(self, media, extra_context):
        indexIsAlbumPage = self.config.getboolean(
            "theme", "INDEX_IS_ALBUM_PAGE")
        imagesPerPage = int(self.config.get("theme", "IMAGES_PER_PAGE"))

        # set up previous and next links
        for i in range(len(media)):
            prevlink = None
            nextlink = None
            if i > 0:
                prevlink = media[i - 1].page
            if i < (len(media) - 1):
                nextlink = media[i + 1].page
            media[i].next_link = nextlink
            media[i].prev_link = prevlink

        pages = int(math.ceil((len(media) / float(imagesPerPage))))

        page_context = {
            'root_url': self.config.get("gallery", "ROOT_URL"),
            'images_per_page': imagesPerPage,
            'pages': pages,
            'imagecount': len(media),
            'gallerytitle': self.config.get("gallery", "title"),
        }

        page_context.update(extra_context)

        pagelinks = []
        for page in range(pages):
            if page == 0 and indexIsAlbumPage:
                pagelinks.append(
                    {'title': (int(page) + 1), 'link': "index.html"})
            else:
                pagelinks.append(
                    {'title': (int(page) + 1), 'link': "page%s.html" % (int(page) + 1)})
        page_context['pagelinks'] = pagelinks

        # generate album pages
        if indexIsAlbumPage:
            currPageName = "index.html"
        else:
            currPageName = "page1.html"
        for page in range(pages):
            pageno = page + 1
            print "generating page %s" % pageno
            page_media = media[page * imagesPerPage:pageno * imagesPerPage]

            # set the owner page for the media items
            for mediaitem in page_media:
                mediaitem.home_page = currPageName

            page_context['media'] = page_media
            page_context['pageno'] = pageno

            prevlink = None
            if page > 0:
                prevlink = "page%s.html" % page
            nextlink = None
            if pageno < pages:
                nextlink = "page%s.html" % (int(pageno) + 1)

            page_context['prevlink'] = prevlink
            page_context['nextlink'] = nextlink

            self.render_page("albumpage.html", currPageName, page_context)

            currPageName = "page%s.html" % (pageno + 1)

        # generate image and video view pages
        for mediaitem in media:
            if mediaitem.type == MediaObject.TYPE_PHOTO:
                local_page_context = {
                    'img': mediaitem,
                    'root_url': self.config.get("gallery", "ROOT_URL"),
                }
                self.render_page(
                    "viewimage.html", mediaitem.page, local_page_context)

            if mediaitem.type == MediaObject.TYPE_VIDEO:
                local_page_context = {
                    'video': mediaitem,
                    'root_url': self.config.get("gallery", "ROOT_URL"),
                }
                self.render_page(
                    "viewvideo.html", mediaitem.page, local_page_context)

        self.render_static_pages(page_context)

    def render_static_pages(self, context):
        indexIsAlbumPage = self.config.getboolean(
            "theme", "INDEX_IS_ALBUM_PAGE")

        if not indexIsAlbumPage:
            self.render_page("index.html", "index.html", context)

        # render any other template not in the list of reserved names
        for template in self.tempEnv.list_templates():
            if template not in RESERVED_TEMPLATES:
                print "rendering static page - %s" % template
                self.render_page(template, template, context)

    def render_page(self, templateName, outputName, context):
        page_template = self.get_template(templateName)

        html = page_template.render(context)
        outfile = open(os.path.join(self.output_path, outputName), "w")
        outfile.write(html)
        outfile.close()

    def generate_images(self, images):
        p = Pool()

        images = p.map(process_image, [[image] for image in images])

        print images

        return images
Beispiel #2
0
class NomnsParse(QApplication):
    """Application Control."""

    def __init__(self, *args):
        super().__init__(*args)

        # Plugin support
        self.plugins = PluginManager(self)
        self.plugins.discover_plugins(enable_all=config.data['general']['enable_plugins'])
        # End plugin support

        # Updates
        self._toggled = False
        self._log_reader = None

        # Load Parsers
        self._load_parsers()
        self._settings = SettingsWindow()

        # Tray Icon
        self._system_tray = QSystemTrayIcon()
        self._system_tray.setIcon(QIcon(resource_path('data/ui/icon.png')))
        self._system_tray.setToolTip("nParse")
        # self._system_tray.setContextMenu(self._create_menu())
        self._system_tray.activated.connect(self._menu)
        self._system_tray.show()

        # Turn On
        self._toggle()

        if self.new_version_available():
            self._system_tray.showMessage(
                "nParse Update".format(ONLINE_VERSION),
                "New version available!\ncurrent: {}\nonline: {}".format(
                    CURRENT_VERSION,
                    ONLINE_VERSION
                ),
                msecs=3000
            )

        self.plugins.hook(Plugin.on_app_start, self)

    def _load_parsers(self):
        self._parsers = [
            parsers.Maps(),
            parsers.Spells()
        ]
        for parser in self._parsers:
            self.plugins.hook(Plugin.on_parser_load, parser)
            if parser.name in config.data.keys() and 'geometry' in config.data[parser.name].keys():
                g = config.data[parser.name]['geometry']
                parser.setGeometry(g[0], g[1], g[2], g[3])
            if config.data[parser.name]['toggled']:
                parser.toggle()

    def _toggle(self):
        if not self._toggled:
            try:
                config.verify_paths()
            except ValueError as error:
                self._system_tray.showMessage(
                    error.args[0], error.args[1], msecs=3000)

            else:
                self._log_reader = logreader.LogReader(
                    config.data['general']['eq_log_dir'])
                self._log_reader.new_line.connect(self._parse)
                self._toggled = True
        else:
            if self._log_reader:
                self._log_reader.deleteLater()
                self._log_reader = None
            self._toggled = False

    def _parse(self, new_line):
        if new_line:
            timestamp, text, charname = new_line  # (datetime, text)
            #  don't send parse to non toggled items, except maps.  always parse maps
            for parser in [parser for parser in self._parsers if config.data[parser.name]['toggled'] or parser.name == 'maps']:
                parser.parse(timestamp, text, charname)

    def _menu(self, event):
        """Returns a new QMenu for system tray."""
        menu = QMenu()
        menu.setAttribute(Qt.WA_DeleteOnClose)
        # check online for new version
        new_version_text = ""
        if self.new_version_available():
            new_version_text = "Update Available {}".format(ONLINE_VERSION)
        else:
            new_version_text = "Version {}".format(CURRENT_VERSION)

        check_version_action = menu.addAction(new_version_text)
        menu.addSeparator()
        get_eq_dir_action = menu.addAction('Select EQ Logs Directory')
        menu.addSeparator()

        parser_toggles = set()
        for parser in self._parsers:
            toggle = menu.addAction(parser.name.title())
            toggle.setCheckable(True)
            toggle.setChecked(config.data[parser.name]['toggled'])
            parser_toggles.add(toggle)

        menu.addSeparator()
        settings_action = menu.addAction('Settings')

        # Plugin support for adding menu items
        if self.plugins.has_plugins():
            menu.addSeparator()
        plugin_options = self.plugins.prepare_plugin_menu(menu)
        self.plugins.hook(Plugin.on_menu_display, menu)
        # End plugin support

        menu.addSeparator()
        quit_action = menu.addAction('Quit')

        # Show the menu
        action = menu.exec_(QCursor.pos())

        # Plugin support for handling menu actions
        if plugin_options:
            plugin_options(action)
        self.plugins.hook(Plugin.on_menu_click, action)
        # End plugin support

        if action == check_version_action:
            webbrowser.open('https://github.com/nomns/nparse/releases')

        elif action == get_eq_dir_action:
            dir_path = str(QFileDialog.getExistingDirectory(
                None, 'Select Everquest Logs Directory'))
            if dir_path:
                config.data['general']['eq_log_dir'] = dir_path
                config.save()
                self._toggle()

        elif action == settings_action:
            if self._settings.exec_():
                # Update required settings
                for parser in self._parsers:
                    if parser.windowOpacity() != config.data['general']['parser_opacity']:
                        parser.setWindowOpacity(
                            config.data['general']['parser_opacity'] / 100)
                        parser.settings_updated()
            # some settings are saved within other settings automatically
            # force update
            for parser in self._parsers:
                if parser.name == "spells":
                    parser.load_custom_timers()

        elif action == quit_action:
            if self._toggled:
                self._toggle()

            # save parser geometry
            for parser in self._parsers:
                g = parser.geometry()
                config.data[parser.name]['geometry'] = [
                    g.x(), g.y(), g.width(), g.height()
                ]
                config.save()

            self._system_tray.setVisible(False)

            # Plugin support
            self.plugins.hook(Plugin.on_app_quit, self)

            self.quit()

        elif action in parser_toggles:
            parser = [
                parser for parser in self._parsers if parser.name == action.text().lower()][0]
            parser.toggle()

    def new_version_available(self):
        # this will only work if numbers go up
        try:
            for (o, c) in zip(ONLINE_VERSION.split('.'), CURRENT_VERSION.split('.')):
                if int(o) > int(c):
                    return True
        except:
            return False