def addAction(self, objectName, icon, text, shortcut = "", slot = None, menuName = None):
    act = KAction(KIcon(icon), text, self)
    act.setObjectName(objectName)
    
    # Set shortcut
    if not act.objectName() in kate.configuration:
        kate.configuration[act.objectName()] = shortcut
    act.setShortcut(kate.configuration[act.objectName()])

    # Set slots
    if slot != None:
        act.triggered.connect( slot )
    kate.mainInterfaceWindow().window().actionCollection().addAction(act.objectName(), act)
    
    # Add to menu
    if menuName != None:
      menu = kate.mainInterfaceWindow().window().findChild(QMenu, menuName.lower())
      if menu == None:
        menu = kate.mainInterfaceWindow().window().menuBar().addMenu(menuName)
      menu.addAction(act)

    # Save changes to shortcut
    act.changed.connect( self.onActionChange )
    
    return act
Exemple #2
0
    def setupActions (self):
        clearAction = KAction(KIcon("edit-clear"), i18n("Clear"), self)
        

        dfltShortcut   = KAction.ShortcutTypes (KAction.DefaultShortcut)
        activeShortcut = KAction.ShortcutTypes (KAction.ActiveShortcut)

        clearAction.setShortcut(Qt.CTRL+Qt.Key_W, dfltShortcut | activeShortcut)

        self.actionCollection().addAction("clear", clearAction)

        self.connect (clearAction, SIGNAL ("triggered(bool)"), self.textArea.clear)

 
        KStandardAction.quit (app.quit, self.actionCollection())

        self.setupGUI(QSize (600, 400), KXmlGuiWindow.Default, os.path.join (sys.path [0], "kactionui.rc"))
Exemple #3
0
    def setupActions(self):
        clearAction = KAction(KIcon("edit-clear"), i18n("Clear"), self)

        dfltShortcut = KAction.ShortcutTypes(KAction.DefaultShortcut)
        activeShortcut = KAction.ShortcutTypes(KAction.ActiveShortcut)

        clearAction.setShortcut(Qt.CTRL + Qt.Key_W,
                                dfltShortcut | activeShortcut)

        self.actionCollection().addAction("clear", clearAction)

        self.connect(clearAction, SIGNAL("triggered(bool)"),
                     self.textArea.clear)

        KStandardAction.quit(app.quit, self.actionCollection())

        self.setupGUI(QSize(600, 400), KXmlGuiWindow.Default,
                      os.path.join(sys.path[0], "kactionui.rc"))
Exemple #4
0
def create (parent, ac):
    """here be common actions for satyr skins"""
    actions= (
        ('queue',    Qt.CTRL+Qt.Key_Q, False, "Queue songs"),
        ('rename',   Qt.CTRL+Qt.Key_R, False, "Arrange songs"),
        ('toggleVA', Qt.CTRL+Qt.Key_V, False, "Toggle 'Various Artists' flag"),
        ('delete',   Qt.CTRL+Qt.Key_D, False, "Delete songs"),

        # globals
        ('player.prev',  KShortcut (Qt.Key_MediaPrevious),  True, "Previous song"),
        ('player.stop',  KShortcut (Qt.Key_MediaStop),      True, "Stop"),
        ('player.play',  KShortcut (Qt.Key_MediaPlay),      True, "Play"),
        ('player.pause', KShortcut (Qt.Key_Pause),     True, "Toggle Pause"),
        ('player.play_pause', KShortcut (Qt.Key_MediaPlay), True, "Switch between Play and Pause"),
        ('player.next',  KShortcut (Qt.Key_MediaNext),      True, "Next song"),
        ('player.toggleStopAfter', KShortcut (Qt.Key_Eject), True, "Stop after playing current song"),
        # TODO: S-Play/Pause -> cycle random
        # TODO: S-|<</>>| -> beginning/prev album, next album
        )

    for fqn, shortcut, globalSC, text in actions:
        try:
            obj, name= traverseObjects (parent, fqn)
        except AttributeError, e:
            logger.warning ("actions.create(): %s, shortcut for %s not set", e.args[0], fqn)
        else:
            fqn= "satyr."+fqn
            action= KAction (text, parent)
            action.setObjectName (fqn)
            if globalSC:
                action.setGlobalShortcut (shortcut)
            else:
                action.setShortcut (shortcut)
            ac.addAction (fqn, action)

            # the skin can decide to not implement an action!
            method= getattr (obj, name, None)
            if method is not None:
                action.triggered.connect (method)
            else:
                logger.warning ("actions.create(): no method %s, shortcut for %s not set", name, fqn)
Exemple #5
0
 def __init__(self, tool, part):
     super(Player, self).__init__(tool.mainwin)
     self.player = part
     self._currentFile = None
     self._currentFileList = None
     self._tempo = 60.0
     
     layout = QGridLayout()
     self.setLayout(layout)
     layout.setSpacing(0)
     
     fl = self.fileList = QComboBox()
     fl.activated.connect(self.slotItemActivated)
     fl.setEnabled(False)
     layout.addWidget(fl, 0, 0, 1, 2)
     
     pb = self.pauseButton = QToolButton()
     pb.setIcon(KIcon('media-playback-pause'))
     pb.clicked.connect(self.pause)
     pb.setToolTip(i18n("Pause"))
     layout.addWidget(pb, 1, 0)
     
     lcd = self.lcd = QLCDNumber()
     lcd.setMaximumHeight(60)
     lcd.setSegmentStyle(QLCDNumber.Flat)
     lcd.setStyleSheet("""QLCDNumber {
         border-width: 5 3 2 4;
         border-image: url('css:lcd-borders.png') repeat;
         background-image: url('css:lcd-background.png') repeat;
         color: #151B19;
     }""")
     layout.addWidget(lcd, 2, 0, 1, 2)
     
     vs = self.volumeSlider = QSlider(Qt.Vertical)
     vs.setRange(0, 20)
     vs.setValue(int(self.readProperty('volumeFactor') * 10))
     vs.setToolTip(i18n("Volume"))
     layout.addWidget(vs, 0, 2, 3, 1)
     
     # KMid Part widget
     widget = self.widget = part.widget()
     layout.addWidget(widget, 1, 1)
     
     # make smaller
     widget.layout().setSpacing(0)
     widget.layout().setContentsMargins(0, 0, 0, 0)
     
     # set auto start off
     self.writeProperty('autoStart', False)
     
     # connect stuff
     part.connect(part, SIGNAL("stateChanged(int)"),
         self.slotStateChanged, Qt.QueuedConnection)
     part.connect(part, SIGNAL("beat(int,int,int)"), self.slotBeat)
     part.connect(part, SIGNAL("tempoEvent(double)"), self.slotTempoEvent)
     vs.valueChanged.connect(self.setVolumeFactor)
 
     tool.mainwin.aboutToClose.connect(self.quit)
     tool.mainwin.currentDocumentChanged.connect(self.setCurrentDocument)
     tool.mainwin.jobManager().jobFinished.connect(self.jobFinished)
     self.slotBeat(0, 0, 0)
     self.setCurrentDocument(tool.mainwin.currentDocument())
     
     # keyboard action to pause playback, works when the MIDI tool is visible
     # (hardcoded to Pause and MediaPlay)
     a = KAction(self)
     a.setShortcut(KShortcut(
         QKeySequence(Qt.Key_Pause), QKeySequence(Qt.Key_MediaPlay)))
     a.triggered.connect(self.slotPlayPause)
     self.addAction(a)
     
     # keyboard action to stop playback, ESC and MediaStop
     a = KAction(self)
     a.setShortcut(KShortcut(
         QKeySequence(Qt.Key_Escape), QKeySequence(Qt.Key_MediaStop)))
     a.triggered.connect(self.stop)
     self.addAction(a)
Exemple #6
0
class KateReload(QObject):
  def __init__(self):
    QObject.__init__(self)
    
    self.window = kate.mainInterfaceWindow().window()
    
    kate.configuration.root.clear()
    
    self.act = KAction(KIcon("reload"), i18n("Auto Reload"), self)
    self.act.setObjectName("auto reload")
        
    self.window.actionCollection().addAction(self.act.objectName(), self.act)    
    self.window.findChild(QMenu, 'view').addAction(self.act)

    if not self.act.objectName() in kate.configuration:
        kate.configuration[self.act.objectName()] = "alt+r"
    self.act.setShortcut(kate.configuration[self.act.objectName()])

    self.act.setCheckable(True)
    self.act.setChecked(False)

    
    self.act.changed.connect(self.onActionChange)
    self.act.toggled.connect(self.toggle)
    
    kate.mainInterfaceWindow().viewChanged.connect(self.onViewChanged)
        
  def onViewChanged(self):
      try:
        doc = sip.cast(kate.activeDocument(), KateDocument)
      except kate.api.NoActiveView:
        return
    
      self.act.blockSignals(True)
      if doc.property('AutoReload'):
          self.act.setChecked(True)
      else:
          self.act.setChecked(False)
      self.act.blockSignals(False)
      

  def onActionChange(self):
      kate.configuration[self.sender().objectName()] = self.sender().shortcut().toString()
      kate.configuration.save()
  
  def toggle(self, state):
      doc = sip.cast(kate.activeDocument(), KateDocument)
      if state == True:
        self.enable(doc)
      else:
        self.disable(doc)
  
  def enable(self, doc):
      if doc.url() == '':
        self.act.blockSignals(True)
        showError(i18n('Can\'t auto-reload unsaved file'))
        self.act.setChecked(False)
        self.act.blockSignals(False)
        return

      doc.setModifiedOnDiskWarning(False)
      doc.modifiedOnDisk.connect(doc.documentReload)
      doc.setProperty('AutoReload', True)
      
      showOk(i18n('Auto-Reload enabled'))
      
  def disable(self, doc):
      if doc.property('AutoReload'):
        doc.setModifiedOnDiskWarning(True)
        doc.modifiedOnDisk.disconnect(doc.documentReload)
        doc.setProperty('AutoReload', False)
        showOk(i18n('Auto-Reload disabled'))
      else:
        print('Error disabled called on something with no auto-reload')
Exemple #7
0
    def setupActions(self):
        """Sets up all actions (signal/slot combinations)."""
        # standard action
        KStandardAction.quit(g_app.quit, self.actionCollection())

        # dictionary actions
        self.dictionaryPage.registerGlobalActions(self.actionCollection())
        # update dictionaries
        if self.updateDialog:
            self.updateAction = self.updateDialog.updateAction(
                self.actionCollection())
            # optimise database
            self.updateDialog.optimiseAction(self.actionCollection())
        else:
            self.updateAction = None

        # search bar
        self.characterCombo = KHistoryComboBox()
        self.characterCombo.setSizePolicy(QSizePolicy.Expanding,
            QSizePolicy.Fixed)
        font = QFont()
        font.setPointSize(13)
        self.characterCombo.setFont(font)
        self.characterCombo.setObjectName("characterCombo")
        self.connect(self.characterCombo, SIGNAL("activated(const QString &)"),
            self.slotCharacterComboActivated)

        comboAction = KAction(self)
        comboAction.setText(i18n("Search bar"))
        comboAction.setShortcut(Qt.Key_F6)
        self.connect(comboAction, SIGNAL("triggered()"),
            self.slotSearchComboActivated)
        comboAction.setDefaultWidget(self.characterCombo)
        comboAction.setWhatsThis(
            i18n("<html>Search bar<br/><br/>Enter character of search string</html>"))
        self.actionCollection().addAction("searchbar", comboAction)

        goUrl = self.actionCollection().addAction("go_search")
        goUrl.setIcon(KIcon("go-jump-locationbar"))
        goUrl.setText(i18n("Go"))
        self.connect(goUrl, SIGNAL("triggered()"),
            lambda: self.slotCharacterComboActivated(
                self.characterCombo.currentText()))
        goUrl.setWhatsThis(
            i18n("<html>Go<br /><br />Searches for the string given in the search bar.</html>"))

        # clear search bar action
        clearLocationAction = KAction(KIcon("edit-clear-locationbar-ltr"),
            i18n("Clear &Location Bar"), self)
        clearLocationAction.setShortcut(Qt.CTRL + Qt.Key_L)
        clearLocationAction.setWhatsThis(
            i18n("Clears the location bar and places the cursor inside"))
        self.actionCollection().addAction("clearlocationbar",
            clearLocationAction)
        self.connect(clearLocationAction, SIGNAL("triggered(bool)"),
            self.characterCombo.clearEditText)
        self.connect(clearLocationAction, SIGNAL("triggered(bool)"),
            self.characterCombo.setFocus)

        # show/hide character page
        self.toggleToolboxAction = KToggleAction(KIcon("view-sidetree"),
            i18n("Show Character Toolbox"), self)
        self.toggleToolboxAction.setShortcut(Qt.Key_F9)
        self.toggleToolboxAction.setWhatsThis(
            i18n("Shows and Hides the character choosing toolbox"))
        self.actionCollection().addAction("showtoolbox",
            self.toggleToolboxAction)
        self.connect(self.toggleToolboxAction, SIGNAL("triggered(bool)"),
            self.slotToggleToolbox)

        # auto-lookup clipboard
        self.autoLookupAction = KToggleAction(i18n("&Auto-Lookup"), self)
        self.autoLookupAction.setToolTip(
            i18n("Automatically look up text selected by the mouse cursor."))
        self.autoLookupAction.setWhatsThis(
            i18n("Automatically look up text selected by the mouse cursor."))
        self.actionCollection().addAction("autolookup", self.autoLookupAction)
        self.connect(self.autoLookupAction, SIGNAL("triggered(bool)"),
            self.setAutoLookup)
        self.autoLookupAction.setIcon(
            QIcon(util.getIcon('auto-lookup-selection.png')))

        self.connect(QApplication.clipboard(), SIGNAL("selectionChanged()"),
            self.slotSelectionChanged)
Exemple #8
0
class KateReload(QObject):
    def __init__(self):
        QObject.__init__(self)

        self.window = kate.mainInterfaceWindow().window()

        kate.configuration.root.clear()

        self.act = KAction(KIcon("reload"), i18n("Auto Reload"), self)
        self.act.setObjectName("auto reload")

        self.window.actionCollection().addAction(self.act.objectName(),
                                                 self.act)
        self.window.findChild(QMenu, 'view').addAction(self.act)

        if not self.act.objectName() in kate.configuration:
            kate.configuration[self.act.objectName()] = "alt+r"
        self.act.setShortcut(kate.configuration[self.act.objectName()])

        self.act.setCheckable(True)
        self.act.setChecked(False)

        self.act.changed.connect(self.onActionChange)
        self.act.toggled.connect(self.toggle)

        kate.mainInterfaceWindow().viewChanged.connect(self.onViewChanged)

    def onViewChanged(self):
        try:
            doc = sip.cast(kate.activeDocument(), KateDocument)
        except kate.api.NoActiveView:
            return

        self.act.blockSignals(True)
        if doc.property('AutoReload'):
            self.act.setChecked(True)
        else:
            self.act.setChecked(False)
        self.act.blockSignals(False)

    def onActionChange(self):
        kate.configuration[
            self.sender().objectName()] = self.sender().shortcut().toString()
        kate.configuration.save()

    def toggle(self, state):
        doc = sip.cast(kate.activeDocument(), KateDocument)
        if state == True:
            self.enable(doc)
        else:
            self.disable(doc)

    def enable(self, doc):
        if doc.url() == '':
            self.act.blockSignals(True)
            showError(i18n('Can\'t auto-reload unsaved file'))
            self.act.setChecked(False)
            self.act.blockSignals(False)
            return

        doc.setModifiedOnDiskWarning(False)
        doc.modifiedOnDisk.connect(doc.documentReload)
        doc.setProperty('AutoReload', True)

        showOk(i18n('Auto-Reload enabled'))

    def disable(self, doc):
        if doc.property('AutoReload'):
            doc.setModifiedOnDiskWarning(True)
            doc.modifiedOnDisk.disconnect(doc.documentReload)
            doc.setProperty('AutoReload', False)
            showOk(i18n('Auto-Reload disabled'))
        else:
            print('Error disabled called on something with no auto-reload')
class MainWindow(KXmlGuiWindow):

    "Class which displays the main Danbooru Client window."

    def __init__(self, *args):

        "Initialize a new main window."

        super(MainWindow, self).__init__(*args)
        self.cache = KPixmapCache("danbooru")
        self.preferences = preferences.Preferences()
        self.api = None
        self.__ratings = None
        self.__step = 0

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

        self.statusbar = self.statusBar()
        self.progress = QProgressBar()
        self.thumbnailarea = None
        self.tag_dock = None
        self.pool_dock = None
        self.first_fetch_widget = None

        self.progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        # FIXME: Hackish, but how to make it small otherwise?
        self.progress.setMinimumSize(100, 1)
        self.statusbar.addPermanentWidget(self.progress)
        self.progress.hide()

        self.setup_welcome_widget()
        self.setup_actions()

    def reload_config(self):
        """Reload configuration after a change"""

        urls = self.preferences.boards_list

        if self.first_fetch_widget is not None:
            self.first_fetch_widget.setup_urls(urls)

        if self.thumbnailarea is not None:

            max_thumbnail = self.preferences.thumbnail_no
            max_rating = self.preferences.max_allowed_rating

            self.thumbnailarea.fetchwidget.limit = max_thumbnail
            self.thumbnailarea.fetchwidget.rating = max_rating
            self.thumbnailarea.fetchwidget.update_values()

            self.thumbnailarea.connectwidget.setup_urls(urls)

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

    def setup_welcome_widget(self):
        """Load the welcome widget at startup."""

        widget = QWidget()
        layout = QVBoxLayout()

        welcome = QLabel(parent=self)
        pix = QPixmap(KStandardDirs.locate("appdata", "logo.png"))

        welcome.setPixmap(pix)
        welcome.setAlignment(Qt.AlignCenter)

        self.first_fetch_widget = connectwidget.ConnectWidget(
            self.preferences.boards_list, self)

        self.statusbar.addPermanentWidget(self.first_fetch_widget, 300)

        self.first_fetch_widget.connectionEstablished.connect(
            self.handle_connection)
        self.first_fetch_widget.rejected.connect(self.first_fetch_widget.hide)

        self.first_fetch_widget.hide()

        self.first_fetch_widget.setSizePolicy(QSizePolicy.Preferred,
                                              QSizePolicy.Fixed)

        layout.addWidget(self.first_fetch_widget)
        layout.addWidget(welcome)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def setup_tooltips(self):
        """Set tooltips for the actions."""

        self.connect_action.setToolTip(i18n("Connect to a Danbooru board"))
        self.fetch_action.setToolTip(
            i18n("Fetch thumbnails from a Danbooru board"))
        self.batch_download_action.setToolTip(i18n("Batch download images"))

    def create_actions(self):
        """Create actions for the main window."""

        self.connect_action = KAction(KIcon("document-open-remote"),
                                      i18n("Connect"), self)
        self.fetch_action = KAction(KIcon("download"), i18n("Download"), self)
        self.clean_action = KAction(KIcon("trash-empty"),
                                    i18n("Clear thumbnail cache"), self)
        self.batch_download_action = KAction(KIcon("download"),
                                             i18n("Batch download"), self)
        self.pool_toggle_action = KToggleAction(KIcon("image-x-generic"),
                                                i18n("Pools"), self)
        self.tag_display_action = KDualAction(i18n("Show tags"),
                                              i18n("Hide tags"), self)
        self.tag_display_action.setIconForStates(KIcon("image-x-generic"))
        self.tag_display_action.setEnabled(False)

        # Shortcuts
        connect_default = KAction.ShortcutTypes(KAction.DefaultShortcut)
        connect_active = KAction.ShortcutTypes(KAction.ActiveShortcut)

        self.connect_action.setShortcut(KStandardShortcut.open())
        self.fetch_action.setShortcut(KStandardShortcut.find())

        self.fetch_action.setEnabled(False)
        self.batch_download_action.setEnabled(False)
        self.pool_toggle_action.setEnabled(False)

    def setup_action_collection(self):
        """Set up the action collection by adding the actions."""

        action_collection = self.actionCollection()

        # Addition to the action collection
        action_collection.addAction("connect", self.connect_action)
        action_collection.addAction("fetch", self.fetch_action)
        action_collection.addAction("clean", self.clean_action)
        action_collection.addAction("batchDownload",
                                    self.batch_download_action)
        action_collection.addAction("poolDownload", self.pool_toggle_action)
        action_collection.addAction("tagDisplay", self.tag_display_action)

        KStandardAction.quit(self.close, action_collection)
        KStandardAction.preferences(self.show_preferences, action_collection)

        action_collection.removeAction(
            action_collection.action("help_contents"))
        action_collection.actionHovered.connect(self.setup_action_tooltip)

    def setup_actions(self):
        """Set up the relevant actions, tooltips, and load the RC file."""

        self.create_actions()
        self.setup_tooltips()
        self.setup_action_collection()

        # Connect signals
        self.connect_action.triggered.connect(self.connect)
        self.fetch_action.triggered.connect(self.get_posts)
        self.clean_action.triggered.connect(self.clean_cache)
        self.batch_download_action.triggered.connect(self.batch_download)
        self.pool_toggle_action.toggled.connect(self.pool_toggle)
        self.tag_display_action.activeChanged.connect(self.tag_display)

        window_options = self.StandardWindowOption(self.ToolBar | self.Keys
                                                   | self.Create | self.Save
                                                   | self.StatusBar)

        setupGUI_args = [
            QSize(500, 400),
            self.StandardWindowOption(window_options)
        ]

        #Check first in standard locations for danbooruui.rc

        rc_file = KStandardDirs.locate("appdata", "danbooruui.rc")

        if rc_file.isEmpty():
            setupGUI_args.append(os.path.join(sys.path[0], "danbooruui.rc"))
        else:
            setupGUI_args.append(rc_file)

        self.setupGUI(*setupGUI_args)

    def setup_action_tooltip(self, action):

        "Show statusbar help when actions are hovered."

        if action.isEnabled():
            self.statusBar().showMessage(action.toolTip(), 2000)

    def setup_connections(self):
        """Set up connections for post and tag retrieval."""

        if self.api is None:
            return

        self.api.postRetrieved.connect(self.update_progress)
        self.api.postDownloadFinished.connect(self.download_finished)
        self.api.tagRetrieved.connect(self.tag_dock.widget().add_tags)
        self.tag_dock.widget().itemDoubleClicked.connect(
            self.fetch_tagged_items)

    def show_preferences(self):

        "Show the preferences dialog."

        if KConfigDialog.showDialog("Preferences dialog"):
            return
        else:
            dialog = preferences.PreferencesDialog(self, "Preferences dialog",
                                                   self.preferences)
            dialog.show()
            dialog.settingsChanged.connect(self.reload_config)

    def connect(self, ok):

        "Connect to a Danbooru board."

        if self.thumbnailarea is None:
            self.first_fetch_widget.show()
        else:
            self.thumbnailarea.connectwidget.show()

    def restore(self):

        self.statusbar.removeWidget(self.connect_widget)

    def handle_connection(self, connection):

        self.api = None
        self.api = connection
        self.api.cache = self.cache

        if self.pool_dock is not None:
            self.pool_dock.hide()
            self.pool_dock.widget().clear()
            self.pool_toggle_action.setChecked(False)

        if self.thumbnailarea is not None:
            #TODO: Investigate usability
            self.clear(clear_pool=True)
            self.thumbnailarea.clear()
            self.thumbnailarea.api_data = self.api
            self.setup_connections()

        else:
            self.first_fetch_widget.connectionEstablished.disconnect()
            self.first_fetch_widget.rejected.disconnect()
            self.statusbar.removeWidget(self.first_fetch_widget)
            self.setup_area()

        self.api.cache = self.cache

        self.statusBar().showMessage(i18n("Connected to %s" % self.api.url),
                                     3000)
        self.fetch_action.setEnabled(True)

        # Set up pool widget

        pool_widget = poolwidget.DanbooruPoolWidget(self.api)
        self.pool_dock = QDockWidget("Pools", self)
        self.pool_dock.setObjectName("PoolDock")
        self.pool_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.pool_dock.setWidget(pool_widget)
        #self.pool_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.pool_dock)
        self.pool_dock.widget().poolDownloadRequested.connect(
            self.pool_prepare)
        self.pool_dock.hide()

        self.pool_toggle_action.setEnabled(True)
        self.clear()  # Needed to show properly the stuff after connecting

        self.api.get_post_list(tags="",
                               limit=self.thumbnailarea.post_limit,
                               rating=self.preferences.max_allowed_rating,
                               blacklist=list(self.preferences.tag_blacklist))
        self.api.get_tag_list(name="",
                              blacklist=list(self.preferences.tag_blacklist),
                              limit=20)

    def get_posts(self, ok):

        "Get posts from the connected Danbooru board."

        if not self.api:
            return

        self.thumbnailarea.fetchwidget.show()

    def handle_fetching(self, tags, max_rating, limit):
        """Slot connected to the dataSent signal of the fetch widget.

        The widgets are set up if they don't exist, and the API is queried
        to do the actual downloading of tags and

        """

        self.clear()

        self.thumbnailarea.fetchwidget.hide()

        if self.tag_dock is not None:
            self.tag_dock.widget().clear()

        self.thumbnailarea.post_limit = limit
        blacklist = list(self.preferences.tag_blacklist)
        self.api.get_post_list(tags=tags,
                               limit=limit,
                               rating=max_rating,
                               blacklist=blacklist)

        tags = [item for item in tags if item]

        if not tags:
            # No related tags, fetch the most recent 20
            tags = ""
            self.api.get_tag_list(name=tags, blacklist=blacklist, limit=20)
        else:
            self.api.get_related_tags(tags=tags, blacklist=blacklist)

    def fetch_tagged_items(self, item):
        """Fetch items found in the tag list widget."""

        tag_name = unicode(item.text())
        self.clear()

        blacklist = self.preferences.tag_blacklist
        limit = self.preferences.thumbnail_no
        rating = self.preferences.max_allowed_rating

        self.api.get_post_list(page=1,
                               tags=[tag_name],
                               blacklist=blacklist,
                               limit=limit,
                               rating=rating)
        self.api.get_related_tags(tags=[tag_name], blacklist=blacklist)

    def pool_toggle(self, checked):

        "Toggle the presence/absence of the pool dock."

        if not self.api:
            return

        if not checked:
            self.pool_dock.hide()
        else:
            self.pool_dock.show()

    def pool_prepare(self, pool_id):
        """Prepare the central area for pool image loading."""

        if self.thumbnailarea is None:
            self.setup_area()
        else:
            self.clear(clear_pool=False)

        self.api.get_pool(pool_id,
                          blacklist=self.preferences.tag_blacklist,
                          rating=self.preferences.max_allowed_rating)

    def batch_download(self, ok):

        "Download images in batch."

        selected_items = self.thumbnailarea.selected_images()

        if not selected_items:
            return

        start_url = KUrl("kfiledialog:///danbooru")
        caption = i18n("Select a directory to save the images to")
        directory = KFileDialog.getExistingDirectoryUrl(
            start_url, self, caption)

        if directory.isEmpty():
            return

        for item in selected_items:

            file_url = item.url_label.url()
            tags = item.data.tags

            # Make a local copy to append paths as addPath works in-place
            destination = KUrl(directory)

            file_name = KUrl(file_url).fileName()
            destination.addPath(file_name)

            job = KIO.file_copy(KUrl(file_url), destination, -1)
            job.setProperty("tags", QVariant(tags))
            job.result.connect(self.batch_download_slot)

    def setup_area(self):

        "Set up the central widget to display thumbnails."

        self.thumbnailarea = thumbnailarea.DanbooruTabWidget(
            self.api, self.preferences, self.preferences.thumbnail_no, self)

        self.setCentralWidget(self.thumbnailarea)

        self.thumbnailarea.connectwidget.connectionEstablished.connect(
            self.handle_connection, type=Qt.UniqueConnection)
        self.thumbnailarea.connectwidget.rejected.connect(
            self.thumbnailarea.connectwidget.hide, type=Qt.UniqueConnection)

        self.thumbnailarea.fetchwidget.dataSent.connect(
            self.handle_fetching, type=Qt.UniqueConnection)
        self.thumbnailarea.fetchwidget.rejected.connect(
            self.thumbnailarea.fetchwidget.hide, type=Qt.UniqueConnection)

        # Set up tag widget

        blacklist = self.preferences.tag_blacklist
        tag_widget = tagwidget.DanbooruTagWidget(blacklist, self)
        self.tag_display_action.setActive(True)
        self.tag_display_action.setEnabled(True)
        self.tag_dock = QDockWidget("Similar tags", self)
        self.tag_dock.setObjectName("TagDock")
        self.tag_dock.setAllowedAreas(Qt.RightDockWidgetArea)
        self.tag_dock.setWidget(tag_widget)
        #self.tag_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tag_dock)
        self.tag_dock.hide()

        # Container signal-slot connections

        self.setup_connections()

    def download_finished(self):
        """Slot called when all the data has been completed. Clears the progress
        bar and resets it to 0."""

        if not self.batch_download_action.isEnabled():
            self.batch_download_action.setEnabled(True)

        self.__step = 0
        self.progress.hide()

    def update_progress(self):

        "Update the progress bar."

        if not self.progress.isVisible():
            self.progress.show()

        self.__step += 1
        self.progress.setValue(self.__step)

    def clear(self, clear_pool=True):

        "Clear the central widget."

        if self.thumbnailarea is None:
            return

        self.thumbnailarea.clear()
        self.tag_dock.widget().clear()
        if clear_pool:
            self.pool_dock.widget().clear()
        self.batch_download_action.setEnabled(False)

    def clean_cache(self):

        "Purge the thumbnail cache."

        self.cache.discard()
        self.statusBar().showMessage(i18n("Thumbnail cache cleared."))

    def batch_download_slot(self, job):
        """Slot called when doing batch download, for each file retrieved.

        If Nepomuk tagging is enabled, each file is tagged using the item's
        respective tags.

        """

        if job.error():
            job.ui().showErrorMessage()
        else:
            if self.preferences.nepomuk_enabled:
                tags = job.property("tags").toPyObject()
                #danbooru2nepomuk.tag_danbooru_item(job.destUrl().path(),
                #                                   tags)

    def tag_display(self, state):
        """Display or hide the tag dock."""

        if self.tag_dock is None:
            self.tag_display_action.setActive(False)
            return

        if state:
            self.tag_dock.show()
        else:
            self.tag_dock.hide()
class MainWindow(KXmlGuiWindow):

    "Class which displays the main Danbooru Client window."

    def __init__(self,  *args):

        "Initialize a new main window."

        super(MainWindow,  self).__init__(*args)
        self.cache = KPixmapCache("danbooru")
        self.preferences = preferences.Preferences()
        self.api = None
        self.__ratings = None
        self.__step = 0

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

        self.statusbar = self.statusBar()
        self.progress = QProgressBar()
        self.thumbnailarea = None
        self.tag_dock = None
        self.pool_dock = None
        self.first_fetch_widget = None

        self.progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        # FIXME: Hackish, but how to make it small otherwise?
        self.progress.setMinimumSize(100, 1)
        self.statusbar.addPermanentWidget(self.progress)
        self.progress.hide()

        self.setup_welcome_widget()
        self.setup_actions()

    def reload_config(self):

        """Reload configuration after a change"""

        urls = self.preferences.boards_list

        if self.first_fetch_widget is not None:
            self.first_fetch_widget.setup_urls(urls)

        if self.thumbnailarea is not None:

            max_thumbnail = self.preferences.thumbnail_no
            max_rating = self.preferences.max_allowed_rating

            self.thumbnailarea.fetchwidget.limit = max_thumbnail
            self.thumbnailarea.fetchwidget.rating = max_rating
            self.thumbnailarea.fetchwidget.update_values()

            self.thumbnailarea.connectwidget.setup_urls(urls)

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no




    def setup_welcome_widget(self):

        """Load the welcome widget at startup."""

        widget = QWidget()
        layout = QVBoxLayout()

        welcome = QLabel(parent=self)
        pix = QPixmap(KStandardDirs.locate("appdata","logo.png"))

        welcome.setPixmap(pix)
        welcome.setAlignment(Qt.AlignCenter)

        self.first_fetch_widget = connectwidget.ConnectWidget(
        self.preferences.boards_list, self)

        self.statusbar.addPermanentWidget(self.first_fetch_widget, 300)

        self.first_fetch_widget.connectionEstablished.connect(
            self.handle_connection)
        self.first_fetch_widget.rejected.connect(
            self.first_fetch_widget.hide)

        self.first_fetch_widget.hide()

        self.first_fetch_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)

        layout.addWidget(self.first_fetch_widget)
        layout.addWidget(welcome)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def setup_tooltips(self):

        """Set tooltips for the actions."""

        self.connect_action.setToolTip(i18n("Connect to a Danbooru board"))
        self.fetch_action.setToolTip(
            i18n("Fetch thumbnails from a Danbooru board")
        )
        self.batch_download_action.setToolTip(i18n("Batch download images"))

    def create_actions(self):

        """Create actions for the main window."""

        self.connect_action = KAction(KIcon("document-open-remote"),
                                 i18n("Connect"), self)
        self.fetch_action = KAction(KIcon("download"), i18n("Download"),
                                    self)
        self.clean_action = KAction(KIcon("trash-empty"),
                               i18n("Clear thumbnail cache"),
                               self)
        self.batch_download_action = KAction(KIcon("download"),
                                             i18n("Batch download"), self)
        self.pool_toggle_action = KToggleAction(KIcon("image-x-generic"),
                                            i18n("Pools"), self)
        self.tag_display_action = KDualAction(i18n("Show tags"),
                                              i18n("Hide tags"),
                                              self)
        self.tag_display_action.setIconForStates(KIcon("image-x-generic"))
        self.tag_display_action.setEnabled(False)

        # Shortcuts
        connect_default = KAction.ShortcutTypes(KAction.DefaultShortcut)
        connect_active = KAction.ShortcutTypes(KAction.ActiveShortcut)

        self.connect_action.setShortcut(KStandardShortcut.open())
        self.fetch_action.setShortcut(KStandardShortcut.find())

        self.fetch_action.setEnabled(False)
        self.batch_download_action.setEnabled(False)
        self.pool_toggle_action.setEnabled(False)

    def setup_action_collection(self):

        """Set up the action collection by adding the actions."""

        action_collection = self.actionCollection()

        # Addition to the action collection
        action_collection.addAction("connect", self.connect_action)
        action_collection.addAction("fetch", self.fetch_action)
        action_collection.addAction("clean", self.clean_action)
        action_collection.addAction("batchDownload", self.batch_download_action)
        action_collection.addAction("poolDownload", self.pool_toggle_action)
        action_collection.addAction("tagDisplay", self.tag_display_action)

        KStandardAction.quit (self.close, action_collection)
        KStandardAction.preferences(self.show_preferences,
                                    action_collection)

        action_collection.removeAction(
            action_collection.action("help_contents"))
        action_collection.actionHovered.connect(self.setup_action_tooltip)

    def setup_actions(self):

        """Set up the relevant actions, tooltips, and load the RC file."""

        self.create_actions()
        self.setup_tooltips()
        self.setup_action_collection()

        # Connect signals
        self.connect_action.triggered.connect(self.connect)
        self.fetch_action.triggered.connect(self.get_posts)
        self.clean_action.triggered.connect(self.clean_cache)
        self.batch_download_action.triggered.connect(self.batch_download)
        self.pool_toggle_action.toggled.connect(self.pool_toggle)
        self.tag_display_action.activeChanged.connect(self.tag_display)

        window_options = self.StandardWindowOption(self.ToolBar| self.Keys |
                                                   self.Create | self.Save |
                                                   self.StatusBar)

        setupGUI_args = [
            QSize(500, 400), self.StandardWindowOption(window_options)
        ]

        #Check first in standard locations for danbooruui.rc

        rc_file = KStandardDirs.locate("appdata", "danbooruui.rc")

        if rc_file.isEmpty():
            setupGUI_args.append(os.path.join(sys.path [0],
                                              "danbooruui.rc"))
        else:
            setupGUI_args.append(rc_file)

        self.setupGUI(*setupGUI_args)

    def setup_action_tooltip(self, action):

        "Show statusbar help when actions are hovered."

        if action.isEnabled():
            self.statusBar().showMessage(action.toolTip(), 2000)

    def setup_connections(self):

        """Set up connections for post and tag retrieval."""

        if self.api is None:
            return

        self.api.postRetrieved.connect(self.update_progress)
        self.api.postDownloadFinished.connect(self.download_finished)
        self.api.tagRetrieved.connect(self.tag_dock.widget().add_tags)
        self.tag_dock.widget().itemDoubleClicked.connect(
            self.fetch_tagged_items)

    def show_preferences(self):

        "Show the preferences dialog."

        if KConfigDialog.showDialog("Preferences dialog"):
            return
        else:
            dialog = preferences.PreferencesDialog(self, "Preferences dialog",
                                                   self.preferences)
            dialog.show()
            dialog.settingsChanged.connect(self.reload_config)

    def connect(self, ok):

        "Connect to a Danbooru board."

        if self.thumbnailarea is None:
            self.first_fetch_widget.show()
        else:
            self.thumbnailarea.connectwidget.show()


    def restore(self):

        self.statusbar.removeWidget(self.connect_widget)

    def handle_connection(self, connection):

        self.api = None
        self.api = connection
        self.api.cache = self.cache

        if self.pool_dock is not None:
            self.pool_dock.hide()
            self.pool_dock.widget().clear()
            self.pool_toggle_action.setChecked(False)

        if self.thumbnailarea is not None:
            #TODO: Investigate usability
            self.clear(clear_pool=True)
            self.thumbnailarea.clear()
            self.thumbnailarea.api_data = self.api
            self.setup_connections()

        else:
            self.first_fetch_widget.connectionEstablished.disconnect()
            self.first_fetch_widget.rejected.disconnect()
            self.statusbar.removeWidget(self.first_fetch_widget)
            self.setup_area()

        self.api.cache = self.cache

        self.statusBar().showMessage(i18n("Connected to %s" % self.api.url),
                                     3000)
        self.fetch_action.setEnabled(True)

        # Set up pool widget

        pool_widget = poolwidget.DanbooruPoolWidget(self.api)
        self.pool_dock = QDockWidget("Pools", self)
        self.pool_dock.setObjectName("PoolDock")
        self.pool_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.pool_dock.setWidget(pool_widget)
        #self.pool_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.pool_dock)
        self.pool_dock.widget().poolDownloadRequested.connect(
            self.pool_prepare)
        self.pool_dock.hide()

        self.pool_toggle_action.setEnabled(True)
        self.clear() # Needed to show properly the stuff after connecting

        self.api.get_post_list(tags="", limit=self.thumbnailarea.post_limit,
                               rating=self.preferences.max_allowed_rating,
                               blacklist=list(self.preferences.tag_blacklist))
        self.api.get_tag_list(name="",blacklist=list(self.preferences.tag_blacklist),
                              limit=20)

    def get_posts(self, ok):

        "Get posts from the connected Danbooru board."

        if not self.api:
            return

        self.thumbnailarea.fetchwidget.show()



    def handle_fetching(self, tags, max_rating, limit):

        """Slot connected to the dataSent signal of the fetch widget.

        The widgets are set up if they don't exist, and the API is queried
        to do the actual downloading of tags and

        """

        self.clear()

        self.thumbnailarea.fetchwidget.hide()

        if self.tag_dock is not None:
            self.tag_dock.widget().clear()

        self.thumbnailarea.post_limit = limit
        blacklist= list(self.preferences.tag_blacklist)
        self.api.get_post_list(tags=tags, limit=limit,
                               rating=max_rating,
                               blacklist=blacklist)

        tags = [item for item in tags if item]

        if not tags:
            # No related tags, fetch the most recent 20
            tags = ""
            self.api.get_tag_list(name=tags,blacklist=blacklist,
                                  limit=20)
        else:
            self.api.get_related_tags(tags=tags, blacklist=blacklist)

    def fetch_tagged_items(self, item):

        """Fetch items found in the tag list widget."""

        tag_name = unicode(item.text())
        self.clear()

        blacklist = self.preferences.tag_blacklist
        limit = self.preferences.thumbnail_no
        rating = self.preferences.max_allowed_rating

        self.api.get_post_list(page=1, tags=[tag_name],
                                blacklist=blacklist,
                                limit=limit,
                                rating=rating)
        self.api.get_related_tags(tags=[tag_name], blacklist=blacklist)

    def pool_toggle(self, checked):

        "Toggle the presence/absence of the pool dock."

        if not self.api:
            return

        if not checked:
            self.pool_dock.hide()
        else:
            self.pool_dock.show()

    def pool_prepare(self, pool_id):

        """Prepare the central area for pool image loading."""

        if self.thumbnailarea is None:
            self.setup_area()
        else:
            self.clear(clear_pool=False)

        self.api.get_pool(pool_id, blacklist=self.preferences.tag_blacklist,
                          rating=self.preferences.max_allowed_rating)

    def batch_download(self, ok):

        "Download images in batch."

        selected_items = self.thumbnailarea.selected_images()

        if not selected_items:
            return

        start_url = KUrl("kfiledialog:///danbooru")
        caption = i18n("Select a directory to save the images to")
        directory = KFileDialog.getExistingDirectoryUrl(start_url, self,
                                                        caption)

        if directory.isEmpty():
            return

        for item in selected_items:

            file_url = item.url_label.url()
            tags = item.data.tags

            # Make a local copy to append paths as addPath works in-place
            destination = KUrl(directory)

            file_name = KUrl(file_url).fileName()
            destination.addPath(file_name)

            job = KIO.file_copy(KUrl(file_url), destination, -1)
            job.setProperty("tags", QVariant(tags))
            job.result.connect(self.batch_download_slot)

    def setup_area(self):

        "Set up the central widget to display thumbnails."

        self.thumbnailarea = thumbnailarea.DanbooruTabWidget(self.api,
            self.preferences, self.preferences.thumbnail_no, self)

        self.setCentralWidget(self.thumbnailarea)

        self.thumbnailarea.connectwidget.connectionEstablished.connect(
                    self.handle_connection, type=Qt.UniqueConnection)
        self.thumbnailarea.connectwidget.rejected.connect(
            self.thumbnailarea.connectwidget.hide, type=Qt.UniqueConnection)

        self.thumbnailarea.fetchwidget.dataSent.connect(
            self.handle_fetching, type=Qt.UniqueConnection)
        self.thumbnailarea.fetchwidget.rejected.connect(
            self.thumbnailarea.fetchwidget.hide, type=Qt.UniqueConnection)

        # Set up tag widget

        blacklist = self.preferences.tag_blacklist
        tag_widget = tagwidget.DanbooruTagWidget(blacklist, self)
        self.tag_display_action.setActive(True)
        self.tag_display_action.setEnabled(True)
        self.tag_dock = QDockWidget("Similar tags", self)
        self.tag_dock.setObjectName("TagDock")
        self.tag_dock.setAllowedAreas(Qt.RightDockWidgetArea)
        self.tag_dock.setWidget(tag_widget)
        #self.tag_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tag_dock)
        self.tag_dock.hide()

        # Container signal-slot connections

        self.setup_connections()

    def download_finished(self):

        """Slot called when all the data has been completed. Clears the progress
        bar and resets it to 0."""

        if not self.batch_download_action.isEnabled():
            self.batch_download_action.setEnabled(True)

        self.__step = 0
        self.progress.hide()

    def update_progress(self):

        "Update the progress bar."

        if not self.progress.isVisible():
            self.progress.show()

        self.__step += 1
        self.progress.setValue(self.__step)

    def clear(self, clear_pool=True):

        "Clear the central widget."

        if self.thumbnailarea is None:
            return

        self.thumbnailarea.clear()
        self.tag_dock.widget().clear()
        if clear_pool:
            self.pool_dock.widget().clear()
        self.batch_download_action.setEnabled(False)

    def clean_cache(self):

        "Purge the thumbnail cache."

        self.cache.discard()
        self.statusBar().showMessage(i18n("Thumbnail cache cleared."))

    def batch_download_slot(self, job):

        """Slot called when doing batch download, for each file retrieved.

        If Nepomuk tagging is enabled, each file is tagged using the item's
        respective tags.

        """

        if job.error():
            job.ui().showErrorMessage()
        else:
            if self.preferences.nepomuk_enabled:
                tags = job.property("tags").toPyObject()
                #danbooru2nepomuk.tag_danbooru_item(job.destUrl().path(),
                #                                   tags)

    def tag_display(self, state):

        """Display or hide the tag dock."""

        if self.tag_dock is None:
            self.tag_display_action.setActive(False)
            return

        if state:
            self.tag_dock.show()
        else:
            self.tag_dock.hide()