diff --git a/build_ui.sh b/build_ui.sh
index f9351b9..639c88f 100755
--- a/build_ui.sh
+++ b/build_ui.sh
@@ -1,4 +1,8 @@
#!/bin/bash
-/usr/bin/pyuic5 ui/mainwindow.ui > src/nailab/ui_gen/mainwindow.py
+/usr/bin/pyuic5 ui/csvdatasourceconfigwidget.ui > src/nailab/ui_gen/csvdatasourceconfigwidget.py
+/usr/bin/pyuic5 ui/mainwindow.ui > src/nailab/ui_gen/mainwindow.py.py
+/usr/bin/pyuic5 ui/newdatasourcedialog.ui > src/nailab/ui_gen/newdatasourcedialog.py
/usr/bin/pyuic5 ui/strategywidget.ui > src/nailab/ui_gen/strategywidget.py
+
+
diff --git a/src/nailab/data/csvfolderdatasource.py b/src/nailab/data/csvfolderdatasource.py
index d458eb8..a11e0de 100644
--- a/src/nailab/data/csvfolderdatasource.py
+++ b/src/nailab/data/csvfolderdatasource.py
@@ -11,10 +11,19 @@ class CsvFolderDataSource(DataSource):
def __init__(self, name, path):
super().__init__(name)
+ self.type = "csv"
+
self.path = path
self.feeds = []
self._discover_feeds()
+ @classmethod
+ def deserialize(self, data):
+ return CsvFolderDataSource(data[0], data[1])
+
+ def serialize(self):
+ return (self.name, self.path)
+
def available_feeds(self):
return [f[1] for f in self.feeds]
diff --git a/src/nailab/data/datasourcemanager.py b/src/nailab/data/datasourcemanager.py
index 8e26855..6d4819f 100644
--- a/src/nailab/data/datasourcemanager.py
+++ b/src/nailab/data/datasourcemanager.py
@@ -6,11 +6,19 @@ class DataSourceManager:
def __init__(self):
self.sources = []
- def save_sources(self):
- pass
+ def save_sources(self, settings):
+ serialized = []
+ for source in self.sources:
+ serialized.append((source.type, source.serialize()))
+ settings.setValue("data_sources", serialized)
- def load_sources(self):
- self.add_source(CsvFolderDataSource('default', '/tmp'))
+ def load_sources(self, settings):
+ self.sources = []
+ serialized = settings.value("data_sources")
+ if serialized is not None:
+ for s in serialized:
+ if s[0] == "csv":
+ self.add_source(CsvFolderDataSource.deserialize(s[1]))
def add_source(self, source):
self.sources.append(source)
@@ -21,6 +29,12 @@ class DataSourceManager:
return source
return None
+ def remove_source(self, name):
+ for source in self.sources:
+ if source.name == name:
+ self.sources.remove(source)
+ return
+
def all_sources(self):
return self.sources[:]
diff --git a/src/nailab/ui/csvdatasourceconfigwidget.py b/src/nailab/ui/csvdatasourceconfigwidget.py
new file mode 100644
index 0000000..1ed91a8
--- /dev/null
+++ b/src/nailab/ui/csvdatasourceconfigwidget.py
@@ -0,0 +1,19 @@
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.Qsci import *
+
+from ui_gen.csvdatasourceconfigwidget import Ui_CSVDataSourceConfigWidget
+
+class CSVDataSourceConfigWidget(QtWidgets.QWidget):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.ui = Ui_CSVDataSourceConfigWidget()
+ self.ui.setupUi(self)
+
+ def browse(self):
+ dirname = QtWidgets.QFileDialog.getExistingDirectory(self, self.tr("Select a directory..."), "", QtWidgets.QFileDialog.ShowDirsOnly)
+ if dirname != "":
+ self.ui.e_path.setText(dirname)
+
diff --git a/src/nailab/ui/mainwindow.py b/src/nailab/ui/mainwindow.py
index ee2b6f3..989fb06 100644
--- a/src/nailab/ui/mainwindow.py
+++ b/src/nailab/ui/mainwindow.py
@@ -23,7 +23,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.sources = []
self.datasourcemanager = DataSourceManager()
- self.datasourcemanager.load_sources()
+ self.datasourcemanager.load_sources(QtCore.QSettings())
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
@@ -62,16 +62,15 @@ class MainWindow(QtWidgets.QMainWindow):
try:
selected_feeds.append(self.datasourcemanager.get_source(source_id).get_feed(feed_id))
except e:
- print('Error: ' + str(e))
+ self.ui.tabs.currentWidget().setError("Error: " + str(e))
try:
result = executor.execute_from_file(source_file, selected_feeds, self.ui.tabs.currentWidget().get_time_window())
print(result)
self.ui.tabs.currentWidget().set_result(result)
except Exception as e:
- print(e)
+ self.ui.tabs.currentWidget().setError(str(e))
-
def tabCloseRequested(self, tab_index):
del self.sources[tab_index]
self.ui.tabs.widget(tab_index).save_state()
diff --git a/src/nailab/ui/newdatasourcedialog.py b/src/nailab/ui/newdatasourcedialog.py
new file mode 100644
index 0000000..d55ad2e
--- /dev/null
+++ b/src/nailab/ui/newdatasourcedialog.py
@@ -0,0 +1,24 @@
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.Qsci import *
+
+from ui_gen.newdatasourcedialog import Ui_NewDataSourceDialog
+from ui.csvdatasourceconfigwidget import CSVDataSourceConfigWidget
+
+from data.csvfolderdatasource import CsvFolderDataSource
+
+class NewDataSourceDialog(QtWidgets.QDialog):
+
+ def __init__(self, parent):
+ super().__init__(parent)
+
+ self.ui = Ui_NewDataSourceDialog()
+ self.ui.setupUi(self)
+
+ index = self.ui.widgets.addWidget(CSVDataSourceConfigWidget())
+ self.ui.widgets.setCurrentIndex(index)
+
+ def get_data_source(self):
+ return CsvFolderDataSource(self.ui.e_sourceName.text(), self.ui.widgets.currentWidget().ui.e_path.text())
+
+
diff --git a/src/nailab/ui/strategywidget.py b/src/nailab/ui/strategywidget.py
index 97b7b95..bcb4e12 100644
--- a/src/nailab/ui/strategywidget.py
+++ b/src/nailab/ui/strategywidget.py
@@ -4,6 +4,8 @@ from PyQt5.Qsci import *
from ui_gen.strategywidget import Ui_StrategyWidget
+from ui.newdatasourcedialog import NewDataSourceDialog
+
ROLE_FEED_ID = QtCore.Qt.UserRole + 1
class StrategyWidget(QtWidgets.QWidget):
@@ -16,7 +18,10 @@ class StrategyWidget(QtWidgets.QWidget):
self.source_file = source_file
+ s = QtCore.QSettings()
+
self.datasourcemanager = datasourcemanager
+ self.datasourcemanager.load_sources(s)
self.update_feeds_list()
self.ui.splitter.setSizes([20, 80])
@@ -37,20 +42,49 @@ class StrategyWidget(QtWidgets.QWidget):
self.result = []
self.result_widget = None
- s = QtCore.QSettings()
- if s.value("time_window") is not None:
- (from_time, to_time) = s.value("time_window")
- self.ui.rb_timeWindow.setChecked(True)
- self.ui.dte_from.setDateTime(from_time)
- self.ui.dte_to.setDateTime(to_time)
+ try:
+ if s.value("time_window") is not None:
+ (from_time, to_time) = s.value("time_window")
+ self.ui.rb_timeWindow.setChecked(True)
+ self.ui.dte_from.setDateTime(from_time)
+ self.ui.dte_to.setDateTime(to_time)
+
+ self.ui.splitter.restoreState(s.value("strategy_widget_splitter_state"))
+ self.ui.splitter_editor.restoreState(s.value("strategy_widget_splitter_editor_state"))
+
+ except Exception as e:
+ print("Exception: ", e)
+
+ def addDataSource(self):
+ dlg = NewDataSourceDialog(self)
+ if dlg.exec() == QtWidgets.QDialog.Accepted:
+ self.datasourcemanager.add_source(dlg.get_data_source())
+ self.update_feeds_list()
+
+ def deleteDataSource(self):
+ selected = self.ui.tw_feeds.selectedItems()
+ for s in selected:
+ if self.ui.tw_feeds.indexOfTopLevelItem(s) >= 0:
+ name = s.data(0, ROLE_FEED_ID)
+ if name is not None:
+ self.datasourcemanager.remove_source(name[0])
+ self.update_feeds_list()
+
+ def refreshDataSources(self):
+ self.update_feeds_list()
def save_state(self):
s = QtCore.QSettings()
+ self.datasourcemanager.save_sources(s)
if self.ui.rb_allData.isChecked():
s.setValue("time_window", None)
else:
s.setValue("time_window", (self.ui.dte_from.dateTime(), self.ui.dte_to.dateTime()))
+ s.setValue("strategy_widget_splitter_state", self.ui.splitter.saveState())
+ s.setValue("strategy_widget_splitter_editor_state", self.ui.splitter_editor.saveState())
+
+
def save(self):
with open(self.source_file, "w") as f:
f.write(self.ui.editor.text())
@@ -62,11 +96,12 @@ class StrategyWidget(QtWidgets.QWidget):
return (self.ui.dte_from.dateTime(), self.ui.dte_to.dateTime())
def update_feeds_list(self):
+ self.ui.tw_feeds.clear()
sources = self.datasourcemanager.all_sources()
for source in sources:
src_item = QtWidgets.QTreeWidgetItem(self.ui.tw_feeds)
src_item.setText(0, source.name)
- src_item.setData(0, ROLE_FEED_ID, "")
+ src_item.setData(0, ROLE_FEED_ID, (source.name, ""))
for feed in source.available_feeds():
feed_item = QtWidgets.QTreeWidgetItem(src_item)
feed_item.setText(0, feed)
@@ -155,6 +190,7 @@ class StrategyWidget(QtWidgets.QWidget):
self.result_widget.resizeColumnToContents(0)
-
-
+ def setError(self, errmsg):
+ self.ui.te_notes.clear()
+ self.ui.te_notes.appendPlainText(errmsg)
diff --git a/src/nailab/ui_gen/csvdatasourceconfigwidget.py b/src/nailab/ui_gen/csvdatasourceconfigwidget.py
new file mode 100644
index 0000000..940fac6
--- /dev/null
+++ b/src/nailab/ui_gen/csvdatasourceconfigwidget.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'ui/csvdatasourceconfigwidget.ui'
+#
+# Created by: PyQt5 UI code generator 5.5.1
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_CSVDataSourceConfigWidget(object):
+ def setupUi(self, CSVDataSourceConfigWidget):
+ CSVDataSourceConfigWidget.setObjectName("CSVDataSourceConfigWidget")
+ CSVDataSourceConfigWidget.resize(529, 313)
+ self.gridLayout = QtWidgets.QGridLayout(CSVDataSourceConfigWidget)
+ self.gridLayout.setObjectName("gridLayout")
+ self.label = QtWidgets.QLabel(CSVDataSourceConfigWidget)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
+ self.e_path = QtWidgets.QLineEdit(CSVDataSourceConfigWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.e_path.sizePolicy().hasHeightForWidth())
+ self.e_path.setSizePolicy(sizePolicy)
+ self.e_path.setObjectName("e_path")
+ self.gridLayout.addWidget(self.e_path, 0, 1, 1, 1)
+ self.b_browse = QtWidgets.QPushButton(CSVDataSourceConfigWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.b_browse.sizePolicy().hasHeightForWidth())
+ self.b_browse.setSizePolicy(sizePolicy)
+ self.b_browse.setObjectName("b_browse")
+ self.gridLayout.addWidget(self.b_browse, 0, 2, 1, 1)
+ spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.gridLayout.addItem(spacerItem, 1, 0, 1, 1)
+
+ self.retranslateUi(CSVDataSourceConfigWidget)
+ self.b_browse.clicked.connect(CSVDataSourceConfigWidget.browse)
+ QtCore.QMetaObject.connectSlotsByName(CSVDataSourceConfigWidget)
+
+ def retranslateUi(self, CSVDataSourceConfigWidget):
+ _translate = QtCore.QCoreApplication.translate
+ CSVDataSourceConfigWidget.setWindowTitle(_translate("CSVDataSourceConfigWidget", "Form"))
+ self.label.setText(_translate("CSVDataSourceConfigWidget", "CSV folder path"))
+ self.b_browse.setText(_translate("CSVDataSourceConfigWidget", "..."))
+
diff --git a/src/nailab/ui_gen/mainwindow.py.py b/src/nailab/ui_gen/mainwindow.py.py
new file mode 100644
index 0000000..3f05536
--- /dev/null
+++ b/src/nailab/ui_gen/mainwindow.py.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'ui/mainwindow.ui'
+#
+# Created by: PyQt5 UI code generator 5.5.1
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(1060, 587)
+ self.centralwidget = QtWidgets.QWidget(MainWindow)
+ self.centralwidget.setObjectName("centralwidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
+ self.gridLayout.setContentsMargins(3, 3, 3, 3)
+ self.gridLayout.setObjectName("gridLayout")
+ self.tabs = QtWidgets.QTabWidget(self.centralwidget)
+ self.tabs.setTabsClosable(True)
+ self.tabs.setObjectName("tabs")
+ self.gridLayout.addWidget(self.tabs, 0, 0, 1, 1)
+ MainWindow.setCentralWidget(self.centralwidget)
+ self.menubar = QtWidgets.QMenuBar(MainWindow)
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 1060, 19))
+ self.menubar.setObjectName("menubar")
+ self.menuFile = QtWidgets.QMenu(self.menubar)
+ self.menuFile.setObjectName("menuFile")
+ self.menuBacktest = QtWidgets.QMenu(self.menubar)
+ self.menuBacktest.setObjectName("menuBacktest")
+ MainWindow.setMenuBar(self.menubar)
+ self.statusbar = QtWidgets.QStatusBar(MainWindow)
+ self.statusbar.setObjectName("statusbar")
+ MainWindow.setStatusBar(self.statusbar)
+ self.toolBar = QtWidgets.QToolBar(MainWindow)
+ self.toolBar.setObjectName("toolBar")
+ MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
+ self.actionOpenTrades = QtWidgets.QAction(MainWindow)
+ self.actionOpenTrades.setObjectName("actionOpenTrades")
+ self.actionNew_strategy = QtWidgets.QAction(MainWindow)
+ self.actionNew_strategy.setObjectName("actionNew_strategy")
+ self.actionOpen_strategy = QtWidgets.QAction(MainWindow)
+ self.actionOpen_strategy.setObjectName("actionOpen_strategy")
+ self.actionExecute = QtWidgets.QAction(MainWindow)
+ self.actionExecute.setObjectName("actionExecute")
+ self.actionSave_strategy = QtWidgets.QAction(MainWindow)
+ self.actionSave_strategy.setObjectName("actionSave_strategy")
+ self.menuFile.addAction(self.actionNew_strategy)
+ self.menuFile.addAction(self.actionOpen_strategy)
+ self.menuBacktest.addAction(self.actionExecute)
+ self.menubar.addAction(self.menuFile.menuAction())
+ self.menubar.addAction(self.menuBacktest.menuAction())
+ self.toolBar.addAction(self.actionSave_strategy)
+ self.toolBar.addAction(self.actionExecute)
+
+ self.retranslateUi(MainWindow)
+ self.tabs.setCurrentIndex(-1)
+ self.actionOpen_strategy.triggered.connect(MainWindow.openStrategy)
+ self.tabs.tabCloseRequested['int'].connect(MainWindow.tabCloseRequested)
+ self.actionNew_strategy.triggered.connect(MainWindow.newStrategy)
+ self.actionExecute.triggered.connect(MainWindow.executeStrategy)
+ self.actionSave_strategy.triggered.connect(MainWindow.saveStrategy)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "Nailab"))
+ self.menuFile.setTitle(_translate("MainWindow", "File"))
+ self.menuBacktest.setTitle(_translate("MainWindow", "Backtest"))
+ self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
+ self.actionOpenTrades.setText(_translate("MainWindow", "Open..."))
+ self.actionNew_strategy.setText(_translate("MainWindow", "New strategy"))
+ self.actionOpen_strategy.setText(_translate("MainWindow", "Open strategy"))
+ self.actionExecute.setText(_translate("MainWindow", "Execute"))
+ self.actionSave_strategy.setText(_translate("MainWindow", "Save strategy"))
+
diff --git a/src/nailab/ui_gen/newdatasourcedialog.py b/src/nailab/ui_gen/newdatasourcedialog.py
new file mode 100644
index 0000000..15e714a
--- /dev/null
+++ b/src/nailab/ui_gen/newdatasourcedialog.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'ui/newdatasourcedialog.ui'
+#
+# Created by: PyQt5 UI code generator 5.5.1
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_NewDataSourceDialog(object):
+ def setupUi(self, NewDataSourceDialog):
+ NewDataSourceDialog.setObjectName("NewDataSourceDialog")
+ NewDataSourceDialog.resize(786, 334)
+ self.gridLayout = QtWidgets.QGridLayout(NewDataSourceDialog)
+ self.gridLayout.setObjectName("gridLayout")
+ self.widgets = QtWidgets.QStackedWidget(NewDataSourceDialog)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.widgets.sizePolicy().hasHeightForWidth())
+ self.widgets.setSizePolicy(sizePolicy)
+ self.widgets.setObjectName("widgets")
+ self.gridLayout.addWidget(self.widgets, 3, 0, 1, 2)
+ self.e_sourceName = QtWidgets.QLineEdit(NewDataSourceDialog)
+ self.e_sourceName.setObjectName("e_sourceName")
+ self.gridLayout.addWidget(self.e_sourceName, 0, 1, 1, 1)
+ self.label = QtWidgets.QLabel(NewDataSourceDialog)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
+ self.cb_sourceType = QtWidgets.QComboBox(NewDataSourceDialog)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.cb_sourceType.sizePolicy().hasHeightForWidth())
+ self.cb_sourceType.setSizePolicy(sizePolicy)
+ self.cb_sourceType.setObjectName("cb_sourceType")
+ self.cb_sourceType.addItem("")
+ self.gridLayout.addWidget(self.cb_sourceType, 1, 1, 1, 1)
+ self.label_2 = QtWidgets.QLabel(NewDataSourceDialog)
+ self.label_2.setObjectName("label_2")
+ self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1)
+ self.buttonBox = QtWidgets.QDialogButtonBox(NewDataSourceDialog)
+ self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
+ self.buttonBox.setObjectName("buttonBox")
+ self.gridLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
+
+ self.retranslateUi(NewDataSourceDialog)
+ self.widgets.setCurrentIndex(-1)
+ self.buttonBox.accepted.connect(NewDataSourceDialog.accept)
+ self.buttonBox.rejected.connect(NewDataSourceDialog.reject)
+ QtCore.QMetaObject.connectSlotsByName(NewDataSourceDialog)
+
+ def retranslateUi(self, NewDataSourceDialog):
+ _translate = QtCore.QCoreApplication.translate
+ NewDataSourceDialog.setWindowTitle(_translate("NewDataSourceDialog", "New data source"))
+ self.label.setText(_translate("NewDataSourceDialog", "Data source type"))
+ self.cb_sourceType.setItemText(0, _translate("NewDataSourceDialog", "CSV"))
+ self.label_2.setText(_translate("NewDataSourceDialog", "Data source name"))
+
diff --git a/src/nailab/ui_gen/strategywidget.py b/src/nailab/ui_gen/strategywidget.py
index 2827d40..7125cd7 100644
--- a/src/nailab/ui_gen/strategywidget.py
+++ b/src/nailab/ui_gen/strategywidget.py
@@ -29,6 +29,22 @@ class Ui_StrategyWidget(object):
self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget)
self.gridLayout_2.setObjectName("gridLayout_2")
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.b_addSource = QtWidgets.QPushButton(self.gridLayoutWidget)
+ self.b_addSource.setObjectName("b_addSource")
+ self.horizontalLayout.addWidget(self.b_addSource)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.b_refresh = QtWidgets.QPushButton(self.gridLayoutWidget)
+ self.b_refresh.setObjectName("b_refresh")
+ self.horizontalLayout.addWidget(self.b_refresh)
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem1)
+ self.b_deleteSource = QtWidgets.QPushButton(self.gridLayoutWidget)
+ self.b_deleteSource.setObjectName("b_deleteSource")
+ self.horizontalLayout.addWidget(self.b_deleteSource)
+ self.gridLayout_2.addLayout(self.horizontalLayout, 5, 0, 1, 2)
self.dte_to = QtWidgets.QDateTimeEdit(self.gridLayoutWidget)
self.dte_to.setObjectName("dte_to")
self.gridLayout_2.addWidget(self.dte_to, 3, 1, 1, 1)
@@ -48,6 +64,7 @@ class Ui_StrategyWidget(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tw_feeds.sizePolicy().hasHeightForWidth())
self.tw_feeds.setSizePolicy(sizePolicy)
+ self.tw_feeds.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tw_feeds.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.tw_feeds.setHeaderHidden(True)
self.tw_feeds.setObjectName("tw_feeds")
@@ -64,7 +81,10 @@ class Ui_StrategyWidget(object):
self.rb_timeWindow = QtWidgets.QRadioButton(self.gridLayoutWidget)
self.rb_timeWindow.setObjectName("rb_timeWindow")
self.gridLayout_2.addWidget(self.rb_timeWindow, 1, 0, 1, 2)
- self.editor = Qsci.QsciScintilla(self.splitter)
+ self.splitter_editor = QtWidgets.QSplitter(self.splitter)
+ self.splitter_editor.setOrientation(QtCore.Qt.Vertical)
+ self.splitter_editor.setObjectName("splitter_editor")
+ self.editor = Qsci.QsciScintilla(self.splitter_editor)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -72,17 +92,25 @@ class Ui_StrategyWidget(object):
self.editor.setSizePolicy(sizePolicy)
self.editor.setMinimumSize(QtCore.QSize(300, 0))
self.editor.setObjectName("editor")
+ self.te_notes = QtWidgets.QPlainTextEdit(self.splitter_editor)
+ self.te_notes.setObjectName("te_notes")
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
self.tabs.addTab(self.tab, "")
self.gridLayout_3.addWidget(self.tabs, 0, 0, 1, 1)
self.retranslateUi(StrategyWidget)
self.tabs.setCurrentIndex(0)
+ self.b_addSource.clicked.connect(StrategyWidget.addDataSource)
+ self.b_deleteSource.clicked.connect(StrategyWidget.deleteDataSource)
+ self.b_refresh.clicked.connect(StrategyWidget.refreshDataSources)
QtCore.QMetaObject.connectSlotsByName(StrategyWidget)
def retranslateUi(self, StrategyWidget):
_translate = QtCore.QCoreApplication.translate
StrategyWidget.setWindowTitle(_translate("StrategyWidget", "Form"))
+ self.b_addSource.setText(_translate("StrategyWidget", "Add source"))
+ self.b_refresh.setText(_translate("StrategyWidget", "Refresh"))
+ self.b_deleteSource.setText(_translate("StrategyWidget", "Delete source"))
self.dte_to.setDisplayFormat(_translate("StrategyWidget", "dd.MM.yyyy H:mm"))
self.dte_from.setDisplayFormat(_translate("StrategyWidget", "dd.MM.yyyy H:mm"))
self.label_2.setText(_translate("StrategyWidget", "To"))
diff --git a/ui/csvdatasourceconfigwidget.ui b/ui/csvdatasourceconfigwidget.ui
new file mode 100644
index 0000000..7aed141
--- /dev/null
+++ b/ui/csvdatasourceconfigwidget.ui
@@ -0,0 +1,84 @@
+
+
+ CSVDataSourceConfigWidget
+
+
+
+ 0
+ 0
+ 529
+ 313
+
+
+
+ Form
+
+
+ -
+
+
+ CSV folder path
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ ...
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+ b_browse
+ clicked()
+ CSVDataSourceConfigWidget
+ browse()
+
+
+ 482
+ 27
+
+
+ 494
+ 47
+
+
+
+
+
+ browse()
+
+
diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui
index 992b9c5..4973fc1 100644
--- a/ui/mainwindow.ui
+++ b/ui/mainwindow.ui
@@ -45,7 +45,7 @@
0
0
1060
- 23
+ 19