class ParamSlider(QWidget): valueChanged = Signal(int) def __init__(self, interval, ticks=10, reset=0, suffix=None, label=None, bold=False, parent=None): super(ParamSlider, self).__init__(parent) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(interval[0], interval[1]) self.slider.setTickPosition(QSlider.TicksBelow) self.slider.setTickInterval((interval[1] - interval[0] + 1) / ticks) self.slider.setSingleStep(1) self.slider.setPageStep(1) self.slider.setValue(reset) self.slider.mouseDoubleClickEvent = self.doubleClicked self.spin = QSpinBox() self.spin.setRange(interval[0], interval[1]) self.spin.setValue(reset) self.spin.setSuffix(suffix) self.spin.setFixedWidth(50) self.reset = reset self.slider.valueChanged.connect(self.spin.setValue) self.spin.valueChanged.connect(self.slider.setValue) self.slider.valueChanged.connect(self.valueChanged) layout = QHBoxLayout() if label is not None: lab = QLabel(label) modify_font(lab, bold=bold) layout.addWidget(lab) layout.addWidget(self.slider) layout.addWidget(self.spin) self.setLayout(layout) self.setMaximumWidth(200) def doubleClicked(self, _): self.slider.setValue(self.reset) self.spin.setValue(self.reset) def value(self): return self.slider.value() def setValue(self, value): self.spin.setValue(value) self.slider.setValue(value) self.valueChanged.emit(value) def sync(self): self.spin.setValue(self.slider.value()) self.slider.setValue(self.spin.value()) self.valueChanged.emit(self.slider.value())
def get_widget_from_ranking(ranking): assert isinstance(ranking, RankingItem) qual = ranking.qual.name qual_checkbox = QCheckBox(ranking.qual.get_title()) qual_checkbox.setFixedWidth(50) qual_checkbox.setObjectName(qual + '_checkbox') type_combo = AdvComboBox() type_combo.addItems([_('Rank'), _('Max place'), _('Result time')]) type_combo.setFixedWidth(150) type_combo.setObjectName(qual + '_combo') max_place = QSpinBox() max_place.setValue(0) max_place.setFixedWidth(70) max_place.setObjectName(qual + '_place') max_time = QTimeEdit() max_time.setFixedWidth(70) max_time.setDisplayFormat("hh:mm:ss") max_time.setObjectName(qual + '_time') def select_type(): text = type_combo.currentText() max_place.setVisible(text == _('Max place')) max_time.setVisible(text == _('Result time')) def set_enabled(): flag = qual_checkbox.isChecked() type_combo.setEnabled(flag) max_place.setEnabled(flag) max_time.setEnabled(flag) type_combo.currentIndexChanged.connect(select_type) qual_checkbox.stateChanged.connect(set_enabled) if ranking.use_scores: type_combo.setCurrentText(_('Rank')) elif ranking.max_place: type_combo.setCurrentText(_('Max place')) max_place.setValue(ranking.max_place) else: type_combo.setCurrentText(_('Result time')) max_time.setTime(time_to_qtime(ranking.max_time)) qual_checkbox.setChecked(ranking.is_active) select_type() set_enabled() layout = QHBoxLayout() layout.addWidget(qual_checkbox) layout.addWidget(type_combo) layout.addWidget(max_place) layout.addWidget(max_time) return layout
class Code(QWidget): TRIAL_STATUS = ('on', 'off') def __init__(self, callback): super().__init__() self.callback = callback trial_label = QLabel('Trial:') self.trial_box = QSpinBox() self.trial_box.setFixedWidth(64) self.trial_box.setValue(1) #self.trial_box.setFocusPolicy(Qt.NoFocus) trial_status_label = QLabel('Trial Status:') self.trial_status = QComboBox() self.trial_status.addItems(self.TRIAL_STATUS) self.trial_status.setFocusPolicy(Qt.NoFocus) response_label = QLabel('Response:') self.response_box = QComboBox() self.response_box.setFocusPolicy(Qt.NoFocus) self.record_button = QPushButton('Record Event') self.record_button.clicked.connect(self.record_event) self.record_button.setEnabled(False) self.record_button.setFocusPolicy(Qt.NoFocus) layout = QHBoxLayout() layout.addWidget(trial_label) layout.addWidget(self.trial_box) layout.addWidget(trial_status_label) layout.addWidget(self.trial_status) layout.addWidget(response_label) layout.addWidget(self.response_box) layout.addStretch() layout.addWidget(self.record_button) self.setLayout(layout) def set_responses(self, responses): self.response_box.clear() self.response_box.addItems(responses) def record_event(self): event = Event(trial=self.trial_box.value(), status=self.trial_status.currentText() == 'on', response=self.response_box.currentText()) if self.trial_status.currentText() == 'off': self.trial_box.setValue(self.trial_box.value() + 1) self.trial_status.setCurrentText('on') self.callback(event)
class CoordinateWidget(QWidget, PropertyWidget): position_changed = Signal(int, int) def __init__(self, target_property_name): QWidget.__init__(self) PropertyWidget.__init__(self, target_property_name) self.layout = QHBoxLayout() self.x_spinbox = QSpinBox() self.y_spinbox = QSpinBox() self.x_spinbox.setRange(-128, 127) self.y_spinbox.setRange(-128, 127) self.x_spinbox.setFixedWidth(60) self.y_spinbox.setFixedWidth(60) self.layout.addWidget(self.x_spinbox) self.layout.addWidget(self.y_spinbox) self.layout.setAlignment(QtGui.Qt.AlignLeft) self.setLayout(self.layout) self.x_spinbox.valueChanged.connect(lambda v: self._on_edit(v, 0)) self.y_spinbox.valueChanged.connect(lambda v: self._on_edit(v, 1)) self.is_disable_write_back = False def _on_edit(self, value, index): if self.target: buffer = self.target[self.target_property_name].value if buffer[index] != value: if not self.is_disable_write_back: buffer[index] = self._signed_to_unsigned(value) self.position_changed.emit(self.x_spinbox.value(), self.y_spinbox.value()) def _on_target_changed(self): if self.target: buffer = self.target[self.target_property_name].value self.x_spinbox.setValue(self._unsigned_to_signed(buffer[0])) self.y_spinbox.setValue(self._unsigned_to_signed(buffer[1])) else: self.x_spinbox.setValue(0) self.y_spinbox.setValue(0) @staticmethod def _unsigned_to_signed(value): packed = ctypes.c_byte(value) return packed.value @staticmethod def _signed_to_unsigned(value): packed = ctypes.c_ubyte(value) return packed.value def set_disable_write_back(self, is_disabled: bool): self.is_disable_write_back = is_disabled
class CountLayout(QHBoxLayout): """Field with a QSpinBox""" def __init__(self, field, parent=None): QHBoxLayout.__init__(self) self.field = field self.count = QSpinBox() self.count.setFixedWidth(45) self.addWidget(self.field) self.addWidget(self.count) def text(self): return self.field.text() def currentIndex(self): return self.field.currentIndex() def n(self): return self.count.value() def setStyleSheet(self, style): self.field.setStyleSheet(style) self.count.setStyleSheet(style)
class App(QMainWindow): def __init__(self): super().__init__() self.init_ui() self.attach_event() self.setAcceptDrops(True) def init_ui(self): # Define & Configure Components normal_button_size = QSize(80, 24) icon_button_size = QSize(24, 24) icon_size = QSize(18, 18) self.central_widget = QWidget() self.central_layout = QGridLayout() self.central_widget.setLayout(self.central_layout) self.tab_group_widget = QTabWidget() self.tab_group_widget.setMinimumSize(400, 0) self.tab_group_widget.setFixedHeight(150) self.tab1_name = '스폰서 변환' self.tab2_name = '싱크 조절(초)' self.tab3_name = '싱크 조절(%)' self.tab_page_1 = QWidget() self.tab_grid_1 = QGridLayout() self.tab1_search_label = QLabel('검색 텍스트') self.tab1_search = QLineEdit() self.tab1_sponsor = QWidget() self.tab1_sponsor_layout = QHBoxLayout() self.tab1_sponsor_layout.setContentsMargins(0, 0, 0, 0) self.tab1_sponsor_label = QLabel('스폰서 영상 길이') self.tab1_sponsor_value = QDoubleSpinBox() self.tab1_sponsor_value.setFixedWidth(60) self.tab1_sponsor_value.setMinimum(-1000000000) self.tab1_sponsor_value.setValue(10) self.tab1_offset = QWidget() self.tab1_offset_layout = QHBoxLayout() self.tab1_offset_layout.setContentsMargins(0, 0, 0, 0) self.tab1_offset_label = QLabel('라인 오프셋') self.tab1_offset_value = QSpinBox() self.tab1_offset_value.setMinimum(-1000000000) self.tab1_offset_value.setValue(2) self.tab1_offset_value.setFixedWidth(50) self.tab1_ignore = QWidget() self.tab1_ignore_layout = QHBoxLayout() self.tab1_ignore_layout.setContentsMargins(0, 0, 0, 0) self.tab1_ignore_label1 = QLabel('시작부터') self.tab1_ignore_value = QSpinBox() self.tab1_ignore_value.setFixedWidth(50) self.tab1_ignore_value.setValue(5) self.tab1_ignore_label2 = QLabel('줄 ') self.tab1_ignore_sec = QSpinBox() self.tab1_ignore_sec.setFixedWidth(60) self.tab1_ignore_sec.setMaximum(1000) self.tab1_ignore_sec.setValue(90) self.tab1_ignore_label3 = QLabel('초 무시하기') self.tab1_add_button = QPushButton('추가하기') self.tab_page_2 = QWidget() self.tab_grid_2 = QGridLayout() self.tab2_shift = QWidget() self.tab2_shift_layout = QHBoxLayout() self.tab2_shift_layout.setContentsMargins(0, 0, 0, 0) self.tab2_shift_label1 = QLabel('자막 싱크') self.tab2_shift_value = QDoubleSpinBox() self.tab2_shift_value.setFixedWidth(60) self.tab2_shift_label2 = QLabel('초 ') self.tab2_slow_radio = QRadioButton('느리게') self.tab2_slow_radio.setChecked(True) self.tab2_fast_radio = QRadioButton('빠르게') self.tab2_add_button = QPushButton('추가하기') self.tab_page_3 = QWidget() self.tab_grid_3 = QGridLayout() self.tab3_speed_label1 = QLabel('자막 싱크') self.tab3_speed_value = QSpinBox() self.tab3_speed_value.setFixedWidth(70) self.tab3_speed_value.setRange(1, 1000) self.tab3_speed_value.setValue(100) self.tab3_speed_label2 = QLabel('%') self.tab3_add_button = QPushButton('추가하기') self.que_label = QLabel('작업 목록') self.que_label.setFixedHeight(24) self.que_widget = QWidget() self.que_widget.setFixedHeight(114) self.que_layout = QGridLayout() self.que_layout.setContentsMargins(0, 0, 0, 0) self.que_list = QTreeWidget() self.que_list.setHeaderLabels(['작업', '옵션']) self.que_delete_button = QPushButton(QIcon(':/remove.png'), '') self.que_delete_button.setFixedSize(icon_button_size) self.que_delete_button.setIconSize(icon_size) self.que_delete_button.setToolTip('목록 삭제') self.que_up_button = QPushButton(QIcon(':/up.png'), '') self.que_up_button.setIconSize(icon_size) self.que_up_button.setFixedSize(icon_button_size) self.que_up_button.setToolTip('위로') self.que_down_button = QPushButton(QIcon(':/down.png'), '') self.que_down_button.setIconSize(icon_size) self.que_down_button.setFixedSize(icon_button_size) self.que_down_button.setToolTip('아래로') self.que_clear_button = QPushButton(QIcon(':/clear.png'), '') self.que_clear_button.setIconSize(icon_size) self.que_clear_button.setFixedSize(icon_button_size) self.que_clear_button.setToolTip('비우기') self.file_label = QLabel('파일 목록') self.file_label.setFixedHeight(24) self.file_widget = QWidget() self.file_layout = QGridLayout() self.file_layout.setContentsMargins(0, 0, 0, 0) self.file_list = QTreeWidget() self.file_list.setAcceptDrops(True) self.file_list.setHeaderLabels(['이름', '경로']) self.file_file_open = QPushButton(QIcon(':/file.png'), '') self.file_file_open.setFixedSize(icon_button_size) self.file_file_open.setIconSize(icon_size) self.file_file_open.setToolTip('파일 열기') self.file_dir_open = QPushButton(QIcon(':/folder.png'), '') self.file_dir_open.setFixedSize(icon_button_size) self.file_dir_open.setIconSize(icon_size) self.file_dir_open.setToolTip('폴더 열기') self.file_delete = QPushButton(QIcon(':/remove.png'), '') self.file_delete.setFixedSize(icon_button_size) self.file_delete.setIconSize(icon_size) self.file_delete.setToolTip('목록 삭제') self.file_clear = QPushButton(QIcon(':/clear.png'), '') self.file_clear.setFixedSize(icon_button_size) self.file_clear.setIconSize(icon_size) self.file_clear.setToolTip('비우기') self.file_encode = QPushButton(QIcon(':/encode.png'), '') self.file_encode.setFixedSize(icon_button_size) self.file_encode.setIconSize(icon_size) self.file_encode.setToolTip('인코딩 설정') self.save_widget = QGroupBox('저장 옵션') self.save_widget.setMinimumSize(400, 0) self.save_widget.setFixedHeight(82) self.save_layout = QGridLayout() self.save_orig_radio = QRadioButton('원본 위치에 저장') self.save_orig_radio.setChecked(True) self.save_strip = QCheckBox('싱크 꼬임 무시') self.save_strip.setToolTip('싱크 꼬임을 무시하고 모든 자막을 보존합니다.') self.save_dir_radio = QRadioButton('다른 위치에 저장') self.save_dir_line = QLineEdit() self.save_dir_find = QPushButton('...') self.save_dir_find.setFixedWidth(40) self.ok_button = QPushButton('적용') self.ok_button.setFixedSize(normal_button_size) self.cancel_button = QPushButton('취소') self.cancel_button.setFixedSize(normal_button_size) # Display GUI Components self.central_layout.addWidget(self.tab_group_widget, 0, 0, 1, 3) self.central_layout.addWidget(self.que_label, 1, 0, 1, 3) self.central_layout.addWidget(self.que_widget, 2, 0, 1, 3) self.central_layout.addWidget(self.file_label, 3, 0, 1, 3) self.central_layout.addWidget(self.file_widget, 4, 0, 1, 3) self.central_layout.addWidget(self.save_widget, 5, 0, 1, 3) self.central_layout.addWidget(self.ok_button, 6, 1, 1, 1) self.central_layout.addWidget(self.cancel_button, 6, 2, 1, 1) self.tab_group_widget.addTab(self.tab_page_1, QIcon(), self.tab1_name) self.tab_group_widget.addTab(self.tab_page_2, QIcon(), self.tab2_name) self.tab_group_widget.addTab(self.tab_page_3, QIcon(), self.tab3_name) self.tab_page_1.setLayout(self.tab_grid_1) self.tab_grid_1.addWidget(self.tab1_search_label, 0, 0, 1, 1) self.tab_grid_1.addWidget(self.tab1_search, 0, 1, 1, 2) self.tab_grid_1.addWidget(self.tab1_sponsor, 1, 1, 1, 1) self.tab_grid_1.addWidget(self.tab1_offset, 1, 2, 1, 1) self.tab_grid_1.addWidget(self.tab1_ignore, 2, 1, 1, 2) self.tab_grid_1.addWidget(self.tab1_add_button, 3, 0, 1, 3) self.tab1_sponsor.setLayout(self.tab1_sponsor_layout) self.tab1_sponsor_layout.addWidget(self.tab1_sponsor_label) self.tab1_sponsor_layout.addWidget(self.tab1_sponsor_value) self.tab1_sponsor_layout.addStretch(1) self.tab1_offset.setLayout(self.tab1_offset_layout) self.tab1_offset_layout.addWidget(self.tab1_offset_label) self.tab1_offset_layout.addWidget(self.tab1_offset_value) self.tab1_offset_layout.addStretch(1) self.tab1_ignore.setLayout(self.tab1_ignore_layout) self.tab1_ignore_layout.addWidget(self.tab1_ignore_label1) self.tab1_ignore_layout.addWidget(self.tab1_ignore_value) self.tab1_ignore_layout.addWidget(self.tab1_ignore_label2) self.tab1_ignore_layout.addWidget(self.tab1_ignore_sec) self.tab1_ignore_layout.addWidget(self.tab1_ignore_label3) self.tab1_ignore_layout.addStretch(1) self.tab_page_2.setLayout(self.tab_grid_2) self.tab_grid_2.setRowStretch(0, 1) self.tab_grid_2.addWidget(self.tab2_shift, 1, 0, 2, 1) self.tab_grid_2.addWidget(self.tab2_slow_radio, 1, 1, 1, 1) self.tab_grid_2.addWidget(self.tab2_fast_radio, 2, 1, 1, 1) self.tab_grid_2.setColumnStretch(2, 1) self.tab_grid_2.setRowStretch(3, 1) self.tab_grid_2.addWidget(self.tab2_add_button, 4, 0, 1, 3) self.tab2_shift.setLayout(self.tab2_shift_layout) self.tab2_shift_layout.addWidget(self.tab2_shift_label1) self.tab2_shift_layout.addWidget(self.tab2_shift_value) self.tab2_shift_layout.addWidget(self.tab2_shift_label2) self.tab_page_3.setLayout(self.tab_grid_3) self.tab_grid_3.setRowStretch(0, 1) self.tab_grid_3.addWidget(self.tab3_speed_label1, 1, 0, 1, 1) self.tab_grid_3.addWidget(self.tab3_speed_value, 1, 1, 1, 1) self.tab_grid_3.addWidget(self.tab3_speed_label2, 1, 2, 1, 1) self.tab_grid_3.setColumnStretch(3, 1) self.tab_grid_3.setRowStretch(2, 1) self.tab_grid_3.addWidget(self.tab3_add_button, 3, 0, 1, 4) self.que_widget.setLayout(self.que_layout) self.que_layout.addWidget(self.que_list, 0, 0, 4, 1) self.que_layout.addWidget(self.que_delete_button, 0, 1, 1, 1) self.que_layout.addWidget(self.que_up_button, 1, 1, 1, 1) self.que_layout.addWidget(self.que_down_button, 2, 1, 1, 1) self.que_layout.addWidget(self.que_clear_button, 3, 1, 1, 1) self.file_widget.setLayout(self.file_layout) self.file_layout.addWidget(self.file_list, 0, 0, 6, 1) self.file_layout.addWidget(self.file_file_open, 0, 1, 1, 1) self.file_layout.addWidget(self.file_dir_open, 1, 1, 1, 1) self.file_layout.addWidget(self.file_delete, 2, 1, 1, 1) self.file_layout.addWidget(self.file_clear, 3, 1, 1, 1) self.file_layout.addWidget(self.file_encode, 5, 1, 1, 1) self.save_widget.setLayout(self.save_layout) self.save_layout.addWidget(self.save_orig_radio, 0, 0, 1, 1) self.save_layout.setColumnStretch(1, 1) self.save_layout.addWidget(self.save_strip, 0, 2, 1, 2) self.save_layout.addWidget(self.save_dir_radio, 1, 0, 1, 1) self.save_layout.addWidget(self.save_dir_line, 1, 1, 1, 2) self.save_layout.addWidget(self.save_dir_find, 1, 3, 1, 1) self.setWindowTitle('Batch SAMI Sync v0.2') self.setCentralWidget(self.central_widget) self.adjustSize() def attach_event(self): # Default encoding hack self.encoding = '자동' # Define and Connect event handlers def tab1_add(): sponsor_text = self.tab1_search.text() sponsor_time = self.tab1_sponsor_value.value() line_offset = self.tab1_offset_value.value() line_ignore = self.tab1_ignore_value.value() time_ignore = self.tab1_ignore_sec.value() data = [1, sponsor_time, sponsor_text, line_offset, line_ignore, time_ignore] item = QTreeWidgetItem(self.que_list, [self.tab1_name, '스폰서 영상 시간 : ' + str(sponsor_time) + '초, 오프셋 : ' + str(line_offset) + '줄, 시작부터 ' + str(line_ignore) + '번째 줄, ' + str(time_ignore) + '초 무시 - 검색어 : ' + sponsor_text]) item.setData(2, 2, data) def tab2_add(): shift_time = self.tab2_shift_value.value() shift_direction = self.tab2_fast_radio.isChecked() direction_text = '빠르게' if shift_direction else '느리게' data = [2, shift_time, shift_direction] item = QTreeWidgetItem(self.que_list, [self.tab2_name, '자막 싱크 ' + str(shift_time) + '초 ' + direction_text]) item.setData(2, 2, data) def tab3_add(): speed_rate = self.tab3_speed_value.value() data = [3, speed_rate] item = QTreeWidgetItem(self.que_list, [self.tab3_name, '자막 속도 ' + str(speed_rate) + '%']) item.setData(2, 2, data) def file_open(): selected = QFileDialog.getOpenFileNames(self, "자막 파일 선택", "", "SAMI Files (*.smi);;All Files (*)") for file in selected[0]: name = ntpath.basename(file) Utils.insert_list(self.file_list, name, file) def dir_open(): selected = QFileDialog.getExistingDirectory(self, "자막 폴더 선택") for paths, subdirs, files in os.walk(selected): for file in files: if fnmatch(file, '*.smi'): name = ntpath.basename(file) Utils.insert_list(self.file_list, name, file) def open_encode_dialog(): self.dialog = QInputDialog(self) self.dialog.setWindowTitle('인코딩 설정') self.dialog.setLabelText('텍스트 인코딩 설정') self.dialog.setComboBoxItems(['자동', 'EUC-KR', 'UTF-8', 'UTF-16LE', 'UTF-16BE', '직접 입력']) self.dialog.show() self.dialog.textValueChanged.connect(type_encode) self.dialog.textValueSelected.connect(set_encode) def type_encode(text): if text == '직접 입력': self.dialog.setComboBoxItems([]) self.dialog.setComboBoxEditable(True) def set_encode(text): self.encoding = text def save_dir(): selected = QFileDialog.getExistingDirectory(self, "저장 위치 선택") self.save_dir_line.setText(selected) def apply(): self.ok_button.setEnabled(False) ques = Utils.read_list(self.que_list, False) files = Utils.read_list(self.file_list, False) strip = False if self.save_strip.isChecked() else True log = [] for file in files: try: text = Utils.launch_que(file[1], ques, self.encoding, strip) if len(text): if self.save_orig_radio.isChecked(): savepath = file[1] else: savepath = self.save_dir_line.text() + '/' + file[0] Utils.save_file(savepath, text) except Exception as e: log.append(file[0] + ' 처리 오류 : ' + str(e)) if log: ScrollMessageBox(QMessageBox.Warning, 'Batch SAMI Sync', "\n".join(log)) else: QMessageBox.information(self, 'Batch SAMI Sync', '변환 완료!') self.ok_button.setEnabled(True) self.tab1_add_button.clicked.connect(tab1_add) self.tab2_add_button.clicked.connect(tab2_add) self.tab3_add_button.clicked.connect(tab3_add) self.que_delete_button.clicked.connect(lambda: Utils.delete_list(self.que_list)) self.que_clear_button.clicked.connect(lambda: Utils.clear_list(self.que_list)) self.que_up_button.clicked.connect(lambda: Utils.up_list(self.que_list)) self.que_down_button.clicked.connect(lambda: Utils.down_list(self.que_list)) self.file_file_open.clicked.connect(file_open) self.file_dir_open.clicked.connect(dir_open) self.file_delete.clicked.connect(lambda: Utils.delete_list(self.file_list)) self.file_clear.clicked.connect(lambda: Utils.clear_list(self.file_list)) self.file_encode.clicked.connect(open_encode_dialog) self.save_dir_find.clicked.connect(save_dir) self.ok_button.clicked.connect(apply) self.cancel_button.clicked.connect(sys.exit) def dragEnterEvent(self, event): if event.mimeData().hasUrls: event.accept() else: event.ignore() def dragMoveEvent(self, event): if event.mimeData().hasUrls(): event.setDropAction(Qt.CopyAction) event.accept() else: event.ignore() def dropEvent(self, event): if event.mimeData().hasUrls(): event.setDropAction(Qt.CopyAction) event.accept() for url in event.mimeData().urls(): if url.isLocalFile(): file = str(url.toLocalFile()) if fnmatch(file, '*.smi'): name = ntpath.basename(file) Utils.insert_list(self.file_list, name, file) elif not fnmatch(file, '*.*'): for paths, subdirs, files in os.walk(file): for file in files: if fnmatch(file, '*.smi'): name = ntpath.basename(file) Utils.insert_list(self.file_list, name, file) else: event.ignore()
class SettingsEditionDialog(QDialog): languages = {"Français": "fr", "English": "en"} def __init__(self): QDialog.__init__(self) self.setWindowTitle(tr("btn_config")) self.setFixedSize(QSize(700, 675)) # Retrieve current settings self.settings = AssetManager.getInstance().config_to_dico( AssetManager.getInstance().get_config_parser()) self.__restart_needed = False self.__restore_required = False # Version self.lab_version = QLabel(self.settings['main']['version']) # Language self.combo_language = QComboBox() self.combo_language.addItems(list(self.languages.keys())) for lang in self.languages: # Look for the current language to select it if self.languages[lang] == self.settings['main']['language']: self.combo_language.setCurrentText(lang) break # CSV separator self.csv_sep_edit = QLineEdit() self.csv_sep_edit.setMaxLength(2) self.csv_sep_edit.setFixedWidth(25) self.csv_sep_edit.setAlignment(Qt.AlignCenter) self.csv_sep_edit.setText(self.settings['main']['csv_separator']) # BDD path self.btn_bdd_path = QPushButton(self.settings['main']['bdd_path']) self.btn_bdd_path.clicked.connect(self.choose_bdd_path) # Port self.wepapp_port = QSpinBox() self.wepapp_port.setMinimum(1024) self.wepapp_port.setMaximum(65535) self.wepapp_port.setValue(int(self.settings['webapp']['port'])) # Colors self.tile_color = ColorChooser(self.settings['colors']['tile']) self.hovered_tile_color = ColorChooser( self.settings['colors']['hovered_tile']) self.hovered_empty_tile_color = ColorChooser( self.settings['colors']['hovered_empty_tile']) self.dragged_tile_color = ColorChooser( self.settings['colors']['dragged_tile']) self.drag_selected_tile_color = ColorChooser( self.settings['colors']['drag_selected_tile']) self.selected_tile_color = ColorChooser( self.settings['colors']['selected_tile']) self.tile_text_color = ColorChooser( self.settings['colors']['tile_text']) self.room_bg_color = ColorChooser(self.settings['colors']['room_bg']) self.room_grid_color = ColorChooser( self.settings['colors']['room_grid']) self.main_bg_color = ColorChooser(self.settings['colors']['main_bg']) self.board_bg_color = ColorChooser(self.settings['colors']['board_bg']) self.attr_colors = "" # Chosen colors self.attributes_colors_chooser = AttrColorsChooser( self.settings['colors']['attr_colors'].split()) # Sizes # Desk sizes self.desk_size_h = QSpinBox() self.desk_size_h.setMinimum(10) self.desk_size_h.setMaximum(200) self.desk_size_h.setValue(int(self.settings['size']['desk_height'])) self.desk_size_h.setFixedWidth(50) self.desk_size_w = QSpinBox() self.desk_size_w.setMinimum(10) self.desk_size_w.setMaximum(200) self.desk_size_w.setValue(int(self.settings['size']['desk_width'])) self.desk_size_w.setFixedWidth(50) # Font size self.desk_font_size = QSpinBox() self.desk_font_size.setMinimum(4) self.desk_font_size.setValue(int(self.settings['size']['font_size'])) self.desk_font_size.setFixedWidth(50) # Grid rows self.grid_rows = QSpinBox() self.grid_rows.setMinimum(1) self.grid_rows.setMaximum(40) self.grid_rows.setValue(int( self.settings['size']['default_room_rows'])) self.grid_rows.setFixedWidth(50) # Grid columns self.grid_cols = QSpinBox() self.grid_cols.setMinimum(1) self.grid_cols.setMaximum(40) self.grid_cols.setValue( int(self.settings['size']['default_room_columns'])) self.grid_cols.setFixedWidth(50) # --- Buttons --- # Confirm button self.ok_btn = QPushButton(tr("btn_save")) self.ok_btn.clicked.connect(self.accept) self.ok_btn.setFixedWidth(200) self.ok_btn.setFocus() # Cancel button self.cancel_btn = QPushButton(tr("btn_cancel")) self.cancel_btn.clicked.connect(self.reject) self.cancel_btn.setFixedWidth(200) # Restore defaults button self.restore_btn = QPushButton(tr("btn_restore")) self.restore_btn.clicked.connect(self.__restore) self.restore_btn.setFixedWidth(200) self.__set_layout() def __set_layout(self) -> None: """ Sets the dialog layout """ # Main layout layout = QVBoxLayout() layout.setMargin(0) layout.addSpacing(5) # Main section main_layout = SettingsFormLayout() main_layout.addRow(tr("app_version"), self.lab_version) main_layout.addRow(tr("language"), self.combo_language) main_layout.addRow(tr("csv_sep"), self.csv_sep_edit) main_layout.addRow(tr("bdd_path"), self.btn_bdd_path) # Web app widget_port = QWidget() layout_port = QHBoxLayout() layout_port.setMargin(0) layout_port.addWidget(self.wepapp_port) layout_port.addWidget(WarningToolTip("shutdown_required")) widget_port.setLayout(layout_port) main_layout.addRow(tr("web_port"), widget_port) layout.addLayout(main_layout) Separator(self.width(), layout) # Colors colors_layout1 = SettingsFormLayout() colors_layout1.addRow(tr("tile"), self.tile_color) colors_layout1.addRow(tr("hovered_tile"), self.hovered_tile_color) colors_layout1.addRow(tr("hovered_empty_tile"), self.hovered_empty_tile_color) colors_layout1.addRow(tr("dragged_tile"), self.dragged_tile_color) colors_layout1.addRow(tr("drag_selected_tile"), self.drag_selected_tile_color) colors_layout1.addRow(tr("selected_tile"), self.selected_tile_color) colors_layout2 = SettingsFormLayout() colors_layout2.addRow(tr("tile_text"), self.tile_text_color) colors_layout2.addRow(tr("room_bg"), self.room_bg_color) colors_layout2.addRow(tr("room_grid"), self.room_grid_color) colors_layout2.addRow(tr("main_bg"), self.main_bg_color) colors_layout2.addRow(tr("board_bg"), self.board_bg_color) colors_layout = QHBoxLayout() colors_layout.setMargin(0) colors_layout.addLayout(colors_layout1) colors_layout.addLayout(colors_layout2) layout.addLayout(colors_layout) layout.addSpacing(15) colors_layout3 = SettingsFormLayout() colors_layout3.setMargin(0) colors_layout3.addRow(tr("attr_colors"), self.attributes_colors_chooser) layout.addLayout(colors_layout3) Separator(self.width(), layout) # size data sizes_layout = SettingsFormLayout() sizes_layout.setMargin(0) widget_desk = QWidget() layout_desk = QHBoxLayout() layout_desk.setMargin(0) layout_desk.addWidget(self.desk_size_h) layout_desk.addWidget(self.desk_size_w) layout_desk.addWidget(WarningToolTip("dangerous_parameter")) widget_desk.setLayout(layout_desk) sizes_layout.addRow(tr("desk_size"), widget_desk) sizes_layout.addRow(tr("font_size"), self.desk_font_size) widget_rows = QWidget() layout_rows = QHBoxLayout() layout_rows.setMargin(0) layout_rows.addWidget(self.grid_rows) layout_rows.addWidget(WarningToolTip("dangerous_parameter")) widget_rows.setLayout(layout_rows) sizes_layout.addRow(tr("grid_rows"), widget_rows) widget_cols = QWidget() layout_cols = QHBoxLayout() layout_cols.setMargin(0) layout_cols.addWidget(self.grid_cols) layout_cols.addWidget(WarningToolTip("dangerous_parameter")) widget_cols.setLayout(layout_cols) sizes_layout.addRow(tr("grid_cols"), widget_cols) layout.addLayout(sizes_layout) Separator(self.width(), layout) # Buttons layout_buttons = QHBoxLayout() layout_buttons.addWidget(self.ok_btn) layout_buttons.addWidget(self.restore_btn) layout_buttons.addWidget(self.cancel_btn) layout.addLayout(layout_buttons) layout.addSpacing(5) self.setLayout(layout) self.setStyleSheet(get_stylesheet("dialog2")) def __restore(self) -> None: """ Restore default parameters before closing dialog """ self.__restart_needed = True self.__restore_required = True self.accept() def __new_settings(self) -> dict: """ Retrieves the new settings to use """ settings = self.settings # Language language = self.languages[self.combo_language.currentText()] if language != settings['main']['language']: settings['main']['language'] = language self.__restart_needed = True # CSV separator settings['main']['csv_separator'] = self.csv_sep_edit.text() # BDD path if self.btn_bdd_path.text() != settings['main']['bdd_path']: if self.btn_bdd_path.text().endswith("sdc_db"): settings['main']['bdd_path'] = self.btn_bdd_path.text() else: settings['main']['bdd_path'] = "" self.__restart_needed = True # Port if str(self.wepapp_port.value()) != settings['webapp']['port']: settings['webapp']['port'] = str(self.wepapp_port.value()) # Colors settings['colors']['tile'] = self.tile_color.get_color() settings['colors']['hovered_tile'] = self.hovered_tile_color.get_color( ) settings['colors'][ 'hovered_empty_tile'] = self.hovered_empty_tile_color.get_color() settings['colors']['dragged_tile'] = self.dragged_tile_color.get_color( ) settings['colors'][ 'drag_selected_tile'] = self.drag_selected_tile_color.get_color() settings['colors'][ 'selected_tile'] = self.selected_tile_color.get_color() settings['colors']['tile_text'] = self.tile_text_color.get_color() settings['colors']['room_grid'] = self.room_grid_color.get_color() if self.room_bg_color.get_color() != settings['colors']['room_bg']: settings['colors']['room_bg'] = self.room_bg_color.get_color() self.__restart_needed = True if self.main_bg_color.get_color() != settings['colors']['main_bg']: settings['colors']['main_bg'] = self.main_bg_color.get_color() self.__restart_needed = True if self.board_bg_color.get_color() != settings['colors']['board_bg']: settings['colors']['board_bg'] = self.board_bg_color.get_color() self.__restart_needed = True settings['colors']['attr_colors'] = self.attr_colors # Size settings if str(self.desk_size_h.value()) != settings['size']['desk_height']: settings['size']['desk_height'] = str(self.desk_size_h.value()) self.__restart_needed = True if str(self.desk_size_w.value()) != settings['size']['desk_width']: settings['size']['desk_width'] = str(self.desk_size_w.value()) self.__restart_needed = True if str(self.desk_font_size.value()) != settings['size']['font_size']: settings['size']['font_size'] = str(self.desk_font_size.value()) #self.__restart_needed = False if str(self.grid_rows.value() ) != settings['size']['default_room_rows']: settings['size']['default_room_rows'] = str(self.grid_rows.value()) self.__restart_needed = True if str(self.grid_cols.value() ) != settings['size']['default_room_columns']: settings['size']['default_room_columns'] = str( self.grid_cols.value()) self.__restart_needed = True return settings def new_config(self) -> ConfigParser: """ Retrieves the new config parser object """ conf = ConfigParser() conf.read_dict(self.__new_settings()) return conf def need_restart(self): return self.__restart_needed def restore_default(self) -> bool: return self.__restore_required def accept(self) -> None: """ Performs actions before calling parent's accept method """ self.attr_colors = self.attributes_colors_chooser.get_colors_to_str() super().accept() def choose_bdd_path(self) -> None: """ Opens a file chooser to select the bdd path. Then sets the name as button text. """ bdd_path = QFileDialog.getOpenFileName(self, tr("bdd_path"), self.btn_bdd_path.text())[0] if bdd_path: self.btn_bdd_path.setText(bdd_path)
class MainWindow(QMainWindow): def __init__(self, app, parent=None): super(MainWindow, self).__init__(parent) self.imagesDir = app.dir + '/images/' self.setWindowIcon(QIcon(self.imagesDir + 'icon.png')) self.path = '' self.settings = QSettings() self.lastDir = self.settings.value('lastDir', '') self.setMinimumWidth(540) self.supportedFormats = [] for f in QImageReader.supportedImageFormats(): self.supportedFormats.append(str(f.data(), encoding="utf-8")) self.fileWatcher = QFileSystemWatcher() self.fileWatcher.fileChanged.connect(self.fileChanged) # widgets self.showPixmapWidget = None self.tileWidthSpinBox = QSpinBox() self.tileWidthSpinBox.setValue(16) self.tileWidthSpinBox.setFixedWidth(50) self.tileWidthSpinBox.setMinimum(1) self.tileHeightSpinBox = QSpinBox() self.tileHeightSpinBox.setValue(16) self.tileHeightSpinBox.setFixedWidth(50) self.tileHeightSpinBox.setMinimum(1) self.paddingSpinBox = QSpinBox() self.paddingSpinBox.setFixedWidth(50) self.paddingSpinBox.setMinimum(1) self.transparentCheckbox = QCheckBox("Transparent") self.transparentCheckbox.setChecked(True) self.transparentCheckbox.stateChanged.connect(self.transparentChanged) self.backgroundColorEdit = ColorEdit() self.backgroundColorEdit.setEnabled(False) self.backgroundColorLabel = QLabel("Background color:") self.backgroundColorLabel.setEnabled(False) self.forcePotCheckBox = QCheckBox("Force PoT") self.forcePotCheckBox.setChecked(True) self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged) self.reorderTilesCheckBox = QCheckBox("Reorder tiles") self.generateAndExportButton = QPushButton("Generate and export") self.generateAndExportButton.setFixedHeight(32) self.generateAndExportButton.clicked.connect(self.generateAndExportClicked) self.generateAndExportButton.setEnabled(False) self.pixmapWidget = PixmapWidget() self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.pixmapWidget.setPixmap(self.createDropTextPixmap()) self.pixmapWidget.dropSignal.connect(self.fileDropped) self.pixmapWidget.setMinimumHeight(300) # load settings self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16))) self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16))) self.paddingSpinBox.setValue(int(self.settings.value('padding', 1))) self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False) self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False) self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False) self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF'))) self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry'))) self.restoreState(QByteArray(self.settings.value('MainWindow/windowState'))) # layout hl1 = QHBoxLayout() hl1.setContentsMargins(5, 5, 5, 5) hl1.addWidget(QLabel("Tile width:")) hl1.addSpacing(5) hl1.addWidget(self.tileWidthSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Tile height:")) hl1.addSpacing(5) hl1.addWidget(self.tileHeightSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Padding:")) hl1.addSpacing(5) hl1.addWidget(self.paddingSpinBox) hl1.addSpacing(15) hl1.addWidget(self.forcePotCheckBox) hl1.addSpacing(15) hl1.addWidget(self.reorderTilesCheckBox) hl1.addStretch() hl2 = QHBoxLayout() hl2.setContentsMargins(5, 5, 5, 5) hl2.addWidget(self.transparentCheckbox) hl2.addSpacing(15) hl2.addWidget(self.backgroundColorLabel) hl2.addSpacing(5) hl2.addWidget(self.backgroundColorEdit) hl2.addStretch() hl3 = QHBoxLayout() hl3.setContentsMargins(5, 5, 5, 5) hl3.addWidget(self.generateAndExportButton) vl = QVBoxLayout() vl.setContentsMargins(0, 0, 0, 0) vl.setSpacing(0) vl.addLayout(hl1) vl.addLayout(hl2) vl.addWidget(self.pixmapWidget) vl.addLayout(hl3) w = QWidget() w.setLayout(vl) self.setCentralWidget(w) self.setTitle() def setTitle(self): p = ' - ' + os.path.basename(self.path) if self.path else '' self.setWindowTitle(QCoreApplication.applicationName() + ' ' + QCoreApplication.applicationVersion() + p) def createDropTextPixmap(self): pixmap = QPixmap(481, 300) pixmap.fill(QColor("#333333")) painter = QPainter(pixmap) font = QFont("Arial") font.setPixelSize(28) font.setBold(True) fm = QFontMetrics(font) painter.setFont(font) painter.setPen(QPen(QColor("#888888"), 1)) text = "Drop the tileset image here" x = (pixmap.width()-fm.width(text))/2 y = (pixmap.height()+fm.height())/2 painter.drawText(x, y, text) del painter return pixmap def fileDropped(self, path): path = str(path) name, ext = os.path.splitext(path) ext = ext[1:] if not ext in self.supportedFormats: QMessageBox.warning(self, "Warning", "The dropped file is not supported") return pixmap = QPixmap(path) if pixmap.isNull(): QMessageBox.warning(self, "Warning", "Can't load the image") return if self.path: self.fileWatcher.removePath(self.path) self.path = path self.fileWatcher.addPath(self.path) self.pixmapWidget.setPixmap(pixmap) self.generateAndExportButton.setEnabled(True) self.setTitle() self.activateWindow() def fileChanged(self, path): #self.fileDropped(path) pass def transparentChanged(self): e = self.transparentCheckbox.isChecked() self.backgroundColorEdit.setEnabled(not e) self.backgroundColorLabel.setEnabled(not e) def forcePotChanged(self): e = self.forcePotCheckBox.isChecked() self.reorderTilesCheckBox.setEnabled(e) def generateAndExportClicked(self): g = Generator() g.tileWidth = self.tileWidthSpinBox.value() g.tileHeight = self.tileHeightSpinBox.value() g.forcePot = self.forcePotCheckBox.isChecked() g.isTransparent = self.transparentCheckbox.isChecked() g.bgColor = self.backgroundColorEdit.getColor() g.reorder = self.reorderTilesCheckBox.isChecked() g.padding = self.paddingSpinBox.value() target = g.create(self.pixmapWidget.pixmap); # export self.lastDir = os.path.dirname(self.path) targetPath = QFileDialog.getSaveFileName(self, 'Export', self.lastDir, 'PNG (*.png)') if targetPath: target.save(targetPath[0]) showPixmap = QPixmap.fromImage(target) if self.showPixmapWidget: self.showPixmapWidget.deleteLater() del self.showPixmapWidget self.showPixmapWidget = PixmapWidget() self.showPixmapWidget.setWindowIcon(self.windowIcon()) self.showPixmapWidget.setWindowTitle(os.path.basename(targetPath[0])) self.showPixmapWidget.resize(showPixmap.width(), showPixmap.height()) self.showPixmapWidget.setPixmap(showPixmap) self.showPixmapWidget.show() def closeEvent(self, event): if self.showPixmapWidget: self.showPixmapWidget.close() # save settings self.settings.setValue('tileWidth', self.tileWidthSpinBox.value()) self.settings.setValue('tileHeight', self.tileHeightSpinBox.value()) self.settings.setValue('padding', self.paddingSpinBox.value()) self.settings.setValue('forcePot', self.forcePotCheckBox.isChecked()) self.settings.setValue('reorderTiles', self.reorderTilesCheckBox.isChecked()) self.settings.setValue('transparent', self.transparentCheckbox.isChecked()) self.settings.setValue('backgroundColor', self.backgroundColorEdit.getColor().name()) self.settings.setValue('lastDir', self.lastDir) self.settings.setValue('MainWindow/geometry', self.saveGeometry()) self.settings.setValue('MainWindow/windowState', self.saveState()) super(MainWindow, self).closeEvent(event)
class application(QTabWidget): bot = 0 def __init__(self, parent=None): super(application, self).__init__(parent) self.bot = None self.db = sqlite3.connect('database') # tabs self.tab1 = QWidget() self.tab2 = QWidget() self.tab3 = QWidget() self.tab4 = QWidget() self.tab5 = QWidget() self.resize(640, 400) self.addTab(self.tab1, "Tab 1") self.addTab(self.tab2, "Tab 2") self.addTab(self.tab3, "Tab 3") self.addTab(self.tab4, "Tab 4") self.addTab(self.tab5, "Tab 5") # tab set keys self.h_box_key = QHBoxLayout() self.change_key_b = QPushButton("Edit keys") self.edit_1 = QLineEdit() self.edit_2 = QLineEdit() self.edit_3 = QLineEdit() self.edit_4 = QLineEdit() self.result = QLabel() self.set_button = QPushButton("Set keys") self.handle_info = QLabel() self.follower_info = QLabel() self.ready_lab = QLabel() # tab follow self.box_label = QLabel("Link to tweet") self.combo_label = QLabel("Mode") self.spin_label = QLabel("Limit before sleep") self.prog_bar = QProgressBar() self.combo_box = QComboBox() self.h_box = QHBoxLayout() self.spin_box = QSpinBox() self.link_box = QLineEdit() self.link_result = QLabel() self.follow_button = QPushButton("Follow Retweeters") self.cancel_button = QPushButton("Cancel") self.logger = QPlainTextEdit() self.h_box2 = QHBoxLayout() self.max_box = QSpinBox() self.max_label = QLabel("Max follows before stop") # tab unfollow self.unfollow_button = QPushButton("Unfollow Auto followers") self.unf_logger = QPlainTextEdit() self.unfollow_res = QLabel() self.prog_bar_unf = QProgressBar() self.unfollow_cancel = QPushButton("Cancel") self.unf_confirm = QMessageBox() # tab help self.help_box = QPlainTextEdit() self.help_label = QLabel( "<a href='http://Optumsense.com/'>http://Optumsense.com/</a>") #tab schedule self.tweet_box = QPlainTextEdit() self.date_time = QDateTimeEdit(QDateTime.currentDateTime()) self.schedule_but = QPushButton("Schedule Tweet") self.schedule_info = QLabel() self.schedule_table = QTableView() # threads self.follow_thread = None self.unfollow_thread = None self.schedule_thread = None # tabs self.tab1UI() self.tab2UI() self.tab3UI() self.tab4UI() self.tab5UI() self.setWindowTitle("Optumize") self.setWindowIcon(QtGui.QIcon('assets/oo.png')) # db cursor = self.db.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS keys(one TEXT, two TEXT, three TEXT, four TEXT)''' ) self.db.commit() def tab1UI(self): layout = QFormLayout() layout.addRow(self.h_box) self.h_box.addWidget(self.combo_label) self.combo_label.setAlignment(Qt.AlignRight) self.h_box.addWidget(self.combo_box) self.combo_box.addItem("Follow Retweeters") self.combo_box.addItem("Follow Followers") self.combo_box.currentIndexChanged.connect(self.selection_change) self.h_box.addWidget(self.spin_label) self.spin_label.setAlignment(Qt.AlignRight) self.h_box.addWidget(self.spin_box) self.spin_box.setMinimum(1) self.spin_box.setValue(30) layout.addRow(self.box_label, self.link_box) self.link_result.setAlignment(Qt.AlignCenter) layout.addRow(self.link_result) layout.addRow(self.follow_button) self.follow_button.clicked.connect(self.follow_ret) layout.addRow(self.cancel_button) self.cancel_button.clicked.connect(self.cancel_onclick) layout.addRow(self.h_box2) self.h_box2.addWidget(self.max_label) self.h_box2.addWidget(self.max_box) self.max_box.setFixedWidth(100) self.max_label.setAlignment(Qt.AlignRight) self.max_box.setMaximum(1000000) self.max_box.setValue(100) self.max_label.hide() self.max_box.hide() layout.addRow(self.logger) self.logger.setReadOnly(True) layout.addRow(self.prog_bar) self.prog_bar.setAlignment(Qt.AlignCenter) self.setTabText(0, "Follow") self.setTabIcon(0, QtGui.QIcon('assets/check_mark.png')) self.tab1.setLayout(layout) def selection_change(self, i): if i == 0: self.box_label.setText("Link to tweet") self.follow_button.setText("Follow Retweeters") self.link_result.setText("") self.max_label.hide() self.max_box.hide() self.follow_button.clicked.connect(self.follow_ret) else: self.box_label.setText("Handle of user") self.follow_button.setText("Follow Followers") self.link_result.setText("") self.max_label.show() self.max_box.show() self.max_label.setText("Max follows before stop") self.follow_button.clicked.connect(self.follow_fol) def cancel_onclick(self): if self.follow_thread is None: pass elif self.follow_thread.isRunning(): self.prog_bar.setValue(0) self.logger.appendPlainText("Cancelled script") self.follow_thread.terminate() self.follow_thread = None def follow_ret(self): self.prog_bar.setValue(0) self.follow_button.setEnabled(False) self.link_result.setText("") self.logger.clear() limit = self.spin_box.value() if self.bot is None: self.link_result.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return if self.follow_thread is not None: return link = self.link_box.text() id_tweet = link.split("/")[-1] try: tweet = self.bot.api.get_status(id_tweet) self.logger.appendPlainText( f"following retweeters from link: {link}...") self.follow_thread = FollowThread(self.bot, id_tweet, limit, 1, 0) self.follow_thread.start() self.connect(self.follow_thread, SIGNAL("finished()"), self.done) self.connect(self.follow_thread, SIGNAL("setup_prog(QString)"), self.setup_prog) self.connect(self.follow_thread, SIGNAL("post_follow(QString)"), self.post_follow) except tweepy.error.TweepError: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find tweet</font>") def setup_prog(self, msg): self.prog_bar.setMaximum(int(msg)) def follow_fol(self): self.prog_bar.setValue(0) self.follow_button.setEnabled(False) self.link_result.setText("") self.logger.clear() limit = self.spin_box.value() if self.bot is None: self.link_result.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return if self.follow_thread is not None: return handle = self.link_box.text() if handle == '': self.link_result.setText( "<font color='red'>Enter a handle above</font>") return elif handle[0] == '@': id_user = handle[1:] else: id_user = handle try: man = self.bot.api.get_user(id_user) self.logger.appendPlainText( f"following followers of {man.screen_name}...") self.logger.appendPlainText(f"Collecting") self.follow_thread = FollowThread(self.bot, id_user, limit, 2, self.max_box.value()) self.follow_thread.start() self.connect(self.follow_thread, SIGNAL("finished()"), self.done) self.connect(self.follow_thread, SIGNAL("setup_prog(QString)"), self.setup_prog) self.connect(self.follow_thread, SIGNAL("post_follow(QString)"), self.post_follow) except tweepy.error.TweepError: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find user</font>") def post_follow(self, message): if message == "bad": self.logger.appendPlainText( "Rate limit exceeded... sleeping for cooldown") else: self.logger.appendPlainText(message) self.prog_bar.setValue(self.prog_bar.value() + 1) def done(self): self.follow_thread = None self.follow_button.setEnabled(True) def tab2UI(self): layout = QFormLayout() layout.addRow(self.unfollow_button) layout.addRow(self.unfollow_cancel) layout.addRow(self.unfollow_res) self.unfollow_res.setAlignment(Qt.AlignCenter) self.unfollow_button.clicked.connect(self.unfollow_fol) self.unfollow_cancel.clicked.connect(self.unfollow_can) layout.addWidget(self.unf_logger) self.unf_logger.setReadOnly(True) layout.addRow(self.prog_bar_unf) self.prog_bar_unf.setAlignment(Qt.AlignCenter) self.setTabText(1, "Unfollow") self.setTabIcon(1, QtGui.QIcon('assets/cross.png')) self.tab2.setLayout(layout) def unfollow_fol(self): self.unfollow_button.setEnabled(False) self.unfollow_thread = UnfollowThread(self.bot) self.unfollow_thread.start() self.connect(self.unfollow_thread, SIGNAL("post_unfol(QString)"), self.post_unfol) self.connect(self.unfollow_thread, SIGNAL("finished()"), self.done_unf) def done_unf(self): self.unfollow_thread = None self.unf_logger.appendPlainText("Done") self.unfollow_button.setEnabled(True) def post_unfol(self, msg): if msg == "bad": self.unf_logger.appendPlainText( "rate limit exceeded, resting for 15 minutes") else: self.unf_logger.appendPlainText(f"Unfollowing {msg}") def unfollow_can(self): if self.unfollow_thread is None: pass elif self.unfollow_thread.isRunning(): self.unf_logger.appendPlainText("Cancelled script") self.unfollow_thread.terminate() self.unfollow_thread = None def tab3UI(self): layout = QFormLayout() layout.addWidget(self.tweet_box) self.tweet_box.setMaximumHeight(150) self.tweet_box.setPlaceholderText("Tweet contents") layout.addRow(self.date_time) self.date_time.setCalendarPopup(True) layout.addRow(self.schedule_info) layout.addRow(self.schedule_but) self.schedule_but.clicked.connect(self.schedule_tweet) layout.addWidget(self.schedule_table) self.setTabText(2, "Schedule Tweet") self.setTabIcon(2, QtGui.QIcon('assets/calendar.png')) self.tab3.setLayout(layout) def schedule_tweet(self): tweet_contents = self.tweet_box.toPlainText() if (len(tweet_contents) == 0): print("length of tweet is 0") self.schedule_info.setText("length of tweet is 0") return elif (len(tweet_contents) >= 280): self.schedule_info.setText("Tweet char limit exceeded") return if self.bot is None: self.schedule_info.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return datetime = self.date_time.text() try: print("done") self.schedule_thread.start() self.schedule_thread.add_tweet(tweet_contents, datetime) except: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find user</font>") def done_schedule(self): print("done scheduler") def tab4UI(self): layout = QFormLayout() layout.addRow("API key", self.edit_1) layout.addRow("API key secret", self.edit_2) layout.addRow("Auth token", self.edit_3) layout.addRow("Auth token secret", self.edit_4) self.set_button.clicked.connect(self.set_keys) l = self.read_file() if l is not None: if len(l) == 4: self.edit_1.setText(l[0]) self.edit_2.setText(l[1]) self.edit_3.setText(l[2]) self.edit_4.setText(l[3]) self.set_keys() layout.addRow(self.result) self.result.setAlignment(Qt.AlignCenter) layout.addRow(self.h_box_key) self.h_box_key.addWidget(self.change_key_b) self.h_box_key.addWidget(self.set_button) self.change_key_b.clicked.connect(self.change_keys) layout.addRow(self.handle_info) self.handle_info.setAlignment(Qt.AlignCenter) layout.addRow(self.follower_info) self.follower_info.setAlignment(Qt.AlignCenter) layout.addRow(self.ready_lab) self.ready_lab.setAlignment(Qt.AlignCenter) self.setTabText(3, "Settings") self.setTabIcon(3, QtGui.QIcon('assets/settings.png')) self.tab4.setLayout(layout) def change_keys(self): self.set_button.setEnabled(True) def set_keys(self): self.set_button.setEnabled(False) self.result.setText("") one = self.edit_1.text() two = self.edit_2.text() three = self.edit_3.text() four = self.edit_4.text() try: self.bot = apiconnector.ApiConnector(one, two, three, four) me = self.bot.add_keys(one, two, three, four) self.handle_info.setText("Handle: @" + me.screen_name) self.follower_info.setText("Followers: " + str(me.followers_count)) self.ready_lab.setText("<font color='green'>Ready!</font>") cursor = self.db.cursor() cursor.execute('DELETE FROM keys;', ) cursor.execute( '''INSERT INTO keys(one, two, three, four) VALUES(?,?,?,?)''', (one, two, three, four)) self.db.commit() self.schedule_thread = ScheduleThread(self.bot) except: print("Could not authenticate you") self.result.setText( "<font color='red'>Could not authenticate you</font>") def read_file(self): result = [] try: cursor = self.db.cursor() cursor.execute('''SELECT one, two, three, four FROM keys''') all_rows = cursor.fetchall() for row in all_rows: result.append(row[0]) result.append(row[1]) result.append(row[2]) result.append(row[3]) return result except: return None def tab5UI(self): layout = QFormLayout() layout.addRow("Website", self.help_label) self.help_label.setOpenExternalLinks(True) self.setTabText(4, "Help") self.setTabIcon(4, QtGui.QIcon('assets/help.png')) self.tab5.setLayout(layout)
class Prescreen(QWidget): REASONS = ('Inattentive', 'Child Talking', 'Parent Talking', 'Parent Interference', 'Child Not Looking Before Sound', 'Equipment Malfunction', 'Experiment Ended Early', 'Other') def __init__(self, callback): super().__init__() self.callback = callback trial_label = QLabel('Trial:') self.trial_box = QSpinBox() self.trial_box.setFixedWidth(64) self.trial_box.setValue(1) # self.trial_box.setFocusPolicy(Qt.NoFocus) reason_label = QLabel('Reason:') self.reason_box = QComboBox() self.reason_box.addItems(self.REASONS) self.reason_box.setFocusPolicy(Qt.NoFocus) self.code_radio = QRadioButton('Code') self.nocode_radio = QRadioButton('Do Not Code') self.code_radio.setChecked(True) self.code_radio.setFocusPolicy(Qt.NoFocus) self.nocode_radio.setFocusPolicy(Qt.NoFocus) radio_layout = QVBoxLayout() radio_layout.addStretch() radio_layout.addWidget(self.code_radio) radio_layout.addWidget(self.nocode_radio) radio_layout.addStretch() self.group_code = QButtonGroup() self.group_code.addButton(self.code_radio) self.group_code.addButton(self.nocode_radio) self.record_button = QPushButton('Record Reason') self.record_button.clicked.connect(self.record_reason) self.record_button.setEnabled(False) self.record_button.setFocusPolicy(Qt.NoFocus) self.both_checkbox = QCheckBox('Display both coders') self.both_checkbox.setFocusPolicy(Qt.NoFocus) self.radio_primary = QRadioButton('Primary') self.radio_secondary = QRadioButton('Secondary') self.radio_primary.setChecked(True) self.radio_primary.setFocusPolicy(Qt.NoFocus) self.radio_secondary.setFocusPolicy(Qt.NoFocus) who_layout = QVBoxLayout() who_layout.addWidget(self.both_checkbox) who_layout.addWidget(self.radio_primary) who_layout.addWidget(self.radio_secondary) self.group_who = QButtonGroup() self.group_who.addButton(self.radio_primary, id=1) self.group_who.addButton(self.radio_secondary, id=2) layout = QHBoxLayout() layout.addWidget(trial_label) layout.addWidget(self.trial_box) layout.addWidget(reason_label) layout.addWidget(self.reason_box) layout.addLayout(radio_layout) layout.addWidget(self.record_button) layout.addStretch() layout.addLayout(who_layout) self.setLayout(layout) def record_reason(self): reason = Reason(trial=self.trial_box.value(), include=self.code_radio.isChecked(), reason=self.reason_box.currentText()) self.callback(reason) def prescreener(self): if self.both_checkbox.isChecked(): return 0 else: return self.group_who.checkedId()