class ProfileWizard(StandaloneWizardPage): """Wizard for the creation of a new database profile. .. attribute:: languages .. attribute:: dialects A list of languages allowed in the profile selection, an empty list will allow all languages """ languages = [] dialects = [] def __init__(self, profiles, parent=None): super(ProfileWizard, self).__init__(parent) self._connection_valid = False self.network_reply = None self.profiles = profiles self.setWindowTitle(_('Profile Wizard')) self.set_banner_logo_pixmap(art.Icon('tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Create New/Edit Profile')) self.set_banner_subtitle(_('Please enter the database settings')) self.banner_widget().setStyleSheet('background-color: white;') self.manager = QtNetwork.QNetworkAccessManager( self ) self.manager.finished.connect( self.update_network_status ) #self.manager.networkAccessibleChanged.connect( self.network_accessible_changed ) self.manager.proxyAuthenticationRequired.connect( self.proxy_authentication_required ) self.create_labels_and_widgets() self.create_buttons() self.set_tab_order() self.set_widgets_values() # note: connections come after labels and widgets are created # and have default values self.connect_widgets() self.connect_buttons() timer = QtCore.QTimer(self) timer.timeout.connect( self.new_network_request ) timer.setInterval( 3000 ) timer.start() self.new_network_request() def create_labels_and_widgets(self): assert object_thread( self ) self.profile_label = QLabel(_('Profile Name:')) self.dialect_label = QLabel(_('Driver:')) self.host_label = QLabel(_('Server Host:')) self.port_label = QLabel(_('Port:')) self.database_name_label = QLabel(_('Database Name:')) self.username_label = QLabel(_('Username:'******'Password:'******'Media Location:')) self.language_label = QLabel(_('Language:')) self.proxy_host_label = QLabel(_('Proxy Host:')) self.proxy_port_label = QLabel(_('Port:')) self.proxy_username_label = QLabel(_('Proxy Username:'******'Proxy Password:'******'Media location path '\ 'is not accessible.')) self.not_accessible_media_path_label.setStyleSheet('color: red') self.not_writable_media_path_label = QLabel(_('Media location path '\ 'is not writable.')) self.not_writable_media_path_label.setStyleSheet('color: red') layout = QGridLayout() layout.addWidget(self.profile_label, 0, 0, Qt.AlignRight) layout.addWidget(self.dialect_label, 1, 0, Qt.AlignRight) layout.addWidget(self.host_label, 2, 0, Qt.AlignRight) layout.addWidget(self.port_label, 2, 3, Qt.AlignRight) layout.addWidget(self.database_name_label, 3, 0, Qt.AlignRight) layout.addWidget(self.username_label, 4, 0, Qt.AlignRight) layout.addWidget(self.password_label, 5, 0, Qt.AlignRight) layout.addWidget(self.media_location_label, 7, 0, Qt.AlignRight) layout.addWidget(self.language_label, 8, 0, Qt.AlignRight) layout.addWidget(self.proxy_host_label, 10, 0, Qt.AlignRight) layout.addWidget(self.proxy_port_label, 10, 3, Qt.AlignRight) layout.addWidget(self.proxy_username_label, 11, 0, Qt.AlignRight) layout.addWidget(self.proxy_password_label, 12, 0, Qt.AlignRight) self.profile_editor = QComboBox(self) self.profile_editor.setEditable(True) # 32767 is Qt max length for string # should be more than enough for folders # http://doc.qt.nokia.com/latest/qlineedit.html#maxLength-prop self.dialect_editor = ChoicesEditor(parent=self) self.host_editor = TextLineEditor(self, length=32767) self.host_editor.set_value('') self.port_editor = TextLineEditor(self) self.port_editor.setFixedWidth(60) self.port_editor.set_value('') self.database_name_editor = TextLineEditor(self, length=32767) self.database_name_editor.set_value('') self.username_editor = TextLineEditor(self) self.username_editor.set_value('') self.password_editor = TextLineEditor(self) self.password_editor.setEchoMode(QLineEdit.Password) self.password_editor.set_value('') self.media_location_editor = TextLineEditor(self, length=32767) self.media_location_editor.set_value('') self.language_editor = LanguageEditor(languages=self.languages, parent=self) # # try to find a default language # system_language = QtCore.QLocale.system().name() if self.languages: if system_language in self.languages: self.language_editor.set_value( system_language ) else: self.language_editor.set_value( self.languages[0] ) else: self.language_editor.set_value( system_language ) self.proxy_host_editor = TextLineEditor(self, length=32767) self.proxy_host_editor.set_value('') self.proxy_port_editor = TextLineEditor(self) self.proxy_port_editor.setFixedWidth(60) self.proxy_port_editor.set_value('') self.proxy_username_editor = TextLineEditor(self) self.proxy_username_editor.set_value('') self.proxy_password_editor = TextLineEditor(self) self.proxy_password_editor.set_value('') self.proxy_password_editor.setEchoMode(QLineEdit.Password) layout.addWidget(self.profile_editor, 0, 1, 1, 1) layout.addWidget(self.dialect_editor, 1, 1, 1, 1) layout.addWidget(self.host_editor, 2, 1, 1, 1) layout.addWidget(self.port_editor, 2, 4, 1, 1) layout.addWidget(self.database_name_editor, 3, 1, 1, 1) layout.addWidget(self.username_editor, 4, 1, 1, 1) layout.addWidget(self.password_editor, 5, 1, 1, 1) layout.addWidget(HSeparator(), 6, 0, 1, 5) layout.addWidget(self.media_location_editor, 7, 1, 1, 1) layout.addWidget(self.language_editor, 8, 1, 1, 1) layout.addWidget(HSeparator(), 9, 0, 1, 5) layout.addWidget(self.proxy_host_editor, 10, 1, 1, 1) layout.addWidget(self.proxy_port_editor, 10, 4, 1, 1) layout.addWidget(self.proxy_username_editor, 11, 1, 1, 1) layout.addWidget(self.proxy_password_editor, 12, 1, 1, 1) layout.addWidget(self.network_status_label, 13, 1, 1, 4) self.main_widget().setLayout(layout) def set_widgets_values(self): self.dialect_editor.clear() self.profile_editor.clear() if self.dialects: dialects = self.dialects else: import sqlalchemy.dialects dialects = [name for _importer, name, is_package in \ pkgutil.iter_modules(sqlalchemy.dialects.__path__) \ if is_package] self.dialect_editor.set_choices([(dialect, dialect.capitalize()) \ for dialect in dialects]) self.profile_editor.insertItems(1, [''] + \ [item for item in fetch_profiles()]) self.profile_editor.setFocus() self.update_wizard_values() def connect_widgets(self): self.profile_editor.editTextChanged.connect(self.update_wizard_values) # self.dialect_editor.currentIndexChanged.connect(self.update_wizard_values) def create_buttons(self): self.more_button = QPushButton(_('More')) self.more_button.setCheckable(True) self.more_button.setAutoDefault(False) self.cancel_button = QPushButton(_('Cancel')) self.ok_button = QPushButton(_('OK')) layout = QHBoxLayout() layout.setDirection(QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) layout.addWidget(self.ok_button) layout.addStretch() layout.addWidget(self.more_button) self.buttons_widget().setLayout(layout) self.browse_button = QPushButton(_('Browse')) self.main_widget().layout().addWidget(self.browse_button, 7, 2, 1, 3) self.setup_extension() def setup_extension(self): self.extension = QWidget() self.load_button = QPushButton(_('Load profiles')) self.save_button = QPushButton(_('Save profiles')) extension_buttons_layout = QHBoxLayout() extension_buttons_layout.setContentsMargins(0, 0, 0, 0) extension_buttons_layout.addWidget(self.load_button) extension_buttons_layout.addWidget(self.save_button) extension_buttons_layout.addStretch() extension_layout = QVBoxLayout() extension_layout.setContentsMargins(0, 0, 0, 0) extension_layout.addWidget(HSeparator()) extension_layout.addLayout(extension_buttons_layout) self.extension.setLayout(extension_layout) self.main_widget().layout().addWidget(self.extension, 15, 0, 1, 5) self.extension.hide() def set_tab_order(self): all_widgets = [self.profile_editor, self.dialect_editor, self.host_editor, self.port_editor, self.database_name_editor, self.username_editor, self.password_editor, self.media_location_editor, self.browse_button, self.language_editor, self.proxy_host_editor, self.proxy_port_editor, self.proxy_username_editor, self.proxy_password_editor, self.ok_button, self.cancel_button] i = 1 while i != len(all_widgets): self.setTabOrder(all_widgets[i-1], all_widgets[i]) i += 1 def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.proceed) self.browse_button.pressed.connect(self.fill_media_location) self.more_button.toggled.connect(self.extension.setVisible) self.save_button.pressed.connect(self.save_profiles_to_file) self.load_button.pressed.connect(self.load_profiles_from_file) def proceed(self): if self.is_connection_valid(): profilename, info = self.collect_info() if profilename in self.profiles: self.profiles[profilename].update(info) else: self.profiles[profilename] = info store_profiles(self.profiles) use_chosen_profile(profilename) self.accept() def is_connection_valid(self): profilename, info = self.collect_info() mt = SignalSlotModelThread(lambda:None) mt.start() progress = ProgressDialog(_('Verifying database settings')) mt.post(lambda:self.test_connection( info ), progress.finished, progress.exception) progress.exec_() return self._connection_valid def test_connection(self, profile): self._connection_valid = False connection_string = connection_string_from_profile( profile ) engine = create_engine(connection_string, pool_recycle=True) try: connection = engine.raw_connection() cursor = connection.cursor() cursor.close() connection.close() self._connection_valid = True except Exception, e: self._connection_valid = False raise UserException( _('Could not connect to database, please check host and port'), resolution = _('Verify driver, host and port or contact your system administrator'), detail = unicode(e) )
class QuantOSLoginEngine(QWidget): """风控引擎的管理组件""" #---------------------------------------------------------------------- def __init__(self, gateway, setting, parent=None): """Constructor""" super(QuantOSLoginEngine, self).__init__(parent) self.setting = setting self.gateway = gateway self.connectionMap = {} self.initUi() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'登录') # 设置界面 self.userName = QLineEdit() self.password = QTextEdit() self.comboStrategy = QComboBox() grid = QGridLayout() grid.addWidget(LoginLine(), 1, 0, 1, 2) grid.addWidget(QLabel(u'用户名'), 2, 0) grid.addWidget(self.userName, 2, 1) grid.addWidget(QLabel(u'令牌'), 3, 0) grid.addWidget(self.password, 3, 1) grid.addWidget(LoginLine(), 4, 0, 1, 2) grid.addWidget(QLabel(u'策略'), 5, 0) grid.addWidget(self.comboStrategy, 5, 1) grid.addWidget(LoginLine(), 6, 0, 1, 2) self.buttonCancel = QPushButton(u'取消') self.buttonConfirm = QPushButton(u'确认') hbox = QHBoxLayout() hbox.addWidget(self.buttonConfirm) hbox.addWidget(self.buttonCancel) self.buttonConfirm.setDefault(True) vbox = QVBoxLayout() vbox.addLayout(grid) vbox.addLayout(hbox) self.setLayout(vbox) # 设为固定大小 self.setFixedSize(self.sizeHint()) self.buttonCancel.clicked.connect(self.close) self.buttonConfirm.clicked.connect(self.login) self.userName.returnPressed.connect(self.password.setFocus) # init username & token username = self.setting['username'] token = self.setting['token'] self.userName.setText(username) self.password.setText(token) def login(self): selectedStrat = self.comboStrategy.currentText() if selectedStrat is not None and len(selectedStrat) > 0: username = str(self.userName.text()).strip() password = str(self.password.toPlainText()).strip() if len(username) <= 0 or len(password) <= 0: QMessageBox.warning(self, u'登录', u'输入用户名和密码') else: self.close() self.gateway.login(username, password, selectedStrat) else: self.connect() def connect(self): userName = str(self.userName.text()).strip() password = str(self.password.toPlainText()).strip() if len(userName) <= 0 or len(password) <= 0: QMessageBox.warning(self, u'获取策略', u'输入用户名和密码') else: strategyList = self.gateway.getStrategyList(userName, password) if strategyList is not None and len(strategyList) > 0: self.comboStrategy.clear() strategyList_sl = [] for strategy in strategyList: strategyList_sl.append(str(strategy)) strategyList_sl.sort() self.comboStrategy.addItems(strategyList_sl) self.userName.setEnabled(False) self.password.setEnabled(False) else: QMessageBox.warning(self, u'获取策略', u'无法获取相关策略') self.comboStrategy.clear() self.comboStrategy.setFocus()
class FindInFilesDialog(QDialog, object): """ find in files dialog implementation """ inProject = 0 inDirectory = 1 inOpenFiles = 2 def __init__(self, where, what="", dirPath="", filters=[], parent=None): QDialog.__init__(self, parent) mainWindow = GlobalData().mainWindow self.editorsManager = mainWindow.editorsManagerWidget.editorsManager self.__cancelRequest = False self.__inProgress = False self.searchRegexp = None self.searchResults = [] # Avoid pylint complains self.findCombo = None self.caseCheckBox = None self.wordCheckBox = None self.regexpCheckBox = None self.projectRButton = None self.openFilesRButton = None self.dirRButton = None self.dirEditCombo = None self.dirSelectButton = None self.filterCombo = None self.fileLabel = None self.progressBar = None self.findButton = None self.__createLayout() self.setWindowTitle("Find in files") # Restore the combo box values project = GlobalData().project if project.fileName != "": self.findFilesWhat = project.findFilesWhat self.findFilesDirs = project.findFilesDirs self.findFilesMasks = project.findFilesMasks else: settings = Settings() self.findFilesWhat = settings.findFilesWhat self.findFilesDirs = settings.findFilesDirs self.findFilesMasks = settings.findFilesMasks self.findCombo.addItems(self.findFilesWhat) self.findCombo.setEditText("") self.dirEditCombo.addItems(self.findFilesDirs) self.dirEditCombo.setEditText("") self.filterCombo.addItems(self.findFilesMasks) self.filterCombo.setEditText("") if where == self.inProject: self.setSearchInProject(what, filters) elif where == self.inDirectory: self.setSearchInDirectory(what, dirPath, filters) else: self.setSearchInOpenFiles(what, filters) return def __createLayout(self): """ Creates the dialog layout """ self.resize(600, 300) self.setSizeGripEnabled(True) verticalLayout = QVBoxLayout(self) gridLayout = QGridLayout() # Combo box for the text to search findLabel = QLabel(self) findLabel.setText("Find text:") self.findCombo = QComboBox(self) self.__tuneCombo(self.findCombo) self.findCombo.lineEdit().setToolTip( "Regular expression to search for") self.findCombo.editTextChanged.connect(self.__someTextChanged) gridLayout.addWidget(findLabel, 0, 0, 1, 1) gridLayout.addWidget(self.findCombo, 0, 1, 1, 1) verticalLayout.addLayout(gridLayout) # Check boxes horizontalCBLayout = QHBoxLayout() self.caseCheckBox = QCheckBox(self) self.caseCheckBox.setText("Match &case") horizontalCBLayout.addWidget(self.caseCheckBox) self.wordCheckBox = QCheckBox(self) self.wordCheckBox.setText("Match whole &word") horizontalCBLayout.addWidget(self.wordCheckBox) self.regexpCheckBox = QCheckBox(self) self.regexpCheckBox.setText("Regular &expression") horizontalCBLayout.addWidget(self.regexpCheckBox) verticalLayout.addLayout(horizontalCBLayout) # Files groupbox filesGroupbox = QGroupBox(self) filesGroupbox.setTitle("Find in") sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( filesGroupbox.sizePolicy().hasHeightForWidth()) filesGroupbox.setSizePolicy(sizePolicy) gridLayoutFG = QGridLayout(filesGroupbox) self.projectRButton = QRadioButton(filesGroupbox) self.projectRButton.setText("&Project") gridLayoutFG.addWidget(self.projectRButton, 0, 0) self.projectRButton.clicked.connect(self.__projectClicked) self.openFilesRButton = QRadioButton(filesGroupbox) self.openFilesRButton.setText("&Opened files only") gridLayoutFG.addWidget(self.openFilesRButton, 1, 0) self.openFilesRButton.clicked.connect(self.__openFilesOnlyClicked) self.dirRButton = QRadioButton(filesGroupbox) self.dirRButton.setText("&Directory tree") gridLayoutFG.addWidget(self.dirRButton, 2, 0) self.dirRButton.clicked.connect(self.__dirClicked) self.dirEditCombo = QComboBox(filesGroupbox) self.__tuneCombo(self.dirEditCombo) self.dirEditCombo.lineEdit().setToolTip("Directory to search in") gridLayoutFG.addWidget(self.dirEditCombo, 2, 1) self.dirEditCombo.editTextChanged.connect(self.__someTextChanged) self.dirSelectButton = QPushButton(filesGroupbox) self.dirSelectButton.setText("...") gridLayoutFG.addWidget(self.dirSelectButton, 2, 2) self.dirSelectButton.clicked.connect(self.__selectDirClicked) filterLabel = QLabel(filesGroupbox) filterLabel.setText("Files filter:") gridLayoutFG.addWidget(filterLabel, 3, 0) self.filterCombo = QComboBox(filesGroupbox) self.__tuneCombo(self.filterCombo) self.filterCombo.lineEdit().setToolTip("File names regular expression") gridLayoutFG.addWidget(self.filterCombo, 3, 1) self.filterCombo.editTextChanged.connect(self.__someTextChanged) verticalLayout.addWidget(filesGroupbox) # File label self.fileLabel = FitPathLabel(self) self.fileLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) verticalLayout.addWidget(self.fileLabel) # Progress bar self.progressBar = QProgressBar(self) self.progressBar.setValue(0) self.progressBar.setOrientation(Qt.Horizontal) verticalLayout.addWidget(self.progressBar) # Buttons at the bottom buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Cancel) self.findButton = buttonBox.addButton("Find", QDialogButtonBox.AcceptRole) self.findButton.setDefault(True) self.findButton.clicked.connect(self.__process) verticalLayout.addWidget(buttonBox) buttonBox.rejected.connect(self.__onClose) return @staticmethod def __tuneCombo(comboBox): " Sets the common settings for a combo box " sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( \ comboBox.sizePolicy().hasHeightForWidth() ) comboBox.setSizePolicy(sizePolicy) comboBox.setEditable(True) comboBox.setInsertPolicy(QComboBox.InsertAtTop) comboBox.setAutoCompletion(False) comboBox.setDuplicatesEnabled(False) return def __onClose(self): " Triggered when the close button is clicked " self.__cancelRequest = True if not self.__inProgress: self.close() return def setSearchInProject(self, what="", filters=[]): " Set search ready for the whole project " if GlobalData().project.fileName == "": # No project loaded, fallback to opened files self.setSearchInOpenFiles(what, filters) return # Select the project radio button self.projectRButton.setEnabled(True) self.projectRButton.setChecked(True) self.dirEditCombo.setEnabled(False) self.dirSelectButton.setEnabled(False) openedFiles = self.editorsManager.getTextEditors() self.openFilesRButton.setEnabled(len(openedFiles) != 0) self.setFilters(filters) self.findCombo.setEditText(what) self.findCombo.lineEdit().selectAll() self.findCombo.setFocus() # Check searchability self.__testSearchability() return def setSearchInOpenFiles(self, what="", filters=[]): " Sets search ready for the opened files " openedFiles = self.editorsManager.getTextEditors() if len(openedFiles) == 0: # No opened files, fallback to search in dir self.setSearchInDirectory(what, "", filters) return # Select the radio buttons self.projectRButton.setEnabled(GlobalData().project.fileName != "") self.openFilesRButton.setEnabled(True) self.openFilesRButton.setChecked(True) self.dirEditCombo.setEnabled(False) self.dirSelectButton.setEnabled(False) self.setFilters(filters) self.findCombo.setEditText(what) self.findCombo.lineEdit().selectAll() self.findCombo.setFocus() # Check searchability self.__testSearchability() return def setSearchInDirectory(self, what="", dirPath="", filters=[]): " Sets search ready for the given directory " # Select radio buttons self.projectRButton.setEnabled(GlobalData().project.fileName != "") openedFiles = self.editorsManager.getTextEditors() self.openFilesRButton.setEnabled(len(openedFiles) != 0) self.dirRButton.setEnabled(True) self.dirRButton.setChecked(True) self.dirEditCombo.setEnabled(True) self.dirSelectButton.setEnabled(True) self.dirEditCombo.setEditText(dirPath) self.setFilters(filters) self.findCombo.setEditText(what) self.findCombo.lineEdit().selectAll() self.findCombo.setFocus() # Check searchability self.__testSearchability() return def setFilters(self, filters): " Sets up the filters " # Set filters if provided if filters: self.filterCombo.setEditText(";".join(filters)) else: self.filterCombo.setEditText("") return def __testSearchability(self): " Tests the searchability and sets the Find button status " startTime = time.time() if self.findCombo.currentText().strip() == "": self.findButton.setEnabled(False) self.findButton.setToolTip("No text to search") return if self.dirRButton.isChecked(): dirname = self.dirEditCombo.currentText().strip() if dirname == "": self.findButton.setEnabled(False) self.findButton.setToolTip("No directory path") return if not os.path.isdir(dirname): self.findButton.setEnabled(False) self.findButton.setToolTip("Path is not a directory") return # Now we need to match file names if there is a filter filtersText = self.filterCombo.currentText().strip() if filtersText == "": self.findButton.setEnabled(True) self.findButton.setToolTip("Find in files") return # Need to check the files match try: filterRe = re.compile(filtersText, re.IGNORECASE) except: self.findButton.setEnabled(False) self.findButton.setToolTip( "Incorrect files " \ "filter regular expression" ) return matched = False tooLong = False if self.projectRButton.isChecked(): # Whole project for fname in GlobalData().project.filesList: if fname.endswith(sep): continue matched = filterRe.match(fname) if matched: break # Check the time, it might took too long if time.time() - startTime > 0.1: tooLong = True break elif self.openFilesRButton.isChecked(): # Opened files openedFiles = self.editorsManager.getTextEditors() for record in openedFiles: matched = filterRe.match(record[1]) if matched: break # Check the time, it might took too long if time.time() - startTime > 0.1: tooLong = True break else: # Search in the dir if not dirname.endswith(sep): dirname += sep matched, tooLong = self.__matchInDir(dirname, filterRe, startTime) if matched: self.findButton.setEnabled(True) self.findButton.setToolTip("Find in files") else: if tooLong: self.findButton.setEnabled(True) self.findButton.setToolTip("Find in files") else: self.findButton.setEnabled(False) self.findButton.setToolTip("No files matched to search in") return @staticmethod def __matchInDir(path, filterRe, startTime): " Provides the 'match' and 'too long' statuses " matched = False tooLong = False for item in os.listdir(path): if time.time() - startTime > 0.1: tooLong = True return matched, tooLong if os.path.isdir(path + item): dname = path + item + sep matched, tooLong = FindInFilesDialog.__matchInDir( dname, filterRe, startTime) if matched or tooLong: return matched, tooLong continue if filterRe.match(path + item): matched = True return matched, tooLong return matched, tooLong def __projectClicked(self): " project radio button clicked " self.dirEditCombo.setEnabled(False) self.dirSelectButton.setEnabled(False) self.__testSearchability() return def __openFilesOnlyClicked(self): " open files only radio button clicked " self.dirEditCombo.setEnabled(False) self.dirSelectButton.setEnabled(False) self.__testSearchability() return def __dirClicked(self): " dir radio button clicked " self.dirEditCombo.setEnabled(True) self.dirSelectButton.setEnabled(True) self.dirEditCombo.setFocus() self.__testSearchability() return def __someTextChanged(self, text): " Text to search, filter or dir name has been changed " self.__testSearchability() return def __selectDirClicked(self): " The user selects a directory " dirName = QFileDialog.getExistingDirectory( self, "Select directory to search in", self.dirEditCombo.currentText(), QFileDialog.Options(QFileDialog.ShowDirsOnly)) if dirName: self.dirEditCombo.setEditText(os.path.normpath(dirName)) self.__testSearchability() return def __projectFiles(self, filterRe): " Project files list respecting the mask " mainWindow = GlobalData().mainWindow files = [] for fname in GlobalData().project.filesList: if fname.endswith(sep): continue if filterRe is None or filterRe.match(fname): widget = mainWindow.getWidgetForFileName(fname) if widget is None: # Do not check for broken symlinks if isFileSearchable(fname, False): files.append(ItemToSearchIn(fname, "")) else: if widget.getType() in \ [ MainWindowTabWidgetBase.PlainTextEditor ]: files.append(ItemToSearchIn(fname, widget.getUUID())) QApplication.processEvents() if self.__cancelRequest: raise Exception("Cancel request") return files def __openedFiles(self, filterRe): " Currently opened editor buffers " files = [] openedFiles = self.editorsManager.getTextEditors() for record in openedFiles: uuid = record[0] fname = record[1] if filterRe is None or filterRe.match(fname): files.append(ItemToSearchIn(fname, uuid)) QApplication.processEvents() if self.__cancelRequest: raise Exception("Cancel request") return files def __dirFiles(self, path, filterRe, files): " Files recursively for the dir " for item in os.listdir(path): QApplication.processEvents() if self.__cancelRequest: raise Exception("Cancel request") if os.path.isdir(path + item): if item in [".svn", ".cvs"]: # It does not make sense to search in revision control dirs continue anotherDir, isLoop = resolveLink(path + item) if not isLoop: self.__dirFiles(anotherDir + sep, filterRe, files) continue if not os.path.isfile(path + item): continue realItem, isLoop = resolveLink(path + item) if isLoop: continue if filterRe is None or filterRe.match(realItem): found = False for itm in files: if itm.fileName == realItem: found = True break if not found: mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetForFileName(realItem) if widget is None: if isFileSearchable(realItem): files.append(ItemToSearchIn(realItem, "")) else: if widget.getType() in \ [ MainWindowTabWidgetBase.PlainTextEditor ]: files.append( ItemToSearchIn(realItem, widget.getUUID())) return def __buildFilesList(self): " Builds the list of files to search in " filtersText = self.filterCombo.currentText().strip() if filtersText != "": filterRe = re.compile(filtersText, re.IGNORECASE) else: filterRe = None if self.projectRButton.isChecked(): return self.__projectFiles(filterRe) if self.openFilesRButton.isChecked(): return self.__openedFiles(filterRe) dirname = os.path.realpath(self.dirEditCombo.currentText().strip()) files = [] self.__dirFiles(dirname + sep, filterRe, files) return files def __process(self): " Search process " # Add entries to the combo box if required regexpText = self.findCombo.currentText() if regexpText in self.findFilesWhat: self.findFilesWhat.remove(regexpText) self.findFilesWhat.insert(0, regexpText) if len(self.findFilesWhat) > 32: self.findFilesWhat = self.findFilesWhat[:32] self.findCombo.clear() self.findCombo.addItems(self.findFilesWhat) filtersText = self.filterCombo.currentText().strip() if filtersText in self.findFilesMasks: self.findFilesMasks.remove(filtersText) self.findFilesMasks.insert(0, filtersText) if len(self.findFilesMasks) > 32: self.findFilesMasks = self.findFilesMasks[:32] self.filterCombo.clear() self.filterCombo.addItems(self.findFilesMasks) if self.dirRButton.isChecked(): dirText = self.dirEditCombo.currentText().strip() if dirText in self.findFilesDirs: self.findFilesDirs.remove(dirText) self.findFilesDirs.insert(0, dirText) if len(self.findFilesDirs) > 32: self.findFilesDirs = self.findFilesDirs[:32] self.dirEditCombo.clear() self.dirEditCombo.addItems(self.findFilesDirs) # Save the combo values for further usage if GlobalData().project.fileName != "": GlobalData().project.setFindInFilesHistory(self.findFilesWhat, self.findFilesDirs, self.findFilesMasks) else: Settings().findFilesWhat = self.findFilesWhat Settings().findFilesDirs = self.findFilesDirs Settings().findFilesMasks = self.findFilesMasks self.__inProgress = True numberOfMatches = 0 self.searchResults = [] self.searchRegexp = None # Form the regexp to search if not self.regexpCheckBox.isChecked(): regexpText = re.escape(regexpText) if self.wordCheckBox.isChecked(): regexpText = "\\b%s\\b" % regexpText flags = re.UNICODE | re.LOCALE if not self.caseCheckBox.isChecked(): flags |= re.IGNORECASE try: self.searchRegexp = re.compile(regexpText, flags) except: logging.error("Invalid search expression") self.close() return QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.fileLabel.setPath('Building list of files to search in...') QApplication.processEvents() try: files = self.__buildFilesList() except Exception, exc: if "Cancel request" in str(exc): QApplication.restoreOverrideCursor() self.close() return else: QApplication.restoreOverrideCursor() logging.error(str(exc)) self.close() return QApplication.restoreOverrideCursor() QApplication.processEvents() if len(files) == 0: self.fileLabel.setPath('No files to search in') return self.progressBar.setRange(0, len(files)) index = 1 for item in files: if self.__cancelRequest: self.__inProgress = False self.close() return self.fileLabel.setPath( 'Matches: ' + str( numberOfMatches ) + \ ' Processing: ' + item.fileName ) item.search(self.searchRegexp) found = len(item.matches) if found > 0: numberOfMatches += found self.searchResults.append(item) self.progressBar.setValue(index) index += 1 QApplication.processEvents() if numberOfMatches == 0: if len(files) == 1: self.fileLabel.setPath("No matches in 1 file.") else: self.fileLabel.setPath( "No matches in " + \ str( len( files ) ) + " files." ) self.__inProgress = False else: self.close() return
class GotoLineWidget( QWidget ): " goto bar widget " maxHistory = 12 def __init__( self, editorsManager, parent = None ): QWidget.__init__( self, parent ) self.editorsManager = editorsManager self.__gotoHistory = [] # Common graphics items closeButton = QToolButton( self ) closeButton.setToolTip( "Click to close the dialog (ESC)" ) closeButton.setIcon( PixmapCache().getIcon( "close.png" ) ) closeButton.clicked.connect( self.hide ) lineLabel = QLabel( self ) lineLabel.setText( "Goto line:" ) self.linenumberEdit = QComboBox( self ) self.linenumberEdit.setEditable( True ) self.linenumberEdit.setInsertPolicy( QComboBox.InsertAtTop ) self.linenumberEdit.setAutoCompletion( False ) self.linenumberEdit.setDuplicatesEnabled( False ) sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed ) sizePolicy.setHorizontalStretch( 0 ) sizePolicy.setVerticalStretch( 0 ) sizePolicy.setHeightForWidth( self.linenumberEdit.sizePolicy().hasHeightForWidth() ) self.linenumberEdit.setSizePolicy( sizePolicy ) self.validator = QIntValidator( 1, 100000, self ) self.linenumberEdit.setValidator( self.validator ) self.linenumberEdit.editTextChanged.connect( self.__onEditTextChanged ) self.linenumberEdit.lineEdit().returnPressed.connect( self.__onEnter ) self.goButton = QToolButton( self ) self.goButton.setToolTip( "Click to jump to the line (ENTER)" ) self.goButton.setIcon( PixmapCache().getIcon( "gotoline.png" ) ) self.goButton.setFocusPolicy( Qt.NoFocus ) self.goButton.setEnabled( False ) self.goButton.clicked.connect( self.__onGo ) spacer = QWidget() spacer.setFixedWidth( 1 ) horizontalLayout = QHBoxLayout( self ) horizontalLayout.setMargin( 0 ) horizontalLayout.addWidget( closeButton ) horizontalLayout.addWidget( lineLabel ) horizontalLayout.addWidget( self.linenumberEdit ) horizontalLayout.addWidget( self.goButton ) horizontalLayout.addWidget( spacer ) return def keyPressEvent( self, event ): """ Handles the key press events """ if event.key() == Qt.Key_Escape: activeWindow = self.editorsManager.currentWidget() if activeWindow: activeWindow.setFocus() event.accept() self.hide() return def __updateHistory( self, txt ): " Updates the combo history " while txt in self.__gotoHistory: self.__gotoHistory.remove( txt ) self.__gotoHistory = [ txt ] + self.__gotoHistory self.__gotoHistory = self.__gotoHistory[ : GotoLineWidget.maxHistory ] self.linenumberEdit.clear() self.linenumberEdit.addItems( self.__gotoHistory ) return def show( self ): " Overriden show() method " self.linenumberEdit.lineEdit().selectAll() QWidget.show( self ) self.activateWindow() return def setFocus( self ): " Overridded setFocus " self.linenumberEdit.setFocus() return def updateStatus( self ): " Triggered when the current tab is changed " currentWidget = self.editorsManager.currentWidget() status = currentWidget.getType() in \ [ MainWindowTabWidgetBase.PlainTextEditor, MainWindowTabWidgetBase.VCSAnnotateViewer ] self.linenumberEdit.setEnabled( status ) self.goButton.setEnabled( status and self.linenumberEdit.currentText() != "" ) return def __onGo( self ): " Triggered when the 'Go!' button is clicked " if self.linenumberEdit.currentText() == "": return currentWidget = self.editorsManager.currentWidget() if not currentWidget.getType() in \ [ MainWindowTabWidgetBase.PlainTextEditor, MainWindowTabWidgetBase.VCSAnnotateViewer ]: return txt = self.linenumberEdit.currentText() self.__updateHistory( txt ) editor = currentWidget.getEditor() line = min( int( txt ), editor.lines() ) - 1 editor.setCursorPosition( line, 0 ) editor.ensureLineVisible( line ) currentWidget.setFocus() return def __onEditTextChanged( self, text ): " Triggered when the text has been changed " self.goButton.setEnabled( text != "" ) return def __onEnter( self ): " Triggered when 'Enter' or 'Return' is clicked " self.__onGo() return def selectAll( self ): " Selects the line edit content " self.linenumberEdit.lineEdit().selectAll() return
class ProfileWizard(StandaloneWizardPage): """Wizard for the creation of a new database profile. .. attribute:: languages .. attribute:: dialects A list of languages allowed in the profile selection, an empty list will allow all languages """ languages = [] dialects = [] def __init__(self, profiles, parent=None): super(ProfileWizard, self).__init__(parent) self._connection_valid = False self.network_reply = None self.profiles = profiles self.setWindowTitle(_('Profile Wizard')) self.set_banner_logo_pixmap( art.Icon( 'tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Create New/Edit Profile')) self.set_banner_subtitle(_('Please enter the database settings')) self.banner_widget().setStyleSheet('background-color: white;') self.manager = QtNetwork.QNetworkAccessManager(self) self.manager.finished.connect(self.update_network_status) #self.manager.networkAccessibleChanged.connect( self.network_accessible_changed ) self.manager.proxyAuthenticationRequired.connect( self.proxy_authentication_required) self.create_labels_and_widgets() self.create_buttons() self.set_tab_order() self.set_widgets_values() # note: connections come after labels and widgets are created # and have default values self.connect_widgets() self.connect_buttons() timer = QtCore.QTimer(self) timer.timeout.connect(self.new_network_request) timer.setInterval(3000) timer.start() self.new_network_request() def create_labels_and_widgets(self): assert object_thread(self) self.profile_label = QLabel(_('Profile Name:')) self.dialect_label = QLabel(_('Driver:')) self.host_label = QLabel(_('Server Host:')) self.port_label = QLabel(_('Port:')) self.database_name_label = QLabel(_('Database Name:')) self.username_label = QLabel(_('Username:'******'Password:'******'Media Location:')) self.language_label = QLabel(_('Language:')) self.proxy_host_label = QLabel(_('Proxy Host:')) self.proxy_port_label = QLabel(_('Port:')) self.proxy_username_label = QLabel(_('Proxy Username:'******'Proxy Password:'******'Media location path '\ 'is not accessible.')) self.not_accessible_media_path_label.setStyleSheet('color: red') self.not_writable_media_path_label = QLabel(_('Media location path '\ 'is not writable.')) self.not_writable_media_path_label.setStyleSheet('color: red') layout = QGridLayout() layout.addWidget(self.profile_label, 0, 0, Qt.AlignRight) layout.addWidget(self.dialect_label, 1, 0, Qt.AlignRight) layout.addWidget(self.host_label, 2, 0, Qt.AlignRight) layout.addWidget(self.port_label, 2, 3, Qt.AlignRight) layout.addWidget(self.database_name_label, 3, 0, Qt.AlignRight) layout.addWidget(self.username_label, 4, 0, Qt.AlignRight) layout.addWidget(self.password_label, 5, 0, Qt.AlignRight) layout.addWidget(self.media_location_label, 7, 0, Qt.AlignRight) layout.addWidget(self.language_label, 8, 0, Qt.AlignRight) layout.addWidget(self.proxy_host_label, 10, 0, Qt.AlignRight) layout.addWidget(self.proxy_port_label, 10, 3, Qt.AlignRight) layout.addWidget(self.proxy_username_label, 11, 0, Qt.AlignRight) layout.addWidget(self.proxy_password_label, 12, 0, Qt.AlignRight) self.profile_editor = QComboBox(self) self.profile_editor.setEditable(True) # 32767 is Qt max length for string # should be more than enough for folders # http://doc.qt.nokia.com/latest/qlineedit.html#maxLength-prop self.dialect_editor = ChoicesEditor(parent=self) self.host_editor = TextLineEditor(self, length=32767) self.host_editor.set_value('') self.port_editor = TextLineEditor(self) self.port_editor.setFixedWidth(60) self.port_editor.set_value('') self.database_name_editor = TextLineEditor(self, length=32767) self.database_name_editor.set_value('') self.username_editor = TextLineEditor(self) self.username_editor.set_value('') self.password_editor = TextLineEditor(self) self.password_editor.setEchoMode(QLineEdit.Password) self.password_editor.set_value('') self.media_location_editor = TextLineEditor(self, length=32767) self.media_location_editor.set_value('') self.language_editor = LanguageEditor(languages=self.languages, parent=self) # # try to find a default language # system_language = QtCore.QLocale.system().name() if self.languages: if system_language in self.languages: self.language_editor.set_value(system_language) else: self.language_editor.set_value(self.languages[0]) else: self.language_editor.set_value(system_language) self.proxy_host_editor = TextLineEditor(self, length=32767) self.proxy_host_editor.set_value('') self.proxy_port_editor = TextLineEditor(self) self.proxy_port_editor.setFixedWidth(60) self.proxy_port_editor.set_value('') self.proxy_username_editor = TextLineEditor(self) self.proxy_username_editor.set_value('') self.proxy_password_editor = TextLineEditor(self) self.proxy_password_editor.set_value('') self.proxy_password_editor.setEchoMode(QLineEdit.Password) layout.addWidget(self.profile_editor, 0, 1, 1, 1) layout.addWidget(self.dialect_editor, 1, 1, 1, 1) layout.addWidget(self.host_editor, 2, 1, 1, 1) layout.addWidget(self.port_editor, 2, 4, 1, 1) layout.addWidget(self.database_name_editor, 3, 1, 1, 1) layout.addWidget(self.username_editor, 4, 1, 1, 1) layout.addWidget(self.password_editor, 5, 1, 1, 1) layout.addWidget(HSeparator(), 6, 0, 1, 5) layout.addWidget(self.media_location_editor, 7, 1, 1, 1) layout.addWidget(self.language_editor, 8, 1, 1, 1) layout.addWidget(HSeparator(), 9, 0, 1, 5) layout.addWidget(self.proxy_host_editor, 10, 1, 1, 1) layout.addWidget(self.proxy_port_editor, 10, 4, 1, 1) layout.addWidget(self.proxy_username_editor, 11, 1, 1, 1) layout.addWidget(self.proxy_password_editor, 12, 1, 1, 1) layout.addWidget(self.network_status_label, 13, 1, 1, 4) self.main_widget().setLayout(layout) def set_widgets_values(self): self.dialect_editor.clear() self.profile_editor.clear() if self.dialects: dialects = self.dialects else: import sqlalchemy.dialects dialects = [name for _importer, name, is_package in \ pkgutil.iter_modules(sqlalchemy.dialects.__path__) \ if is_package] self.dialect_editor.set_choices([(dialect, dialect.capitalize()) \ for dialect in dialects]) self.profile_editor.insertItems(1, [''] + \ [item for item in fetch_profiles()]) self.profile_editor.setFocus() self.update_wizard_values() def connect_widgets(self): self.profile_editor.editTextChanged.connect(self.update_wizard_values) # self.dialect_editor.currentIndexChanged.connect(self.update_wizard_values) def create_buttons(self): self.more_button = QPushButton(_('More')) self.more_button.setCheckable(True) self.more_button.setAutoDefault(False) self.cancel_button = QPushButton(_('Cancel')) self.ok_button = QPushButton(_('OK')) layout = QHBoxLayout() layout.setDirection(QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) layout.addWidget(self.ok_button) layout.addStretch() layout.addWidget(self.more_button) self.buttons_widget().setLayout(layout) self.browse_button = QPushButton(_('Browse')) self.main_widget().layout().addWidget(self.browse_button, 7, 2, 1, 3) self.setup_extension() def setup_extension(self): self.extension = QWidget() self.load_button = QPushButton(_('Load profiles')) self.save_button = QPushButton(_('Save profiles')) extension_buttons_layout = QHBoxLayout() extension_buttons_layout.setContentsMargins(0, 0, 0, 0) extension_buttons_layout.addWidget(self.load_button) extension_buttons_layout.addWidget(self.save_button) extension_buttons_layout.addStretch() extension_layout = QVBoxLayout() extension_layout.setContentsMargins(0, 0, 0, 0) extension_layout.addWidget(HSeparator()) extension_layout.addLayout(extension_buttons_layout) self.extension.setLayout(extension_layout) self.main_widget().layout().addWidget(self.extension, 15, 0, 1, 5) self.extension.hide() def set_tab_order(self): all_widgets = [ self.profile_editor, self.dialect_editor, self.host_editor, self.port_editor, self.database_name_editor, self.username_editor, self.password_editor, self.media_location_editor, self.browse_button, self.language_editor, self.proxy_host_editor, self.proxy_port_editor, self.proxy_username_editor, self.proxy_password_editor, self.ok_button, self.cancel_button ] i = 1 while i != len(all_widgets): self.setTabOrder(all_widgets[i - 1], all_widgets[i]) i += 1 def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.proceed) self.browse_button.pressed.connect(self.fill_media_location) self.more_button.toggled.connect(self.extension.setVisible) self.save_button.pressed.connect(self.save_profiles_to_file) self.load_button.pressed.connect(self.load_profiles_from_file) def proceed(self): if self.is_connection_valid(): profilename, info = self.collect_info() if profilename in self.profiles: self.profiles[profilename].update(info) else: self.profiles[profilename] = info store_profiles(self.profiles) use_chosen_profile(profilename) self.accept() def is_connection_valid(self): profilename, info = self.collect_info() mt = SignalSlotModelThread(lambda: None) mt.start() progress = ProgressDialog(_('Verifying database settings')) mt.post(lambda: self.test_connection(info), progress.finished, progress.exception) progress.exec_() return self._connection_valid def test_connection(self, profile): self._connection_valid = False connection_string = connection_string_from_profile(profile) engine = create_engine(connection_string, pool_recycle=True) try: connection = engine.raw_connection() cursor = connection.cursor() cursor.close() connection.close() self._connection_valid = True except Exception, e: self._connection_valid = False raise UserException( _('Could not connect to database, please check host and port'), resolution= _('Verify driver, host and port or contact your system administrator' ), detail=unicode(e))
class SessionsStartup(SettingsGroup): def __init__(self, page): super(SessionsStartup, self).__init__(i18n("Session to load if Frescobaldi is started without arguments"), page) grid = QGridLayout(self) grid.setSpacing(0) self.sessionOptions = {} self.customSession = QComboBox(currentIndexChanged=page.changed) def changed(dummy): page.changed() self.customSession.setEnabled(self.sessionOptions["custom"].isChecked()) for title, name in ( (i18n("Start with no session"), "none"), (i18n("Start with last used session"), "lastused"), (i18n("Start with session:"), "custom"), ): self.sessionOptions[name] = QRadioButton(title, toggled=changed) self.customSession.setToolTip(i18n("Choose a session.")) self.sessionOptions["custom"].clicked.connect(lambda: self.customSession.setFocus()) grid.addWidget(self.sessionOptions["none"], 0, 0, 1, 2) grid.addWidget(self.sessionOptions["lastused"], 1, 0, 1, 2) grid.addWidget(self.sessionOptions["custom"], 2, 0, 1, 1) grid.addWidget(self.customSession, 2, 1, 1, 1) self.customSession.addItem(i18n("Choose...")) self.customSession.addItems(page.dialog.mainwin.sessionManager().names()) def defaults(self): current = self.page.dialog.mainwin.sessionManager().current() if current: for index in range(1, self.customSession.count() + 1): if self.customSession.itemText(index) == current: self.customSession.setCurrentIndex(index) self.sessionOptions["none"].setChecked(True) def loadSettings(self): conf = config("preferences") session = conf.readEntry("custom session", "") if session: for index in range(1, self.customSession.count() + 1): if self.customSession.itemText(index) == session: self.customSession.setCurrentIndex(index) name = conf.readEntry("default session", "") if name not in self.sessionOptions: name = "none" self.sessionOptions[name].setChecked(True) def saveSettings(self): conf = config("preferences") if self.customSession.currentIndex() > 0: session = self.customSession.currentText() else: session = "none" conf.writeEntry("custom session", session) for name, widget in self.sessionOptions.items(): if widget.isChecked(): conf.writeEntry("default session", name) break
class FindInFilesDialog( QDialog, object ): """ find in files dialog implementation """ inProject = 0 inDirectory = 1 inOpenFiles = 2 def __init__( self, where, what = "", dirPath = "", filters = [], parent = None ): QDialog.__init__( self, parent ) mainWindow = GlobalData().mainWindow self.editorsManager = mainWindow.editorsManagerWidget.editorsManager self.__cancelRequest = False self.__inProgress = False self.searchRegexp = None self.searchResults = [] # Avoid pylint complains self.findCombo = None self.caseCheckBox = None self.wordCheckBox = None self.regexpCheckBox = None self.projectRButton = None self.openFilesRButton = None self.dirRButton = None self.dirEditCombo = None self.dirSelectButton = None self.filterCombo = None self.fileLabel = None self.progressBar = None self.findButton = None self.__createLayout() self.setWindowTitle( "Find in files" ) # Restore the combo box values project = GlobalData().project if project.fileName != "": self.findFilesWhat = project.findFilesWhat self.findFilesDirs = project.findFilesDirs self.findFilesMasks = project.findFilesMasks else: settings = Settings() self.findFilesWhat = settings.findFilesWhat self.findFilesDirs = settings.findFilesDirs self.findFilesMasks = settings.findFilesMasks self.findCombo.addItems( self.findFilesWhat ) self.findCombo.setEditText( "" ) self.dirEditCombo.addItems( self.findFilesDirs ) self.dirEditCombo.setEditText( "" ) self.filterCombo.addItems( self.findFilesMasks ) self.filterCombo.setEditText( "" ) if where == self.inProject: self.setSearchInProject( what, filters ) elif where == self.inDirectory: self.setSearchInDirectory( what, dirPath, filters ) else: self.setSearchInOpenFiles( what, filters ) return def __createLayout( self ): """ Creates the dialog layout """ self.resize( 600, 300 ) self.setSizeGripEnabled( True ) verticalLayout = QVBoxLayout( self ) gridLayout = QGridLayout() # Combo box for the text to search findLabel = QLabel( self ) findLabel.setText( "Find text:" ) self.findCombo = QComboBox( self ) self.__tuneCombo( self.findCombo ) self.findCombo.lineEdit().setToolTip( "Regular expression to search for" ) self.findCombo.editTextChanged.connect( self.__someTextChanged ) gridLayout.addWidget( findLabel, 0, 0, 1, 1 ) gridLayout.addWidget( self.findCombo, 0, 1, 1, 1 ) verticalLayout.addLayout( gridLayout ) # Check boxes horizontalCBLayout = QHBoxLayout() self.caseCheckBox = QCheckBox( self ) self.caseCheckBox.setText( "Match &case" ) horizontalCBLayout.addWidget( self.caseCheckBox ) self.wordCheckBox = QCheckBox( self ) self.wordCheckBox.setText( "Match whole &word" ) horizontalCBLayout.addWidget( self.wordCheckBox ) self.regexpCheckBox = QCheckBox( self ) self.regexpCheckBox.setText( "Regular &expression" ) horizontalCBLayout.addWidget( self.regexpCheckBox ) verticalLayout.addLayout( horizontalCBLayout ) # Files groupbox filesGroupbox = QGroupBox( self ) filesGroupbox.setTitle( "Find in" ) sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred ) sizePolicy.setHorizontalStretch( 0 ) sizePolicy.setVerticalStretch( 0 ) sizePolicy.setHeightForWidth( filesGroupbox.sizePolicy().hasHeightForWidth() ) filesGroupbox.setSizePolicy( sizePolicy ) gridLayoutFG = QGridLayout( filesGroupbox ) self.projectRButton = QRadioButton( filesGroupbox ) self.projectRButton.setText( "&Project" ) gridLayoutFG.addWidget( self.projectRButton, 0, 0 ) self.projectRButton.clicked.connect( self.__projectClicked ) self.openFilesRButton = QRadioButton( filesGroupbox ) self.openFilesRButton.setText( "&Opened files only" ) gridLayoutFG.addWidget( self.openFilesRButton, 1, 0 ) self.openFilesRButton.clicked.connect( self.__openFilesOnlyClicked ) self.dirRButton = QRadioButton( filesGroupbox ) self.dirRButton.setText( "&Directory tree" ) gridLayoutFG.addWidget( self.dirRButton, 2, 0 ) self.dirRButton.clicked.connect( self.__dirClicked ) self.dirEditCombo = QComboBox( filesGroupbox ) self.__tuneCombo( self.dirEditCombo ) self.dirEditCombo.lineEdit().setToolTip( "Directory to search in" ) gridLayoutFG.addWidget( self.dirEditCombo, 2, 1 ) self.dirEditCombo.editTextChanged.connect( self.__someTextChanged ) self.dirSelectButton = QPushButton( filesGroupbox ) self.dirSelectButton.setText( "..." ) gridLayoutFG.addWidget( self.dirSelectButton, 2, 2 ) self.dirSelectButton.clicked.connect( self.__selectDirClicked ) filterLabel = QLabel( filesGroupbox ) filterLabel.setText( "Files filter:" ) gridLayoutFG.addWidget( filterLabel, 3, 0 ) self.filterCombo = QComboBox( filesGroupbox ) self.__tuneCombo( self.filterCombo ) self.filterCombo.lineEdit().setToolTip( "File names regular expression" ) gridLayoutFG.addWidget( self.filterCombo, 3, 1 ) self.filterCombo.editTextChanged.connect( self.__someTextChanged ) verticalLayout.addWidget( filesGroupbox ) # File label self.fileLabel = FitPathLabel( self ) self.fileLabel.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed ) verticalLayout.addWidget( self.fileLabel ) # Progress bar self.progressBar = QProgressBar( self ) self.progressBar.setValue( 0 ) self.progressBar.setOrientation( Qt.Horizontal ) verticalLayout.addWidget( self.progressBar ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Cancel ) self.findButton = buttonBox.addButton( "Find", QDialogButtonBox.AcceptRole ) self.findButton.setDefault( True ) self.findButton.clicked.connect( self.__process ) verticalLayout.addWidget( buttonBox ) buttonBox.rejected.connect( self.__onClose ) return @staticmethod def __tuneCombo( comboBox ): " Sets the common settings for a combo box " sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed ) sizePolicy.setHorizontalStretch( 0 ) sizePolicy.setVerticalStretch( 0 ) sizePolicy.setHeightForWidth( \ comboBox.sizePolicy().hasHeightForWidth() ) comboBox.setSizePolicy( sizePolicy ) comboBox.setEditable( True ) comboBox.setInsertPolicy( QComboBox.InsertAtTop ) comboBox.setAutoCompletion( False ) comboBox.setDuplicatesEnabled( False ) return def __onClose( self ): " Triggered when the close button is clicked " self.__cancelRequest = True if not self.__inProgress: self.close() return def setSearchInProject( self, what = "", filters = [] ): " Set search ready for the whole project " if GlobalData().project.fileName == "": # No project loaded, fallback to opened files self.setSearchInOpenFiles( what, filters ) return # Select the project radio button self.projectRButton.setEnabled( True ) self.projectRButton.setChecked( True ) self.dirEditCombo.setEnabled( False ) self.dirSelectButton.setEnabled( False ) openedFiles = self.editorsManager.getTextEditors() self.openFilesRButton.setEnabled( len( openedFiles ) != 0 ) self.setFilters( filters ) self.findCombo.setEditText( what ) self.findCombo.lineEdit().selectAll() self.findCombo.setFocus() # Check searchability self.__testSearchability() return def setSearchInOpenFiles( self, what = "", filters = [] ): " Sets search ready for the opened files " openedFiles = self.editorsManager.getTextEditors() if len( openedFiles ) == 0: # No opened files, fallback to search in dir self.setSearchInDirectory( what, "", filters ) return # Select the radio buttons self.projectRButton.setEnabled( GlobalData().project.fileName != "" ) self.openFilesRButton.setEnabled( True ) self.openFilesRButton.setChecked( True ) self.dirEditCombo.setEnabled( False ) self.dirSelectButton.setEnabled( False ) self.setFilters( filters ) self.findCombo.setEditText( what ) self.findCombo.lineEdit().selectAll() self.findCombo.setFocus() # Check searchability self.__testSearchability() return def setSearchInDirectory( self, what = "", dirPath = "", filters = [] ): " Sets search ready for the given directory " # Select radio buttons self.projectRButton.setEnabled( GlobalData().project.fileName != "" ) openedFiles = self.editorsManager.getTextEditors() self.openFilesRButton.setEnabled( len( openedFiles ) != 0 ) self.dirRButton.setEnabled( True ) self.dirRButton.setChecked( True ) self.dirEditCombo.setEnabled( True ) self.dirSelectButton.setEnabled( True ) self.dirEditCombo.setEditText( dirPath ) self.setFilters( filters ) self.findCombo.setEditText( what ) self.findCombo.lineEdit().selectAll() self.findCombo.setFocus() # Check searchability self.__testSearchability() return def setFilters( self, filters ): " Sets up the filters " # Set filters if provided if filters: self.filterCombo.setEditText( ";".join( filters ) ) else: self.filterCombo.setEditText( "" ) return def __testSearchability( self ): " Tests the searchability and sets the Find button status " startTime = time.time() if self.findCombo.currentText().strip() == "": self.findButton.setEnabled( False ) self.findButton.setToolTip( "No text to search" ) return if self.dirRButton.isChecked(): dirname = self.dirEditCombo.currentText().strip() if dirname == "": self.findButton.setEnabled( False ) self.findButton.setToolTip( "No directory path" ) return if not os.path.isdir( dirname ): self.findButton.setEnabled( False ) self.findButton.setToolTip( "Path is not a directory" ) return # Now we need to match file names if there is a filter filtersText = self.filterCombo.currentText().strip() if filtersText == "": self.findButton.setEnabled( True ) self.findButton.setToolTip( "Find in files" ) return # Need to check the files match try: filterRe = re.compile( filtersText, re.IGNORECASE ) except: self.findButton.setEnabled( False ) self.findButton.setToolTip( "Incorrect files " \ "filter regular expression" ) return matched = False tooLong = False if self.projectRButton.isChecked(): # Whole project for fname in GlobalData().project.filesList: if fname.endswith( sep ): continue matched = filterRe.match( fname ) if matched: break # Check the time, it might took too long if time.time() - startTime > 0.1: tooLong = True break elif self.openFilesRButton.isChecked(): # Opened files openedFiles = self.editorsManager.getTextEditors() for record in openedFiles: matched = filterRe.match( record[ 1 ] ) if matched: break # Check the time, it might took too long if time.time() - startTime > 0.1: tooLong = True break else: # Search in the dir if not dirname.endswith( sep ): dirname += sep matched, tooLong = self.__matchInDir( dirname, filterRe, startTime ) if matched: self.findButton.setEnabled( True ) self.findButton.setToolTip( "Find in files" ) else: if tooLong: self.findButton.setEnabled( True ) self.findButton.setToolTip( "Find in files" ) else: self.findButton.setEnabled( False ) self.findButton.setToolTip( "No files matched to search in" ) return @staticmethod def __matchInDir( path, filterRe, startTime ): " Provides the 'match' and 'too long' statuses " matched = False tooLong = False for item in os.listdir( path ): if time.time() - startTime > 0.1: tooLong = True return matched, tooLong if os.path.isdir( path + item ): dname = path + item + sep matched, tooLong = FindInFilesDialog.__matchInDir( dname, filterRe, startTime ) if matched or tooLong: return matched, tooLong continue if filterRe.match( path + item ): matched = True return matched, tooLong return matched, tooLong def __projectClicked( self ): " project radio button clicked " self.dirEditCombo.setEnabled( False ) self.dirSelectButton.setEnabled( False ) self.__testSearchability() return def __openFilesOnlyClicked( self ): " open files only radio button clicked " self.dirEditCombo.setEnabled( False ) self.dirSelectButton.setEnabled( False ) self.__testSearchability() return def __dirClicked( self ): " dir radio button clicked " self.dirEditCombo.setEnabled( True ) self.dirSelectButton.setEnabled( True ) self.dirEditCombo.setFocus() self.__testSearchability() return def __someTextChanged( self, text ): " Text to search, filter or dir name has been changed " self.__testSearchability() return def __selectDirClicked( self ): " The user selects a directory " dirName = QFileDialog.getExistingDirectory( self, "Select directory to search in", self.dirEditCombo.currentText(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if dirName: self.dirEditCombo.setEditText( os.path.normpath( dirName ) ) self.__testSearchability() return def __projectFiles( self, filterRe ): " Project files list respecting the mask " mainWindow = GlobalData().mainWindow files = [] for fname in GlobalData().project.filesList: if fname.endswith( sep ): continue if filterRe is None or filterRe.match( fname ): widget = mainWindow.getWidgetForFileName( fname ) if widget is None: # Do not check for broken symlinks if isFileSearchable( fname, False ): files.append( ItemToSearchIn( fname, "" ) ) else: if widget.getType() in \ [ MainWindowTabWidgetBase.PlainTextEditor ]: files.append( ItemToSearchIn( fname, widget.getUUID() ) ) QApplication.processEvents() if self.__cancelRequest: raise Exception( "Cancel request" ) return files def __openedFiles( self, filterRe ): " Currently opened editor buffers " files = [] openedFiles = self.editorsManager.getTextEditors() for record in openedFiles: uuid = record[ 0 ] fname = record[ 1 ] if filterRe is None or filterRe.match( fname ): files.append( ItemToSearchIn( fname, uuid ) ) QApplication.processEvents() if self.__cancelRequest: raise Exception( "Cancel request" ) return files def __dirFiles( self, path, filterRe, files ): " Files recursively for the dir " for item in os.listdir( path ): QApplication.processEvents() if self.__cancelRequest: raise Exception( "Cancel request" ) if os.path.isdir( path + item ): if item in [ ".svn", ".cvs" ]: # It does not make sense to search in revision control dirs continue anotherDir, isLoop = resolveLink( path + item ) if not isLoop: self.__dirFiles( anotherDir + sep, filterRe, files ) continue if not os.path.isfile( path + item ): continue realItem, isLoop = resolveLink( path + item ) if isLoop: continue if filterRe is None or filterRe.match( realItem ): found = False for itm in files: if itm.fileName == realItem: found = True break if not found: mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetForFileName( realItem ) if widget is None: if isFileSearchable( realItem ): files.append( ItemToSearchIn( realItem, "" ) ) else: if widget.getType() in \ [ MainWindowTabWidgetBase.PlainTextEditor ]: files.append( ItemToSearchIn( realItem, widget.getUUID() ) ) return def __buildFilesList( self ): " Builds the list of files to search in " filtersText = self.filterCombo.currentText().strip() if filtersText != "": filterRe = re.compile( filtersText, re.IGNORECASE ) else: filterRe = None if self.projectRButton.isChecked(): return self.__projectFiles( filterRe ) if self.openFilesRButton.isChecked(): return self.__openedFiles( filterRe ) dirname = os.path.realpath( self.dirEditCombo.currentText().strip() ) files = [] self.__dirFiles( dirname + sep, filterRe, files ) return files def __process( self ): " Search process " # Add entries to the combo box if required regexpText = self.findCombo.currentText() if regexpText in self.findFilesWhat: self.findFilesWhat.remove( regexpText ) self.findFilesWhat.insert( 0, regexpText ) if len( self.findFilesWhat ) > 32: self.findFilesWhat = self.findFilesWhat[ : 32 ] self.findCombo.clear() self.findCombo.addItems( self.findFilesWhat ) filtersText = self.filterCombo.currentText().strip() if filtersText in self.findFilesMasks: self.findFilesMasks.remove( filtersText ) self.findFilesMasks.insert( 0, filtersText ) if len( self.findFilesMasks ) > 32: self.findFilesMasks = self.findFilesMasks[ : 32 ] self.filterCombo.clear() self.filterCombo.addItems( self.findFilesMasks ) if self.dirRButton.isChecked(): dirText = self.dirEditCombo.currentText().strip() if dirText in self.findFilesDirs: self.findFilesDirs.remove( dirText ) self.findFilesDirs.insert( 0, dirText ) if len( self.findFilesDirs ) > 32: self.findFilesDirs = self.findFilesDirs[ : 32 ] self.dirEditCombo.clear() self.dirEditCombo.addItems( self.findFilesDirs ) # Save the combo values for further usage if GlobalData().project.fileName != "": GlobalData().project.setFindInFilesHistory( self.findFilesWhat, self.findFilesDirs, self.findFilesMasks ) else: Settings().findFilesWhat = self.findFilesWhat Settings().findFilesDirs = self.findFilesDirs Settings().findFilesMasks = self.findFilesMasks self.__inProgress = True numberOfMatches = 0 self.searchResults = [] self.searchRegexp = None # Form the regexp to search if not self.regexpCheckBox.isChecked(): regexpText = re.escape( regexpText ) if self.wordCheckBox.isChecked(): regexpText = "\\b%s\\b" % regexpText flags = re.UNICODE | re.LOCALE if not self.caseCheckBox.isChecked(): flags |= re.IGNORECASE try: self.searchRegexp = re.compile( regexpText, flags ) except: logging.error( "Invalid search expression" ) self.close() return QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) ) self.fileLabel.setPath( 'Building list of files to search in...' ) QApplication.processEvents() try: files = self.__buildFilesList() except Exception, exc: if "Cancel request" in str( exc ): QApplication.restoreOverrideCursor() self.close() return else: QApplication.restoreOverrideCursor() logging.error( str( exc ) ) self.close() return QApplication.restoreOverrideCursor() QApplication.processEvents() if len( files ) == 0: self.fileLabel.setPath( 'No files to search in' ) return self.progressBar.setRange( 0, len( files ) ) index = 1 for item in files: if self.__cancelRequest: self.__inProgress = False self.close() return self.fileLabel.setPath( 'Matches: ' + str( numberOfMatches ) + \ ' Processing: ' + item.fileName ) item.search( self.searchRegexp ) found = len( item.matches ) if found > 0: numberOfMatches += found self.searchResults.append( item ) self.progressBar.setValue( index ) index += 1 QApplication.processEvents() if numberOfMatches == 0: if len( files ) == 1: self.fileLabel.setPath( "No matches in 1 file." ) else: self.fileLabel.setPath( "No matches in " + \ str( len( files ) ) + " files." ) self.__inProgress = False else: self.close() return