--- Title: scieditor2 10 Author: yamasyuh68 Web: https://mimemo.io/m/eQDXzla1XJlPvwk --- 190923 - Scintilla.py ``` import sys ,os ,ctypes , io,subprocess from PyQt5 import QtCore, QtWidgets from PyQt5.QtWidgets import QApplication,QWidget,QMainWindow,QSizePolicy,QVBoxLayout, QTreeWidgetItem,QLabel,\ QMenu,QAction , QDialog , QInputDialog from PyQt5.Qsci import QsciScintilla from PyQt5.QtCore import Qt , QSettings,QSize,QRectF , QTimer,QByteArray from PyQt5.QtGui import QKeyEvent, QStandardItem ,QStandardItemModel,QPixmap,QPainter,QBrush ,QPalette,QColor,\ QCursor from Scintilla_subclass import qsc,myListView from Scintilla_sql import settingsdb import ui from ui_searchload import Ui_Dialog # from numba import jit class MainWindow(QMainWindow): TAB_NUM=0 def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.ui = ui.Ui_MainWindow() # <--------------------------- self.ui.setupUi(self) self.currentSci = None self.ui.listView.LDclicked.connect(self.fileload) self.mes=dispinfo(self) # call information class self.db=settingsdb() # call sql class self.restoreSettings() self.fav=QStandardItemModel() # favoritemodel self.loadfav() self.ui.treeView_2.setContextMenuPolicy(Qt.CustomContextMenu) self.ui.treeView_2.customContextMenuRequested.connect(self.favmenu ) def loadfav(self): fname=os.path.join(os.path.dirname(__file__) , 'Scintilla_fav.ini') self.fav.clear() with open(fname,'r') as f: for line in f: if line[0:1] == '.' : line = line.replace('\n','') line = line.replace('\r','') if line[1:2] == '<' : root = QStandardItem( line[ 2: -1] ) self.fav.appendRow( root ) elif line[1:2] == '.' : root.appendRow( [ QStandardItem( os.path.split(line[2:])[1]) , QStandardItem( line[2:]) ] ) else : self.fav.appendRow( [ QStandardItem( os.path.split(line[2:])[1] ) , QStandardItem( line[1:] ) ] ) self.ui.treeView_2.setModel( self.fav ) self.ui.treeView_2.hideColumn(1) def favmenu(self,e): menu=QMenu() action = QAction('Reload', self) action.triggered.connect(self.loadfav) menu.addAction(action) action = QAction('OpenFolder', self) action.triggered.connect(self.openfolder) menu.addAction(action) menu.exec_(QCursor.pos ()) def openfolder(self): # print(self.ui.treeView_2.selectedIndexes()) item=self.ui.treeView_2.selectedIndexes()[0] # print(item.sibling(item.row(),1).data() ) if item.sibling(item.row(),1).data() : subprocess.Popen( ('explorer' , os.path.split(item.sibling(item.row(),1).data() )[0] )) def ListDClicked(self,item): # favorite open if item.sibling(item.row(),1).data() : self.fileload( item.sibling(item.row(),1).data() ) def restoreSettings(self): try: settings=self.db.gload() self.restoreGeometry( settings[0]) self.ui.splitter.restoreState(settings[1]) self.ui.splitter_2.restoreState(settings[2]) except: self.mes.disp(1,'main loadini fail') def treeClicked(self,item): # outline Clicked i=int(item.siblingAtColumn(1).data()) firstvisible = i-10 if i-10>0 else 0 # ターゲット行は常に上から10行目に表示する self.currentSci.SendScintilla(2613,firstvisible) # SCI_SETFIRSTVISIBLELINE self.currentSci.SendScintilla(2024,i) # SCI_GOTOLINE 2024 self.currentSci.setFocus() def makenewtab(self,name): # 新規作成時もこれが呼ばれる if not name: name='*New*' self.currentSci = qsc(self) self.ui.tabWidget.addTab(self.currentSci, name) self.ui.tabWidget.setCurrentWidget(self.currentSci) self.__lyt = QVBoxLayout() self.__lyt.setContentsMargins(0, 0, 0, 0) self.__lyt.setSpacing(0) self.currentSci.setLayout(self.__lyt) self.currentSci.dropfile.connect(self.fileload) self.currentSci.message.connect(self.mesfromsci) def tabCloseMessage(self,e): if self.currentSci : self.db.save(( self.currentSci.PropDict['fname'] , self.currentSci.SendScintilla(2008 ) ,# SCI_GETCURRENTPOS self.currentSci.SendScintilla(2152 )) ) # SCI_GETFIRSTVISIBLELINE del self.currentSci self.ui.tabWidget.removeTab(e) # e にタブのインデクス def tabChanged(self,e): if not self.ui.tabWidget.count(): self.ui.treeView.setModel (QStandardItemModel()) # 空のモデルをセットしないと消えてくれない return self.currentSci=self.ui.tabWidget.currentWidget() self.ui.treeView.setModel( self.currentSci.PropDict['model'] ) self.searchModel() # set outline index from SCI line self.setWindowTitle(self.currentSci.PropDict['fname']) self.mes.disp(-2,self.currentSci ) self.currentSci.setFocus() def search(self): if self.ui.lineEdit.text(): self.currentSci.findFirst ( self.ui.lineEdit.text() , 1,0,0,1 ) def searchback(self): if self.ui.lineEdit.text(): pos=self.currentSci.SendScintilla(2143) # SCI_GETSELECTIONSTART self.currentSci.SendScintilla(2025,pos) # SCI_GOTOPOS self.currentSci.findFirst ( self.ui.lineEdit.text() , 1,0,0,1,forward=False ) def replace(self): self.currentSci.replace ( self.ui.lineEdit_3.text()) def searchline( self ) : search= self.ui.lineEdit.text().lower() line , index = self.currentSci.getCursorPosition() model = QStandardItemModel() self.ui.treeView.setModel(model) model.appendRow( [ QStandardItem('< 検索時のポジション >' ) , QStandardItem( str(line) ) ] ) counter = 0 for i in range( self.currentSci.lines() ) : if search in self.currentSci.text( i ).lower() : string= '[ ' + str(i+1) + ' 行]' + self.currentSci.text( i )[ : 15] string = string.replace('\n','') # これで改行取れるかな?? string = string.replace('\r','') model.appendRow( [ QStandardItem(string) , QStandardItem( str(i) ) ] ) counter += 1 if counter >50 : self.mes.disp(1,'seach line : Hit over 50 !!') # counter=-1 break def lineEditReturn(self): modifiers = QApplication.keyboardModifiers() if modifiers ==Qt.ControlModifier : self.searchline() elif modifiers ==Qt.ShiftModifier : self.searchback() else : self.search() def searchsave(self): text=QInputDialog.getText(self,r'( ´∀`)','set Name') if text[1]: self.db.searchsave((text[0] ,self.ui.lineEdit.text() , self.ui.lineEdit_3.text())) def searchload(self): # Show Dialog self.sdlg=searchdlg(self) def searchModel(self): line , index = self.currentSci.getCursorPosition() self.hit=self.ui.treeView.model().index(0,0) for i in range(self.ui.treeView.model().rowCount( )) : root = self.ui.treeView.model().index( i,0) # start 0,0 if int(self.ui.treeView.model().index( i,1).data()) > line : self.ui.treeView.setCurrentIndex( self.hit ) return self.hit=root if self.searchModelChild(root , line ): # Recursion self.ui.treeView.setCurrentIndex( self.hit ) return self.ui.treeView.setCurrentIndex( self.hit ) # 文書の最後の場合 def searchModelChild(self , index_prev , line): # Recursion routine count=self.ui.treeView.model().rowCount( index_prev ) if not count: return 0 for i in range( count): if int( index_prev.child( i ,1).data() ) > line : return 1 self.hit=index_prev.child( i ,0) if self.searchModelChild(index_prev.child( i ,0) , line): # Recursion return 1 return 0 def mesfromsci(self,id ,string): # message from sci self.mes.disp(id,string) if id == -1 : # save ok 再度アウトライン解析 if ( self.ui.tabWidget.tabText(self.ui.tabWidget.currentIndex() ) ) == '*New*': self.setWindowTitle(self.currentSci.PropDict['fname']) self.ui.tabWidget.setTabText( self.ui.tabWidget.currentIndex() , os.path.split(self.currentSci.PropDict['fname'])[1] ) self.ui.treeView.setModel( self.currentSci.analyze( ) ) self.searchModel() # set outline index from SCI line self.ui.treeView.hideColumn(1) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): string=e.mimeData().text()[8:] string=string.replace('/','//') self.fileload(string) def fileload(self,string): # 複数から呼ばれる if not os.path.exists(string): return for i in range( self.ui.tabWidget.count() ): # 重複チェック if string==self.ui.tabWidget.widget(i).PropDict['fname'] : self.ui.tabWidget.setCurrentIndex(i) self.currentSci.setFocus() return a=os.path.split(string) self.makenewtab(a[1]) self.ui.treeView.setModel( self.currentSci.load(string) ) self.ui.treeView.hideColumn(1) self.setWindowTitle(self.currentSci.PropDict['fname']) self.mes.disp(-2,self.currentSci ) pos=self.db.load(string) try: self.currentSci.SendScintilla(2613,pos[1]) # SCI_SETFIRSTVISIBLELINE self.currentSci.SendScintilla(2025,pos[0]) # SCI_GOTOPOS except Exception as e: # 全ての例外 self.mes.disp(0,e) self.searchModel() # set outline index from SCI line self.currentSci.setFocus() def keyPressEvent_(self, event): print('kitayo') def closeEvent (self,e): self.db.gsave((self.saveGeometry(),self.ui.splitter.saveState(),self.ui.splitter_2.saveState())) class dispinfo() : def __init__( self , parent ) : self.label=[] self.label.append( QLabel() ) self.label.append( QLabel() ) self.label.append( QLabel() ) parent.ui.statusbar.addPermanentWidget(self.label[0],2) parent.ui.statusbar.addPermanentWidget(self.label[1],1) parent.ui.statusbar.addPermanentWidget(self.label[2],1) self.p=parent def disp( self , id , object ) : # オブジェクトで受ける、最初に判定する if id == -1 : # special message self.saveok() return if id == -2 : # special message self.sciproperty( object ) # カレントチーを引数にする return if id == 5 : # special message self.p.setWindowTitle(object) return if type(object) is str : pass elif type(object) is int : object = str( object ) else : object = self.print_s( object ) self.label[ id ].setText( object ) def saveok(self) : # pal=self.label[0].palette() pal.setColor( QPalette.AlternateBase , QColor(Qt.black) ) pal.setColor( QPalette.Foreground , QColor(Qt.red) ) self.label[0].setPalette( pal ) self.label[0].setText( r'Save OK !! (・∀・)ノ' ) ti=QTimer() ti.singleShot ( 2000, (lambda : self.disp(0,''))) # 表示を消す def sciproperty(self , current): # self.label[2].setText('{} EOL:{} Lines : {} Length : {}'.format( current.PropDict['enc'] , current.PropDict['EOL'] , '{:,}'.format(current.PropDict['Lines']) , '{:,}'.format(current.PropDict['Length'] ))) def print_s(self,object): with io.StringIO() as f: sys.stdout = f print(object) text = f.getvalue() sys.stdout = sys.__stdout__ text = text.replace('\n','') # これで改行取れるかな?? text = text.replace('\r','') return text class searchdlg(QDialog): # Dialog for search data load def __init__(self,parent): super().__init__() self.parent=parent self.ui = Ui_Dialog() self.ui.setupUi(self) self.result=self.parent.db.searchload() if self.result: for l in self.result : self.ui.listWidget.addItem(l[0]) self.show() def listDClicked(self,item): id=item.listWidget().row(item) self.parent.ui.lineEdit.setText( self.result[id][1]) self.parent.ui.lineEdit_3.setText( self.result[id][2]) def listSelect(self,item): id=item.listWidget().row(item) self.ui.label.setText(self.result[id][1]) self.ui.label_2.setText(self.result[id][2]) def delitem(self): self.parent.db.searchdell(self.ui.listWidget.currentItem().text()) # print(self.ui.listWidget.currentItem().text()) if __name__ == '__main__': import sys app = QApplication(sys.argv) main_window = MainWindow() main_window.show() sys.exit(app.exec_()) ``` - Scintilla_subclass.py ``` import sys , ctypes , os, glob , subprocess , re from PyQt5.Qsci import QsciScintilla,QsciLexerPython,QsciMacro from PyQt5.QtWidgets import QMenu , QListView,QAction,QMessageBox ,QColorDialog from PyQt5.QtCore import Qt,QRectF,QSize , pyqtSignal from PyQt5.QtGui import QCursor ,QFont,QFontMetrics,QColor from PyQt5.Qsci import * from PyQt5.QtGui import QCursor ,QFont,QFontMetrics,QColor , QStandardItem ,QStandardItemModel,QPixmap,\ QPainter,QBrush class qsc(QsciScintilla): ARROW_MARKER_NUM = 8 dropfile = pyqtSignal( str ) message = pyqtSignal( int , object) def __init__(self, parent): super().__init__( ) # self.setAcceptDrops(True) self.parent=parent self.set() self.PropDict={'fname':'','enc':'','EOL':0,'Lines':0 , 'Length':0 , 'model':QStandardItemModel() , 'analyzetype':0 } self.Lsp=False self.wrap=0 self.SendScintilla(self.SCI_SETMODEVENTMASK, self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT ) self.SCEN_CHANGE.connect(self.modify) def load(self,fname): with open(fname , mode='rb') as f: s=f.read() # bynary encodeType='UTF-8','cp932','UTF-16','EUC-JP' for i,l in enumerate(encodeType) : try : self.setText(s.decode(encoding=l)) self.PropDict['enc'] =l self.PropDict['fname'] =fname self.PropDict['Lines'] =self.lines() self.PropDict['Length'] =self.length() # self.currentSci.PropDict['EOL'] =self.currentSci.GetEOLMode() # self.analyztree() # self.ShowInfo() break except : if i== len(encodeType)-1 : # 全部だめ self.setText('fail to load ... decode error ') else: pass self.markerDeleteAll(0) if fname[-2:] == 'py' : self.PropDict['analyzetype'] = 1 lexer = QsciLexerPython() self.setLexer(lexer) return self.analyze() def analyze(self) : self.PropDict['model'].clear() if not self.PropDict['analyzetype'] : # normal text import time start = time.time() tree=[] current=0 # 階層 for i in range(0 , self.PropDict['Lines']): linet = self.text( i ) linet = linet.replace('\n',' ') # 改行削除 linet = linet.replace('\r',' ') # 文字数ゼロだとだめなのでここで空白文字を与えておく # i2=0 for i2 , l in enumerate( linet ) : if l == '.' : continue else : break if not i2 : # i2 : 階層 continue if i2 == 1 : # root tree.clear() tree.append( QStandardItem( linet[ 1:] ) ) self.PropDict['model'].appendRow( [ tree[0] , QStandardItem( str( i ) ) ] ) current = 1 else : # child if i2 <= current + 1 : # normal if len( tree ) == i2 -1 : tree.append( None ) tree[ i2-1 ] = QStandardItem( linet[ i2 : ] ) tree[ i2 - 2 ].appendRow( [ tree[ i2 - 1] , QStandardItem( str( i ) ) ] ) current = i2 else : # error self.PropDict['model'].appendRow( [ QStandardItem( ' -- error --' ) , QStandardItem( str( i ) ) ] ) elapsed_time = time.time() - start self.message.emit( 1 , elapsed_time ) else: # py analyze for i in range(0 , self.PropDict['Lines']): linet = self.text( i ) linet = linet.replace('\n','') # これで改行取れるかな?? linet = linet.replace('\r','') if (linet[0:5]=='class') or (' def ' in linet ) : self.PropDict['model'].appendRow( [ QStandardItem(linet) , QStandardItem( str(i) ) ] ) return self.PropDict['model'] def modify(self): linenum=self.SendScintilla(self.SCI_LINEFROMPOSITION ,self.SendScintilla(self.SCI_GETCURRENTPOS)) handle = self.markerAdd(linenum, 0) def keyPressEvent(self, event): # filter # print(str(event.modifiers())) if (event.key() == Qt.Key_D) and (event.modifiers() & Qt.ControlModifier): self.key_selectword() elif (event.key() == Qt.Key_C) and (event.modifiers() & Qt.ControlModifier): self.key_copy() elif (event.key() == Qt.Key_S) and (event.modifiers() & Qt.ControlModifier): self.key_save() elif (event.key() == Qt.Key_1) and (event.modifiers() & Qt.ControlModifier): self.calcline() elif (event.key() == Qt.Key_2) and (event.modifiers() & Qt.ControlModifier): self.calcline2() elif (event.key() == Qt.Key_3) and (event.modifiers() & Qt.ControlModifier): self.key_color() elif (event.key() == Qt.Key_F1): self.key_toggleEOL() elif (event.key() == Qt.Key_F2): self.linewrpping() elif (event.key() == Qt.Key_F3): self.charcount() elif (event.key() == Qt.Key_Escape): self.showhelp() else: super(qsc, self).keyPressEvent(event) # send to parent def calcline(self): self.SendScintilla(2314) # SCI_LINEEND = 2314 line , index = self.getCursorPosition() result = re.findall(r'\d{1,}', self.text( line) ) p= sum( [ int(l) for l in result ] ) p='| ' + str( p ) # 挿入文字列 self.insertAt ( p , line , index ) def calcline2 ( self ) : line , index = self.getCursorPosition() p = re.compile( r'\d+' ) n,sum = 0,0 while( 1 ): res = p.search( self.text( line + n)[index : ] ) if res : sum += int( res[0] ) n += 1 else : break self.insertAt ( str(sum) , line +n+1 , index ) def key_color(self): # color select dialog getcolor = QColorDialog.getColor() colots=getcolor.name() print(colots) def key_toggleEOL(self): # 改行表示 F1 self.setEolVisibility(not self.eolVisibility()) def linewrpping(self): # 折りたたみ F2 self.wrap=0 if self.wrap==2 else 2 self.setWrapMode(self.wrap) def charcount(self): # 文字数カウント F3 mes=self.selectedText().__len__() if self.hasSelectedText() else self.text().__len__() self.message.emit( 1 , '文字数 : {:,}'.format(mes) ) def showhelp(self): self.message.emit(5,'F1:改行表示 F2:折り返し F3:文字数カウント ' \ ' c-1:行数値加算 c-2:縦数値加算 c-3:カラーダイアログ' ) def key_copy(self): if( self.SendScintilla(self.SCI_GETCURRENTPOS) == self.SendScintilla(self.SCI_GETANCHOR )): self.SendScintilla(self.SCI_LINECOPY) else : # self.SendScintilla(self.SCI_COPY) super().SendScintilla(self.SCI_COPY) def key_selectword(self): # C-R pos=self.SendScintilla(self.SCI_GETCURRENTPOS) epos=self.SendScintilla(self.SCI_WORDENDPOSITION,pos) spos=self.SendScintilla(self.SCI_WORDSTARTPOSITION, pos) self.SendScintilla(self.SCI_SETSEL,spos,epos) self.SendScintilla(self.SCI_COPY) # copy def key_save(self): if not self.PropDict['fname'] : self.PropDict['fname'] = self.makesavename() self.PropDict['enc'] = 'UTF-8' self.message.emit(-2,self) fname=self.PropDict['fname'] # enc=self.PropDict['enc'] size=self.SendScintilla(self.SCI_GETLENGTH) s = ctypes.create_string_buffer(size+1) # +1 で確保 self.SendScintilla(self.SCI_GETTEXT , size+1 , s) if self.PropDict['enc'] == 'UTF-8' : with open(fname,'wb') as f :# 書き込み専用 f.write(s) self.message.emit(-1,None) self.markerDeleteAll(0) else: try: s=s.value.decode() senc=s.encode(encoding = self.PropDict['enc']) with open(fname,'wb') as f :# 書き込み専用 f.write(senc) self.message.emit(-1,None) self.markerDeleteAll(0) except Exception as e: self.message.emit(0,e) def makesavename(self): dir=os.path.join(os.path.dirname(__file__) , 'txt') n=0 name='{:02}.txt'.format(n) filepath=os.path.join(dir,name) while os.path.exists(filepath): n+=1 filepath=os.path.join(dir,'{:02}.txt'.format(n) ) # print(filepath) return filepath def dragEnterEvent(self,e): #多分すでに実装されてるからいらないんだと思う e.accept() def dropEvent(self,e): string=e.mimeData().text()[8:] string=string.replace('/','//') self.dropfile.emit(string) def set(self): # -------------------設 定------------------------------ font = QFont() font.setFamily('Ms Gothic') font.setFixedPitch(False) font.setPointSize(10) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers fontmetrics = QFontMetrics(font) self.setMarginsFont(font) self.markerDefine(QsciScintilla.RightArrow, 0) self.setMarginWidth(0, fontmetrics.width("00000") ) self.setMarginLineNumbers(0, True) self.setMarginsForegroundColor(QColor('blue')) self.setMarginsBackgroundColor(QColor("#cccccc")) # Clickable margin 1 for showing markers # self.setMarginSensitivity(1, True) #self.connect(self, # SIGNAL('marginClicked(int, int, Qt::KeyboardModifiers)'), # self.on_margin_clicked) # self.markerDefine(QsciScintilla.ThreeRightArrows, 1) # self.setMarginWidth(1, fontmetrics.width("000") ) # self.setMarkerBackgroundColor(QColor("#ee1111"), self.ARROW_MARKER_NUM) # Brace matching: enable for a brace immediately before or after # the current position self.setBraceMatching(QsciScintilla.SloppyBraceMatch) # Current line visible with special background color self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#fff9cb")) #55ffff # Custom Lexer # lexer = MyLexer(self) # self.setLexer(lexer) text = bytearray(str.encode("Arial")) # 32, "Courier New" self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, text) # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented # here: http://www.scintilla.org/ScintillaDoc.html) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.setUtf8(True) self.setWhitespaceVisibility(True) self.setWhitespaceForegroundColor(QColor('#e5e5e5')) #'red' blue#EEEEEE self.setWhitespaceSize(2) class myListView(QListView): LDclicked = pyqtSignal( str ) def __init__(self,p): super().__init__() self.iconsize=70 self.setIconSize(QSize(self.iconsize,self.iconsize)) self.setSpacing(1) self.foldadir=None self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.cmenu ) self.loadfolda() def loadfolda(self): # print('kita') model = QStandardItemModel() self.setModel(model) f=os.path.join(os.path.dirname(__file__) , 'txt', '**') self.foldadir=f[:-2] # print(self.foldadir) for i , p in enumerate(glob.iglob(f )): l= os.path.split(p)[1] with open(p,'r',encoding='UTF-8',errors='ignore') as f2: # 指定文字数を読み込む buf=f2.read(35) model.appendRow(QStandardItem(l)) img=QPixmap(self.iconsize,self.iconsize) paint=QPainter() paint.begin(img) paint.setBrush( Qt.white ) paint.setPen( Qt.white ) paint.drawRect(0,0,self.iconsize-1,self.iconsize-1) paint.setPen( Qt.black ) paint.drawRoundedRect(0,0,self.iconsize-1,self.iconsize-1 ,10,10) paint.drawText( QRectF(0,3,self.iconsize-1,self.iconsize-1) , buf) paint.end() model.setData( model.index(i,0) , img , Qt.DecorationRole ) def openfolder(self): subprocess.Popen( ('explorer' , self.foldadir) ) # print(self.foldadir) def browserDclicked(self,index): f=os.path.join(self.foldadir , index.data(Qt.DisplayRole)) self.LDclicked.emit(f) def cmenu (self,e): menu=QMenu(self) action = QAction('DELL', self) action.triggered.connect(self.fileDel) menu.addAction(action) action = QAction('CUT', self) action.triggered.connect(self.fileCut) menu.addAction(action) menu.exec_(QCursor.pos ()) def fileDel(self,index): f=os.path.join(self.foldadir , self.selectedIndexes()[0].data(Qt.DisplayRole)) reply = QMessageBox.question(self, f,"want to DELL ?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: os.remove(f) self.loadfolda() def fileCut(self,index): pass ``` - Scintilla_sql.py ``` import os , sqlite3 , datetime class settingsdb(): def __init__(self): self.db=os.path.join(os.path.dirname(__file__) , 'settings.db') conn = sqlite3.connect(self.db) c = conn.cursor() c.execute('create table IF NOT EXISTS database(path PRIMARY KEY,line,times,date)') c.execute('create table IF NOT EXISTS general(gpos , splpos1 , splpos2)') c.execute('create table IF NOT EXISTS spattern( name , word , replace )') c.close() conn.commit() conn.close() def searchload( self ): # search pattern conn = sqlite3.connect( self.db ) c = conn.cursor() c.execute( 'select * from spattern' ) res=c.fetchall() c.close() conn.close() return res # 結果を全て渡す、タプルのリスト def searchsave( self , lists ): conn = sqlite3.connect( self.db ) c = conn.cursor() c.execute( "INSERT INTO spattern ( name , word , replace ) VALUES (?,?,?)" , lists ) c.close() conn.commit() conn.close() def searchdell( self , key ): conn = sqlite3.connect( self.db ) c = conn.cursor() c.execute( "DELETE FROM spattern WHERE name= ?" , (key,) ) c.close() conn.commit() conn.close() def gload(self): conn = sqlite3.connect(self.db) c = conn.cursor() c.execute('select gpos , splpos1 , splpos2 from general ') res=c.fetchall() c.close() conn.close() if res : return res[0] else: return 0 def gsave(self,lists): conn = sqlite3.connect(self.db) c = conn.cursor() c.execute('DELETE FROM general') c.execute( "INSERT INTO general (gpos , splpos1 , splpos2) VALUES (?,?,?)" ,lists) c.close() conn.commit() conn.close() def save(self,lists): conn = sqlite3.connect(self.db) c = conn.cursor() date="{0:%Y%m%d}".format( datetime.datetime.now() ) times=1 try: c.execute( "INSERT INTO database (path,line,page,times,date) VALUES (?,?,?,?,?)" , ( lists[0] , lists[1] , lists[2] , times,date )) except: c.execute('select times from database where path = ?',(lists[0] , )) times=c.fetchone()[0]+1 c.execute('update database set line= ? , page=? , times=? ,date=? where path = ? ', ( lists[1] ,lists[2] , times, date ,lists[0] ) ) c.close() conn.commit() conn.close() # print(line,times) def load(self,fname): conn = sqlite3.connect(self.db) c = conn.cursor() c.execute('select line ,page from database where path = ?',(fname, )) res=c.fetchone() c.close() conn.close() if res : return res else: return 0 ``` --- ---> [scieditor2](https://mimemo.io/m/zeXgworpjz4K0Ek)