Exemple #1
0
def load_html_templates():
    html = namedtuple('HTMLTemplates', 'entry index_page tags progress')
    path = lambda fname: local_path(join('templates', fname))
    return html(read_file(path('entry_template.html')),
                read_file(path('index_page_template.html')),
                read_file(path('tags_template.html')),
                read_file(path('progress_template.html')))
Exemple #2
0
def load_html_templates():
    path = lambda fname: local_path(join('templates', fname))
    return {
        'entry': read_file(path('entry_template.html')),
        'page': read_file(path('index_page_template.html')),
        'tags': read_file(path('tags_template.html'))
    }
Exemple #3
0
    def __init__(self, configdir, activation_event, dry_run):
        super().__init__()
        self.setWindowTitle('Nomia')
        if configdir:
            self.configdir = configdir
        else:
            self.configdir = join(getenv('HOME'), '.config', 'nomia')
        activation_event.connect(self.reload_settings)
        self.force_quit_flag = False

        # Create layouts
        self.stack = QtGui.QStackedLayout(self)

        # Index viewer
        self.index_viewer = IndexFrame(self, dry_run, self.configdir)
        self.stack.addWidget(self.index_viewer)

        # Popup viewer
        self.popup_viewer = FileViewer(self)
        self.stack.addWidget(self.popup_viewer)
        self.popuphomekey = QtGui.QShortcut(QtGui.QKeySequence(),
                                            self.popup_viewer,
                                            self.show_index)

        # Load settings
        self.defaultstyle = read_json(local_path('defaultstyle.json'))
        self.css_template = read_file(local_path(join('templates','template.css')))
        self.index_css_template = read_file(local_path(join('templates','index_page.css')))
        self.settings, self.style = {}, {}
        self.reload_settings()
        self.index_viewer.populate_view()

        # Misc
        #self.connect_signals()
        self.show()
Exemple #4
0
 def cmd_revision_control(self, arg):
     fname = self.current_page_path()
     firstline, _ = read_file(fname).split('\n', 1)
     jsondata = json.loads(firstline)
     if arg == '+':
         if self.revisionactive:
             self.terminal.error('Can\'t create new revision when viewing an old one')
             return
         saved = self.save_tab()
         if saved:
             # Do this again in case something got saved before
             _, data = read_file(fname).split('\n', 1)
             f = join(self.root, fname)
             rev = jsondata['revision']
             shutil.copy2(f, f + '.rev{}'.format(rev))
             jsondata['revision'] += 1
             jsondata['revision created'] = datetime.now().isoformat()
             write_file(f, json.dumps(jsondata) + '\n' + data)
             self.terminal.print_('Revision increased to {}'.format(rev + 1))
     # Show a certain revision
     elif arg.isdigit():
         revfname = join(self.root, fname + '.rev{}'.format(arg))
         if not os.path.exists(revfname):
             self.terminal.error('Revision {} not found'.format(arg))
             return
         saved = self.save_tab()
         if not saved:
             return
         try:
             _, data = read_file(revfname).split('\n', 1)
         except Exception as e:
             print(str(e))
             self.error('Something went wrong when loading the revision')
         else:
             self.textarea.setPlainText(data)
             self.textarea.document().setModified(False)
             self.revisionactive = True
             self.revisionnotice.setText('Showing revision {}. Changes will not be saved.'.format(arg))
             self.revisionnotice.show()
     elif arg == '#':
         self.terminal.print_('Current revision: {}'.format(jsondata['revision']))
     elif not arg:
         if not self.revisionactive:
             self.terminal.error('Already showing latest revision')
         else:
             currenttab = self.tabbar.currentIndex()
             self.set_tab_index(currenttab)
     else:
         self.terminal.error('Unknown argument: "{}"'.format(arg))
Exemple #5
0
    def __init__(self, parent):
        super().__init__(parent)
        self.fullscreen = False
        self.setDisabled(True)

        hotkeypairs = (
            ('home', self.goto_index),
            ('toggle fullscreen', self.toggle_fullscreen),
            ('zoom in', self.zoom_in),
            ('zoom out', self.zoom_out),
            ('reset zoom', self.zoom_reset)
        )
        self.hotkeys = {
            key: QtGui.QShortcut(QtGui.QKeySequence(), self, callback)
            for key, callback in hotkeypairs
        }

        self.template = read_file(local_path(join('templates', 'viewer_page_template.html')))
        self.css = "" # Is set every time the config is reloaded
        self.rawtext = ""
        self.formatconverters = []
        self.chapterstrings = []

        # Layout
        layout = QtGui.QVBoxLayout(self)
        kill_theming(layout)

        self.webview = QtWebKit.QWebView(self)
        layout.addWidget(self.webview)
        layout.setStretchFactor(self.webview, 1)
        self.webview.settings().setDefaultTextEncoding('utf-8')

        self.info_panel = InfoPanel(self)
        layout.addWidget(self.info_panel, 0)
Exemple #6
0
 def view_page(self, data):
     self.setEnabled(True)
     self.data = data
     self.info_panel.set_data(data)
     self.rawtext = format_rawtext(read_file(data.file), self.formatconverters,
                                   self.chapterstrings)
     self.set_html()
 def start_logging(self, arg):
     arg = arg.lower().strip()
     filepath = self.textarea.file_path
     if not filepath:
         self.error('Can\'t log an unnamed file! Save and try again (without offset)')
         return
     # Paths
     logdir, indexpath, relative_filepath = self.get_logpaths()
     index = get_index(indexpath)
     if not arg:
         if relative_filepath in index:
             self.print_('File is being logged.')
         else:
             self.print_('File is not being logged.')
         return
     if arg not in ('y','n'):
         self.error('Argument should be y/n! (use offset/no offset)')
         return
     if relative_filepath in index:
         self.error('File already logged!')
         return
     # Offsets
     if arg == 'y':
         offset = len(re.findall(r'\S+', read_file(self.textarea.file_path)))
     else:
         offset = 0
     # Init
     logfname = generate_logfilename(logdir, relative_filepath)
     index[relative_filepath] = logfname
     write_file(join(logdir, logfname), str(offset) + '\n')
     write_json(indexpath, index)
     self.print_('Started logging file!')
Exemple #8
0
    def save_tab(self):
        """
        Attempt to save the active tab, both the text and the scrollbar/cursor
        position.

        Return True if it succeeds, return False if it fails.
        """
        if self.revisionactive:
            return True
        currenttab = self.tabbar.currentIndex()
        if self.textarea.document().isModified():
            try:
                fname = join(self.root, self.tabbar.current_page_fname())
                firstline, _ = read_file(fname).split('\n', 1)
                data = self.textarea.toPlainText()
                write_file(fname, firstline + '\n' + data)
            except Exception as e:
                print(str(e))
                self.terminal.error('Something went wrong when saving! (Use q! to force)')
                return False
        cursorpos = self.textarea.textCursor().position()
        scrollpos = self.textarea.verticalScrollBar().sliderPosition()
        self.tabbar.set_page_position(currenttab, cursorpos, scrollpos)
        self.textarea.document().setModified(False)
        return True
Exemple #9
0
def index_stories(path):
    """
    Find all files that match the filter, and return a sorted list
    of them with wordcount, paths and all data from the metadata file.
    """
    attributes = (
        ('title', {'filter': 'text', 'parser': 'text'}),
        ('tags', {'filter': 'tags', 'parser': 'tags'}),
        ('description', {'filter': 'text', 'parser': 'text'}),
        ('wordcount', {'filter': 'number'}),
        ('current_page', {'filter': 'number', 'parser': 'text'}),
        ('length', {'filter': 'number', 'parser': 'text'}),
        ('file', {}),
        ('lastmodified', {'filter': 'number'}),
        ('metadatafile', {}),
    )
    metafile = lambda dirpath, fname: join(dirpath, '.'+fname+'.metadata')
    files = ((read_json(metafile(dirpath, fname)), join(dirpath, fname), metafile(dirpath, fname))
             for dirpath, _, filenames in os.walk(path)
             for fname in filenames
             if exists(metafile(dirpath, fname)))
    entries = ((metadata['title'],
                frozenset(metadata['tags']),
                metadata['description'],
                len(re.findall(r'\S+', read_file(fname))),
                int(metadata['current_page']),
                int(metadata['length']),
                fname,
                os.path.getmtime(fname),
                metadatafile)
               for metadata, fname, metadatafile in files)
    return attributes, entries
Exemple #10
0
def get_anime_images(rootdir):
    from urllib.request import urlretrieve
    outdir = local_path('imgcache')
    rx = r'<a href="http://myanimelist.net/anime/\d+/.+?/pics">\s*<img src="(http://.+?)" alt'
    for fname in os.listdir(rootdir):
        rawdata = read_file(os.path.join(rootdir, fname))
        imgurl = re.search(rx, rawdata).group(1)
        urlretrieve(imgurl, os.path.join(outdir, fname + '.jpg'))
Exemple #11
0
 def cmd_print_filename(self, arg):
     fname = self.current_page_path()
     if arg == 'c':
         firstline, _ = read_file(fname).split('\n', 1)
         date = json.loads(firstline)['created']
         self.terminal.print_('File created at ' + date)
     else:
         self.terminal.print_(self.tabbar.current_page_fname())
 def read_config(self):
     # config
     configfile = os.path.join(self.configpath, 'kalpana-chapters.conf')
     make_sure_config_exists(configfile, os.path.join(self.pluginpath, 'default_config.json'))
     self.sidebar.settings = read_json(configfile)
     # stylesheet
     cssfile = os.path.join(self.configpath, 'kalpana-chapters.css')
     make_sure_config_exists(cssfile, os.path.join(self.pluginpath, 'default_theme.css'))
     self.sidebar.setStyleSheet(parse_stylesheet(read_file(cssfile)))
Exemple #13
0
def save_pages(path, name, pages):
    template = read_file(local_path('pagetemplate.html'))
    for n, page in enumerate(pages):
        controls = gen_controls(name, n, len(pages))
        out = template.format(controls=controls, **page)
        fpath = os.path.join(path, name)
        if len(pages) > 1:
            fpath += ' - Page {:03}'.format(n + 1)
        fpath += '.html'
        write_file(fpath, out)
Exemple #14
0
def save_pages(path, name, pages):
    template = read_file(local_path('pagetemplate.html'))
    for n, page in enumerate(pages):
        controls = gen_controls(name, n, len(pages))
        out = template.format(controls=controls, **page)
        fpath = os.path.join(path, name)
        if len(pages) > 1:
            fpath += ' - Page {:03}'.format(n+1)
        fpath += '.html'
        write_file(fpath, out)
Exemple #15
0
 def add_to_recent_files(self, filename):
     listfname = self.get_path('recentfiles')
     length = self.get_setting('recent file list length')
     # This fixes both symlinks and relative paths
     realfname = os.path.realpath(filename)
     recentfiles = [realfname]
     if os.path.exists(listfname):
         oldrecentfiles = read_file(listfname).splitlines()
         recentfiles += [x for x in oldrecentfiles if x != realfname][:length-1]
     write_file(listfname, '\n'.join(recentfiles))
     self.update_recent_files.emit()
Exemple #16
0
    def reload_settings(self):
        self.defaultstyle = read_json(local_path('defaultstyle.json'))
        self.css_template = read_file(local_path(join('templates','template.css')))
        self.index_css_template = read_file(local_path(join('templates','index_page.css')))

        settings, style, stylepath = read_config(self.configdir, self.defaultstyle)
        # TODO: FIX THIS UGLY ASS SHIT
        # Something somewhere f***s up and changes the settings dict,
        # therefor the deepcopy(). Fix pls.
        #if settings != self.settings:
        if settings['title']:
            self.setWindowTitle(settings['title'])
        else:
            self.setWindowTitle('Nomia')
        self.settings = copy.deepcopy(settings)
        self.index_viewer.update_settings(settings)
        self.popuphomekey.setKey(QtGui.QKeySequence(settings['hotkey home']))
        #if style != self.style:
        self.style = style.copy()
        self.update_style(style)
        write_json(stylepath, style)
Exemple #17
0
 def set_page(self,
              text: Optional[str] = None,
              fname: Optional[str] = None,
              css: Optional[str] = default_css,
              format: str = 'auto') -> None:
     assert (text and not fname) or (fname and not text)
     if not css:
         css = default_css
     if not text:
         text = read_file(fname)
     page = generate_page(text, fname, css, format)
     self.setHtml(page)
 def on_save(self):
     logdir, indexpath, relative_filepath = self.get_logpaths()
     index = get_index(indexpath)
     # Abort if the current file isn't in the index (= isn't being logged)
     if relative_filepath not in index:
         return
     logfile = join(logdir, index[relative_filepath])
     wc = self.textarea.get_wordcount()
     lastwc = read_file(logfile).splitlines()[-1].split(';',1)[-1]
     if int(lastwc) == wc:
         return
     data = '{};{}\n'.format(datetime.now(), wc)
     with open(logfile, 'a', encoding='utf-8') as f:
         f.write(data)
Exemple #19
0
 def cmd_rename_current_page(self, title):
     if not title.strip():
         oldtitle = self.tabbar.pages[self.tabbar.currentIndex()][0]
         self.terminal.prompt('r {}'.format(oldtitle))
         return
     try:
         self.tabbar.rename_page(title)
     except KeyError as e:
         self.terminal.error(e.args[0])
     else:
         fname = self.current_page_path()
         firstline, data = read_file(fname).split('\n', 1)
         jsondata = json.loads(firstline)
         jsondata['title'] = title
         write_file(fname, json.dumps(jsondata) + '\n' + data)
Exemple #20
0
    def __init__(self, configdir):
        super().__init__()
        self.paths = get_paths(configdir)
        for x in ('config_dir', 'plugins', 'spellcheck-pwl'):
            if not exists(self.paths[x]):
                os.makedirs(self.paths[x], mode=0o755, exist_ok=True)
        self.current_style = {}
        self.css_template = common.read_file(common.local_path('template.css'))

        self.default_config = get_default_config()
        self.auto_setting_acronyms = get_auto_setting_acronym(self.default_config)
        self.setting_types = get_setting_types(self.default_config)
        self.setting_callbacks = defaultdict(list)

        self.auto_settings, self.manual_settings = {}, {}
        self.settings = ChainMap()
Exemple #21
0
    def load_tab(self, newtab):
        """
        Load a new tab with the correct data and scrollbar/cursor position.

        Note that this does not in any way save existing data.
        """
        self.tabbar.setCurrentIndex(newtab)
        self.update_tabcounter()
        fname = self.current_page_path()
        _, data = read_file(fname).split('\n', 1)
        self.textarea.setPlainText(data)
        self.textarea.document().setModified(False)
        # Set the scrollbar/cursor positions
        cursorpos, scrollpos = self.tabbar.get_page_position(newtab)
        tc = self.textarea.textCursor()
        tc.setPosition(min(cursorpos, self.textarea.document().characterCount()-1))
        self.textarea.setTextCursor(tc)
        self.textarea.verticalScrollBar().setSliderPosition(scrollpos)
Exemple #22
0
def get_backstory_data(fname):
    out = {'wordcount': 0, 'pages': 0}
    root = fname + '.metadir'
    if not os.path.isdir(root):
        return out
    for dirpath, _, filenames in os.walk(root):
        for f in filenames:
            # Skip old revision files
            if re.search(r'\.rev\d+$', f) is not None:
                continue
            try:
                data = read_file(join(dirpath, f)).split('\n',1)[1]
                words = len(re.findall(r'\S+', data))
            except:
                # Just ignore the file if something went wrong
                # TODO: add something here if being verbose?
                pass
            else:
                out['wordcount'] += words
                out['pages'] += 1
    return out
Exemple #23
0
def get_plugins(plugin_root_path, loadorder_path):
    # Create the loadorder file if it doesn't exist
    if not os.path.exists(loadorder_path):
        open(loadorder_path, 'w').close()
    loadorder = [l for l in common.read_file(loadorder_path).splitlines()
                 if l and not l.startswith('#')]
    out = []
    for plugin_name in loadorder:
        plugin_path = join(plugin_root_path,plugin_name)
        if not os.path.exists(plugin_path):
            print("Plugin directory {} doesn't exist.".format(plugin_name))
            continue
        sys.path.append(plugin_path)
        try:
            loaded_plugin = importlib.import_module(plugin_name)
        except ImportError:
            print("Plugin {} could not be imported. Most likely because it's "
                  "not a valid plugin.".format(plugin_name))
        else:
            print("Plugin {} loaded.".format(plugin_name))
            out.append((plugin_name, plugin_path, loaded_plugin))
    return out
Exemple #24
0
 def load_pages(self, root):
     """
     Read all pages from the specified directory and build a list of them.
     """
     fnames = os.listdir(root)
     for f in fnames:
         if re.search(r'\.rev\d+$', f) is not None:
             continue
         if os.path.isdir(join(root, f)):
             continue
         firstline, data = read_file(join(root, f)).split('\n', 1)
         try:
             jsondata = json.loads(firstline)
         except ValueError:
             self.print_('Bad/no properties found on page {}, fixing...'.format(f))
             title = fixtitle(f)
             jsondata = generate_page_metadata(title)
             write_file(join(root, f), '\n'.join([jsondata, firstline, data]))
             yield [title, f, 0, 0]
         else:
             fixedjsondata = check_and_fix_page_metadata(jsondata, data, join(root, f))
             yield [fixedjsondata['title'], f, 0, 0]
Exemple #25
0
def extract_html_data(rootdir):
    """
    Get the relevant data from the files:
    * Studio(s)
    * Episode length
    * Rating
    """
    ratingrx = r'<span.+?>Rating:</span>\s*(\S+?)\s+-\s+.+?\s*</div>'
    studiorx = r'<span.+?>Studios:</span>\s*<a href="/anime/producer/\d+/.+?" title=".+?">(.+?)</a>'
    nostudiorx = r'<span.+?>Studios:</span>\s*None found, <a href=".+?">add some</a>'
    eplengthrx = r'<span.+?>Duration:</span>\s*((?P<hours>\d+)\s+hr\.\s*)?((?P<mins>\d+)\s+min\.\s*)?(per\s+ep\.)?\s*</div>'
    data = {}
    for fname in os.listdir(rootdir):
        rawdata = read_file(os.path.join(rootdir, fname))
        try:
            rating = re.search(ratingrx, rawdata).group(1)
        except AttributeError:
            print('rating', fname)
            return
        try:
            studio = re.search(studiorx, rawdata).group(1)
        except AttributeError:
            if re.search(nostudiorx, rawdata) is not None:
                studio = ''
            else:
                print('studio', fname)
        try:
            raweplength = re.search(eplengthrx, rawdata).groupdict(0)
        except AttributeError:
            print('ep length', fname)
            return
        eplength = int(raweplength['hours'])*3600 + int(raweplength['mins'])*60
        data[fname] = {
            'rating': unescape(rating),
            'studio': unescape(studio),
            'episode_length': eplength
        }
    return data
Exemple #26
0
                format = 'html'
            elif ext == '.txt':
                format = 'rawtext'
            else:
                format = fallback
        else:
            format = fallback
    # Check to see if the markdown lib exists
    if format == 'markdown' and not markdown_available:
        format = fallback
    # Check if format is supported at all
    if format not in formats:
        format = fallback
    # Parse the shit
    if format == 'rawtext':
        body = html.escape(text).replace('\n', '<br>')
        return html_boilerplate.format(body='<pre>{}</pre>'.format(body), css=css)
    elif format == 'markdown':
        body = markdown.markdown(text)
        return html_boilerplate.format(body=body, css=css)
    elif format == 'html':
        return text


if __name__ == '__main__':
    from libsyntyche.common import write_file
    fname = '/home/nycz/gitprojects/sapfo/README.md'
    text = read_file(fname)
    page = generate_page(text, fname, '', 'auto')
    write_file('/home/nycz/gitprojects/libsyntyche/test.html', page)
Exemple #27
0
 def __init__(self, textarea, local_path):
     super().__init__()
     self.html = read_file(os.path.join(local_path, 'sidebar.html'))
     self.setStyleSheet("Sidebar {border: 0px; border-left: 2px solid #111}")
     self.setReadOnly(True)
     self.hide()
Exemple #28
0
 def update_recent_files(self):
     listfname = self.get_path('recentfiles')
     if not os.path.exists(listfname):
         return
     self.recent_files = read_file(listfname).splitlines()
     self.recent_files_index = 0