683 else: |
696 else: |
684 score += 1 |
697 score += 1 |
685 |
698 |
686 return score |
699 return score |
687 |
700 |
|
701 @pyqtSlot() |
|
702 def on_installButton_clicked(self): |
|
703 """ |
|
704 Private slot to handle pressing the Install button.. |
|
705 """ |
|
706 self.__install() |
|
707 |
|
708 @pyqtSlot() |
|
709 def on_installUserSiteButton_clicked(self): |
|
710 """ |
|
711 Private slot to handle pressing the Install to User-Site button.. |
|
712 """ |
|
713 self.__install(userSite=True) |
|
714 |
|
715 def __install(self, userSite=False): |
|
716 """ |
|
717 Private slot to install the selected packages. |
|
718 |
|
719 @param userSite flag indicating to install to the user directory |
|
720 @type bool |
|
721 """ |
|
722 venvName = self.environmentsComboBox.currentText() |
|
723 if venvName: |
|
724 packages = [] |
|
725 for itm in self.searchResultList.selectedItems(): |
|
726 packages.append(itm.text(0).strip()) |
|
727 if packages: |
|
728 self.__pip.installPackages(packages, venvName=venvName, |
|
729 userSite=userSite) |
|
730 |
|
731 @pyqtSlot() |
|
732 def on_showDetailsButton_clicked(self): |
|
733 """ |
|
734 Private slot to handle pressing the Show Details button. |
|
735 """ |
|
736 self.__showDetails() |
|
737 |
|
738 @pyqtSlot(QTreeWidgetItem, int) |
|
739 def on_searchResultList_itemActivated(self, item, column): |
|
740 """ |
|
741 Private slot reacting on an search result item activation. |
|
742 |
|
743 @param item reference to the activated item |
|
744 @type QTreeWidgetItem |
|
745 @param column activated column |
|
746 @type int |
|
747 """ |
|
748 self.__showDetails(item) |
|
749 |
|
750 def __showDetails(self, item=None): |
|
751 """ |
|
752 Private slot to show details about the selected package. |
|
753 |
|
754 @param item reference to the search result item to show details for |
|
755 @type QTreeWidgetItem |
|
756 """ |
|
757 self.showDetailsButton.setEnabled(False) |
|
758 QApplication.setOverrideCursor(Qt.WaitCursor) |
|
759 QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) |
|
760 |
|
761 self.__detailsData = {} |
|
762 |
|
763 if not item: |
|
764 item = self.searchResultList.selectedItems()[0] |
|
765 |
|
766 packageVersions = item.data(0, self.SearchVersionRole) |
|
767 if len(packageVersions) == 1: |
|
768 packageVersion = packageVersions[0] |
|
769 elif len(packageVersions) == 0: |
|
770 packageVersion = "" |
|
771 else: |
|
772 packageVersion, ok = QInputDialog.getItem( |
|
773 self, |
|
774 self.tr("Show Package Details"), |
|
775 self.tr("Select the package version:"), |
|
776 packageVersions, |
|
777 0, False) |
|
778 if not ok: |
|
779 return |
|
780 |
|
781 packageName = item.text(0) |
|
782 self.__client.call( |
|
783 "release_data", |
|
784 (packageName, packageVersion), |
|
785 lambda d: self.__getPackageDownloadsData(packageName, |
|
786 packageVersion, |
|
787 d), |
|
788 lambda c, s: self.__detailsError(packageName, c, s) |
|
789 ) |
|
790 |
|
791 def __getPackageDownloadsData(self, packageName, packageVersion, data): |
|
792 """ |
|
793 Private method to store the details data and get downloads |
|
794 information. |
|
795 |
|
796 @param packageName name of the package |
|
797 @type str |
|
798 @param packageVersion version info |
|
799 @type str |
|
800 @param data result data with package details in the first |
|
801 element |
|
802 @type tuple |
|
803 """ |
|
804 if data and data[0]: |
|
805 self.__detailsData = data[0] |
|
806 self.__client.call( |
|
807 "release_urls", |
|
808 (packageName, packageVersion), |
|
809 self.__displayPackageDetails, |
|
810 lambda c, s: self.__detailsError(packageName, c, s) |
|
811 ) |
|
812 else: |
|
813 QApplication.restoreOverrideCursor() |
|
814 E5MessageBox.warning( |
|
815 self, |
|
816 self.tr("Search PyPI"), |
|
817 self.tr("""<p>No package details info for <b>{0}</b>""" |
|
818 """ available.</p>""").format(packageName)) |
|
819 |
|
820 def __displayPackageDetails(self, data): |
|
821 """ |
|
822 Private method to display the returned package details. |
|
823 |
|
824 @param data result data with downloads information in the first element |
|
825 @type tuple |
|
826 """ |
|
827 from .PipPackageDetailsDialog import PipPackageDetailsDialog |
|
828 |
|
829 QApplication.restoreOverrideCursor() |
|
830 self.showDetailsButton.setEnabled(True) |
|
831 |
|
832 if self.__packageDetailsDialog is not None: |
|
833 self.__packageDetailsDialog.close() |
|
834 |
|
835 self.__packageDetailsDialog = \ |
|
836 PipPackageDetailsDialog(self.__detailsData, data[0], self) |
|
837 self.__packageDetailsDialog.show() |
|
838 |
|
839 def __detailsError(self, packageName, errorCode, errorString): |
|
840 """ |
|
841 Private method handling a details error. |
|
842 |
|
843 @param packageName name of the package |
|
844 @type str |
|
845 @param errorCode code of the error |
|
846 @type int |
|
847 @param errorString error message |
|
848 @type str |
|
849 """ |
|
850 QApplication.restoreOverrideCursor() |
|
851 self.showDetailsButton.setEnabled(True) |
|
852 E5MessageBox.warning( |
|
853 self, |
|
854 self.tr("Search PyPI"), |
|
855 self.tr("""<p>Package details info for <b>{0}</b> could not be""" |
|
856 """ retrieved.</p><p>Reason: {1}</p>""") |
|
857 .format(packageName, errorString) |
|
858 ) |
|
859 |
688 ####################################################################### |
860 ####################################################################### |
689 ## Menu related methods below |
861 ## Menu related methods below |
690 ####################################################################### |
862 ####################################################################### |
691 |
863 |
692 def __initPipMenu(self): |
864 def __initPipMenu(self): |
693 """ |
865 """ |
694 Private method to create the super menu and attach it to the super |
866 Private method to create the super menu and attach it to the super |
695 menu button. |
867 menu button. |
696 """ |
868 """ |
697 self.__pip.initActions() |
869 self.__pipMenu = QMenu() |
698 |
870 self.__installPipAct = self.__pipMenu.addAction( |
699 self.__pipMenu = self.__pip.initMenu() |
871 self.tr("Install Pip"), |
|
872 self.__installPip) |
|
873 self.__installPipUserAct = self.__pipMenu.addAction( |
|
874 self.tr("Install Pip to User-Site"), |
|
875 self.__installPipUser) |
|
876 self.__repairPipAct = self.__pipMenu.addAction( |
|
877 self.tr("Repair Pip"), |
|
878 self.__repairPip) |
|
879 self.__pipMenu.addSeparator() |
|
880 self.__installPackagesAct = self.__pipMenu.addAction( |
|
881 self.tr("Install Packages"), |
|
882 self.__installPackages) |
|
883 self.__installLocalPackageAct = self.__pipMenu.addAction( |
|
884 self.tr("Install Local Package"), |
|
885 self.__installLocalPackage) |
|
886 self.__pipMenu.addSeparator() |
|
887 self.__installRequirementsAct = self.__pipMenu.addAction( |
|
888 self.tr("Install Requirements"), |
|
889 self.__installRequirements) |
|
890 self.__uninstallRequirementsAct = self.__pipMenu.addAction( |
|
891 self.tr("Uninstall Requirements"), |
|
892 self.__uninstallRequirements) |
|
893 self.__generateRequirementsAct = self.__pipMenu.addAction( |
|
894 self.tr("Generate Requirements..."), |
|
895 self.__generateRequirements) |
|
896 self.__pipMenu.addSeparator() |
|
897 # editUserConfigAct |
|
898 self.__pipMenu.addAction( |
|
899 self.tr("Edit User Configuration..."), |
|
900 self.__editUserConfiguration) |
|
901 self.__editVirtualenvConfigAct = self.__pipMenu.addAction( |
|
902 self.tr("Edit Current Virtualenv Configuration..."), |
|
903 self.__editVirtualenvConfiguration) |
|
904 self.__pipMenu.addSeparator() |
|
905 # pipConfigAct |
|
906 self.__pipMenu.addAction( |
|
907 self.tr("Configure..."), |
|
908 self.__pipConfigure) |
|
909 |
|
910 self.__pipMenu.aboutToShow.connect(self.__aboutToShowPipMenu) |
700 |
911 |
701 self.pipMenuButton.setMenu(self.__pipMenu) |
912 self.pipMenuButton.setMenu(self.__pipMenu) |
|
913 |
|
914 def __aboutToShowPipMenu(self): |
|
915 """ |
|
916 Private slot to set the action enabled status. |
|
917 """ |
|
918 enable = bool(self.environmentsComboBox.currentText()) |
|
919 enablePip = self.__isPipAvailable() |
|
920 |
|
921 self.__installPipAct.setEnabled(not enablePip) |
|
922 self.__installPipUserAct.setEnabled(not enablePip) |
|
923 self.__repairPipAct.setEnabled(enablePip) |
|
924 |
|
925 self.__installPackagesAct.setEnabled(enablePip) |
|
926 self.__installLocalPackageAct.setEnabled(enablePip) |
|
927 |
|
928 self.__installRequirementsAct.setEnabled(enablePip) |
|
929 self.__uninstallRequirementsAct.setEnabled(enablePip) |
|
930 self.__generateRequirementsAct.setEnabled(enablePip) |
|
931 |
|
932 self.__editVirtualenvConfigAct.setEnabled(enable) |
|
933 |
|
934 @pyqtSlot() |
|
935 def __installPip(self): |
|
936 """ |
|
937 Private slot to install pip into the selected environment. |
|
938 """ |
|
939 venvName = self.environmentsComboBox.currentText() |
|
940 if venvName: |
|
941 self.__pip.installPip(venvName) |
|
942 |
|
943 @pyqtSlot() |
|
944 def __installPipUser(self): |
|
945 """ |
|
946 Private slot to install pip into the user site for the selected |
|
947 environment. |
|
948 """ |
|
949 venvName = self.environmentsComboBox.currentText() |
|
950 if venvName: |
|
951 self.__pip.installPip(venvName, userSite=True) |
|
952 |
|
953 @pyqtSlot() |
|
954 def __repairPip(self): |
|
955 """ |
|
956 Private slot to repair the pip installation of the selected |
|
957 environment. |
|
958 """ |
|
959 venvName = self.environmentsComboBox.currentText() |
|
960 if venvName: |
|
961 self.__pip.repairPip(venvName) |
|
962 |
|
963 @pyqtSlot() |
|
964 def __installPackages(self): |
|
965 """ |
|
966 Private slot to install packages to be given by the user. |
|
967 """ |
|
968 venvName = self.environmentsComboBox.currentText() |
|
969 if venvName: |
|
970 from .PipPackagesInputDialog import PipPackagesInputDialog |
|
971 dlg = PipPackagesInputDialog(self, self.tr("Install Packages")) |
|
972 if dlg.exec_() == QDialog.Accepted: |
|
973 packages, user = dlg.getData() |
|
974 if packages: |
|
975 self.__pip.installPackages(packages, venvName=venvName, |
|
976 userSite=user) |
|
977 |
|
978 @pyqtSlot() |
|
979 def __installLocalPackage(self): |
|
980 """ |
|
981 Private slot to install a package available on local storage. |
|
982 """ |
|
983 venvName = self.environmentsComboBox.currentText() |
|
984 if venvName: |
|
985 from .PipFileSelectionDialog import PipFileSelectionDialog |
|
986 dlg = PipFileSelectionDialog(self, "package") |
|
987 if dlg.exec_() == QDialog.Accepted: |
|
988 package, user = dlg.getData() |
|
989 if package and os.path.exists(package): |
|
990 self.__pip.installPackages([package], venvName=venvName, |
|
991 userSite=user) |
|
992 |
|
993 @pyqtSlot() |
|
994 def __installRequirements(self): |
|
995 """ |
|
996 |
|
997 """ |
|
998 # TODO: call pip.installRequirements() |
|
999 |
|
1000 @pyqtSlot() |
|
1001 def __uninstallRequirements(self): |
|
1002 """ |
|
1003 |
|
1004 """ |
|
1005 # TODO: call pip.uninstallRequirements() |
|
1006 |
|
1007 @pyqtSlot() |
|
1008 def __generateRequirements(self): |
|
1009 """ |
|
1010 Private slot to generate the contents for a requirements file. |
|
1011 """ |
|
1012 # TODO: modify to get selected environment |
|
1013 from .PipFreezeDialog import PipFreezeDialog |
|
1014 self.__freezeDialog = PipFreezeDialog(self) |
|
1015 self.__freezeDialog.show() |
|
1016 self.__freezeDialog.start() |
|
1017 |
|
1018 @pyqtSlot() |
|
1019 def __editUserConfiguration(self): |
|
1020 """ |
|
1021 Private slot to edit the user configuration. |
|
1022 """ |
|
1023 self.__editConfiguration() |
|
1024 |
|
1025 @pyqtSlot() |
|
1026 def __editVirtualenvConfiguration(self): |
|
1027 """ |
|
1028 Private slot to edit the current virtualenv configuration. |
|
1029 """ |
|
1030 # TODO: modify to get selected environment |
|
1031 self.__editConfiguration(virtualenv=True) |
|
1032 |
|
1033 def __editConfiguration(self, virtualenv=False): |
|
1034 """ |
|
1035 Private method to edit a configuration. |
|
1036 |
|
1037 @param virtualenv flag indicating to edit the current virtualenv |
|
1038 configuration file |
|
1039 @type bool |
|
1040 """ |
|
1041 # TODO: modify to use venvName |
|
1042 from QScintilla.MiniEditor import MiniEditor |
|
1043 if virtualenv: |
|
1044 cfgFile = self.__getVirtualenvConfig() |
|
1045 if not cfgFile: |
|
1046 return |
|
1047 else: |
|
1048 cfgFile = self.__getUserConfig() |
|
1049 cfgDir = os.path.dirname(cfgFile) |
|
1050 if not cfgDir: |
|
1051 E5MessageBox.critical( |
|
1052 None, |
|
1053 self.tr("Edit Configuration"), |
|
1054 self.tr("""No valid configuration path determined.""" |
|
1055 """ Is a virtual environment selected? Aborting""")) |
|
1056 return |
|
1057 |
|
1058 try: |
|
1059 if not os.path.isdir(cfgDir): |
|
1060 os.makedirs(cfgDir) |
|
1061 except OSError: |
|
1062 E5MessageBox.critical( |
|
1063 None, |
|
1064 self.tr("Edit Configuration"), |
|
1065 self.tr("""No valid configuration path determined.""" |
|
1066 """ Is a virtual environment selected? Aborting""")) |
|
1067 return |
|
1068 |
|
1069 if not os.path.exists(cfgFile): |
|
1070 try: |
|
1071 f = open(cfgFile, "w") |
|
1072 f.write("[global]\n") |
|
1073 f.close() |
|
1074 except (IOError, OSError): |
|
1075 # ignore these |
|
1076 pass |
|
1077 |
|
1078 # check, if the destination is writeable |
|
1079 if not os.access(cfgFile, os.W_OK): |
|
1080 E5MessageBox.critical( |
|
1081 None, |
|
1082 self.tr("Edit Configuration"), |
|
1083 self.tr("""No valid configuartion path determined.""" |
|
1084 """ Is a virtual environment selected? Aborting""")) |
|
1085 return |
|
1086 |
|
1087 self.__editor = MiniEditor(cfgFile, "Properties") |
|
1088 self.__editor.show() |
|
1089 |
|
1090 def __pipConfigure(self): |
|
1091 """ |
|
1092 Private slot to open the configuration page. |
|
1093 """ |
|
1094 e5App().getObject("UserInterface").showPreferences("pipPage") |