class NotebookListDialog(QDialog): """ Funtions to display, create, remove, modify notebookList """ def __init__(self, parent=None): super(NotebookListDialog, self).__init__(parent) self.notebookList = QListWidget() self.moveUp = QPushButton('<<') self.moveDown = QPushButton('>>') self.add = QPushButton('Add') self.remove = QPushButton('Remove') self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) layout = QGridLayout() layout.addWidget(self.notebookList, 0, 0, 4, 6) layout.addWidget(self.moveUp, 1, 6) layout.addWidget(self.moveDown, 2, 6) layout.addWidget(self.add, 4, 0) layout.addWidget(self.remove, 4, 1) layout.addWidget(self.buttonBox, 4, 5, 1, 2) self.setLayout(layout) self.notebookList.setItemDelegate(ListDelegate(self.notebookList)) self.notebookList.currentRowChanged.connect(self.updateUi) self.add.clicked.connect(self.actionAdd) self.remove.clicked.connect(self.actionRemove) self.moveUp.clicked.connect(self.moveItemUp) self.moveDown.clicked.connect(self.moveItemDown) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.initList() def initList(self): self.notebookList.clear() notebooks = Mikibook.read() for nb in notebooks: item = QListWidgetItem() item.setData(Qt.DisplayRole, nb[0]) item.setData(Qt.UserRole, nb[1]) self.notebookList.addItem(item) self.updateUi(len(notebooks) != 0) self.notebookList.setCurrentRow(0) # QListWidgetItem(nb, self.notebookList) def updateUi(self, row): flag = (row != -1) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(flag) self.remove.setEnabled(flag) self.moveUp.setEnabled(flag) self.moveDown.setEnabled(flag) def actionAdd(self): Mikibook.create() self.initList() count = self.notebookList.count() self.notebookList.setCurrentRow(count-1) def actionRemove(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() name = item.data(Qt.DisplayRole) path = item.data(Qt.UserRole) self.notebookList.takeItem(row) Mikibook.remove(name, path) def moveItemUp(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() if row != 0: # self.notebookList.removeItemWidget(item) self.notebookList.takeItem(row) self.notebookList.insertItem(row-1, item) self.notebookList.setCurrentRow(row-1) def moveItemDown(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() count = self.notebookList.count() if row != count-1: self.notebookList.takeItem(row) self.notebookList.insertItem(row+1, item) self.notebookList.setCurrentRow(row+1) def accept(self): notebookPath = self.notebookList.currentItem().data(Qt.UserRole) notebookName = self.notebookList.currentItem().data(Qt.DisplayRole) settings = Setting([[notebookName, notebookPath]]) window = mikidown.MikiWindow(settings) window.show() count = self.notebookList.count() notebooks = [] for i in range(count): name = self.notebookList.item(i).data(Qt.DisplayRole) path = self.notebookList.item(i).data(Qt.UserRole) notebooks.append([name, path]) Mikibook.write(notebooks) QDialog.accept(self)
class NotebookListDialog(QDialog): """ Functions to display, create, remove, modify notebookList """ def __init__(self, parent=None): super(NotebookListDialog, self).__init__(parent) self.notebookList = QListWidget() self.moveUp = QPushButton('<<') self.moveDown = QPushButton('>>') self.add = QPushButton('Add') self.remove = QPushButton('Remove') self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) layout = QGridLayout() layout.addWidget(self.notebookList, 0, 0, 4, 6) layout.addWidget(self.moveUp, 1, 6) layout.addWidget(self.moveDown, 2, 6) layout.addWidget(self.add, 4, 0) layout.addWidget(self.remove, 4, 1) layout.addWidget(self.buttonBox, 4, 5, 1, 2) self.setLayout(layout) self.notebookList.setItemDelegate(ListDelegate(self.notebookList)) self.notebookList.currentRowChanged.connect(self.updateUi) self.add.clicked.connect(self.actionAdd) self.remove.clicked.connect(self.actionRemove) self.moveUp.clicked.connect(self.moveItemUp) self.moveDown.clicked.connect(self.moveItemDown) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.initList() def initList(self): self.notebookList.clear() notebooks = Mikibook.read() for nb in notebooks: item = QListWidgetItem() item.setData(Qt.DisplayRole, nb[0]) item.setData(Qt.UserRole, nb[1]) self.notebookList.addItem(item) self.updateUi(len(notebooks) != 0) self.notebookList.setCurrentRow(0) # QListWidgetItem(nb, self.notebookList) def updateUi(self, row): flag = (row != -1) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(flag) self.remove.setEnabled(flag) self.moveUp.setEnabled(flag) self.moveDown.setEnabled(flag) def actionAdd(self): Mikibook.create() self.initList() count = self.notebookList.count() self.notebookList.setCurrentRow(count - 1) def actionRemove(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() name = item.data(Qt.DisplayRole) path = item.data(Qt.UserRole) self.notebookList.takeItem(row) Mikibook.remove(name, path) def moveItemUp(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() if row != 0: # self.notebookList.removeItemWidget(item) self.notebookList.takeItem(row) self.notebookList.insertItem(row - 1, item) self.notebookList.setCurrentRow(row - 1) def moveItemDown(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() count = self.notebookList.count() if row != count - 1: self.notebookList.takeItem(row) self.notebookList.insertItem(row + 1, item) self.notebookList.setCurrentRow(row + 1) def accept(self): notebookPath = self.notebookList.currentItem().data(Qt.UserRole) notebookName = self.notebookList.currentItem().data(Qt.DisplayRole) settings = Setting([[notebookName, notebookPath]]) window = mikidown.MikiWindow(settings) window.show() count = self.notebookList.count() notebooks = [] for i in range(count): name = self.notebookList.item(i).data(Qt.DisplayRole) path = self.notebookList.item(i).data(Qt.UserRole) notebooks.append([name, path]) Mikibook.write(notebooks) QDialog.accept(self)
class ProjectPropertiesDialog( QDialog, object ): """ project properties dialog implementation """ def __init__( self, project = None, parent = None ): QDialog.__init__( self, parent ) # The dialog caller reads this member if the dialog was finished # successfully. self.absProjectFileName = None self.__createLayout() self.__project = project if project is None: # It a new project creation self.setWindowTitle( "New Project Properties" ) userRecord = pwd.getpwuid( os.getuid() ) if not userRecord[ 5 ].endswith( os.path.sep ): self.dirEdit.setText( userRecord[ 5 ] + os.path.sep ) else: self.dirEdit.setText( userRecord[ 5 ] ) self.initialDirName = self.dirEdit.text() self.lastProjectName = "" if userRecord[ 4 ] != "": self.authorEdit.setText( userRecord[ 4 ].split( ',' )[ 0 ].strip() ) else: self.authorEdit.setText( userRecord[ 0 ] ) try: self.emailEdit.setText( userRecord[ 0 ] + "@" + socket.gethostname() ) except: pass self.versionEdit.setText( "0.0.1" ) self.licenseEdit.setText( "GPL v3" ) self.copyrightEdit.setText( "Copyright (c) " + self.authorEdit.text() + ", " + str( datetime.date.today().year ) ) self.creationDateEdit.setText( getLocaleDate() ) self.nameEdit.setFocus() elif type( project ) == type( "" ): self.setWindowTitle( "Viewing Project Properties" ) # This is viewing properties and the argument is the path to the # project file scriptName, importDirs, creationDate, author, lic, \ copy_right, description, \ version, email, uuid = getProjectProperties( project ) if not os.path.isabs( scriptName ) and scriptName != "": scriptName = os.path.normpath( os.path.dirname( project ) + os.path.sep + scriptName ) self.nameEdit.setText( os.path.basename( project ) ) self.nameEdit.setToolTip( "" ) self.dirEdit.setText( os.path.dirname( project ) ) self.dirEdit.setToolTip( "" ) self.scriptEdit.setText( scriptName ) self.versionEdit.setText( version ) self.authorEdit.setText( author ) self.emailEdit.setText( email ) self.licenseEdit.setText( lic ) self.copyrightEdit.setText( copy_right ) self.descriptionEdit.setText( description ) self.creationDateEdit.setText( creationDate ) self.uuidEdit.setText( str( uuid ) ) self.uuidEdit.setToolTip( settingsDir + str( uuid ) + os.path.sep + " (double click to copy path)" ) for item in importDirs: self.importDirList.addItem( item ) self.disableEditing() else: self.setWindowTitle( "Editing Project Properties" ) # This is editing the loaded project. self.nameEdit.setText( os.path.basename( project.fileName ) ) self.nameEdit.setToolTip( "" ) self.dirEdit.setText( project.getProjectDir() ) self.dirEdit.setToolTip( "" ) self.scriptEdit.setText( project.getProjectScript() ) self.versionEdit.setText( project.version ) self.authorEdit.setText( project.author ) self.emailEdit.setText( project.email ) self.licenseEdit.setText( project.license ) self.copyrightEdit.setText( project.copyright ) self.descriptionEdit.setText( project.description ) self.creationDateEdit.setText( project.creationDate ) self.uuidEdit.setText( str( project.uuid ) ) self.uuidEdit.setToolTip( project.userProjectDir + " (double click to copy path)" ) self.setReadOnly() for item in project.importDirs: self.importDirList.addItem( item ) if self.importDirList.count() > 0: self.importDirList.setCurrentRow( 0 ) self.delImportDirButton.setEnabled( True ) # The project could be the one belonging to another user # so there might be no write permissions. if not os.access( project.fileName, os.W_OK ): # Disable editing self.setWindowTitle( "Viewing Project Properties (no write permissions)" ) self.disableEditing() else: self.scriptEdit.setFocus() return def __createLayout( self ): """ Creates the dialog layout """ self.resize( 600, 400 ) self.setSizeGripEnabled( True ) verticalLayout = QVBoxLayout( self ) gridLayout = QGridLayout() # Project name nameLabel = QLabel( self ) nameLabel.setText( "Project name:" ) gridLayout.addWidget( nameLabel, 0, 0, 1, 1 ) self.nameEdit = QLineEdit( self ) self.nameEdit.setToolTip( "Type a project name without a path" ) self.nameEdit.installEventFilter( self ) gridLayout.addWidget( self.nameEdit, 0, 1, 1, 1 ) # Project dir dirLabel = QLabel( self ) dirLabel.setText( "Project directory:" ) gridLayout.addWidget( dirLabel, 1, 0, 1, 1 ) self.dirEdit = QLineEdit( self ) self.dirEdit.setToolTip( "Not existed directories will be created" ) gridLayout.addWidget( self.dirEdit, 1, 1, 1, 1 ) self.dirButton = QPushButton( self ) self.dirButton.setText( "..." ) gridLayout.addWidget( self.dirButton, 1, 2, 1, 1 ) self.dirCompleter = DirCompleter( self.dirEdit ) # Project script mainScriptLabel = QLabel( "Main script:", self ) gridLayout.addWidget( mainScriptLabel, 2, 0, 1, 1 ) self.scriptEdit = QLineEdit( self ) self.scriptEdit.setToolTip( "Project main script, " "used when the project is run" ) gridLayout.addWidget( self.scriptEdit, 2, 1, 1, 1 ) self.scriptButton = QPushButton( "...", self ) gridLayout.addWidget( self.scriptButton, 2, 2, 1, 1 ) self.fileCompleter = FileCompleter( self.scriptEdit ) # Import dirs importLabel = QLabel( self ) importLabel.setText( "Import directories:" ) importLabel.setAlignment( Qt.AlignTop ) gridLayout.addWidget( importLabel, 3, 0, 1, 1 ) self.importDirList = QListWidget( self ) self.importDirList.setAlternatingRowColors( True ) self.importDirList.setSelectionMode( QAbstractItemView.SingleSelection ) self.importDirList.setSelectionBehavior( QAbstractItemView.SelectRows ) self.importDirList.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.importDirList.setToolTip( "Directories where to look for " "project specific imports" ) gridLayout.addWidget( self.importDirList, 3, 1, 1, 1 ) self.addImportDirButton = QPushButton( self ) self.addImportDirButton.setText( "Add dir" ) self.delImportDirButton = QPushButton( self ) self.delImportDirButton.setText( "Delete dir" ) self.delImportDirButton.setEnabled( False ) vLayout = QVBoxLayout() vLayout.addWidget( self.addImportDirButton ) vLayout.addWidget( self.delImportDirButton ) vLayout.addStretch( 0 ) gridLayout.addLayout( vLayout, 3, 2, 1, 1 ) # Version versionLabel = QLabel( self ) versionLabel.setText( "Version:" ) gridLayout.addWidget( versionLabel, 4, 0, 1, 1 ) self.versionEdit = QLineEdit( self ) gridLayout.addWidget( self.versionEdit, 4, 1, 1, 1 ) # Author authorLabel = QLabel( self ) authorLabel.setText( "Author:" ) gridLayout.addWidget( authorLabel, 5, 0, 1, 1 ) self.authorEdit = QLineEdit( self ) gridLayout.addWidget( self.authorEdit, 5, 1, 1, 1 ) # E-mail emailLabel = QLabel( self ) emailLabel.setText( "E-mail:" ) gridLayout.addWidget( emailLabel, 6, 0, 1, 1 ) self.emailEdit = QLineEdit( self ) gridLayout.addWidget( self.emailEdit, 6, 1, 1, 1 ) # License licenseLabel = QLabel( self ) licenseLabel.setText( "License:" ) gridLayout.addWidget( licenseLabel, 7, 0, 1, 1 ) self.licenseEdit = QLineEdit( self ) gridLayout.addWidget( self.licenseEdit, 7, 1, 1, 1 ) # Copyright copyrightLabel = QLabel( self ) copyrightLabel.setText( "Copyright:" ) gridLayout.addWidget( copyrightLabel, 8, 0, 1, 1 ) self.copyrightEdit = QLineEdit( self ) gridLayout.addWidget( self.copyrightEdit, 8, 1, 1, 1 ) # Description descriptionLabel = QLabel( self ) descriptionLabel.setText( "Description:" ) descriptionLabel.setAlignment( Qt.AlignTop ) gridLayout.addWidget( descriptionLabel, 9, 0, 1, 1 ) self.descriptionEdit = QTextEdit( self ) self.descriptionEdit.setTabChangesFocus( True ) self.descriptionEdit.setAcceptRichText( False ) gridLayout.addWidget( self.descriptionEdit, 9, 1, 1, 1 ) # Creation date creationDateLabel = QLabel( self ) creationDateLabel.setText( "Creation date:" ) gridLayout.addWidget( creationDateLabel, 10, 0, 1, 1 ) self.creationDateEdit = FramedLabelWithDoubleClick() self.creationDateEdit.setToolTip( "Double click to copy" ) gridLayout.addWidget( self.creationDateEdit, 10, 1, 1, 1 ) # Project UUID uuidLabel = QLabel( self ) uuidLabel.setText( "UUID:" ) gridLayout.addWidget( uuidLabel, 11, 0, 1, 1 ) self.uuidEdit = FramedLabelWithDoubleClick( "", self.__copyProjectPath ) gridLayout.addWidget( self.uuidEdit, 11, 1, 1, 1 ) verticalLayout.addLayout( gridLayout ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Cancel | \ QDialogButtonBox.Ok ) verticalLayout.addWidget( buttonBox ) nameLabel.setBuddy( self.nameEdit ) dirLabel.setBuddy( self.dirEdit ) versionLabel.setBuddy( self.versionEdit ) authorLabel.setBuddy( self.authorEdit ) emailLabel.setBuddy( self.emailEdit ) licenseLabel.setBuddy( self.licenseEdit ) copyrightLabel.setBuddy( self.copyrightEdit ) descriptionLabel.setBuddy( self.descriptionEdit ) buttonBox.accepted.connect( self.onOKButton ) buttonBox.rejected.connect( self.reject ) self.dirButton.clicked.connect( self.onDirButton ) self.scriptButton.clicked.connect( self.onScriptButton ) self.importDirList.currentRowChanged.connect( self.onImportDirRowChanged ) self.addImportDirButton.clicked.connect( self.onAddImportDir ) self.delImportDirButton.clicked.connect( self.onDelImportDir ) self.nameEdit.textEdited.connect( self.onProjectNameChanged ) self.setTabOrder( self.nameEdit, self.dirEdit ) self.setTabOrder( self.dirEdit, self.dirButton ) self.setTabOrder( self.dirButton, self.scriptEdit ) self.setTabOrder( self.scriptEdit, self.scriptButton ) self.setTabOrder( self.scriptButton, self.importDirList ) self.setTabOrder( self.importDirList, self.addImportDirButton ) self.setTabOrder( self.addImportDirButton, self.delImportDirButton ) self.setTabOrder( self.delImportDirButton, self.versionEdit ) self.setTabOrder( self.versionEdit, self.authorEdit ) self.setTabOrder( self.authorEdit, self.emailEdit ) self.setTabOrder( self.emailEdit, self.licenseEdit ) self.setTabOrder( self.licenseEdit, self.copyrightEdit ) self.setTabOrder( self.copyrightEdit, self.descriptionEdit ) self.setTabOrder( self.descriptionEdit, buttonBox ) return def eventFilter( self, obj, event ): " Event filter for the project name field " # Do not allow path separators if event.type() == QEvent.KeyPress: if event.key() == ord( os.path.sep ): return True return QObject.eventFilter( self, obj, event ) def onDirButton( self ): " Displays a directory selection dialog " dirName = QFileDialog.getExistingDirectory( self, "Select project directory", self.dirEdit.text(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if dirName: self.dirEdit.setText( os.path.normpath( dirName ) ) return def onScriptButton( self ): " Displays a file selection dialog " scriptName = QFileDialog.getOpenFileName( self, "Select project main script", self.dirEdit.text() ) if scriptName: self.scriptEdit.setText( os.path.normpath( scriptName ) ) return def onImportDirRowChanged( self, row ): " Triggered when a current row in the import dirs is changed " self.delImportDirButton.setEnabled( row != -1 ) return def onAddImportDir( self ): " Displays a directory selection dialog " dirName = QFileDialog.getExistingDirectory( self, "Select import directory", self.dirEdit.text(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if not dirName: return # There are 2 cases: new project or # editing the existed project properties if self.__project is None: # It a new project; the project path could be editedd dirToInsert = dirName else: # This is an existed project; no way the project path is changed # Let's decide it a relative path should be used here if self.__project.isProjectDir( dirName ): dirToInsert = relpath( dirName, self.dirEdit.text() ) else: dirToInsert = dirName index = 0 while index < self.importDirList.count(): if self.importDirList.item( index ).text() == dirToInsert: logging.warning( "The directory '" + dirName + "' is already in the list of " "imported directories and is not added." ) return index += 1 self.importDirList.addItem( dirToInsert ) self.importDirList.setCurrentRow( self.importDirList.count() - 1 ) return def onDelImportDir( self ): " Triggered when an import dir should be deleted " rowToDelete = self.importDirList.currentRow() if rowToDelete == -1: self.delImportDirButton.setEnabled( False ) return self.importDirList.takeItem( rowToDelete ) if self.importDirList.count() == 0: self.delImportDirButton.setEnabled( False ) else: self.importDirList.setCurrentRow( self.importDirList.count() - 1 ) return def onOKButton( self ): " Checks that the mandatory fields are filled properly " # The checks must be done for a new project only if not self.nameEdit.isEnabled(): self.accept() return # Check that the project name does not have path separators and is not # empty if not self.nameEdit.text().strip(): QMessageBox.critical( self, "Error", "The project name must not be empty" ) return if os.path.sep in self.nameEdit.text(): QMessageBox.critical( self, "Error", "The project name must not " "contain path separators" ) return # Check that the project directory is given dirName = self.dirEdit.text().strip() if not dirName: QMessageBox.critical( self, "Error", "The project directory must not be empty" ) return dirName = os.path.abspath( dirName ) self.dirEdit.setText( dirName ) # Check that the project file does not exist projectFileName = dirName if not projectFileName.endswith( os.path.sep ): projectFileName += os.path.sep projectFileName += self.nameEdit.text().strip() if not projectFileName.endswith( ".cdm" ): projectFileName += ".cdm" if os.path.exists( projectFileName ): QMessageBox.critical( self, "Error", "The project file " + projectFileName + " exists. Please provide another " "directory / project name." ) return # Check that the project dir is not a file if os.path.exists( dirName ): # It might be a link, so read it first dirName = os.path.realpath( dirName ) if not os.path.exists( dirName ): QMessageBox.critical( self, "Error", "Broken link: " + dirName ) return if not os.path.isdir( dirName ): QMessageBox.critical( self, "Error", "The project directory " "may not be a file" ) return # Check that the dir is writable if not os.access( dirName, os.W_OK ): QMessageBox.critical( self, "Error", "You don't have write permissions on " + dirName ) return else: # Create the directory try: os.makedirs( dirName ) except OSError: QMessageBox.critical( self, "Error", "Cannot create the project directory" ) return # Save the absolute file name for further reading it by the caller self.absProjectFileName = projectFileName # The minimum is provided so we can accept it self.accept() return def onProjectNameChanged( self, newName ): " Called when the project name changed " if newName.endswith( ".cdm" ): newName = newName[ :-4 ] if self.dirEdit.text().strip() == (self.initialDirName + self.lastProjectName): self.dirEdit.setText( self.initialDirName + newName ) self.lastProjectName = newName return def setReadOnly( self ): """ Disables editing some fields """ self.dirEdit.setReadOnly( True ) self.dirEdit.setFocusPolicy( Qt.NoFocus ) self.dirEdit.setDisabled( True ) self.dirButton.setDisabled( True ) self.dirButton.setFocusPolicy( Qt.NoFocus ) self.nameEdit.setReadOnly( True ) self.nameEdit.setFocusPolicy( Qt.NoFocus ) self.nameEdit.setDisabled( True ) return def disableEditing( self ): " Disables all the editing " self.nameEdit.setDisabled( True ) self.dirEdit.setDisabled( True ) self.dirButton.setDisabled( True ) self.scriptEdit.setDisabled( True ) self.scriptButton.setDisabled( True ) self.importDirList.setDisabled( True ) self.addImportDirButton.setDisabled( True ) self.delImportDirButton.setDisabled( True ) self.versionEdit.setDisabled( True ) self.authorEdit.setDisabled( True ) self.emailEdit.setDisabled( True ) self.licenseEdit.setDisabled( True ) self.copyrightEdit.setDisabled( True ) self.descriptionEdit.setDisabled( True ) return def __copyProjectPath( self ): " Copies the project path when a label is double clicked " text = self.uuidEdit.text().strip() if text: path = settingsDir + text + os.path.sep QApplication.clipboard().setText( path ) return