Mon, 05 Aug 2024 18:37:16 +0200
Implemented most of the Chat History widgets.
# -*- coding: utf-8 -*- # Copyright (c) 2024 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the ollama Interface plug-in. """ import os from PyQt6.QtCore import QObject, Qt, QTranslator, pyqtSignal from PyQt6.QtGui import QKeySequence from eric7 import Preferences from eric7.EricGui import EricPixmapCache from eric7.EricGui.EricAction import EricAction from eric7.EricWidgets.EricApplication import ericApp try: from eric7.UI.UserInterface import UserInterfaceSide _Side = UserInterfaceSide.Right except ImportError: # backward compatibility for eric < 24.2 from eric7.UI.UserInterface import UserInterface _Side = UserInterface.RightSide # Start-Of-Header __header__ = { "name": "ollama Interface", "author": "Detlev Offenbach <detlev@die-offenbachs.de>", "autoactivate": True, "deactivateable": True, "version": "10.0.0", "className": "PluginOllamaInterface", "packageName": "OllamaInterface", "shortDescription": "Grapgical 'ollama' client for eric-ide.", "longDescription": ( "Plug-in implementing an 'ollama' client and interface widgets." ), "needsRestart": False, "pyqtApi": 2, } # End-Of-Header error = "" # noqa: U200 ollamaInterfacePluginObject = None def pageCreationFunction(configDlg): """ Function to create the Translator configuration page. @param configDlg reference to the configuration dialog @type ConfigurationWidget @return reference to the configuration page @rtype TranslatorPage """ # TODO: not implemented yet page = None # change this line to create the configuration page return page def getConfigData(): """ Function returning data as required by the configuration dialog. @return dictionary containing the relevant data @rtype dict """ # TODO: not implemented yet return { "<unique key>": [ "<display string>", "<pixmap filename>", pageCreationFunction, None, None, ], } def prepareUninstall(): """ Function to prepare for an un-installation. """ Preferences.getSettings().remove(PluginOllamaInterface.PreferencesKey) def clearPrivateData(): """ Function to clear the private data of the plug-in. """ if ollamaInterfacePluginObject is not None: widget = ollamaInterfacePluginObject.getWidget() if widget is not None: widget.clearHistory() class PluginOllamaInterface(QObject): """ Class implementing the ollama Interface plug-in. @signal preferencesChanged() emitted to signal a change of preferences. This signal is simply relayed from the main UI. """ PreferencesKey = "Ollama" preferencesChanged = pyqtSignal() def __init__(self, ui): """ Constructor @param ui reference to the user interface object @type UI.UserInterface """ super().__init__(ui) self.__ui = ui self.__initialize() self.__defaults = { "OllamaScheme": "http", "OllamaHost": "localhost", "OllamaPort": 11434, "OllamaHeartbeatInterval": 5, # 5 seconds heartbeat time; 0 = disabled } self.__translator = None self.__loadTranslator() def __initialize(self): """ Private slot to (re)initialize the plugin. """ self.__widget = None def activate(self): """ Public method to activate this plug-in. @return tuple of None and activation status @rtype bool """ from OllamaInterface.OllamaWidget import OllamaWidget global error, ollamaInterfacePluginObject error = "" # clear previous error ollamaInterfacePluginObject = self usesDarkPalette = ericApp().usesDarkPalette() iconSuffix = "dark" if usesDarkPalette else "light" self.__widget = OllamaWidget(self, fromEric=True) iconName = ( "sbOllama96" if self.__ui.getLayoutType() == "Sidebars" else "ollama22-{0}".format(iconSuffix) ) self.__ui.addSideWidget( _Side, self.__widget, EricPixmapCache.getIcon(os.path.join("OllamaInterface", "icons", iconName)), self.tr("ollama AI Interface"), ) self.__activateAct = EricAction( self.tr("ollama AI Interface"), self.tr("ollama AI Interface"), QKeySequence(self.tr("Ctrl+Alt+Shift+O")), 0, self, "ollama_interface_activate", ) self.__activateAct.setStatusTip( self.tr("Switch the input focus to the ollama AI window.") ) self.__activateAct.setWhatsThis( self.tr( """<b>Activate ollama AI Interface</b>""" """<p>This switches the input focus to the ollama AI window.</p>""" ) ) self.__activateAct.triggered.connect(self.__activateWidget) self.__ui.addEricActions([self.__activateAct], "ui") menu = self.__ui.getMenu("subwindow") menu.addAction(self.__activateAct) self.__ui.preferencesChanged.connect(self.preferencesChanged) return None, True def deactivate(self): """ Public method to deactivate this plug-in. """ self.__ui.preferencesChanged.disconnect(self.preferencesChanged) menu = self.__ui.getMenu("subwindow") menu.removeAction(self.__activateAct) self.__ui.removeEricActions([self.__activateAct], "ui") self.__ui.removeSideWidget(self.__widget) self.__initialize() def __loadTranslator(self): """ Private method to load the translation file. """ if self.__ui is not None: loc = self.__ui.getLocale() if loc and loc != "C": locale_dir = os.path.join( os.path.dirname(__file__), "OllamaInterface", "i18n" ) translation = "ollama_{0}".format(loc) translator = QTranslator(None) loaded = translator.load(translation, locale_dir) if loaded: self.__translator = translator ericApp().installTranslator(self.__translator) else: print( "Warning: translation file '{0}' could not be" " loaded.".format(translation) ) print("Using default.") def getWidget(self): """ Public method to get a reference to the 'ollama' widget. @return reference to the 'ollama' widget @rtype OllamaWidget """ return self.__widget def __activateWidget(self): """ Private slot to handle the activation of the pipx interface. """ uiLayoutType = self.__ui.getLayoutType() if uiLayoutType == "Toolboxes": self.__ui.rToolboxDock.show() self.__ui.rToolbox.setCurrentWidget(self.__widget) elif uiLayoutType == "Sidebars": try: self.__ui.activateLeftRightSidebarWidget(self.__widget) except AttributeError: self.__activateLeftRightSidebarWidget(self.__widget) else: self.__widget.show() self.__widget.setFocus(Qt.FocusReason.ActiveWindowFocusReason) def getPreferences(self, key): """ Public method to retrieve the various settings values. @param key the key of the value to get @type str @return the requested setting value @rtype Any """ if key in ("OllamaPort", "OllamaHeartbeatInterval"): return int( Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) ) else: return Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) return None def setPreferences(self, key, value): """ Public method to store the various settings values. @param key the key of the setting to be set @type str @param value the value to be set @type Any """ Preferences.Prefs.settings.setValue(self.PreferencesKey + "/" + key, value) ############################################################################ ## Methods for backward compatibility with eric-ide < 24.9 ############################################################################ def __activateLeftRightSidebarWidget(self, widget): """ Private method to activate the given widget in the left or right sidebar. @param widget reference to the widget to be activated @type QWidget """ # This is for backward compatibility with eric-ide < 24.9. sidebar = ( self.__ui.leftSidebar if Preferences.getUI("CombinedLeftRightSidebar") else self.__ui.rightSidebar ) sidebar.show() sidebar.setCurrentWidget(widget) # # eflag: noqa = M801, U200