Exemple #1
0
  def _updateThread(self, thread, encoding=None, ignoreType=False):
    """
    @param  thread  textman.TextThread
    @param  ignoreType  bool
    """
    encoding = encoding or self._encoding()
    keepsThreads = self._keepsThreads()
    try:
      view = self._threadViews[thread.signature]
      if not ignoreType:
        view.setThreadType(thread.type)
      view.setKeepsThreads(keepsThreads)
    except KeyError:
      skevents.runlater(self.q.sizeChanged.emit)
      view = self._threadViews[thread.signature] = TextThreadView(
          name=thread.name, signature=thread.signature)
      if not ignoreType:
        view.setThreadType(thread.type)
      if keepsThreads:
        view.setKeepsThreads(keepsThreads)
      view.threadTypeChanged.connect(self._setThreadType)
      view.threadTypeChanged.connect(self._refreshSaveButton)

      n = self.threadLayout.count()
      row = n / THREADLAYOUT_COLUMN_COUNT
      col = n % THREADLAYOUT_COLUMN_COUNT
      self.threadLayout.addWidget(view, row, col)

    f = lambda it: self._transformText(textutil.to_unicode(it, encoding))
    text = '\n\n'.join(imap(f, thread.data))
    view.setText(text)
Exemple #2
0
    def quit(self):
        if self.hasQuit:
            return

        self.hasQuit = True

        import curtheme
        curtheme.unload()

        for w in self.widgets:
            if w.isVisible():
                w.hide()

        # wait for for done or kill all threads
        from PySide.QtCore import QThreadPool
        if QThreadPool.globalInstance().activeThreadCount():
            dwarn("warning: wait for active threads")
            QThreadPool.globalInstance().waitForDone(config.QT_THREAD_TIMEOUT)
            dprint("leave qthread pool")

        dprint("send quit signal to qApp")
        qApp = QCoreApplication.instance()

        # Make sure settings.sync is the last signal conneced with aboutToQuit
        #qApp.aboutToQuit.connect(self.settings.sync)

        skevents.runlater(qApp.quit)
Exemple #3
0
    def _createView(self, signature, role, text=''):
        """
    @param  text  unicode
    @param  signature  long
    @param  role  int
    @return  TextThreadView
    """
        skevents.runlater(self.q.sizeChanged.emit)
        view = self._threadViews[signature] = TextThreadView(
            signature=signature)
        if role and role != defs.OTHER_TEXT_ROLE:
            view.setRole(role)
        #if not ignoreType:
        #  view.setThreadType(thread.type)
        view.roleChanged.connect(self._setRole)
        view.roleChanged.connect(self._refreshSaveButton)

        n = self.threadLayout.count()
        row = n / THREADLAYOUT_COLUMN_COUNT
        col = n % THREADLAYOUT_COLUMN_COUNT
        self.threadLayout.addWidget(view, row, col)

        if text:
            view.setText(text)
        return view
Exemple #4
0
  def run(self, args):
    """Starting point for the entire app
    @param  args  [unicode]
    """
    dprint("enter: args =", args)
    args = args[2:] # remove the leading python exe and the script name

    d = self.__d
    args = [it for it in args if not it.startswith('--')]
    if len(args) < 2:
      dwarn("missing arguments")
      d.quit()
    else:
      d.setLocation(args[0])
      d.setVideoIds(uniquelist(args[1:]))
      if len(d.vids) > 1:
        d.createLog()
      dprint("show root window")

      #d.window.debugRequested.connect(d.solver.show)

      d.window.show()

      skevents.runlater(d.start)

    dprint("leave")
Exemple #5
0
  def quit(self):
    if self.hasQuit:
      return

    self.hasQuit = True

    dprint("schedule to kill all python instances in a few seconds")
    skevents.runlater(lambda:
        os.system("tskill pythonw & tskill python"),
        config.QT_QUIT_TIMEOUT + config.QT_THREAD_TIMEOUT)

    # wait for for done or kill all threads
    from PySide.QtCore import QThreadPool
    if QThreadPool.globalInstance().activeThreadCount():
      dwarn("warning: wait for active threads")
      QThreadPool.globalInstance().waitForDone(config.QT_THREAD_TIMEOUT)
      dprint("leave qthread pool")

    dprint("send quit signal to qApp")
    qApp = QCoreApplication.instance()

    # Make sure settings.sync is the last signal conneced with aboutToQuit
    #qApp.aboutToQuit.connect(self.settings.sync)

    skevents.runlater(qApp.quit)
Exemple #6
0
 def _submitPost(self, postData, imageData):
     if self.topicId and netman.manager().isOnline():
         import forumapi
         skevents.runlater(
             partial(forumapi.manager().submitPost,
                     postData,
                     imageData,
                     topicId=self.topicId))
Exemple #7
0
 def initializePage(self):
   """@reimp @public"""
   self._complete = False
   profile = self.wizard().profile()
   if not profile.hasThread():
     skevents.runlater(lambda: (
       profile.updateThread(),
       profile.updateHook(),
     ), 200)
   dprint("pass")
Exemple #8
0
 def _save(self):
     item = self._currentItem()
     if item:  #and item.get('type') == self._selectedType():
         dprint("key: %s, title: %s" % (item['key'], item['title']))
         type = item['type']
         if type in ('digiket', 'gyutto', 'holyseal', 'melon', 'stream'):
             skevents.runlater(partial(self._saveNew, item),
                               200)  # runlater so that it won't block GUI
         else:
             self.q.itemSelected.emit(item)
Exemple #9
0
    def quit(self, interval=200):
        dprint("enter: interval = %i" % interval)
        d = self.__d
        if d.hasQuit:
            dprint("leave: has quit")
            return

        d.mainWindow.hide()

        skevents.runlater(self.__d.quit, interval)
        dprint("leave")
Exemple #10
0
    def _save(self):
        if not self._canSave():
            return
        q = self.q

        tm = textman.manager()

        agent = gameagent.global_()
        engine = agent.engine()
        engineName = defs.to_ith_engine_name(engine)

        scenesig = self._scenarioSignature()
        namesig = self._nameSignature()
        enc = self._encoding()
        lang = self._language()
        #threads = tm.threadsBySignature()
        changed = False
        if scenesig:
            if lang != tm.gameLanguage():
                dprint("language changed")
                changed = True
                skevents.runlater(partial(q.languageChanged.emit, lang))
            if scenesig != self._lastScenarioSignature or enc != self._lastEncoding:
                dprint("scenario thread changed")
                changed = True
                self._lastScenarioSignature = scenesig
                self._lastEncoding = enc
                agent.setEncoding(enc)
                agent.setScenarioSignature(scenesig)
                #name = threads[sig].name
                skevents.runlater(
                    partial(q.scenarioThreadChanged.emit, scenesig, engineName,
                            enc))

        if namesig != self._lastNameSignature:
            dprint("name thread changed")
            changed = True
            self._lastNameSignature = namesig
            agent.setNameSignature(namesig)
            if not namesig:
                skevents.runlater(q.nameThreadDisabled.emit)
            else:
                #name = threads[namesig].name
                skevents.runlater(
                    partial(q.nameThreadChanged.emit, namesig, engineName))

        #sig_set = set(self._otherSignatures())
        #if sig_set != tm.otherSignatures():
        #  dprint("other threads changed")
        #  changed = True
        #  skevents.runlater(partial(
        #      q.otherThreadsChanged.emit,
        #      {sig:threads[sig].name for sig in sig_set}))

        msg = (my.tr("Text settings are saved")
               if changed else my.tr("Text settings are not changed"))
        q.message.emit(msg)
        growl.msg(msg)

        dprint("pass")
Exemple #11
0
 def setVisible(self, value):
     """@reimp @public"""
     d = self.__d
     if value and not self.isVisible():
         d.refresh()
         gameId = d.gameId
         if gameId and netman.manager().isOnline():
             g = dataman.manager().queryGame(id=gameId)
             #if not g:
             #  skevents.runlater(d.updateAndRefresh, 2000) # 2 seconds
             #else:
             if g:
                 t = g.refsUpdateTime
                 now = skdatetime.current_unixtime()
                 if t + config.APP_UPDATE_REFS_INTERVAL < now:
                     g.refsUpdateTime = now
                     skevents.runlater(d.updateAndRefresh,
                                       2000)  # 2 seconds
     super(GameView, self).setVisible(value)
     if not value:
         d.webView.clear()
Exemple #12
0
  def dropMimeData(mime):
    """
    @param  mime  QMimeData
    """
    try:
      url = mime.urls()[0]
      path = url.toLocalFile()
      suf = os.path.splitext(path)[1]
      suf = suf[1:].lower()
      if suf in IMAGE_SUFFICES:
        dprint("drop image")
        settings.global_().setSpringBoardWallpaperUrl(url.toString())
      elif suf in ('exe', 'lnk'):
        dprint("drop game")

        import main
        #m = main.manager()
        #f = m.openGame if settings.global_().springBoardLaunchesGame() else m.addGame
        skevents.runlater(partial(main.manager().addGame, path=path), 200)
      else:
        derror("unreachable unknown suffix: %s" % suf)
    except (AttributeError, IndexError): pass
Exemple #13
0
  def setVisible(self, visible):
    """@reimp @public"""
    d = self.__d
    if visible:
      g = _gameprofile()
      icon = g.icon() if g else None
      if not icon or icon.isNull():
        icon = rc.icon('logo-reader')
      self.setWindowIcon(icon)

      title = "%s (%s)" % (
        mytr_("Text Settings"),
        my.tr("Engine: ITH"),
      )

      name = g.name() if g else None
      if name:
        title = "%s - %s" % (name, title)
      self.setWindowTitle(title)

    if visible:
      texthook.global_().hijackProcess()

    if visible != self.isVisible():
      if visible:
        d.clear()
        d.load()
        self.updateEnabled()
        skevents.runlater(self.updateSize)
      else:
        d.unload()

    texthook.global_().setWhitelistEnabled(not visible)

    d.setActive(visible)
    super(TextPrefsDialog, self).setVisible(visible)
Exemple #14
0
  def translateApply(self, func, text, fr='ja', to='', keepsNewLine=None, mark=None, scriptEnabled=None, ehndEnabled=None, rubyEnabled=None, context='', **kwargs):
    """Specialized for textman
    @param  func  function(unicode sub, unicode lang, unicode provider)
    @param  text  unicode
    @param* fr  unicode  language
    @param* mark  bool or None
    @param* kwargs  pass to func
    """
    if not features.MACHINE_TRANSLATION or not text:
      return
    d = self.__d
    if not to:
      to = d.language

    text = d.normalizeText(text)
    if mark is None:
      mark = d.marked

    #translators = d.iterTranslators(reverseOnline=True)
    translators = itertools.chain(
      d.iterOfflineTranslators(),
      d.iterOnlineTranslators(reverse=True),
    )
    for it in translators:
      kw = {'fr':fr, 'to':to, 'mark':mark, 'async':False, 'keepsNewLine':keepsNewLine, 'context':context}
      it = d.findRetranslator(it, to=to, fr=fr) or it

      align = None
      if it.alignSupported:
        if it.key == 'retr':
          if d.getAlignEnabled(it.second.key):
            align = []
        else:
          if d.getAlignEnabled(it.key):
            align = []
      kw['align'] = align

      if align is not None:
        kw['mark'] = False

      thisRubyEnabled = rubyEnabled if align is None else False

      if scriptEnabled != False:
        if it.key == 'retr':
          kw['scriptEnabled1'] = scriptEnabled or d.getScriptEnabled(it.first.key)
          kw['scriptEnabled2'] = scriptEnabled or d.getScriptEnabled(it.second.key)
        else:
          kw['scriptEnabled'] = scriptEnabled or d.getScriptEnabled(it.key)

      if it.key == 'eztrans':
        kw['ehndEnabled'] = ehndEnabled if ehndEnabled is not None else d.ehndEnabled
      if it.onlineRequired: #or it.parallelEnabled: # rush offline translation speed
        skevents.runlater(partial(d.translateAndApply,
            func, kwargs, it.translate, text, rubyEnabled=thisRubyEnabled, **kw))
      else:
        r = it.translate(text, **kw)
        if r and r[0]:
          t = r[0]
          if d.rubyEnabled and thisRubyEnabled == False:
            t = richutil.removeRuby(t)
          func(t, r[1], r[2], align, **kwargs)
Exemple #15
0
  def _save(self):
    if not self._canSave():
      return
    q = self.q

    tm = textman.manager()
    sig = self._scenarioSignature()
    namesig = self._nameSignature()
    enc = self._encoding()
    lang = self._language()
    threads = tm.threadsBySignature()
    changed = False
    if sig:
      if lang != tm.gameLanguage():
        dprint("language changed")
        changed = True
        skevents.runlater(partial(
            q.languageChanged.emit,
            lang))
      if sig != tm.scenarioSignature() or enc != tm.encoding():
        dprint("scenario thread changed")
        changed = True
        name = threads[sig].name if sig in threads else defs.NULL_THREAD_NAME
        skevents.runlater(partial(
            q.scenarioThreadChanged.emit,
            sig, name, enc))

    if namesig != tm.nameSignature():
      dprint("name thread changed")
      changed = True
      if not namesig or namesig not in threads:
        skevents.runlater(q.nameThreadDisabled.emit)
      else:
        name = threads[namesig].name
        skevents.runlater(partial(
            q.nameThreadChanged.emit,
            namesig, name))

    sig_set = set(self._otherSignatures())
    if sig_set != tm.otherSignatures():
      dprint("other threads changed")
      changed = True
      skevents.runlater(partial(
          q.otherThreadsChanged.emit,
          {sig:threads[sig].name for sig in sig_set}))

    if sig:
      if self._removesRepeat() != tm.removesRepeatText():
        changed = True
        skevents.runlater(partial(
            q.removesRepeatTextChanged.emit,
            self._removesRepeat()))

      if self._ignoresRepeat() != self.currentIgnoresRepeat:
        self.currentIgnoresRepeat = self._ignoresRepeat()
        changed = True
        skevents.runlater(partial(
            q.ignoresRepeatTextChanged.emit,
            self.currentIgnoresRepeat))

      if self._keepsSpace() != self.currentKeepsSpace:
        self.currentKeepsSpace = self._keepsSpace()
        changed = True
        skevents.runlater(partial(
            q.keepsSpaceChanged.emit,
            self.currentKeepsSpace))

      if self._keepsThreads() != tm.keepsThreads():
        changed = True
        skevents.runlater(partial(
            q.keepsThreadsChanged.emit,
            self._keepsThreads()))

    msg = (my.tr("Text settings are saved") if changed else
           my.tr("Text settings are not changed"))
    q.message.emit(msg)
    growl.msg(msg)

    dprint("pass")
Exemple #16
0
 def finishLater(self, timeout=0):
     from sakurakit import skevents
     img = QPixmap(rc.image_path('splash-ready'))
     self.setPixmap(img)
     skevents.runlater(self.finishWindow, timeout)
     dprint("pass")
Exemple #17
0
        """
    @param  data  [dataman.Comment|dataman.Term]
    """
        self.ready = False
        async = len(data) > 15000
        async = True
        cursor = skcursor.SkAutoBusyCursor(
        ) if async else skcursor.SkAutoWaitCursor()

        WINDOW_FLAGS = Qt.Dialog | Qt.WindowMinMaxButtonsHint
        super(ChartDialog, self).__init__(parent, WINDOW_FLAGS)
        skqss.class_(self, 'texture')
        self.resize(*_ChartDialog.SIZE)
        self.__d = _ChartDialog(self, data, async=async)

        skevents.runlater(partial(self.setReady, True))

    def isReady(self):
        return self.ready

    def setReady(self, val):
        self.ready = val

    #def setVisible(self, visible):
    #  """@reimp @public"""
    #  if visible and not self.isVisible():
    #    self.__d.refresh()
    #  super(ChartDialog, self).setVisible(visible)


## Dialogs ##
Exemple #18
0
 def _updateTopic(self, topicData, imageData, ticketData):
     if netman.manager().isOnline():
         import forumapi
         skevents.runlater(
             partial(forumapi.manager().updateTopic, topicData, imageData,
                     ticketData))
Exemple #19
0
    def save(self):
        if self._canSave():
            dm = dataman.manager()
            user = dm.user()
            if not user.name:
                return
            gameId = self.gameId or dm.currentGameId()
            md5 = dm.currentGameMd5()
            #if not gameId and not md5:
            #  return
            lang = self._getTargetLanguage()
            sourceLang = self._getSourceLanguage()
            type = self._getType()
            host = self._getHost() if type in dataman.Term.HOST_TYPES else ''
            context = self._getContext(
            ) if type in dataman.Term.CONTEXT_TYPES else ''
            role = self.roleEdit.text().strip(
            ) if type in dataman.Term.ROLE_TYPES else ''
            ruby = self.rubyEdit.text().strip(
            ) if type in dataman.Term.RUBY_TYPES else ''
            pattern = self.patternEdit.text().strip()
            comment = self.commentEdit.text().strip()
            text = self.textEdit.text().strip()
            priority = self._getPriority()
            if priority == len(pattern):
                priority = 0.0
            #regex = type == 'macro' or (self.regexButton.isChecked() and type != 'suffix')
            regex = type != 'proxy' and self.regexButton.isChecked(
            )  #and type != 'suffix')
            icase = type not in ('macro',
                                 'proxy') and self.icaseButton.isChecked()
            phrase = type not in ('macro',
                                  'proxy') and self.phraseButton.isChecked()
            #syntax = type == 'trans' and self.syntaxButton.isChecked() and not user.isGuest()
            special = self.specialButton.isChecked() and bool(gameId or md5)
            private = (type == 'proxy' or
                       self.privateButton.isChecked()) and not user.isGuest()
            ret = dataman.Term(
                gameId=gameId,
                gameMd5=md5,
                userId=user.id,
                language=lang,
                sourceLanguage=sourceLang,
                type=type,
                host=host,
                context=context,
                private=private,
                special=special,
                regex=regex,
                phrase=phrase,
                icase=icase,  #syntax=syntax,
                timestamp=skdatetime.current_unixtime(),
                priority=priority,
                pattern=pattern,
                text=text,
                ruby=ruby,
                role=role,
                comment=comment)

            self.clear()
            self.q.hide()

            skevents.runlater(partial(dm.submitTerm, ret), 200)

            from sakurakit.skstr import escapehtml
            growl.msg('<br/>'.join((
                my.tr("Add new term"),
                "%s = %s" % (escapehtml(pattern), escapehtml(text)
                             or "(%s)" % tr_('empty')),
            )))
Exemple #20
0
def main():
    """
  @return  int
  """
    import os, sys
    from PySide.QtCore import QTextCodec
    # Use UTF-8 encoding for Qt
    #sys_codec = QTextCodec.codecForLocale()
    u8codec = QTextCodec.codecForName("UTF-8")
    QTextCodec.setCodecForCStrings(u8codec)
    QTextCodec.setCodecForTr(u8codec)

    debug = '--debug' in sys.argv  # bool
    print >> sys.stderr, "reader: debug = %s" % debug

    from sakurakit import skdebug
    #skdebug.DEBUG = config.APP_DEBUG or '--debug' in sys.argv
    skdebug.DEBUG = debug

    import config
    config.APP_DEBUG = debug

    from sakurakit.skdebug import dprint, dwarn
    dprint("enter")

    if '--help' in sys.argv:
        print_help()
        dprint("exit: help")
        #sys.exit(os.EX_USAGE)
        return 0

    # Singleton
    # - Through mutex
    #   See: http://code.activestate.com/recipes/474070-creating-a-single-instance-application/
    #   See: http://code.google.com/p/python-windows-tiler/source/browse/singleinstance.py
    # - Through file
    #   See: http://stackoverflow.com/questions/380870/python-single-instance-of-program
    dprint("check single instance")

    from lockfile import lockfile

    app_mutex = lockfile.SingleProcessMutex()
    single_app = app_mutex.tryLock()
    if not single_app:
        dprint("multiple instances are running")

    dprint("python = %s" % sys.executable)
    #dprint("rootdir = %s" % rootdir)
    #dprint("mecabrc = %s" % mecabrc_path)

    from sakurakit import skos
    # Must be set before any GUI is showing up
    # http://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7
    if skos.WIN:
        dprint("set app id")
        from sakurakit import skwin
        skwin.set_app_id("org.sakurakit.reader")

    # Detect user language
    import settings

    ss = settings.global_()

    uilang = ss.uiLanguage()
    if not uilang:
        uilang = guess_language()
        ss.setValue('Language', uilang)

    lang = ss.userLanguage()
    if not lang:
        lang = guess_language()
        ss.setValue('UserLanguage', lang)

    dprint("user language = %s" % lang)

    # Warm-up shiboken dlls
    #if os.name == 'nt':
    #  dprint("load shiboken plugins")
    #  import pytexscript
    #  import pytexthook

    #Switch to OpenGL engine
    #from Qt5.QtWidgets import QApplication
    #QApplication.setGraphicsSystem("opengl")

    #dprint("elevate process priviledges")
    #from sakurakit import skos
    #if skos.WIN:
    #  from sakurakit import skwin
    #  skwin.enable_drop_event()

    dprint("init dic locations")
    from opencc import opencc
    opencc.setdicpaths(config.OPENCC_DICS)

    from hanviet import hanviet
    hanviet.setdicpaths(config.HANVIET_DICS)

    from hanjaconv import hanjaconv
    hanjaconv.setdicdir(config.HANJA_DIC_PATH)

    from pinyinconv import pinyinconv
    pinyinconv.setdicpath(config.PINYIN_DIC_PATH)

    dprint("create app")
    import app
    a = app.Application(sys.argv)

    #dprint("os default font:", a.font())
    #a.setFont(config.FONT_DEFAULT)
    #dprint("current default font:", a.font())

    # Fix the encoding issue for the current directory
    #from PySide.QtCore import QDir
    #QDir.setCurrent(a.applicationDirPath())

    if not single_app:
        from rpcman import RpcClient
        dprint("send metacall")
        r = RpcClient()
        r.start()
        if r.waitForConnected():
            r.activate()
            a.processEvents()
        else:
            dprint("warning: cannot connect to the server")
        dwarn("leave: multiple instance")
        #sys.exit(os.EX_UNAVAILABLE)
        return 0

    # Must come after QApplication is created
    dprint("load fonts")
    from PySide.QtGui import QFontDatabase
    for path in config.FONT_LOCATIONS.itervalues():
        if os.path.exists(path):
            for root, dirs, files in os.walk(path):
                FONT_EXTS = frozenset(('.otf', '.ttf', '.ttc'))
                for f in files:
                    if os.path.splitext(f.lower())[1] in FONT_EXTS:
                        p = os.path.join(root, f)
                        index = QFontDatabase.addApplicationFont(p)
                        if index >= 0:
                            dprint(
                                QFontDatabase.applicationFontFamilies(index))
                        else:
                            dwarn("failed to load font %s" % f)

    ff = config.ui_font(ss.uiLanguage())
    if ff:
        a.setFontFamily(ff)

    #ff = ss.applicationFontFamily()
    #if ff:
    #  dprint("font family = %s" % ff)
    #  a.setFontFamily(ff)
    #ss.applicationFontFamilyChanged.connect(a.setFontFamily)

    dprint("load translation")
    a.loadTranslations()

    dprint("autosync settings")
    ss.autoSync()  # Load before qapplication is created

    opt_splash = '--nosplash' not in sys.argv

    if opt_splash:
        dprint("show splash")
        from splashscreen import StartupSplashScreen
        splash = StartupSplashScreen()
        splash.show()

    a.processEvents()  # process event to make it show

    #dprint("cache fonts")
    #import fonts
    #fonts.test()

    # Take the ownership of sakurakit translation
    dprint("take the ownership of translations")
    from sakurakit import sktr
    sktr.manager().setParent(a)

    import mytr
    mytr.manager().setParent(a)
    mytr.my.setParent(a)

    # There should be at least one existing window (rootWindow), or sth is wrong
    #a.setQuitOnLastWindowClosed(False)

    #dprint("check unicode codec")
    #from sakurakit.skunicode import qunicode
    #ustr = qunicode("あのね", 'utf8')
    #assert ustr, "failed to load text code plugin from qt.conf"

    #dprint('init directories')
    #from PySide.QtCore import QDir

    import rc
    from sakurakit import skfileio
    dprint("remove broken caches")
    for it in rc.DIR_APP_TMP, :
        if os.path.exists(it):
            skfileio.removetree(it)

    map(
        skfileio.makedirs,
        (
            rc.DIR_YAML_SUB,
            rc.DIR_XML_COMMENT,
            rc.DIR_XML_VOICE,
            rc.DIR_XML_REF,
            #rc.DIR_DICT_MECAB, # not used
            rc.DIR_CACHE_AVATAR,
            rc.DIR_CACHE_AWS,
            rc.DIR_CACHE_DATA,
            rc.DIR_CACHE_IMAGE,
            rc.DIR_CACHE_DMM,
            rc.DIR_CACHE_TOKUTEN,
            rc.DIR_CACHE_FREEM,
            rc.DIR_CACHE_STEAM,
            rc.DIR_CACHE_MELON,
            rc.DIR_CACHE_GETCHU,
            rc.DIR_CACHE_GYUTTO,
            rc.DIR_CACHE_DIGIKET,
            rc.DIR_CACHE_DLSITE,
            rc.DIR_CACHE_HOLYSEAL,
            rc.DIR_CACHE_SCAPE,
            rc.DIR_CACHE_TRAILERS,
            rc.DIR_CACHE_WEB,
            rc.DIR_CACHE_SYNC,
            rc.DIR_TMP_OCR,
            rc.DIR_TMP_TERM,  # not needed, though
            rc.DIR_TMP_TTS,
        ))

    if skos.WIN:
        from sakurakit import skwin
        for it in rc.DIR_APP_LIBRARY, rc.DIR_APP_CACHE:
            if os.path.exists(it):
                skwin.set_file_readonly(it)

    dprint("load settings")
    ss.setParent(a)

    dprint("append library path")

    from sakurakit import skpaths
    skpaths.append_paths((
        # TransCAT must be initialized BEFORE JBeijing, or the translation will fail
        ss.transcatLocation(),
        ss.jbeijingLocation(),
        ss.ezTransLocation(),
        ss.atlasLocation(),
        ss.zunkoLocation(),
        ss.localeEmulatorLocation(),
        ss.ntleasLocation(),
        os.path.join(ss.dreyeLocation(), r"DreyeMT\SDK\bin")
        if ss.dreyeLocation() else "",
    ))

    path = ss.lecLocation()
    if path:
        skpaths.append_paths((
            os.path.join(path, r"Nova\JaEn"),
            os.path.join(path, r"PARS\EnRU"),
        ))

    path = ss.fastaitLocation()
    if path:
        path = os.path.join(path, 'GTS')
        if os.path.exists(path):
            dllpaths = skfileio.listdirs(path)
            if dllpaths:
                skpaths.append_paths(dllpaths)

    if sys.getrecursionlimit() < config.PY_RECURSION_LIMIT:
        dprint("increase recursion limit")
        sys.setrecursionlimit(config.PY_RECURSION_LIMIT)

    dprint("reduce socket timeout")
    import socket
    socket.setdefaulttimeout(config.PY_SOCKET_TIMEOUT)

    #import threading
    #if threading.stack_size() < config.PY_STACK_SIZE:
    #  dprint("increase stack size")
    #  threading.stack_size(config.PY_STACK_SIZE)

    # On unix:
    # stackoverflow.com/questions/5061582/setting-stacksize-in-a-python-script
    #import resource
    #resource.setrlimit(resource.RLIMIT_STACK, (2**29,-1))

    dprint("config python site-packages")

    # Disable requests SSL certificate warning
    # https://github.com/kennethreitz/requests/issues/2214
    import requests
    requests.packages.urllib3.disable_warnings()

    # Disable HTTP request session
    # See: http://docs.python-requests.org/en/latest/user/advanced/#keep-alive
    # See: http://stackoverflow.com/questions/10115126/python-requests-close-http-connection
    #import requests
    #s = requests.session()
    #s.config['keep_alive'] = False

    import numpy
    numpy.seterr(all='ignore')  # ignore overflow warning

    dprint("update settings")

    ss_version = ss.version()
    if ss_version != config.VERSION_TIMESTAMP:
        dprint("app update detected, migrate settings")
        if ss_version:
            migrate(ss_version)

        from sakurakit import skdatetime
        ss.setUpdateTime(skdatetime.current_unixtime())

        ss.setVersion(config.VERSION_TIMESTAMP)
        ss.sync()

    if not ss.userName() or not ss.userId():
        dprint("set user credential to guest")
        # Must be consistent with dataman.GUEST
        ss.setValue('UserId', 4)
        ss.setValue('UserName', 'guest')
        ss.setValue('UserPassword', 'guest')
        ss.setValue('UserGender', '')
        ss.setValue('UserAvatar', '')
        ss.setValue('UserColor', '')

    if ss.isCursorThemeEnabled():
        dprint("load cursor theme")
        import curtheme
        curtheme.load()

    # Disable RBMT if CaboCha or UniDic is disabled
    #if ss.isTranslationSyntaxEnabled() and not (
    #    ss.isCaboChaEnabled() and ss.meCabDictionary() == 'unidic'):
    #  ss.setTranslationSyntaxEnabled(False)

    #dprint("set max thread count")
    from PySide.QtCore import QThreadPool
    currentThreadCount = QThreadPool.globalInstance().maxThreadCount()
    if currentThreadCount < config.QT_THREAD_COUNT:
        dprint("increase thread pool capacity: %s -> %s" %
               (currentThreadCount, config.QT_THREAD_COUNT))
        QThreadPool.globalInstance().setMaxThreadCount(config.QT_THREAD_COUNT)

    dprint("register qml plugins")
    import qmlplugin

    dprint("query system metrics")
    import sysinfo

    dprint("create main object")

    import main
    m = main.MainObject(a)
    m.init()

    if opt_splash:
        dprint("schedule to finish splash")
        splash.finishLater(1500)  # hide after 1.5 seconds

    from functools import partial
    from sakurakit import skevents
    skevents.runlater(partial(m.run, a.arguments()), 50)
    #m.run(a.arguments())

    #import netman
    #netman.manager().queryComments(gameId=183)

    #import hashutil
    #print hashutil.md5sum('/Users/jichi/tmp/t.cpp')

    dprint("exec")
    returnCode = a.exec_()

    # FIXME: Cannot normally exit
    # Shiboken 1.2 hang on exit!
    # All destructors are Invoked!

    dprint("unlock the mutex")
    app_mutex.unlock()

    import defs
    if returnCode == defs.EXIT_RESTART:
        skos.restart_my_process(['-B'])  # -B: force disabling *.pyc and *.pyo
    else:
        #sys.exit(returnCode)
        #if skos.WIN: # prevent hanging on windows/mac
        skos.kill_my_process()