From d9824bc3ab99fb7af9d2ac99f5b924cd641fba4d Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 29 Jun 2021 08:13:33 +0100 Subject: [PATCH] Added pyeix --- form.ui | 219 ++++++++ pyeix/.eric6project/PyEix.eqj | 10 + pyeix/.eric6project/PyEix.etj | 23 + pyeix/PyEix.epj | 96 ++++ pyeix/PyEix.py | 10 + pyeix/pyeix | 519 ++++++++++++++++++ pyeix/ui/Ui_mainwindow.py | 175 ++++++ pyeix/ui/__init__.py | 0 .../__pycache__/Ui_mainwindow.cpython-39.pyc | Bin 0 -> 5227 bytes pyeix/ui/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 133 bytes .../ui/__pycache__/mainwindow.cpython-39.pyc | Bin 0 -> 10745 bytes pyeix/ui/mainwindow.py | 367 +++++++++++++ pyeix/ui/mainwindow.ui | 264 +++++++++ 13 files changed, 1683 insertions(+) create mode 100644 form.ui create mode 100644 pyeix/.eric6project/PyEix.eqj create mode 100644 pyeix/.eric6project/PyEix.etj create mode 100644 pyeix/PyEix.epj create mode 100755 pyeix/PyEix.py create mode 100755 pyeix/pyeix create mode 100644 pyeix/ui/Ui_mainwindow.py create mode 100644 pyeix/ui/__init__.py create mode 100644 pyeix/ui/__pycache__/Ui_mainwindow.cpython-39.pyc create mode 100644 pyeix/ui/__pycache__/__init__.cpython-39.pyc create mode 100644 pyeix/ui/__pycache__/mainwindow.cpython-39.pyc create mode 100644 pyeix/ui/mainwindow.py create mode 100644 pyeix/ui/mainwindow.ui diff --git a/form.ui b/form.ui new file mode 100644 index 0000000..6dba237 --- /dev/null +++ b/form.ui @@ -0,0 +1,219 @@ + + + MainWindow + + + + 0 + 0 + 460 + 300 + + + + + 460 + 300 + + + + MainWindow + + + + + + + + + + + + Search + + + + + + + + + + + Only match packages with a stable version + + + Stable + + + + + + + Only match packages with a testing version + + + Testing + + + + + + + Only match installed packages + + + Installed + + + + + + + Only match packages with at least one version in an overlay + + + Overlay + + + false + + + + + + + + + + + Search the description field + + + Description + + + + + + + Search for packages instealled with that use flag diabled + + + Use Disabled + + + + + + + Search any field + + + Any + + + + + + + Search the name field + + + Name + + + + + + + Search the category field + + + Category + + + + + + + Search for packages that can have that use flag enabled + + + Use flags (IUSE) + + + + + + + Search for packages installed with that use flag enabled + + + Use enabled + + + + + + + + + + + + + + 0 + 0 + 460 + 26 + + + + + + + _search + + + Return + + + + + le_search + pb_search + cb_stable + cb_testing + cb_installed + cb_overlay + rb_any + rb_decription + rb_category + rb_name + rb_iuse + rb_use_enabled + rb_use_disabled + tv_results + + + + + pb_search + clicked() + action_search + trigger() + + + 410 + 47 + + + -1 + -1 + + + + + diff --git a/pyeix/.eric6project/PyEix.eqj b/pyeix/.eric6project/PyEix.eqj new file mode 100644 index 0000000..b8d68c0 --- /dev/null +++ b/pyeix/.eric6project/PyEix.eqj @@ -0,0 +1,10 @@ +{ + "header": { + "comment": "eric user project file for project PyEix", + "saved": "2021-06-29, 07:33:06" + }, + "user_data": { + "VCSOVERRIDE": "", + "VCSSTATUSMONITORINTERVAL": 0 + } +} \ No newline at end of file diff --git a/pyeix/.eric6project/PyEix.etj b/pyeix/.eric6project/PyEix.etj new file mode 100644 index 0000000..befa67c --- /dev/null +++ b/pyeix/.eric6project/PyEix.etj @@ -0,0 +1,23 @@ +{ + "header": { + "comment": "eric tasks file for project PyEix", + "warning": "This file was generated automatically, do not edit.", + "saved": "2021-06-29, 07:33:06" + }, + "ProjectScanFilter": "", + "Tasks": [ + { + "summary": "WARNING: Any manual changes made to this file will be lost when pyuic5 is", + "description": "", + "priority": 1, + "lineno": 7, + "completed": false, + "created": 1624948329.6457803, + "type": 2, + "uid": "{d9298fed-a068-4f89-97a0-5fcdd927106e}", + "parent_uid": "", + "expanded": false, + "filename": "/home/andrew/Projects/pyeix/ui/Ui_mainwindow.py" + } + ] +} \ No newline at end of file diff --git a/pyeix/PyEix.epj b/pyeix/PyEix.epj new file mode 100644 index 0000000..2f32eaf --- /dev/null +++ b/pyeix/PyEix.epj @@ -0,0 +1,96 @@ +{ + "header": { + "comment": "eric project file for project PyEix", + "copyright": "Copyright (C) 2021 Ralphred, PyEix@liquid.me.uk", + "saved": "2021-06-29, 07:33:06" + }, + "project": { + "AUTHOR": "Ralphred", + "CHECKERSPARMS": {}, + "DESCRIPTION": "Simple GUI front end to eix", + "DOCSTRING": "ericdoc", + "DOCUMENTATIONPARMS": {}, + "EMAIL": "PyEix@liquid.me.uk", + "EOL": 0, + "FILETYPES": { + "*.e4p": "OTHERS", + "*.epj": "OTHERS", + "*.idl": "INTERFACES", + "*.md": "OTHERS", + "*.proto": "PROTOCOLS", + "*.py": "SOURCES", + "*.py3": "SOURCES", + "*.pyw": "SOURCES", + "*.pyw3": "SOURCES", + "*.qm": "TRANSLATIONS", + "*.qrc": "RESOURCES", + "*.rst": "OTHERS", + "*.ts": "TRANSLATIONS", + "*.txt": "OTHERS", + "*.ui": "FORMS", + "GNUmakefile": "OTHERS", + "Makefile": "OTHERS", + "README": "OTHERS", + "README.*": "OTHERS", + "makefile": "OTHERS" + }, + "FORMS": [ + "ui/mainwindow.ui" + ], + "HASH": "ea418876ac01b612acd0a2860033e175bbb2bedb", + "IDLPARAMS": { + "DefinedNames": [], + "IncludeDirs": [], + "UndefinedNames": [] + }, + "INTERFACES": [], + "LEXERASSOCS": {}, + "MAINSCRIPT": "PyEix", + "MAKEPARAMS": { + "MakeEnabled": false, + "MakeExecutable": "", + "MakeFile": "", + "MakeParameters": "", + "MakeTarget": "", + "MakeTestOnly": true + }, + "MIXEDLANGUAGE": false, + "OTHERS": [], + "OTHERTOOLSPARMS": {}, + "PACKAGERSPARMS": {}, + "PROGLANGUAGE": "Python3", + "PROJECTTYPE": "PyQt5", + "PROJECTTYPESPECIFICDATA": {}, + "PROTOCOLS": [], + "RCCPARAMS": { + "CompressLevel": 0, + "CompressionDisable": false, + "CompressionThreshold": 70, + "PathPrefix": "" + }, + "RESOURCES": [], + "SOURCES": [ + "__init__.py", + "ui/__init__.py", + "ui/Ui_mainwindow.py", + "ui/mainwindow.py", + "PyEix.py" + ], + "SPELLEXCLUDES": "", + "SPELLLANGUAGE": "", + "SPELLWORDS": "", + "TRANSLATIONEXCEPTIONS": [], + "TRANSLATIONPATTERN": "", + "TRANSLATIONS": [], + "TRANSLATIONSBINPATH": "", + "UICPARAMS": { + "Package": "", + "PackagesRoot": "", + "RcSuffix": "" + }, + "VCS": "None", + "VCSOPTIONS": {}, + "VCSOTHERDATA": {}, + "VERSION": "0.1" + } +} \ No newline at end of file diff --git a/pyeix/PyEix.py b/pyeix/PyEix.py new file mode 100755 index 0000000..617831d --- /dev/null +++ b/pyeix/PyEix.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +from PyQt5 import QtWidgets +from ui.mainwindow import MainWindow + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + ui = MainWindow() + ui.show() + sys.exit(app.exec_()) diff --git a/pyeix/pyeix b/pyeix/pyeix new file mode 100755 index 0000000..59b79fe --- /dev/null +++ b/pyeix/pyeix @@ -0,0 +1,519 @@ +#!/usr/bin/env python +#pyqt front end to some eix search functions + +from PyQt5 import QtCore, QtWidgets +from PyQt5.QtWidgets import QMainWindow +from PyQt5.QtGui import QStandardItemModel,QStandardItem +import sys, subprocess, re + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(938, 483) + MainWindow.setMinimumSize(QtCore.QSize(460, 300)) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.le_search = QtWidgets.QLineEdit(self.centralwidget) + self.le_search.setObjectName("le_search") + self.horizontalLayout_2.addWidget(self.le_search) + self.pb_search = QtWidgets.QPushButton(self.centralwidget) + self.pb_search.setObjectName("pb_search") + self.horizontalLayout_2.addWidget(self.pb_search) + self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.cb_stable = QtWidgets.QCheckBox(self.centralwidget) + self.cb_stable.setObjectName("cb_stable") + self.horizontalLayout.addWidget(self.cb_stable) + self.cb_testing = QtWidgets.QCheckBox(self.centralwidget) + self.cb_testing.setObjectName("cb_testing") + self.horizontalLayout.addWidget(self.cb_testing) + self.cb_installed = QtWidgets.QCheckBox(self.centralwidget) + self.cb_installed.setObjectName("cb_installed") + self.horizontalLayout.addWidget(self.cb_installed) + self.cb_overlay = QtWidgets.QCheckBox(self.centralwidget) + self.cb_overlay.setTristate(False) + self.cb_overlay.setObjectName("cb_overlay") + self.horizontalLayout.addWidget(self.cb_overlay) + self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1) + self.horizontalLayout_6 = QtWidgets.QHBoxLayout() + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.rb_any = QtWidgets.QRadioButton(self.centralwidget) + self.rb_any.setObjectName("rb_any") + self.horizontalLayout_6.addWidget(self.rb_any) + self.rb_decription = QtWidgets.QRadioButton(self.centralwidget) + self.rb_decription.setObjectName("rb_decription") + self.horizontalLayout_6.addWidget(self.rb_decription) + self.rb_category = QtWidgets.QRadioButton(self.centralwidget) + self.rb_category.setObjectName("rb_category") + self.horizontalLayout_6.addWidget(self.rb_category) + self.rb_name = QtWidgets.QRadioButton(self.centralwidget) + self.rb_name.setObjectName("rb_name") + self.horizontalLayout_6.addWidget(self.rb_name) + self.gridLayout.addLayout(self.horizontalLayout_6, 2, 0, 1, 1) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.rb_iuse = QtWidgets.QRadioButton(self.centralwidget) + self.rb_iuse.setObjectName("rb_iuse") + self.horizontalLayout_5.addWidget(self.rb_iuse) + self.rb_use_enabled = QtWidgets.QRadioButton(self.centralwidget) + self.rb_use_enabled.setObjectName("rb_use_enabled") + self.horizontalLayout_5.addWidget(self.rb_use_enabled) + self.rb_use_disabled = QtWidgets.QRadioButton(self.centralwidget) + self.rb_use_disabled.setObjectName("rb_use_disabled") + self.horizontalLayout_5.addWidget(self.rb_use_disabled) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.l_res_count = QtWidgets.QLabel(self.centralwidget) + self.l_res_count.setObjectName("l_res_count") + self.horizontalLayout_4.addWidget(self.l_res_count) + self.horizontalLayout_5.addLayout(self.horizontalLayout_4) + self.gridLayout.addLayout(self.horizontalLayout_5, 3, 0, 1, 1) + self.tv_results = QtWidgets.QTreeView(self.centralwidget) + self.tv_results.setObjectName("tv_results") + self.gridLayout.addWidget(self.tv_results, 4, 0, 1, 1) + self.line = QtWidgets.QFrame(self.centralwidget) + self.line.setFrameShape(QtWidgets.QFrame.HLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.gridLayout.addWidget(self.line, 5, 0, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.pb_expand_all = QtWidgets.QPushButton(self.centralwidget) + self.pb_expand_all.setObjectName("pb_expand_all") + self.horizontalLayout_3.addWidget(self.pb_expand_all) + self.pb_expand_pkg = QtWidgets.QPushButton(self.centralwidget) + self.pb_expand_pkg.setObjectName("pb_expand_pkg") + self.horizontalLayout_3.addWidget(self.pb_expand_pkg) + self.pb_collapse = QtWidgets.QPushButton(self.centralwidget) + self.pb_collapse.setObjectName("pb_collapse") + self.horizontalLayout_3.addWidget(self.pb_collapse) + self.pb_updatedb = QtWidgets.QPushButton(self.centralwidget) + self.pb_updatedb.setObjectName("pb_updatedb") + self.horizontalLayout_3.addWidget(self.pb_updatedb) + self.le_command = QtWidgets.QLineEdit(self.centralwidget) + self.le_command.setEnabled(False) + self.le_command.setObjectName("le_command") + self.horizontalLayout_3.addWidget(self.le_command) + self.gridLayout.addLayout(self.horizontalLayout_3, 6, 0, 1, 1) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 938, 26)) + self.menubar.setObjectName("menubar") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + MainWindow.setTabOrder(self.le_search, self.pb_search) + MainWindow.setTabOrder(self.pb_search, self.cb_stable) + MainWindow.setTabOrder(self.cb_stable, self.cb_testing) + MainWindow.setTabOrder(self.cb_testing, self.cb_installed) + MainWindow.setTabOrder(self.cb_installed, self.cb_overlay) + MainWindow.setTabOrder(self.cb_overlay, self.rb_any) + MainWindow.setTabOrder(self.rb_any, self.rb_decription) + MainWindow.setTabOrder(self.rb_decription, self.rb_category) + MainWindow.setTabOrder(self.rb_category, self.rb_name) + MainWindow.setTabOrder(self.rb_name, self.rb_iuse) + MainWindow.setTabOrder(self.rb_iuse, self.rb_use_enabled) + MainWindow.setTabOrder(self.rb_use_enabled, self.rb_use_disabled) + MainWindow.setTabOrder(self.rb_use_disabled, self.tv_results) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "PyEix")) + self.pb_search.setText(_translate("MainWindow", "Search")) + self.cb_stable.setToolTip(_translate("MainWindow", "Only match packages with a stable version")) + self.cb_stable.setText(_translate("MainWindow", "Stable")) + self.cb_testing.setToolTip(_translate("MainWindow", "Only match packages with a testing version")) + self.cb_testing.setText(_translate("MainWindow", "Testing")) + self.cb_installed.setToolTip(_translate("MainWindow", "Only match installed packages")) + self.cb_installed.setText(_translate("MainWindow", "Installed")) + self.cb_overlay.setToolTip(_translate("MainWindow", "Only match packages with at least one version in an overlay")) + self.cb_overlay.setText(_translate("MainWindow", "Overlay")) + self.rb_any.setToolTip(_translate("MainWindow", "Search any field")) + self.rb_any.setText(_translate("MainWindow", "Any")) + self.rb_decription.setToolTip(_translate("MainWindow", "Search the description field")) + self.rb_decription.setText(_translate("MainWindow", "Description")) + self.rb_category.setToolTip(_translate("MainWindow", "Search the category field")) + self.rb_category.setText(_translate("MainWindow", "Category")) + self.rb_name.setToolTip(_translate("MainWindow", "Search the name field")) + self.rb_name.setText(_translate("MainWindow", "Name")) + self.rb_iuse.setToolTip(_translate("MainWindow", "Search for packages that can have that use flag enabled")) + self.rb_iuse.setText(_translate("MainWindow", "Use flags (IUSE)")) + self.rb_use_enabled.setToolTip(_translate("MainWindow", "Search for packages installed with that use flag enabled")) + self.rb_use_enabled.setText(_translate("MainWindow", "Use enabled")) + self.rb_use_disabled.setToolTip(_translate("MainWindow", "Search for packages instealled with that use flag diabled")) + self.rb_use_disabled.setText(_translate("MainWindow", "Use Disabled")) + self.l_res_count.setText(_translate("MainWindow", " Results: ")) + self.pb_expand_all.setText(_translate("MainWindow", "Expand All")) + self.pb_expand_pkg.setText(_translate("MainWindow", "Expand Pkgs")) + self.pb_collapse.setText(_translate("MainWindow", "Collapse")) + self.pb_updatedb.setToolTip(_translate("MainWindow", "

Update eix\'s database (uses sudo)

")) + self.pb_updatedb.setText(_translate("MainWindow", "Update DB")) + self.le_command.setText(_translate("MainWindow", "eix")) + +class Category: + def __init__(self): + self.UID=1 + self.PUID=0 + self.Name='' + self.Packages=[] + +class Package: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Name='' + self.Description='' + self.Homepage='' + self.Installed=[] + self.Available=[] + +class Installed: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Version='' + self.Use='' + self.Homepage='Installed ->' + +class Available: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Version='' + self.Use='' + self.Homepage='Available ->' + +class Result: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Category='' + self.Name='' + self.Description='' + self.Homepage='' + self.Version='' + self.Use='' + +class MainWindow(QMainWindow, Ui_MainWindow): + def __init__(self, parent=None): + super(MainWindow, self).__init__(parent) + self.setupUi(self) + self.cb_option={ + 'cb_stable':[self.cb_stable,'--stable'], + 'cb_testing':[self.cb_testing,'--testing'], + 'cb_installed':[self.cb_installed,'--installed'], + 'cb_overlay':[self.cb_overlay,'--overlay'], + } + self.rb_option={ + 'rb_decription':[self.rb_decription,'--description'], + 'rb_use_disabled':[self.rb_use_disabled,'--installed-without-use'], + 'rb_any':[self.rb_any,'--any'], + 'rb_name':[self.rb_name,'--name'], + 'rb_category':[self.rb_category,'--category'], + 'rb_iuse':[self.rb_iuse,'--use'], + 'rb_use_enabled':[self.rb_use_enabled,'--installed-with-use'], + } + self.find={ + 'Category':[re.compile('^\[[0-9I]\] [A-z0-9]|^\* [A-z0-9]'), self.getCat, 0], + 'Name':[re.compile('^\[[0-9I]\] [A-z0-9]|^\* [A-z0-9]'), self.getName, 1], + 'Description':[re.compile('Description:'), self.getDesc, 2], + 'Homepage':[re.compile('Homepage:'), self.getHome, 3], + 'Installed':[re.compile('Installed versions:'), self.getInstVers, 4], + 'Installed_use':[re.compile('Installed versions:'), self.getIuse, 5], + 'Available':[re.compile('Available versions:'), self.getAvailVers, 6], + 'Available_use':[re.compile('\{.*\}'), self.getAuse, 7], + 'avail_ver_single':re.compile('(\)|[0-9]|c|\]) [0-9~\*\[]'), + 'avail_ver_multi':re.compile('([0-9]|c) [0-9~\*\[]'), + } + self.cats=0 + + def on_le_search_returnPressed(self): + self.on_pb_search_released() + + def on_pb_expand_pkg_released(self): + model=self.tv_results.model() + for a in range(0,self.cats+1): + self.tv_results.expand(model.createIndex(a,1)) + + def on_pb_expand_all_released(self): + self.tv_results.expandAll() + + def on_pb_collapse_released(self): + self.tv_results.collapseAll() + + def on_pb_search_released(self): + options=['eix','-n'] + for rb in self.rb_option: + if self.rb_option[rb][0].isChecked(): + options.append(self.rb_option[rb][1]) + break + for cb in self.cb_option: + if self.cb_option[cb][0].isChecked(): + options.append(self.cb_option[cb][1]) + terms=re.sub(' ','|',self.le_search.text()) + options.append(terms) + self.le_command.setText(' '.join(options)) + self.doSearch(options) + + def doSearch(self, options): + process=subprocess.Popen(options,encoding='utf-8',stdout=subprocess.PIPE, env={'EIX_LIMIT':'0', 'HOME':'$HOME'}) + results=[] + result=[] + in_result=False + starter=re.compile('^\[[0-9I]\] [A-z0-9]|^\* [A-z0-9]') + overlay=re.compile('^\[[0-9]\] "') + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + if starter.match(output): + in_result=True + elif output=='\n': + in_result=False + elif overlay.match(output) and not in_result: + list=output.split(' ') + result=['* Overlays/%s: %s'%(list[1][1:-1],list[0]),'Description: %s'%list[2]] + in_result=False + if output and in_result: + result.append(output.strip()) + elif result and not in_result: + results.append(result) + result=[] + model = self.createResultsModel(self) + uid=1 + cats=[] + self.l_res_count.setText('Results: %s'%len(results)) + for result in results: + cats,uid=self.formatResult(cats,uid,result) + ex_cats=self.sortResults(cats) + self.addResults(model,ex_cats) + self.cats=len(cats) + self.tv_results.setModel(model) + + def formatResult(self,cats,uid,result): + cat=None + in_avail=False + for field in result: + if self.find['Category'][0].search(field): + cat_name=self.find['Category'][1](field) + for pcat in cats: + if pcat.Name==cat_name: + cat=pcat + break + if not cat: + cat=Category() + cat.Name=cat_name + cat.UID=uid + cats.append(cat) + uid+=1 + pkg=Package() + pkg.Name=self.find['Name'][1](field) + pkg.UID=uid + uid+=1 + pkg.PUID=cat.UID + cat.Packages.append(pkg) + continue + if self.find['Description'][0].search(field): + in_avail=False + pkg.Description=self.find['Description'][1](field) + continue + if self.find['Homepage'][0].search(field): + in_avail=False + pkg.Homepage=self.find['Homepage'][1](field) + continue + if self.find['Installed'][0].search(field): + in_avail=False + for installed,use in self.find['Installed'][1](field): + inst=Installed() + inst.Version=installed + inst.Use='Use flags: %s'%use + inst.PUID=pkg.UID + inst.UID=uid + uid+=1 + pkg.Installed.append(inst) + continue + if self.find['Available'][0].search(field): + in_avail=True + versions=self.find['Available'][1](field,self.find['avail_ver_single']) + for version in versions: + if version=='':continue + avail=Available() + avail.Version=version + avail.PUID=pkg.UID + avail.UID=uid + avail.Use='Use flags: %s'%self.getAuse(field) + uid+=1 + pkg.Available.append(avail) + if self.find['Available_use'][0].search(field): + in_avail=False + use=self.find['Available_use'][1](field) + if use: + for avail in pkg.Available: + avail.Use='Use flags: %s'%use + continue + if self.find['Available_use'][0].search(field): + in_avail=False + use=self.find['Available_use'][1](field,) + if use: + for avail in pkg.Available: + avail.Use='Use flags: %s'%use + continue + if in_avail: + versions=self.find['Available'][1](field,self.find['avail_ver_multi']) + for version in versions: + avail=Available() + avail.Version=version + avail.PUID=pkg.UID + avail.UID=uid + uid+=1 + pkg.Available.append(avail) + + return cats,uid + + def sortResults(self, results): + sorted=[] + for cat in results: + result=Result() + result.UID=cat.UID + result.Category=cat.Name + sorted.append(result) + for pkg in cat.Packages: + result=Result() + result.Name=pkg.Name + result.UID=pkg.UID + result.PUID=pkg.PUID + result.Description=pkg.Description + result.Homepage=pkg.Homepage + sorted.append(result) + for inst in pkg.Installed: + result=Result() + result.UID=inst.UID + result.PUID=inst.PUID + result.Name=inst.Homepage + result.Description=inst.Version + result.Homepage=inst.Use + sorted.append(result) + for avail in pkg.Available: + if avail.Version[0]=='(' and avail.Version[len(avail.Version)-1]==')': continue + result=Result() + result.UID=avail.UID + result.PUID=avail.PUID + result.Name=avail.Homepage + result.Description=avail.Version + result.Homepage=avail.Use + sorted.append(result) + return sorted + + def getName(self, str): + return str.split('/')[1] + + def getCat(self, str): + return str.split(' ')[1].split('/')[0] + + def getAvailVers(self,str,RE): + result=[] + use=self.getAuse(str) + if use: str=str[:str.find('{')] + str=self.clean(str) + match=RE.search(str) + while match: + ver=str[:match.start()+1] + result.append(ver) + str=str[match.end()-1:] + match=RE.search(str) + result.append(str) + return result + + def getInstVers(self, str): + result=[] + str=re.sub('Installed versions: *','',str) + match=re.search('\) [0-9]',str) + while match: + ver=str[:match.start()+1] + use=self.getIuse(ver) + if use: ver=ver[:ver.rfind('(')] + ver=self.clean(ver) + result.append([ver,use]) + str=str[match.end()-1:] + match=re.search('\) [0-9]',str) + use=self.getIuse(str) + if use: str=str[:str.rfind('(')] + str=self.clean(str) + result.append([str,use]) + return result + + def getHome(self, str): + t=self.find['Homepage'][0].match(str) + home=str[t.end()+1:].strip() + return home + + def getDesc(self, str): + t=self.find['Description'][0].match(str) + desc=str[t.end()+1:].strip() + return desc + + def getIuse(self, str): + iuse='' + match=re.search('\)\([A-z0-9\-]',str) + if match: + iuse=str[match.end()-1:str.rfind(')')] + return iuse + + def getAuse(self, str): + t=self.find['Available_use'][0].search(str) + if t: + return str[t.start()+1:t.end()-1] + else: + return '' + + def clean(self,str): + strip={ '\^[a-z]{1,3}':'','\*l':'','\(~\)':'~','Available versions: *':'', + '\(([0-9]{2}:){2}[0-9]{2} ([0-9]{2}/){2}[0-9]{2}\)':''} + for RE in strip: + str=re.sub(RE,strip[RE],str) + return str + + def createResultsModel(self,parent): + headers=['Category','Name','Description','Homepage' ] + model = QStandardItemModel() + model.setHorizontalHeaderLabels(headers) + return model + + def addResults(self,model,results): + items={} + for result in results: + if result.PUID==0: + parent=model.invisibleRootItem() + else: + parent=items[result.PUID] + try: + parent.appendRow([ QStandardItem(result.Category), + QStandardItem(result.Name), + QStandardItem(result.Description), + QStandardItem(result.Homepage), + ]) + except: + print(result.Category,result.Name,result.Description,result.Homepage) + sys.exit() + items[result.UID] = parent.child(parent.rowCount()-1) + return model + + def on_pb_updatedb_released(self): + child=subprocess.Popen(['sudo','eix-update']) + child.wait() + sys.argv[0] + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + ui = MainWindow() + ui.show() + sys.exit(app.exec_()) diff --git a/pyeix/ui/Ui_mainwindow.py b/pyeix/ui/Ui_mainwindow.py new file mode 100644 index 0000000..10ae172 --- /dev/null +++ b/pyeix/ui/Ui_mainwindow.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/andrew/Projects/pyeix/ui/mainwindow.ui' +# +# Created by: PyQt5 UI code generator 5.15.1 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore,QtWidgets + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(938, 483) + MainWindow.setMinimumSize(QtCore.QSize(460, 300)) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.le_search = QtWidgets.QLineEdit(self.centralwidget) + self.le_search.setObjectName("le_search") + self.horizontalLayout_2.addWidget(self.le_search) + self.pb_search = QtWidgets.QPushButton(self.centralwidget) + self.pb_search.setObjectName("pb_search") + self.horizontalLayout_2.addWidget(self.pb_search) + self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.cb_stable = QtWidgets.QCheckBox(self.centralwidget) + self.cb_stable.setObjectName("cb_stable") + self.horizontalLayout.addWidget(self.cb_stable) + self.cb_testing = QtWidgets.QCheckBox(self.centralwidget) + self.cb_testing.setObjectName("cb_testing") + self.horizontalLayout.addWidget(self.cb_testing) + self.cb_installed = QtWidgets.QCheckBox(self.centralwidget) + self.cb_installed.setObjectName("cb_installed") + self.horizontalLayout.addWidget(self.cb_installed) + self.cb_overlay = QtWidgets.QCheckBox(self.centralwidget) + self.cb_overlay.setTristate(False) + self.cb_overlay.setObjectName("cb_overlay") + self.horizontalLayout.addWidget(self.cb_overlay) + self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1) + self.horizontalLayout_6 = QtWidgets.QHBoxLayout() + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.rb_any = QtWidgets.QRadioButton(self.centralwidget) + self.rb_any.setObjectName("rb_any") + self.horizontalLayout_6.addWidget(self.rb_any) + self.rb_decription = QtWidgets.QRadioButton(self.centralwidget) + self.rb_decription.setObjectName("rb_decription") + self.horizontalLayout_6.addWidget(self.rb_decription) + self.rb_category = QtWidgets.QRadioButton(self.centralwidget) + self.rb_category.setObjectName("rb_category") + self.horizontalLayout_6.addWidget(self.rb_category) + self.rb_name = QtWidgets.QRadioButton(self.centralwidget) + self.rb_name.setObjectName("rb_name") + self.horizontalLayout_6.addWidget(self.rb_name) + self.gridLayout.addLayout(self.horizontalLayout_6, 2, 0, 1, 1) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.rb_iuse = QtWidgets.QRadioButton(self.centralwidget) + self.rb_iuse.setObjectName("rb_iuse") + self.horizontalLayout_5.addWidget(self.rb_iuse) + self.rb_use_enabled = QtWidgets.QRadioButton(self.centralwidget) + self.rb_use_enabled.setObjectName("rb_use_enabled") + self.horizontalLayout_5.addWidget(self.rb_use_enabled) + self.rb_use_disabled = QtWidgets.QRadioButton(self.centralwidget) + self.rb_use_disabled.setObjectName("rb_use_disabled") + self.horizontalLayout_5.addWidget(self.rb_use_disabled) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.l_res_count = QtWidgets.QLabel(self.centralwidget) + self.l_res_count.setObjectName("l_res_count") + self.horizontalLayout_4.addWidget(self.l_res_count) + self.horizontalLayout_5.addLayout(self.horizontalLayout_4) + self.gridLayout.addLayout(self.horizontalLayout_5, 3, 0, 1, 1) + self.tv_results = QtWidgets.QTreeView(self.centralwidget) + self.tv_results.setObjectName("tv_results") + self.gridLayout.addWidget(self.tv_results, 4, 0, 1, 1) + self.line = QtWidgets.QFrame(self.centralwidget) + self.line.setFrameShape(QtWidgets.QFrame.HLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.gridLayout.addWidget(self.line, 5, 0, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.pb_expand_all = QtWidgets.QPushButton(self.centralwidget) + self.pb_expand_all.setObjectName("pb_expand_all") + self.horizontalLayout_3.addWidget(self.pb_expand_all) + self.pb_expand_pkg = QtWidgets.QPushButton(self.centralwidget) + self.pb_expand_pkg.setObjectName("pb_expand_pkg") + self.horizontalLayout_3.addWidget(self.pb_expand_pkg) + self.pb_collapse = QtWidgets.QPushButton(self.centralwidget) + self.pb_collapse.setObjectName("pb_collapse") + self.horizontalLayout_3.addWidget(self.pb_collapse) + self.pb_updatedb = QtWidgets.QPushButton(self.centralwidget) + self.pb_updatedb.setObjectName("pb_updatedb") + self.horizontalLayout_3.addWidget(self.pb_updatedb) + self.le_command = QtWidgets.QLineEdit(self.centralwidget) + self.le_command.setEnabled(False) + self.le_command.setObjectName("le_command") + self.horizontalLayout_3.addWidget(self.le_command) + self.gridLayout.addLayout(self.horizontalLayout_3, 6, 0, 1, 1) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 938, 26)) + self.menubar.setObjectName("menubar") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + MainWindow.setTabOrder(self.le_search, self.pb_search) + MainWindow.setTabOrder(self.pb_search, self.cb_stable) + MainWindow.setTabOrder(self.cb_stable, self.cb_testing) + MainWindow.setTabOrder(self.cb_testing, self.cb_installed) + MainWindow.setTabOrder(self.cb_installed, self.cb_overlay) + MainWindow.setTabOrder(self.cb_overlay, self.rb_any) + MainWindow.setTabOrder(self.rb_any, self.rb_decription) + MainWindow.setTabOrder(self.rb_decription, self.rb_category) + MainWindow.setTabOrder(self.rb_category, self.rb_name) + MainWindow.setTabOrder(self.rb_name, self.rb_iuse) + MainWindow.setTabOrder(self.rb_iuse, self.rb_use_enabled) + MainWindow.setTabOrder(self.rb_use_enabled, self.rb_use_disabled) + MainWindow.setTabOrder(self.rb_use_disabled, self.tv_results) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "PyEix")) + self.pb_search.setText(_translate("MainWindow", "Search")) + self.cb_stable.setToolTip(_translate("MainWindow", "Only match packages with a stable version")) + self.cb_stable.setText(_translate("MainWindow", "Stable")) + self.cb_testing.setToolTip(_translate("MainWindow", "Only match packages with a testing version")) + self.cb_testing.setText(_translate("MainWindow", "Testing")) + self.cb_installed.setToolTip(_translate("MainWindow", "Only match installed packages")) + self.cb_installed.setText(_translate("MainWindow", "Installed")) + self.cb_overlay.setToolTip(_translate("MainWindow", "Only match packages with at least one version in an overlay")) + self.cb_overlay.setText(_translate("MainWindow", "Overlay")) + self.rb_any.setToolTip(_translate("MainWindow", "Search any field")) + self.rb_any.setText(_translate("MainWindow", "Any")) + self.rb_decription.setToolTip(_translate("MainWindow", "Search the description field")) + self.rb_decription.setText(_translate("MainWindow", "Description")) + self.rb_category.setToolTip(_translate("MainWindow", "Search the category field")) + self.rb_category.setText(_translate("MainWindow", "Category")) + self.rb_name.setToolTip(_translate("MainWindow", "Search the name field")) + self.rb_name.setText(_translate("MainWindow", "Name")) + self.rb_iuse.setToolTip(_translate("MainWindow", "Search for packages that can have that use flag enabled")) + self.rb_iuse.setText(_translate("MainWindow", "Use flags (IUSE)")) + self.rb_use_enabled.setToolTip(_translate("MainWindow", "Search for packages installed with that use flag enabled")) + self.rb_use_enabled.setText(_translate("MainWindow", "Use enabled")) + self.rb_use_disabled.setToolTip(_translate("MainWindow", "Search for packages instealled with that use flag diabled")) + self.rb_use_disabled.setText(_translate("MainWindow", "Use Disabled")) + self.l_res_count.setText(_translate("MainWindow", " Results: ")) + self.pb_expand_all.setText(_translate("MainWindow", "Expand All")) + self.pb_expand_pkg.setText(_translate("MainWindow", "Expand Pkgs")) + self.pb_collapse.setText(_translate("MainWindow", "Collapse")) + self.pb_updatedb.setToolTip(_translate("MainWindow", "

Update eix\'s database (uses sudo)

")) + self.pb_updatedb.setText(_translate("MainWindow", "Update DB")) + self.le_command.setText(_translate("MainWindow", "eix")) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + MainWindow = QtWidgets.QMainWindow() + ui = Ui_MainWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) diff --git a/pyeix/ui/__init__.py b/pyeix/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyeix/ui/__pycache__/Ui_mainwindow.cpython-39.pyc b/pyeix/ui/__pycache__/Ui_mainwindow.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e43e4abed16dcd27710f67249448e3de27f8d14a GIT binary patch literal 5227 zcmbVQTXWmS6$bBjiKcb2EXjg=lNr0BFL9iUs@hf@Co}Pdk=)GSg@uT<2pI&}1!##J zclwa@e^8I@Q-4T*0bVoH8U2Mm^*g&u2sD*+rsQC`=R4myyJr`>=SXIyQq=IV{~7*i z7P`9rsIbathLuke35}IUvnLvUbE7INjxL;Ngj$(h zt)4x_xLQ3GW}Cr|$61(Z2G9F;SZD@6+SUOJ{5BEdpCp9Gc>EPKOfwReW+bhImHb&V zQdY`J<2Nmxhm|*W>xF5%KiaP49kt1H{Gomx&ki2{aaPklBu0pzW`-WzS*eqx=qH2J zC~d*zNs_cdW|aK^-UqFf`=A}>V3k#Po@AjZpjUtflCUVAXyBKCmVo9JT8{V?^eWI` z9Wf@cW(ZNd*@#y~uL@pqf>%{iVRV6PE&7(N@<}E(b`6>uEXO`CMn31zn}cRXd8vu9 z=hWC|ym|2E!JD1n%}?U4iZjc;neG ziS@ifJZNMrOV*`xVp)TJ4VFt&K6PkxXf7)+Yr>~K#ajn&9Xt`G@J2DOPw}n-y$YU) zGU8oTJo&a>1AYyhafH_)%ay%>-VJERF*&=-p9Go1TZgyR81>N|A^$FtHA}=2`Kw#kCj7|=H=*Ce*w@Jp z=lblNHK1ugGmdFf%&IZPy9?f3@NTM+CGYMO?;d#fz}uMM-J9aw2k$<3wtUGgv|pb$@Sl~J~@jY_uE6*kME|>)NS?%*rUH=QGq+rr`jx2^BZf!7bhTF2w| z&~pRRkx1))Sa4X&XC`lV!a{FfbvYbqr__Yik8Q$28??aOcUV|NH(-8Xy9Z$zecOe? zahUauP#<9-%q`F_iE2Vn)j7Hf067ucQ~mLRsxfE{>z5auAbW|y5(B0a~; zL&327J_~0+#czwbG%+ijRkCIK5}1zt)3D^UIP+U=ukQw@SV}D{2JZ>#JAr>nbxW9b zY?qy8&L96lSizF917%r*JW;h-{fHd%NX>1bn8#UiqC>q`-iL@yu?~y;h1j^nK1+Sh3(qies>o#r!_J% zP0^>R8@Z+|Z+MQRQuBHAB5*27fPDMZJC-j3FA!2_evfFMS$4pwq%#VpWl0|(zwY~; zr~M%CTwWS0m2pKH?{rxE9bEDm$b6QXDm52KUBYztxJ`jEUL&O3{K2$rPx-t^%sFc2 zsac@r5;aTI(DLwQYN#SJvd!>d&e$JqcEs1D@*9qY;_D>P;t6rLWA>Pl z`IaISYd1zwv>DmmzWa{3{2EO7b!u)@tR;#>Y79%*zrF8y8-67|YS@<|@f`wr(P>iJEz3KMlbT@`dC z?BMY~$H5D2oP`)7Ig1f;L2)j{5Xo7Jkeb?^%Mo%>AI)>?!tDl1(gBA>6n6o=HvydFHWk8ux)OgyZ=a-D(RHG_6X@0sm)<^l8dBRlBm zrj8pF8BRxP^^q`PBIMyGzhRrfhhN2*AI&Jx9cKE0 z?zz#dblcTUS6BJp$i0$IX$g(@i;iq?B(x9!07L9W&6|m~zK_&!mKELVxR+2f8XLhSfI; z@%3BZz1e+MAAWwGtFv_!8zwwY`6`jGvEwg(%?%T^l-&49Kb9@3nqisze64Dn;hcW< z`9W4OU+Tl+Gf|-EPaJ1hQvKKO4tyiOqiU1kcUzsH>uhgzm}xb(xAr}2u)WpWej~~i z9T{T7*HO8c`zD6Fg=l=;?^|AdtI^xuYDjuRxEL0c(brGI6b$Q^WMNWm(!XAw^m>ks zZKF!B5aly@96l-+4I zv-+qQTVc7?`g7lO=%sG8_yf#COe;23O7>jLmogMpVm?)a`9%IbCxjeRqHncc)@vc| zoo4V*Y!Rod#zoPa^+dTT_bDK1`XtUWn=>`UjX;#xU8p#q3as wbiAW5&5rFL%&=qDZk;#RFux^3+@{jfr!sIZRsE~BjAg`k0*C)M5OULen3%vR%&udv3@~iYG#FgX{LUBd}dx|NqoFsLFFwDo80`A(wtN~kQtwWm;nGG C#2uvo literal 0 HcmV?d00001 diff --git a/pyeix/ui/__pycache__/mainwindow.cpython-39.pyc b/pyeix/ui/__pycache__/mainwindow.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91e0fdcfec33c05ddfe85b695e9b3b577c589347 GIT binary patch literal 10745 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 II8iD8zf|xP^#A|> literal 0 HcmV?d00001 diff --git a/pyeix/ui/mainwindow.py b/pyeix/ui/mainwindow.py new file mode 100644 index 0000000..211fd1c --- /dev/null +++ b/pyeix/ui/mainwindow.py @@ -0,0 +1,367 @@ +# -*- coding: utf-8 -*- + +''' +Module implementing MainWindow. +''' +from PyQt5.QtWidgets import QMainWindow +from PyQt5.QtGui import QStandardItemModel,QStandardItem +import sys, subprocess, re +from .Ui_mainwindow import Ui_MainWindow + +class Category: + def __init__(self): + self.UID=1 + self.PUID=0 + self.Name='' + self.Packages=[] + +class Package: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Name='' + self.Description='' + self.Homepage='' + self.Installed=[] + self.Available=[] + +class Installed: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Version='' + self.Use='' + self.Homepage='Installed ->' + +class Available: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Version='' + self.Use='' + self.Homepage='Available ->' + +class Result: + def __init__(self): + self.UID=0 + self.PUID=0 + self.Category='' + self.Name='' + self.Description='' + self.Homepage='' + self.Version='' + self.Use='' + +class MainWindow(QMainWindow, Ui_MainWindow): + def __init__(self, parent=None): + super(MainWindow, self).__init__(parent) + self.setupUi(self) + self.cb_option={ + 'cb_stable':[self.cb_stable,'--stable'], + 'cb_testing':[self.cb_testing,'--testing'], + 'cb_installed':[self.cb_installed,'--installed'], + 'cb_overlay':[self.cb_overlay,'--overlay'], + } + self.rb_option={ + 'rb_decription':[self.rb_decription,'--description'], + 'rb_use_disabled':[self.rb_use_disabled,'--installed-without-use'], + 'rb_any':[self.rb_any,'--any'], + 'rb_name':[self.rb_name,'--name'], + 'rb_category':[self.rb_category,'--category'], + 'rb_iuse':[self.rb_iuse,'--use'], + 'rb_use_enabled':[self.rb_use_enabled,'--installed-with-use'], + } + self.find={ + 'Category':[re.compile('^\[[0-9I]\] [A-z0-9]|^\* [A-z0-9]'), self.getCat, 0], + 'Name':[re.compile('^\[[0-9I]\] [A-z0-9]|^\* [A-z0-9]'), self.getName, 1], + 'Description':[re.compile('Description:'), self.getDesc, 2], + 'Homepage':[re.compile('Homepage:'), self.getHome, 3], + 'Installed':[re.compile('Installed versions:'), self.getInstVers, 4], + 'Installed_use':[re.compile('Installed versions:'), self.getIuse, 5], + 'Available':[re.compile('Available versions:'), self.getAvailVers, 6], + 'Available_use':[re.compile('\{.*\}'), self.getAuse, 7], + 'avail_ver_single':re.compile('(\)|[0-9]|c|\]) [0-9~\*\[]'), + 'avail_ver_multi':re.compile('([0-9]|c) [0-9~\*\[]'), + } + self.cats=0 + + def on_le_search_returnPressed(self): + self.on_pb_search_released() + + def on_pb_expand_pkg_released(self): + model=self.tv_results.model() + for a in range(0,self.cats+1): + self.tv_results.expand(model.createIndex(a,1)) + + def on_pb_expand_all_released(self): + self.tv_results.expandAll() + + def on_pb_collapse_released(self): + self.tv_results.collapseAll() + + def on_pb_search_released(self): + options=['eix','-n'] + for rb in self.rb_option: + if self.rb_option[rb][0].isChecked(): + options.append(self.rb_option[rb][1]) + break + for cb in self.cb_option: + if self.cb_option[cb][0].isChecked(): + options.append(self.cb_option[cb][1]) + terms=re.sub(' ','|',self.le_search.text()) + options.append(terms) + self.le_command.setText(' '.join(options)) + self.doSearch(options) + + def doSearch(self, options): + process=subprocess.Popen(options,encoding='utf-8',stdout=subprocess.PIPE, env={'EIX_LIMIT':'0', 'HOME':'$HOME'}) + results=[] + result=[] + in_result=False + starter=re.compile('^\[[0-9I]\] [A-z0-9]|^\* [A-z0-9]') + overlay=re.compile('^\[[0-9]\] "') + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + if starter.match(output): + in_result=True + elif output=='\n': + in_result=False + elif overlay.match(output) and not in_result: + list=output.split(' ') + result=['* Overlays/%s: %s'%(list[1][1:-1],list[0]),'Description: %s'%list[2]] + in_result=False + if output and in_result: + result.append(output.strip()) + elif result and not in_result: + results.append(result) + result=[] + model = self.createResultsModel(self) + uid=1 + cats=[] + self.l_res_count.setText('Results: %s'%len(results)) + for result in results: + cats,uid=self.formatResult(cats,uid,result) + ex_cats=self.sortResults(cats) + self.addResults(model,ex_cats) + self.cats=len(cats) + self.tv_results.setModel(model) + + def formatResult(self,cats,uid,result): + cat=None + in_avail=False + for field in result: + if self.find['Category'][0].search(field): + cat_name=self.find['Category'][1](field) + for pcat in cats: + if pcat.Name==cat_name: + cat=pcat + break + if not cat: + cat=Category() + cat.Name=cat_name + cat.UID=uid + cats.append(cat) + uid+=1 + pkg=Package() + pkg.Name=self.find['Name'][1](field) + pkg.UID=uid + uid+=1 + pkg.PUID=cat.UID + cat.Packages.append(pkg) + continue + if self.find['Description'][0].search(field): + in_avail=False + pkg.Description=self.find['Description'][1](field) + continue + if self.find['Homepage'][0].search(field): + in_avail=False + pkg.Homepage=self.find['Homepage'][1](field) + continue + if self.find['Installed'][0].search(field): + in_avail=False + for installed,use in self.find['Installed'][1](field): + inst=Installed() + inst.Version=installed + inst.Use='Use flags: %s'%use + inst.PUID=pkg.UID + inst.UID=uid + uid+=1 + pkg.Installed.append(inst) + continue + if self.find['Available'][0].search(field): + in_avail=True + versions=self.find['Available'][1](field,self.find['avail_ver_single']) + for version in versions: + if version=='':continue + avail=Available() + avail.Version=version + avail.PUID=pkg.UID + avail.UID=uid + avail.Use='Use flags: %s'%self.getAuse(field) + uid+=1 + pkg.Available.append(avail) + if self.find['Available_use'][0].search(field): + in_avail=False + use=self.find['Available_use'][1](field) + if use: + for avail in pkg.Available: + avail.Use='Use flags: %s'%use + continue + if self.find['Available_use'][0].search(field): + in_avail=False + use=self.find['Available_use'][1](field,) + if use: + for avail in pkg.Available: + avail.Use='Use flags: %s'%use + continue + if in_avail: + versions=self.find['Available'][1](field,self.find['avail_ver_multi']) + for version in versions: + avail=Available() + avail.Version=version + avail.PUID=pkg.UID + avail.UID=uid + uid+=1 + pkg.Available.append(avail) + + return cats,uid + + def sortResults(self, results): + sorted=[] + for cat in results: + result=Result() + result.UID=cat.UID + result.Category=cat.Name + sorted.append(result) + for pkg in cat.Packages: + result=Result() + result.Name=pkg.Name + result.UID=pkg.UID + result.PUID=pkg.PUID + result.Description=pkg.Description + result.Homepage=pkg.Homepage + sorted.append(result) + for inst in pkg.Installed: + result=Result() + result.UID=inst.UID + result.PUID=inst.PUID + result.Name=inst.Homepage + result.Description=inst.Version + result.Homepage=inst.Use + sorted.append(result) + for avail in pkg.Available: + if avail.Version[0]=='(' and avail.Version[len(avail.Version)-1]==')': continue + result=Result() + result.UID=avail.UID + result.PUID=avail.PUID + result.Name=avail.Homepage + result.Description=avail.Version + result.Homepage=avail.Use + sorted.append(result) + return sorted + + + def getName(self, str): + return str.split('/')[1] + + def getCat(self, str): + return str.split(' ')[1].split('/')[0] + + def getAvailVers(self,str,RE): + result=[] + use=self.getAuse(str) + if use: str=str[:str.find('{')] + str=self.clean(str) + match=RE.search(str) + while match: + ver=str[:match.start()+1] + result.append(ver) + str=str[match.end()-1:] + match=RE.search(str) + result.append(str) + return result + + def getInstVers(self, str): + result=[] + str=re.sub('Installed versions: *','',str) + match=re.search('\) [0-9]',str) + while match: + ver=str[:match.start()+1] + use=self.getIuse(ver) + if use: ver=ver[:ver.rfind('(')] + ver=self.clean(ver) + result.append([ver,use]) + str=str[match.end()-1:] + match=re.search('\) [0-9]',str) + use=self.getIuse(str) + if use: str=str[:str.rfind('(')] + str=self.clean(str) + result.append([str,use]) + return result + + def getHome(self, str): + t=self.find['Homepage'][0].match(str) + home=str[t.end()+1:].strip() + return home + + def getDesc(self, str): + t=self.find['Description'][0].match(str) + desc=str[t.end()+1:].strip() + return desc + + def getIuse(self, str): + iuse='' + match=re.search('\)\([A-z0-9\-]',str) + if match: + iuse=str[match.end()-1:str.rfind(')')] + return iuse + + def getAuse(self, str): + t=self.find['Available_use'][0].search(str) + if t: + return str[t.start()+1:t.end()-1] + else: + return '' + + def clean(self,str): + strip={ '\^[a-z]{1,3}':'','\*l':'','\(~\)':'~','Available versions: *':'', + '\(([0-9]{2}:){2}[0-9]{2} ([0-9]{2}/){2}[0-9]{2}\)':''} + for RE in strip: + str=re.sub(RE,strip[RE],str) + return str + + def createResultsModel(self,parent): + headers=['Category','Name','Description','Homepage' ] + model = QStandardItemModel() + model.setHorizontalHeaderLabels(headers) + return model + + def addResults(self,model,results): + #headers=['Category','Name','Description','Homepage' ] + items={} + for result in results: + if result.PUID==0: + parent=model.invisibleRootItem() + else: + parent=items[result.PUID] + try: + parent.appendRow([ QStandardItem(result.Category), + QStandardItem(result.Name), + QStandardItem(result.Description), + QStandardItem(result.Homepage), + ]) + except: + print(result.Category,result.Name,result.Description,result.Homepage) + sys.exit() + items[result.UID] = parent.child(parent.rowCount()-1) + + #for index in headers: + # model.setData(model.index(0,self.find[index][2]),results[index]) + return model + + def on_pb_updatedb_released(self): + child=subprocess.Popen(['sudo','eix-update']) + child.wait() + sys.argv[0] diff --git a/pyeix/ui/mainwindow.ui b/pyeix/ui/mainwindow.ui new file mode 100644 index 0000000..e81d648 --- /dev/null +++ b/pyeix/ui/mainwindow.ui @@ -0,0 +1,264 @@ + + + MainWindow + + + + 0 + 0 + 938 + 483 + + + + + 460 + 300 + + + + PyEix + + + + + + + + + + + + Search + + + + + + + + + + + Only match packages with a stable version + + + Stable + + + + + + + Only match packages with a testing version + + + Testing + + + + + + + Only match installed packages + + + Installed + + + + + + + Only match packages with at least one version in an overlay + + + Overlay + + + false + + + + + + + + + + + Search any field + + + Any + + + + + + + Search the description field + + + Description + + + + + + + Search the category field + + + Category + + + + + + + Search the name field + + + Name + + + + + + + + + + + Search for packages that can have that use flag enabled + + + Use flags (IUSE) + + + + + + + Search for packages installed with that use flag enabled + + + Use enabled + + + + + + + Search for packages instealled with that use flag diabled + + + Use Disabled + + + + + + + + + Results: + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + Expand All + + + + + + + Expand Pkgs + + + + + + + Collapse + + + + + + + <html><head/><body><p>Update eix's database (uses sudo)</p></body></html> + + + Update DB + + + + + + + false + + + eix + + + + + + + + + + + 0 + 0 + 938 + 26 + + + + + + + le_search + pb_search + cb_stable + cb_testing + cb_installed + cb_overlay + rb_any + rb_decription + rb_category + rb_name + rb_iuse + rb_use_enabled + rb_use_disabled + tv_results + + + + + on_pb_search_clicked() + + -- 2.44.2