Exemple #1
0
class PangoFileWidget(PangoDockWidget):
    def __init__(self, title, parent=None):
        super().__init__(title, parent)
        self.setFixedWidth(160)

        self.file_model = QFileSystemModel()
        self.file_model.setFilter(QDir.Files | QDir.NoDotAndDotDot)
        self.file_model.setNameFilters(["*.jpg", "*.png"])
        self.file_model.setNameFilterDisables(False)
        self.th_provider = ThumbnailProvider()
        self.file_model.setIconProvider(self.th_provider)

        self.file_view = QListView()
        self.file_view.setModel(self.file_model)
        self.file_view.setViewMode(QListView.IconMode)
        self.file_view.setFlow(QListView.LeftToRight)
        self.file_view.setIconSize(QSize(150, 150))
        
        self.setWidget(self.file_view)

    def select_next_image(self):
        c_idx = self.file_view.currentIndex()
        idx = c_idx.siblingAtRow(c_idx.row()+1)
        if idx.row() != -1:
            self.file_view.setCurrentIndex(idx)

    def select_prev_image(self):
        c_idx = self.file_view.currentIndex()
        idx = c_idx.siblingAtRow(c_idx.row()-1)
        if idx.row() != -1:
            self.file_view.setCurrentIndex(idx)
Exemple #2
0
class TeamChooserWidget(QWidget):
    def __init__(self, parent, on_next, league=None):
        super().__init__(parent)
        self.layout = QVBoxLayout()
        self.list_view = QListView()
        self.league = league
        self.model = TeamListModel(league)
        self.list_view.setModel(self.model)
        self.list_view.setSelectionMode(QAbstractItemView.MultiSelection)
        self.list_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.list_view.customContextMenuRequested.connect(self.list_context_menu)
        self.layout.addWidget(self.list_view)
        self.team_add = AddItemWidget(self, "New Team Name: ", self.add_team, unavailable_options=self.model.all_team_names)
        self.layout.addWidget(self.team_add)

        self.button_h_layout = QHBoxLayout()
        self.button_cancel = QPushButton("Cancel")
        self.button_cancel.clicked.connect(self.on_cancel)
        self.button_next = QPushButton("Next")
        self.button_next.clicked.connect(on_next)
        self.button_h_layout.addWidget(self.button_cancel)
        self.button_h_layout.addWidget(self.button_next)
        self.layout.addLayout(self.button_h_layout)
        self.setLayout(self.layout)
        self.new_teams = []

    def add_team(self, name):
        self.new_teams.append(name)
        team = Team.create(name=name)
        self.model.add_team(team)

    def list_context_menu(self, pos):
        self.listMenu = QMenu()
        current_index = self.list_view.currentIndex()
        select = self.listMenu.addAction("Select")
        select.triggered.connect(
            lambda: self.list_view.selectionModel().select(current_index, QtCore.QItemSelectionModel.Select)
        )

        deselect = self.listMenu.addAction("Deselect")
        deselect.triggered.connect(
            lambda: self.list_view.selectionModel().select(current_index, QtCore.QItemSelectionModel.Deselect)
        )
        delete = self.listMenu.addAction("Delete")
        delete.setDisabled(current_index.data() not in self.new_teams)
        delete.triggered.connect(lambda: self.model.delete_team(current_index.row()))

        parentPosition = self.list_view.mapToGlobal(QtCore.QPoint(0, 0))
        self.listMenu.move(parentPosition + pos)
        self.listMenu.show()

    def on_cancel(self):
        self.model.delete_added_teams()
        self.window().close()

    def get_selected_teams(self):
        teams = []
        for i in self.list_view.selectedIndexes():
            teams.append(self.model.get_team(i.row()))
        return teams
class TBox(QWidget):
    def __init__(self):
        super().__init__()

        exitShortcut = QShortcut(QKeySequence('Ctrl+W'), self, qApp.quit)

        self.connect = Connect()

        self.all_models = self.connect.session.query(Models).all()

        self.labelkey_name = QLabel('Name', self)
        self.labelkey_parts = QLabel('Parts', self)
        self.labelkey_current_quantity = QLabel('Current Quantity', self)

        self.labelval_name = QLabel('Name', self)
        self.labelval_parts = QLabel('Parts', self)
        self.labelval_current_quantity = QLabel('Current Quantity', self)

        self.showInfo('M1')

        self.list = QListView(self)
        self.list_model = QStandardItemModel(self.list)
        self.createList()

        print('Current index of view: ', self.list.currentIndex())

        self.hboxlayout = QHBoxLayout()
        self.label_grid = QGridLayout()
        self.buildLayout()

        self.show()

    def showInfo(self, queryitem):
        query = self.connect.session.query(Models).filter_by(
            name=queryitem).one()
        self.labelval_name.setText(query.name)
        self.labelval_parts.setText(query.parts)
        self.labelval_current_quantity.setText(str(query.current_quantity))

    def createList(self):
        for model in self.all_models:
            item = QStandardItem(model.name)
            self.list_model.appendRow(item)
        self.list.setModel(self.list_model)
        self.list.setMinimumSize(150, 200)
        self.list.setMaximumSize(150, 600)
        self.list.show()

    def buildLayout(self):

        self.label_grid.addWidget(self.labelkey_name, 0, 0)
        self.label_grid.addWidget(self.labelkey_parts, 1, 0)
        self.label_grid.addWidget(self.labelkey_current_quantity, 2, 0)
        self.label_grid.addWidget(self.labelval_name, 0, 1)
        self.label_grid.addWidget(self.labelval_parts, 1, 1)
        self.label_grid.addWidget(self.labelval_current_quantity, 2, 1)

        self.hboxlayout.addWidget(self.list)
        self.hboxlayout.addLayout(self.label_grid)
        self.setLayout(self.hboxlayout)
Exemple #4
0
class NameList(QDockWidget):
    def __init__(self, window):
        super(NameList, self).__init__('Current Plots')
        self.namelist_model = QStandardItemModel()
        self.namelist_view = QListView()
        self.namelist_view.setModel(self.namelist_model)
        self.setWidget(self.namelist_view)
        self.window = window
        self.plot_dict = {}

        self.namelist_view.doubleClicked.connect(self.activate_item)
        self.namelist_view.setContextMenuPolicy(QtConst.ActionsContextMenu)
        delete_action = QAction("Delete Selected", self.namelist_view)
        ###
        pause_action = QAction("Stop Script", self.namelist_view)
        delete_action.triggered.connect(self.delete_item)
        pause_action.triggered.connect(self.pause)
        self.namelist_view.addAction(delete_action)
        ###
        self.namelist_view.addAction(pause_action)

    def activate_item(self, index):
        item = self.namelist_model.itemFromIndex(index)
        plot = self.plot_dict[str(item.text())]
        if plot.closed:
            plot.closed = False
            self.window.add_plot(plot)

    def delete_item(self):
        index = self.namelist_view.currentIndex()
        item = self.namelist_model.itemFromIndex(index)
        del self[str(item.text())]

    def pause(self):
        sock = socket.socket()
        sock.connect(('localhost', 9091))
        sock.send(b'stop')
        sock.close()

    def __getitem__(self, item):
        return self.plot_dict[item]

    def __setitem__(self, name, plot):
        model = QStandardItem(name)
        model.setEditable(False)
        self.namelist_model.appendRow(model)
        self.plot_dict[name] = plot

    def __contains__(self, value):
        return value in self.plot_dict

    def __delitem__(self, name):
        self.namelist_model.removeRow(self.namelist_model.findItems(name)[0].index().row())
        self.plot_dict[name].close()
        del self.plot_dict[name]

    def keys(self):
        return list(self.plot_dict.keys());
Exemple #5
0
class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()

        self.item_list = ['item %s' % i for i in range(11)]  # 1
        self.model_1 = QStringListModel(self)
        self.model_1.setStringList(self.item_list)

        self.model_2 = QStringListModel(self)  # 2

        self.listview_1 = QListView(self)  # 3
        self.listview_1.setModel(self.model_1)
        self.listview_1.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.listview_1.doubleClicked.connect(
            lambda: self.change_func(self.listview_1))

        self.listview_2 = QListView(self)  # 4
        self.listview_2.setModel(self.model_2)
        self.listview_2.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.listview_2.doubleClicked.connect(
            lambda: self.change_func(self.listview_2))

        self.pic_label = QLabel(self)  # 5
        self.pic_label.setPixmap(QPixmap('arrow.png'))

        self.h_layout = QHBoxLayout()
        self.h_layout.addWidget(self.listview_1)
        self.h_layout.addWidget(self.pic_label)
        self.h_layout.addWidget(self.listview_2)
        self.setLayout(self.h_layout)

    def change_func(self, listview):
        if listview == self.listview_1:  # 6
            self.model_2.insertRows(self.model_2.rowCount(), 1)

            data = self.listview_1.currentIndex().data()
            index = self.model_2.index(self.model_2.rowCount() - 1)
            self.model_2.setData(index, data)
        else:  # 7
            self.model_2.removeRows(self.listview_2.currentIndex().row(), 1)
class SettingWindow(QWidget):
#	on_addButtonClicked=pyqtSignal()
#	on_removeButtonClicked=pyqtSignal()
#	on_okButtonClicked=pyqtSignal()
	finished=pyqtSignal()
	def __init__(self):
		QWidget.__init__(self)
		self.listview=QListView(self)
		self.addButton=QPushButton(self)
		self.removeButton=QPushButton(self)
		self.resize(630,440)
		self.okButton=QPushButton(self)
		self.listview.setGeometry(30,30,410,351)
		self.addButton.setGeometry(490,40,80,22)
		self.addButton.setText("add")
		self.addButton.clicked.connect(self.click_add)
		self.removeButton.setGeometry(490,80,80,22)
		self.removeButton.setText("remove")
		self.removeButton.clicked.connect(self.click_remove)
		self.okButton.setGeometry(490,150,80,22)
		self.okButton.setText("ok")
		self.okButton.clicked.connect(self.click_ok)
#		self.aw=null


		self.fresh()
	def click_ok(self):
		self.finished.emit()
		self.close()
	def click_add(self):
		self.aw=AddWindow()
		self.aw.show()
		self.aw.okSig.connect(self.fresh)
	def click_remove(self):
		self.remove()
	def fresh(self):
		confFile=open("conf","r")
		self.listModel=QStandardItemModel()
		self.itemList=cPickle.load(confFile)
		confFile.close()
		for  item in self.itemList:
			itemView=QStandardItem(QIcon(item.path),item.name)
			itemView.setEditable(False)
			self.listModel.appendRow(itemView)
			self.listview.setModel(self.listModel)
	def remove(self):
		index=self.listview.currentIndex().row()
		self.itemList.pop(index)
		self.listModel.removeRow(index)
		confFile=open("conf","w")
		cPickle.dump(self.itemList,confFile)
		confFile.close()
Exemple #7
0
class HardwareSelector(QDialog):
    def __init__(self, host, port, parent=None):
        QDialog.__init__(self, parent)
        self.host = host
        self.port = port

        self._layout = QVBoxLayout(self)
        self.setWindowTitle("Hardware on " + self.host + ":" + str(self.port))
        self.setMinimumSize(800, 600)

        self.hardware = None
        self.selectedHW = None
        self._model = None

        self._lbl_status = QLabel()
        self._layout.addWidget(self._lbl_status)

        self._layoutH = QHBoxLayout()
        self._layout.addLayout(self._layoutH)

        self._hwlist = QListView()
        self._layoutH.addWidget(self._hwlist)

        self._lbl_hw = QLabel()
        self._lbl_hw.setMinimumWidth(400)
        self._lbl_hw.setMargin(10)
        self._lbl_hw.setFont(QFontDatabase.systemFont(QFontDatabase.FixedFont))
        #self._layoutH.addWidget(self._hwlabel)
        self._hwscroll = QScrollArea()
        self._hwscroll.setWidget(self._lbl_hw)
        self._layoutH.addWidget(self._hwscroll)

        self._layoutB = QHBoxLayout()
        self._layout.addLayout(self._layoutB)

        self._btn_select = QPushButton("Select")
        self._layoutB.addWidget(self._btn_select)
        self._btn_rescan = QPushButton("Rescan")
        self._layoutB.addWidget(self._btn_rescan)
        self._btn_cancel = QPushButton("Cancel")
        self._layoutB.addWidget(self._btn_cancel)

        self._btn_select.clicked.connect(self._select)
        self._btn_cancel.clicked.connect(lambda:
                                         (self._quitScan(), self.close()))
        self._btn_rescan.clicked.connect(self._prepareScan)

        self._disable()
        self._start()

    def _start(self, ret=None):
        if not ret:
            self._prepareScan()
            ret = self._getHardware()
        if ret:
            self.hardware = ret[0]
            if len(self.hardware) == 0:
                self._lbl_status.setText(
                    "No Hardware detected. Is Caffepath set?")
            elif ret[1] == 0:
                self._lbl_status.setText("Currently selected CPU: " +
                                         ret[0][0]["name"])
            else:
                self._lbl_status.setText("Currently selected GPU " +
                                         str(ret[1]) + ": " +
                                         ret[0][ret[1]]["name"])
            self._model = self.HardwareListModel(self.hardware)
            self._hwlist.setModel(self._model)
            self._hwlist.selectionModel().currentChanged.connect(
                self._onSelection)
            self._enable()

    def _enable(self):
        self._hwlist.setEnabled(True)
        self._btn_rescan.setEnabled(True)

    def _disable(self):
        self._hwlist.setEnabled(False)
        self._btn_select.setEnabled(False)
        self._btn_rescan.setEnabled(False)
        self._lbl_hw.setText("")
        if self._hwlist.selectionModel():
            self._hwlist.selectionModel().currentChanged.disconnect()
            self._hwlist.setModel(None)

    def _select(self):
        self.selectedHW = self._hwlist.currentIndex().row()
        self.close()

    def _onSelection(self):
        row = self._hwlist.currentIndex().row()
        if row != -1:
            self._lbl_hw.setText(self._getText(row))
            self._lbl_hw.adjustSize()
            self._btn_select.setEnabled(True)
        else:
            self._lbl_hw.setText("")

    def _getText(self, row):
        log = self.hardware[row]["log"]
        text = ""
        for l in log:
            text += l + "\n"
        return text

    def _prepareScan(self):
        self._disable()
        ct = buildTransaction(self.host, self.port)
        if ct:
            self.ct = ct
            msg = {"key": Protocol.SCANHARDWARE}
            self.ct.send(msg)
            self.ct.bufferReady.connect(self._processScan)
            self.ct.socketClosed.connect(self._socketClosed)
            self._lbl_status.setText("Start scanning...")
        else:
            self._lbl_status.setText("Failed to start Scan.")

    def _processScan(self):
        msg = self.ct.asyncRead()
        if msg["status"]:
            if "finished" in msg.keys():
                if msg["finished"]:
                    self._quitScan()
                    self._lbl_status.setText("Scan finished.")
                    self._start([msg["hardware"], msg["current"]])
                else:
                    if "id" in msg.keys():
                        self._lbl_status.setText("Found GPU " +
                                                 str(msg["id"]) + ": " +
                                                 msg["name"])
                    else:
                        self._lbl_status.setText("Found CPU: " + msg["name"])
        else:
            self._lbl_status.setText("Scan failed: " + msg["error"])

    def _socketClosed(self):
        self._quitScan()
        self._enable()
        self._lbl_status.setText("Connection lost!")

    def _quitScan(self):
        if hasattr(self, "ct"):
            self.ct.bufferReady.disconnect()
            self.ct.socketClosed.disconnect()
            self.ct.close()
            del self.ct

    def _getHardware(self):
        msg = {"key": Protocol.GETHARDWARE}
        ret = sendMsgToHost(self.host, self.port, msg)
        if ret and "hardware" in ret:
            return [ret["hardware"], ret["current"]]

    class HardwareListModel(QAbstractListModel):
        def __init__(self, data):
            QAbstractListModel.__init__(self)
            self.data = data

        def rowCount(self, parent=None, *args, **kwargs):
            return len(self.data)

        def data(self, index, role=None):
            row = index.row()
            if role == Qt.DisplayRole:
                if row == 0:
                    return "CPU: " + self.data[row]["name"]
                return "GPU " + str(
                    self.data[row]["id"]) + ": " + self.data[row]["name"]
Exemple #8
0
class MusicPlayer(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.options = self.parent().options

        self.ffmpeg = self.options['paths']['ffmpeg_bin']
        self.thumbnails = self.options['paths']['thumbnails']
        self.thumb_width = self.options['thumbnail']['width']
        self.thumb_height = self.options['thumbnail']['height']

        self.jumping = False
        self.blocked = False
        self.durations = {}
        self.playback_value = 0

        self.text = ["None", "Repeat", "Random"]
        self.playlist_list = []
        self.values = [
            QMediaPlaylist.Loop, QMediaPlaylist.CurrentItemInLoop,
            QMediaPlaylist.Random
        ]

        # Thumbnail widget
        self.image_label = QLabel()

        # Control widgets
        self.playButton = QToolButton(clicked=self.play)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

        self.stopButton = QToolButton(clicked=self.stop)
        self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.stopButton.setEnabled(False)

        self.playbackButton = QToolButton(clicked=self.playback_mode)
        self.playbackButton.setText(self.text[0])

        self.nextButton = QToolButton(clicked=self.next_song)
        self.nextButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))

        self.previousButton = QToolButton(clicked=self.previous_song)
        self.previousButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipBackward))

        self.muteButton = QToolButton(clicked=self.mute_clicked)
        self.muteButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume))

        self.volumeSlider = QSlider(Qt.Horizontal,
                                    sliderMoved=self.change_volume)
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setPageStep(1)
        self.volumeSlider.setValue(50)

        # Player and playlist setup

        self.player = QMediaPlayer()
        self.player.setVolume(50)
        self.player.stateChanged.connect(self.waveform)

        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(self.values[0])
        self.playlist.setCurrentIndex(1)

        self.player.setPlaylist(self.playlist)

        self.playlistModel = PlaylistModel()
        self.playlistModel.setPlaylist(self.playlist)

        self.playlistView = QListView()
        self.playlistView.setModel(self.playlistModel)
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))
        self.playlistView.activated.connect(self.jump)
        self.playlistView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.playlistView.customContextMenuRequested.connect(
            self.list_view_menu)
        self.playlist.currentIndexChanged.connect(
            lambda position: self.change_thumbnail(position))

        song_search = QLineEdit()
        song_search.textChanged.connect(self.search)
        song_search.setClearButtonEnabled(True)

        # Playlist
        self.playlist_name = QComboBox()
        self.playlist_name.currentTextChanged.connect(self.switch_playlist)
        self.refresh_lists()

        self.up_button = QToolButton(clicked=self.move_up)
        self.up_button.setIcon(self.style().standardIcon(QStyle.SP_ArrowUp))
        self.down_button = QToolButton(clicked=self.move_down)
        self.down_button.setIcon(self.style().standardIcon(
            QStyle.SP_ArrowDown))

        # Sound wave widget

        self.wave_graphic = WaveGraphic(self)
        #self.wave_graphic.hide()

        # Testing slider again
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)

        # Shortcuts
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self, song_search.setFocus)

        # Layouts setup

        playlist_layout = QHBoxLayout()
        playlist_layout.addWidget(self.playlist_name)
        playlist_layout.addWidget(self.up_button)
        playlist_layout.addWidget(self.down_button)

        control_layout = QHBoxLayout()
        control_layout.setContentsMargins(0, 0, 0, 0)
        control_layout.addWidget(self.stopButton)
        control_layout.addWidget(self.previousButton)
        control_layout.addWidget(self.playButton)
        control_layout.addWidget(self.nextButton)
        control_layout.addWidget(self.muteButton)
        control_layout.addWidget(self.volumeSlider)
        control_layout.addWidget(self.playbackButton)

        display_layout = QVBoxLayout()
        display_layout.addWidget(song_search)
        display_layout.addWidget(self.playlistView)
        display_layout.addLayout(playlist_layout)

        music_layout = QVBoxLayout()
        music_layout.addWidget(self.image_label)
        music_layout.addWidget(self.slider)
        music_layout.addLayout(control_layout)

        main_layout = QHBoxLayout()
        main_layout.addLayout(music_layout)
        main_layout.addLayout(display_layout)

        main_2_layout = QVBoxLayout()
        main_2_layout.addLayout(main_layout)
        main_2_layout.addWidget(self.wave_graphic)

        self.setLayout(main_2_layout)

    def waveform(self, status):
        if status == QMediaPlayer.PlayingState:
            self.wave_graphic.start()
        elif status == QMediaPlayer.PausedState:
            self.wave_graphic.pause()
        else:
            self.wave_graphic.stop()

    def list_view_menu(self, point):
        menu = QMenu("Menu", self)
        recommend_action = QAction('&Recommend Songs', self)
        menu.addAction(recommend_action)

        # TODO: [FEATURE] add rename song
        recommend_action.triggered.connect(
            lambda: self.parent().call_download_manager(self.get_links()))

        rename_action = QAction('&Rename', self)
        menu.addAction(rename_action)

        # TODO: [FEATURE] add rename song
        rename_action.triggered.connect(lambda: print("rename"))

        # Show the context menu.
        menu.exec_(self.playlistView.mapToGlobal(point))

    def get_links(self):
        title = self.playlistView.selectedIndexes()[0].data()
        link = getYoutubeURLFromSearch(title)
        if len(link) > 1:
            return youtube_recommendations(link)

    def move_up(self):
        index = self.playlistView.currentIndex().row()
        if index - 1 >= 0:
            item, above = self.playlist.media(index), self.playlist.media(
                index - 1)
            self.playlist.removeMedia(index)
            self.playlist.removeMedia(index - 1)
            self.playlist.insertMedia(index - 1, item)
            self.playlist.insertMedia(index, above)
            self.blocked = True
            self.playlistView.setCurrentIndex(
                self.playlistModel.index(index - 1, 0))
            self.blocked = False
            self.stop()

    def move_down(self):
        index = self.playlistView.currentIndex().row()
        if index + 1 <= self.playlistModel.rowCount():
            item, below = self.playlist.media(index), self.playlist.media(
                index + 1)
            self.playlist.removeMedia(index + 1)
            self.playlist.removeMedia(index)
            self.playlist.insertMedia(index, below)
            self.playlist.insertMedia(index + 1, item)
            self.blocked = True
            self.playlistView.setCurrentIndex(
                self.playlistModel.index(index + 1, 0))
            self.blocked = False
            self.stop()

    def search(self, part_of_song):
        for index in range(self.playlistModel.rowCount()):
            item = self.playlistModel.data(self.playlistModel.index(
                index, 0)).lower()
            self.playlistView.setRowHidden(index,
                                           part_of_song.lower() not in item)

    def change_thumbnail(self, position=0):

        self.playlistView.setCurrentIndex(self.playlistModel.index(
            position, 0))

        song = self.playlistView.selectedIndexes()[0].data()
        if self.wave_graphic.is_song_cached(song):
            self.wave_graphic.load_waves(song)
        else:
            wc_ = WaveConverter(song, self.wave_graphic.set_wav)
            wc_.convert()

        if self.playlistView.currentIndex().data() is None or self.blocked:
            return

        max_ratio = 0
        img = None

        for item in listdir(self.thumbnails):
            if item.endswith('.jpg'):
                ratio = similar(
                    item,
                    self.playlistView.currentIndex().data().replace(
                        '.mp3', '.jpg'))
                if ratio > max_ratio:
                    max_ratio = ratio
                    img = item

        if img:
            p = QPixmap(self.thumbnails + img)
            self.image_label.setPixmap(
                p.scaled(self.thumb_width, self.thumb_height,
                         Qt.KeepAspectRatio))

    def switch_playlist(self, current_text):
        self.playlist.clear()
        if current_text == "No Playlist":
            self.refresh()
        else:
            if read_playlist(current_text):
                songs = read_playlist(current_text).split('\n')
                for song in songs:
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(song)))

    def refresh(self):
        # Change it so it will go to same song.
        if self.playlist_name.currentText() != "No Playlist":
            return

        paths = fetch_options()['paths']['music_path'].split(';')

        current_songs = [
            self.playlistModel.data(self.playlistModel.index(row, 0))
            for row in range(self.playlistModel.rowCount())
        ]

        for path in paths:
            if not path:
                continue
            for item in listdir(path):
                if isfile(join(path, item)) and item.endswith(".mp3") and (
                        item not in current_songs):
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(join(path, item))))

    def refresh_lists(self):
        path = fetch_options()['paths']['playlist']
        self.playlist_name.clear()
        self.playlist_list = ["No Playlist"]
        self.playlist_name.addItem("No Playlist")
        for item in listdir(path):
            if isfile(join(path, item)) and item.endswith(".lst"):
                self.playlist_list.append(item.split('.')[0])
                self.playlist_name.addItem(item.split('.')[0])

    def playback_mode(self):
        # Normal -> Loop -> Random
        def up_value(value, max_value=3):
            if value + 1 == max_value:
                return 0
            return value + 1

        self.playback_value = up_value(self.playback_value)
        self.playlist.setPlaybackMode(self.values[self.playback_value])
        self.playbackButton.setText(self.text[self.playback_value])

    def jump(self, index):
        if index.isValid() and not self.blocked:
            self.playlist.setCurrentIndex(index.row())
            self.jumping = True
            self.play()

    def play(self):
        if self.blocked:
            return
        if self.player.state() != QMediaPlayer.PlayingState or self.jumping:
            self.player.play()
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
            self.jumping = False
        else:
            self.player.pause()
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))
        self.stopButton.setEnabled(True)

    def change_volume(self, value):
        self.player.setVolume(value)

    def stop(self):
        if self.player.state() != QMediaPlayer.StoppedState:
            self.player.stop()
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.stopButton.setEnabled(False)

    def next_song(self):
        self.playlist.next()
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

    def previous_song(self):
        self.playlist.previous()
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

    def mute_clicked(self):
        self.player.setMuted(not self.player.isMuted())
        self.muteButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume if not self.player.isMuted() else QStyle.
            SP_MediaVolumeMuted))

    def durationChanged(self, duration):
        duration /= 1000
        self.slider.setMaximum(duration)

    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)
Exemple #9
0
class ClientGui(QWidget):
    def __init__(self):
        self.service_msg_deq = []  # очередь сервисных сообщений, очищать!
        self.icon_user = QIcon("user.svg")
        self.icon_new_msg = QIcon("message.svg")
        super().__init__()

        self.get_login_dialog()

    def initUI(self):

        # Кнопки: добавить/удалить контакты в контакт лист
        self.button_add_contact = QPushButton('add', self)
        self.button_add_contact.clicked.connect(self.add_contact)
        self.button_del_contact = QPushButton('del', self)
        self.button_del_contact.clicked.connect(self.del_contact)
        self.button_settings = QPushButton('men', self)
        self.button_settings.setEnabled(False)  # не работает
        self.button_connect = QPushButton('conn', self)
        self.button_connect.setEnabled(False)  # не работает

        self.box_button = QHBoxLayout()
        self.box_button.addWidget(self.button_add_contact)
        self.box_button.addWidget(self.button_del_contact)
        self.box_button.addWidget(self.button_settings)
        self.box_button.addWidget(self.button_connect)

        # создаю модель для листа контактов, подключаю отображение
        cl = bd_client_app.BDContacts().get_contacts()
        self.model_cl = QStandardItemModel()
        for user in cl:
            row = QStandardItem(self.icon_user, user)
            self.model_cl.appendRow(row)

        self.contact_list = QListView()
        self.contact_list.setModel(self.model_cl)
        self.contact_list.setSelectionMode(QListView.SingleSelection)
        self.contact_list.setEditTriggers(QListView.NoEditTriggers)
        self.contact_list.clicked.connect(self.select_conlist)

        # строка и кнопка отправки сообщений
        qButton = QPushButton('>>', self)
        qButton.clicked.connect(self.send_click)
        self.sendBox = QLineEdit(self)
        self.sendBox.returnPressed.connect(self.send_click)

        self.messageBox = QStackedWidget()
        # два словаря, в первом: логин ключ виджет значение, второй наоборот
        self.messageBox_dict_ctw = {}
        self.messageBox_dict_wtc = {}
        for user in cl:
            self.messageBox_dict_ctw[user] = QListWidget()
            self.messageBox_dict_wtc[self.messageBox_dict_ctw[user]] = user
            self.messageBox.addWidget(self.messageBox_dict_ctw[user])

        grid = QGridLayout()
        # строка, столбец, растянуть на строк, растянуть на столбцов
        grid.addWidget(self.contact_list, 0, 0, 2, 3)
        grid.addLayout(self.box_button, 2, 0)
        grid.addWidget(self.messageBox, 0, 3, 2, 3)
        grid.addWidget(self.sendBox, 2, 3, 1, 2)
        grid.addWidget(qButton, 2, 5)

        grid.setSpacing(5)
        grid.setColumnMinimumWidth(3, 200)
        grid.setColumnStretch(3, 10)
        self.setLayout(grid)

        self.resize(800, 300)
        self.center()
        self.setWindowTitle('Avocado')
        self.setWindowIcon(QIcon('icon.svg'))
        self.show()

    def initThreads(self):
        self.print_thread = ClientThreads(self.client, self)
        self.print_thread.print_signal.connect(self.add_message)
        self.print_thread.start()

    def get_login_dialog(self):

        text, ok = QInputDialog.getText(self, 'Login', 'Connect with login:')
        self.login_name = str(text)

        if ok:
            self.service_msg_deq.clear()  # жду свой ответ

            self.init_client()
            self.initThreads()

            # while not self.service_msg_deq:
            #     print(self.service_msg_deq)
            #     pass  # жду ответ
            # if self.service_msg_deq[0] is True:
            time.sleep(1)
            self.initUI()
            # else:
            #     self.exit()
        else:
            self.exit()

    def init_client(self):
        self.client = client.Client(self.login_name, "localhost", 7777)
        self.client.start_th_gui_client()

    def center(self):
        # центрирую окно
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    @pyqtSlot()
    def send_click(self):
        text_to_send = self.sendBox.text()
        if text_to_send.rstrip():
            self.messageBox.currentWidget().addItem("<< " + text_to_send)
            self.client.inp_queue.put(text_to_send)
        self.sendBox.clear()

    @pyqtSlot(QModelIndex)
    def select_conlist(self, curr):
        self.messageBox.setCurrentIndex(curr.row())
        self.model_cl.itemFromIndex(curr).setIcon(self.icon_user)
        self.client.to_user = self.messageBox_dict_wtc[
            self.messageBox.currentWidget()]

    @pyqtSlot(tuple)
    def add_message(self, message):
        msg = message[0]
        from_u = message[1]

        try:
            client_widget = self.messageBox_dict_ctw[from_u]
        except KeyError:
            mesg_con_log.error("Message from user from not in contact list:")
            mesg_con_log.error("%s, %s" % (from_u, msg))
        else:
            client_widget.addItem(">> " + msg)
            message_from = self.model_cl.findItems(from_u)[0]
            if self.contact_list.currentIndex() != self.model_cl.indexFromItem(
                    message_from):
                message_from.setIcon(self.icon_new_msg)

    @pyqtSlot()
    def del_contact(self):
        user = self.client.to_user
        self.client.inp_queue.put("del_contact " + user)
        self.messageBox.removeWidget(self.messageBox_dict_ctw[user])
        self.model_cl.takeRow(
            self.model_cl.indexFromItem(
                self.model_cl.findItems(user)[0]).row())

    @pyqtSlot()
    def add_contact(self):
        user = self.sendBox.text()
        self.service_msg_deq.clear()  # жду свой ответ
        self.client.inp_queue.put("add_contact " + user)

        while not self.service_msg_deq:
            pass  # жду ответ

        if self.service_msg_deq[0] is True:
            row = QStandardItem(self.icon_user, user)
            self.model_cl.appendRow(row)

            self.messageBox_dict_ctw[user] = QListWidget()
            self.messageBox_dict_wtc[self.messageBox_dict_ctw[user]] = user
            self.messageBox.addWidget(self.messageBox_dict_ctw[user])
        else:
            pass

        self.sendBox.clear()
Exemple #10
0
class MainWindow(QMainWindow):
    logout_signal = pyqtSignal()
    send_message_signal = pyqtSignal(str, str)
    start_chatting_signal = pyqtSignal(str)
    switch_to_add_contact = pyqtSignal()
    switch_to_del_contact = pyqtSignal()

    def __init__(self, client_name):
        super().__init__()

        self.setFixedSize(756, 574)
        self.setWindowTitle(f'Python Messenger ({client_name})')

        central_widget = QWidget()

        self.label_contacts = QLabel('Contact list:', central_widget)
        self.label_contacts.setGeometry(QRect(10, 0, 101, 16))

        self.add_contact_btn = QPushButton('Add contact', central_widget)
        self.add_contact_btn.setGeometry(QRect(10, 450, 121, 31))

        self.remove_contact_btn = QPushButton('Remove contact', central_widget)
        self.remove_contact_btn.setGeometry(QRect(140, 450, 121, 31))

        self.label_history = QLabel('Chat room:', central_widget)
        self.label_history.setGeometry(QRect(300, 0, 391, 21))

        self.text_message = QTextEdit(central_widget)
        self.text_message.setGeometry(QRect(300, 360, 441, 71))

        self.label_new_message = QLabel('Enter message here:', central_widget)
        self.label_new_message.setGeometry(QRect(300, 330, 450, 16))

        self.toolbar = self.addToolBar('Formatting')

        self.char_style_resolver = {
            'bold': self.set_text_to_bold,
            'italic': self.set_text_to_italic,
            'underline': self.set_text_to_underline,
        }
        self.font_weight = 50
        self.font_italic = False
        self.font_underline = False

        self.text_font = QFont()

        self.text_bold = QAction(QIcon('client/ui/icons/b.jpg'), 'Bold', self)
        self.text_bold.triggered.connect(lambda: self.set_char_style('bold'))

        self.text_italic = QAction(QIcon('client/ui/icons/i.jpg'), 'Italic',
                                   self)
        self.text_italic.triggered.connect(
            lambda: self.set_char_style('italic'))

        self.text_underline = QAction(QIcon('client/ui/icons/u.jpg'),
                                      'Underline', self)
        self.text_underline.triggered.connect(
            lambda: self.set_char_style('underline'))

        self.toolbar.addActions(
            [self.text_bold, self.text_italic, self.text_underline])

        self.list_contacts = QListView(central_widget)
        self.list_contacts.setGeometry(QRect(10, 20, 251, 411))
        self.contacts_model = QStandardItemModel()
        self.list_contacts.setModel(self.contacts_model)

        self.list_messages = QListView(central_widget)
        self.list_messages.setGeometry(QRect(300, 20, 441, 301))
        self.messages_model = QStandardItemModel()
        self.list_messages.setModel(self.messages_model)
        self.is_list_messages_disable = False

        self.send_btn = QPushButton('Send', central_widget)
        self.send_btn.setGeometry(QRect(610, 450, 131, 31))

        self.clear_btn = QPushButton('Clear', central_widget)
        self.clear_btn.setGeometry(QRect(460, 450, 131, 31))

        self.setCentralWidget(central_widget)

        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 756, 21))

        self.menu = QMenu('File', self.menubar)
        self.menu_2 = QMenu('Contacts', self.menubar)

        self.setMenuBar(self.menubar)

        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

        self.menu_exit = QAction('Exit', self)
        self.menu_logout = QAction('Logout', self)
        self.menu.addAction(self.menu_exit)
        self.menu.addAction(self.menu_logout)

        self.add_contact_menu = QAction('Add new', self)
        self.del_contact_menu = QAction('Remove some', self)
        self.menu_2.addAction(self.add_contact_menu)
        self.menu_2.addAction(self.del_contact_menu)
        self.menu_2.addSeparator()

        self.menubar.addAction(self.menu.menuAction())
        self.menubar.addAction(self.menu_2.menuAction())

        self.message = QMessageBox()

        self.menu_exit.triggered.connect(qApp.exit)
        self.menu_logout.triggered.connect(self.menu_logout_handler)
        self.send_btn.clicked.connect(self.send_btn_handler)
        self.add_contact_btn.clicked.connect(self.add_contact_btn_handler)
        self.add_contact_menu.triggered.connect(self.add_contact_btn_handler)
        self.remove_contact_btn.clicked.connect(self.del_contact_btn_handler)
        self.del_contact_menu.triggered.connect(self.del_contact_btn_handler)
        self.list_contacts.doubleClicked.connect(
            self.list_contacts_click_handler)

    def set_elements_disable_status(self, status):
        if not isinstance(status, bool):
            raise ValueError(
                f'Disable status must be bool. Got {type(status)}')

        self.send_btn.setDisabled(status)
        self.clear_btn.setDisabled(status)
        self.text_message.setDisabled(status)
        self.is_list_messages_disable = status

    def render_welcome_message(self):
        self.messages_model.clear()
        msg = QStandardItem(
            f'Doubleclick to contact in contact list for start chatting.')
        msg.setEditable(False)
        self.messages_model.appendRow(msg)

    def render_contacts(self, contacts):
        self.contacts_model.clear()

        if contacts and isinstance(contacts, list):
            for contact in contacts:
                rendered_contact = QStandardItem(contact.friend)
                rendered_contact.setEditable(False)
                self.contacts_model.appendRow(rendered_contact)

    def render_messages(self, friend, client_name, messages):
        self.messages_model.clear()

        if messages and isinstance(messages, list):
            for message in messages:
                self.render_message(friend, client_name, message)

            self.list_messages.scrollToBottom()

    def render_message(self, friend, client_name, message):
        if not self.is_list_messages_disable:
            if message.from_client in (friend, client_name):
                date = message.created.replace(microsecond=0)
                text = message.text
                from_client = message.from_client

                msg = QStandardItem(f'{date}\n{from_client}:\n{text}')
                msg.setEditable(False)

                if from_client == client_name:
                    msg.setTextAlignment(Qt.AlignRight)
                    msg.setBackground(QBrush(QColor(240, 240, 240)))

                self.messages_model.appendRow(msg)
                self.list_messages.scrollToBottom()

    def menu_logout_handler(self):
        self.logout_signal.emit()

    def send_btn_handler(self):
        message = self.text_message.toPlainText()
        to_client_name = self.list_contacts.currentIndex().data()
        if message and to_client_name:
            self.send_message_signal.emit(to_client_name, message)
            self.text_message.clear()

    def add_contact_btn_handler(self):
        self.switch_to_add_contact.emit()

    def del_contact_btn_handler(self):
        self.switch_to_del_contact.emit()

    def list_contacts_click_handler(self):
        self.messages_model.clear()
        self.set_elements_disable_status(False)
        friend = self.list_contacts.currentIndex().data()
        self.start_chatting_signal.emit(friend)

    def set_char_style(self, style):
        cursor = self.text_message.textCursor()
        char_format = QTextCharFormat()
        self.char_style_resolver[style](char_format)
        cursor.mergeCharFormat(char_format)

    def set_text_to_bold(self, char_format):
        bold_weight = 600
        thin_weight = 50

        weight = bold_weight if self.font_weight < bold_weight else thin_weight
        char_format.setFontWeight(weight)
        self.font_weight = weight

    def set_text_to_italic(self, char_format):
        char_format.setFontItalic(not self.font_italic)
        self.font_italic = not self.font_italic

    def set_text_to_underline(self, char_format):
        char_format.setFontUnderline(not self.font_underline)
        self.font_underline = not self.font_underline
Exemple #11
0
class PwdManager(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowTitleHint)
        self.setWindowTitle('Password Manager')
        self.setFixedSize(400, 300)
        self.PwdViewer = QListView()
        self.PwdViewer.clicked.connect(self.ClickPwd)
        self.AddButton = QPushButton('Add')
        self.AddButton.clicked.connect(self.AddPwd)
        self.DelButton = QPushButton('Delete')
        self.DelButton.clicked.connect(self.DelPwd)
        self.PwdBox = QLineEdit()
        self.PwdBox.textEdited.connect(self.PwdChanged)

        vbox = QVBoxLayout()
        vbox.addWidget(self.AddButton)
        vbox.addWidget(self.DelButton)
        vbox.addStretch(1)
        hbox = QHBoxLayout()
        hbox.addWidget(self.PwdViewer)
        hbox.addLayout(vbox)
        MainBox = QVBoxLayout()
        MainBox.addWidget(self.PwdBox)
        MainBox.addLayout(hbox)
        self.setLayout(MainBox)

    def showEvent(self, event):
        self.center()
        self.LoadPwdToList()
        if self.Model.rowCount() == 0:
            self.AddPwd()
        self.IsChanged = False

    def closeEvent(self, event):
        self.RemoveEmpty()
        pwdf = open('password.pwd', 'w')
        for index in range(self.Model.rowCount()):
            pwdf.write(self.Model.data(self.Model.index(index, 0)) + '\n')
        pwdf.close()
        if self.IsChanged:
            self.done(1)
        else:
            self.done(0)

    def center(self):
        frameGm = self.frameGeometry()
        screen = QApplication.desktop().screenNumber(
            QApplication.desktop().cursor().pos())
        centerPoint = QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

    def LoadPwdToList(self):
        if not os.path.exists(r'password.pwd'):
            open("password.pwd", "wb").close()
        pwdf = open('password.pwd', 'r')
        pwdlist = pwdf.read().splitlines()
        pwdf.close()
        self.Model = QStandardItemModel(self.PwdViewer)
        for pwd in pwdlist:
            item = QStandardItem(pwd)
            item.setEditable(False)
            self.Model.appendRow(item)
        self.PwdViewer.setModel(self.Model)
        self.PwdViewer.setCurrentIndex(self.Model.index(0, 0))
        self.GetPwd(self.PwdViewer.currentIndex())

    def ClickPwd(self, index):
        self.RemoveEmpty()
        if self.Model.rowCount() == 0:
            self.AddPwd()
        self.GetPwd(index)

    def GetPwd(self, index):
        self.PwdBox.setText(self.Model.data(index))
        self.PwdBox.setFocus()

    def PwdChanged(self):
        self.IsChanged = True
        self.Model.setData(self.PwdViewer.currentIndex(), self.PwdBox.text())
        if self.PwdBox.text() == '':
            self.DelPwd()

    def DelPwd(self):
        self.Model.removeRow(self.PwdViewer.currentIndex().row())
        self.GetPwd(self.PwdViewer.currentIndex())
        if self.Model.rowCount() == 0:
            self.AddPwd()

    def AddPwd(self):
        item = QStandardItem()
        item.setEditable(False)
        self.Model.appendRow(item)
        self.PwdViewer.setCurrentIndex(
            self.Model.index(self.Model.rowCount() - 1, 0))
        self.GetPwd(self.PwdViewer.currentIndex())

    def RemoveEmpty(self):
        for item in self.Model.findItems('', Qt.MatchFixedString):
            self.Model.removeRow(item.row())
Exemple #12
0
class Documents_Tab(QWidget):
    
    def __init__(self):
        super(QWidget, self).__init__()
        
        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)
        
        
        self.tree_labels = QWidget()
        self.tree_labels_layout = QHBoxLayout()
        self.tree_labels.setLayout(self.tree_labels_layout)
        
        self.documents_tree_label = QLabel("List of Documents for Group:")
        self.documents_tree_label.setAlignment(Qt.AlignRight)
        self.documents_tree_group = QLabel("My Group")
        self.documents_tree_group.setAlignment(Qt.AlignLeft)
        self.tree_labels_layout.addWidget(self.documents_tree_label)
        self.tree_labels_layout.addWidget(self.documents_tree_group)
        
        self.tree_labels_layout.setAlignment(Qt.AlignCenter)

        
        self.documents_tree = QListView()
        self.documents_tree_model = QStandardItemModel()
        self.documents_tree.setModel(self.documents_tree_model)
        # self.documents_tree_model.appendRow(StandardItem("medsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"))
        #self.documents_tree.setGeometry(30,10,200,400)
        
        self.create_doc_widget = QWidget()
        
        self.create_doc_widget_layout = QVBoxLayout()
        self.create_doc_widget.setLayout(self.create_doc_widget_layout)
        
        self.create_doc_edits_widget = QWidget()
        self.create_doc_edits_widget_layout = QHBoxLayout()
        self.create_doc_edits_widget.setLayout(self.create_doc_edits_widget_layout)
        
        self.create_doc_label = QLabel("Create a Document")
        self.create_doc_label.setAlignment(Qt.AlignCenter)
        self.create_doc_edit = QLineEdit()
        self.create_doc_button = QPushButton("Create")
        self.create_doc_button.clicked.connect(lambda: self.create_doc(self.create_doc_edit.text()))
        
        self.create_doc_edits_widget_layout.addWidget(self.create_doc_edit)
        self.create_doc_edits_widget_layout.addWidget(self.create_doc_button)
        
        self.create_doc_widget_layout.addWidget(self.create_doc_label)
        self.create_doc_widget_layout.addWidget(self.create_doc_edits_widget)
        ###########################################################################
        
        self.share_doc_widget = QWidget()
        
        self.share_doc_widget_layout = QVBoxLayout()
        self.share_doc_widget.setLayout(self.share_doc_widget_layout)
        
        self.share_doc_edits_widget = QWidget()
        self.share_doc_edits_widget_layout = QHBoxLayout()
        self.share_doc_edits_widget.setLayout(self.share_doc_edits_widget_layout)
        
        self.share_doc_label = QLabel("Share a Document")
        self.share_doc_label.setAlignment(Qt.AlignCenter)
        self.share_doc_edit = QLineEdit()
        self.share_doc_button = QPushButton("Share")
        self.share_doc_button.clicked.connect(lambda: self.share_doc(self.share_doc_edit.text()))
        
        self.share_doc_edits_widget_layout.addWidget(self.share_doc_edit)
        self.share_doc_edits_widget_layout.addWidget(self.share_doc_button)
        
        self.share_doc_widget_layout.addWidget(self.share_doc_label)
        self.share_doc_widget_layout.addWidget(self.share_doc_edits_widget)
        ###########################################################################
        self.delete_doc_widget = QWidget()
        self.delete_doc_widget_layout = QVBoxLayout()
        self.delete_doc_widget.setLayout(self.delete_doc_widget_layout)
        
        self.delete_doc_edits_widget = QWidget()
        self.delete_doc_edits_widget_layout = QHBoxLayout()
        self.delete_doc_edits_widget.setLayout(self.delete_doc_edits_widget_layout)
        
        self.delete_doc_label = QLabel("Delete a Document")
        self.delete_doc_label.setAlignment(Qt.AlignCenter)
        self.delete_doc_edit = QLineEdit()
        self.delete_doc_button = QPushButton("Delete")
        self.delete_doc_button.clicked.connect(lambda: self.delete_doc(self.delete_doc_edit.text()))
        
        self.delete_doc_edits_widget_layout.addWidget(self.delete_doc_edit)
        self.delete_doc_edits_widget_layout.addWidget(self.delete_doc_button)
        
        self.delete_doc_widget_layout.addWidget(self.delete_doc_label)
        self.delete_doc_widget_layout.addWidget(self.delete_doc_edits_widget)
        ###########################################################################
        self.main_layout.addWidget(self.tree_labels)
        self.main_layout.addWidget(self.documents_tree)
        self.main_layout.addWidget(self.create_doc_widget)
        self.main_layout.addWidget(self.share_doc_widget)
        self.main_layout.addWidget(self.delete_doc_widget)

    @pyqtSlot()
    def switch_group(self, group):
        #emit signal to group widget needed
        self.documents_tree_group.setText(group)

    @pyqtSlot()
    def get_group_docs(self):
        # db call to groups docs
        pass
    
    @pyqtSlot()
    def create_doc(self, text):
        if text == "":
            error = "No name for creating a doc"
            
        else:
            print("creating doc:", text)
            self.add_doc_to_list(text)
            self.create_doc_edit.setText("")
        
    
    @pyqtSlot()
    def share_doc(self, text):
        if text == "":
            error = "No link for sharing a doc"
            
        else:
            print("sharing doc:", text)
            self.add_doc_to_list(text)
            self.share_doc_edit.setText("")

    
    @pyqtSlot()
    def delete_doc(self, text):
        if text == "":
            error = "No name for sharing a doc"
            
        else:
            print("deleting doc", text)
            self.delete_doc_edit.setText("")
    
    @pyqtSlot()
    def add_doc_to_list(self, doc):
        link = StandardItem(doc)
        self.documents_tree_model.appendRow(link)    
    
    def contextMenuEvent(self, event):
        contextMenu = QMenu(self.documents_tree)
        newAct = contextMenu.addAction("Delete Doc")
        action = contextMenu.exec_(self.mapToGlobal(event.pos()))
        if action == newAct:
            index = self.documents_tree.currentIndex()
            itemText = index.data()
            itemRow = index.row()
            
            self.documents_tree_model.removeRow(itemRow)
            print(itemText)
            print(itemRow)
Exemple #13
0
class NameList(QDockWidget):
    def __init__(self, window):
        super(NameList, self).__init__('Current Plots')
        self.namelist_model = QStandardItemModel()
        self.namelist_view = QListView()
        self.namelist_view.setModel(self.namelist_model)
        self.setWidget(self.namelist_view)
        self.window = window
        self.plot_dict = {}

        self.namelist_view.doubleClicked.connect(self.activate_item)
        self.namelist_view.setContextMenuPolicy(QtConst.ActionsContextMenu)
        delete_action = QAction("Delete Selected", self.namelist_view)
        ###
        pause_action = QAction("Stop Script", self.namelist_view)
        delete_action.triggered.connect(self.delete_item)
        pause_action.triggered.connect(self.pause)
        self.namelist_view.addAction(delete_action)
        self.namelist_view.addAction(pause_action)

        open_action = QAction('Open 1D Data', self)
        open_action.triggered.connect(self.open_file_dialog)
        self.namelist_view.addAction(open_action)

        open_action_2 = QAction('Open 2D Data', self)
        open_action_2.triggered.connect(self.open_file_dialog_2)
        self.namelist_view.addAction(open_action_2)

    def open_file_dialog(self, directory='', header=0):
        file_path = self.file_dialog(directory=directory)

        header_array = []
        file_to_read = open(file_path, 'r')
        for i, line in enumerate(file_to_read):
            if i is header: break
            temp = line.split(":")
            header_array.append(temp)
        file_to_read.close()

        temp = np.genfromtxt(file_path,
                             dtype=float,
                             delimiter=',',
                             skip_header=1)
        data = np.transpose(temp)

        name_plot = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        pw = self.window.add_new_plot(1, name_plot)
        pw.plot(data[0], data[1], parametric=True, name=file_path, xname='X', xscale ='Arb. U.',\
         yname='Y', yscale ='Arb. u.', scatter='False')

    def open_file_dialog_2(self, directory='', header=0):
        file_path = self.file_dialog(directory=directory)

        header_array = []
        file_to_read = open(file_path, 'r')
        for i, line in enumerate(file_to_read):
            if i is header: break
            temp = line.split(":")
            header_array.append(temp)
        file_to_read.close()

        temp = np.genfromtxt(file_path, dtype=float, delimiter=',')
        data = temp

        name_plot = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        pw = self.window.add_new_plot(2, name_plot)
        pw.setAxisLabels(xname='X', xscale ='Arb. U.',yname='X', yscale ='Arb. U.',\
            zname='X', zscale ='Arb. U.')
        pw.setImage(data, axes={'y': 0, 'x': 1})

    def file_dialog(self, directory=''):
        root = tkinter.Tk()
        root.withdraw()

        file_path = filedialog.askopenfilename(**dict(
            initialdir = directory,
            filetypes = [("CSV", "*.csv"), ("TXT", "*.txt"),\
            ("DAT", "*.dat"), ("all", "*.*")],
            title = 'Select file to open')
            )
        return file_path

    def activate_item(self, index):
        item = self.namelist_model.itemFromIndex(index)
        plot = self.plot_dict[str(item.text())]
        if plot.closed:
            plot.closed = False
            self.window.add_plot(plot)

    def delete_item(self):
        index = self.namelist_view.currentIndex()
        item = self.namelist_model.itemFromIndex(index)
        del self[str(item.text())]

    def pause(self):
        sock = socket.socket()
        sock.connect(('localhost', 9091))
        sock.send(b'Script stopped')
        sock.close()

    def __getitem__(self, item):
        return self.plot_dict[item]

    def __setitem__(self, name, plot):
        model = QStandardItem(name)
        model.setEditable(False)
        self.namelist_model.appendRow(model)
        self.plot_dict[name] = plot

    def __contains__(self, value):
        return value in self.plot_dict

    def __delitem__(self, name):
        self.namelist_model.removeRow(
            self.namelist_model.findItems(name)[0].index().row())
        self.plot_dict[name].close()
        del self.plot_dict[name]

    def keys(self):
        return list(self.plot_dict.keys())
Exemple #14
0
class MemoryMappingWidget(QDockWidget):
    def __init__(self, parent, *args, **kwargs):
        super(MemoryMappingWidget, self).__init__("Memory map", parent)
        self.log = self.parentWidget().log
        layout = QVBoxLayout()
        self.__memory_mapping = [
            MemorySection(".text", 0x00004000, 0x1000, "READ|EXEC"),
            MemorySection(".data", 0x00005000, 0x1000, "READ|WRITE"),
            MemorySection(".stack", 0x00006000, 0x4000, "READ|WRITE"),
            MemorySection(".misc", 0x0000a000, 0x1000, "ALL"),
        ]
        self.model = QStringListModel()
        self.model.setStringList(self.memory_mapping_str)
        self.view = QListView()
        self.view.setModel(self.model)
        layout.addWidget(self.view)
        buttons = QHBoxLayout()
        btn_add = QPushButton("Add Section")
        buttons.addWidget(btn_add)
        btn_add.clicked.connect(self.onAddSectionButtonClicked)
        buttons.addStretch(1)
        btn_del = QPushButton("Remove Section")
        btn_del.clicked.connect(self.onDeleteSectionButtonClicked)
        buttons.addWidget(btn_del)
        layout.addLayout(buttons)
        w = QWidget(self)
        w.setLayout(layout)
        self.setWidget(w)
        return

    @property
    def memory_mapping_str(self) -> None:
        """
        Generator for the string view model
        """
        for entry in self.__memory_mapping:
            yield str(entry)

    def updateView(self) -> bool:
        """
        Refresh the view
        """
        self.model.setStringList(self.memory_mapping_str)
        return True

    @property
    def maps(self) -> List[MemorySection]:
        """
        Exports the memory mapping to a format usable for Unicorn
        """
        self.__maps = self.__memory_mapping[::]
        return self.__maps

    def onAddSectionButtonClicked(self) -> None:
        """
        Callback associated with the click of the "Add Section" button
        """
        self.add_or_edit_section_popup()
        return

    def onDeleteSectionButtonClicked(self) -> None:
        """
        Callback associated with the click of the "Remove Section" button
        """
        idx = self.view.currentIndex()
        line_content = idx.data()
        for i, sect in enumerate(self.__memory_mapping):
            if line_content == str(sect):
                if self.__memory_mapping[i].name in (".text", ".data",
                                                     ".stack"):
                    print("cannot delete required section '{}'".format(
                        self.__memory_mapping[i].name))
                    break
                del self.__memory_mapping[i]
                self.updateView()
                break
        return

    def add_or_edit_section_popup(self) -> None:
        """
        Popup that present a form with all info to submit to create a new section
        """
        msgbox = QMessageBox(self)
        wid = QWidget()

        name = QLabel("Name")
        nameEdit = QLineEdit()

        startAddress = QLabel("Start Address (hex)")
        startAddressEdit = QLineEdit()

        size = QLabel("Size (hex)")
        sizeEdit = QLineEdit()

        perm = QLabel("Permissions")
        permCheck = QWidget()
        permCheckLayout = QHBoxLayout()
        perm_read_btn = QCheckBox("R")
        perm_write_btn = QCheckBox("W")
        perm_exec_btn = QCheckBox("X")
        permCheckLayout.addWidget(perm_read_btn)
        permCheckLayout.addWidget(perm_write_btn)
        permCheckLayout.addWidget(perm_exec_btn)
        permCheck.setLayout(permCheckLayout)

        grid = QGridLayout()
        grid.setSpacing(10)

        grid.addWidget(name, 1, 0)
        grid.addWidget(nameEdit, 1, 1)

        grid.addWidget(startAddress, 2, 0)
        grid.addWidget(startAddressEdit, 2, 1)

        grid.addWidget(size, 3, 0)
        grid.addWidget(sizeEdit, 3, 1)

        grid.addWidget(perm, 4, 0)
        grid.addWidget(permCheck, 4, 1)

        msgbox.setLayout(grid)
        msgbox.setGeometry(300, 300, 350, 300)

        msgbox.setWindowTitle("Add/edit section")
        layout = msgbox.layout()
        wid.setLayout(grid)
        wid.setMinimumWidth(400)
        layout.addWidget(wid)

        msgbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)

        ret = msgbox.exec()
        if ret == QMessageBox.Ok:
            section_name = nameEdit.text()
            section_address = int(startAddressEdit.text(), 16)
            section_size = int(sizeEdit.text(), 16)
            section_perm = []
            if perm_read_btn.isChecked(): section_perm.append("READ")
            if perm_write_btn.isChecked(): section_perm.append("WRITE")
            if perm_exec_btn.isChecked(): section_perm.append("EXEC")
            section = MemorySection(section_name, section_address,
                                    section_size, "|".join(section_perm))
            self.__memory_mapping.append(section)
            self.updateView()
        return
Exemple #15
0
class CollectData(QWidget):
    def __init__(self):
        super().__init__()
        self.init_variable()
        self.init_img()

        self.init_ui()
        self.show()

    def init_img(self):
        self.qlabel = myLabel(self)
        img = cv2.imread('data/test.png')  # 打开图片
        self.qlabel.img = img.copy()
        self.qlabel.img_current = img.copy()
        self.update_img()

    def init_variable(self):
        self.label = 0
        self.transformation_type = 0
        self.total_img_number = 0
        self.current_img_index = 0
        self.folder_path = r"data"
        self.jump_img_index = -1
        self.img_list = []
        self.img_name_list = []

    def init_ui(self):
        self.setGeometry(200, 200, 1000, 800)
        self.setWindowTitle('数据标注')
        self.qlabel.setGeometry(QRect(30, 30, 640, 480))
        self.init_buttons()

        for file_name in os.listdir(self.folder_path + '/'):
            img = cv2.imread(self.folder_path + '/' + file_name)
            if img is None:
                continue
            self.img_list.append(img)
            self.img_name_list.append(
                os.path.splitext(self.folder_path + '/' + file_name)[0])
        #QMessageBox.information(self, 'complete', '图片加载完毕')
        self.total_img_number = len(self.img_list)
        self.current_img_index = 1
        self.refresh_img()

        self.update_list()

    def init_buttons(self):
        self.previous_img_button = QPushButton("上一张图片", self)
        self.next_img_button = QPushButton("下一张图片", self)
        self.save_message_button = QPushButton("保存当前图片信息", self)
        self.show_message_button = QPushButton("显示当前图片信息", self)
        self.open_folder_button = QPushButton("打开文件夹", self)
        self.add_border_button = QPushButton("保存当前框", self)
        self.delete_border_button = QPushButton("删除选中框", self)
        self.img_folder_text = QLineEdit('data', self)
        self.goto_chosen_img_button = QPushButton("跳转图片", self)
        self.jump_img_text = QLineEdit('', self)
        self.show_index_message = QLabel(self)

        self.img_folder_text.selectAll()
        self.img_folder_text.setFocus()

        self.previous_img_button.setGeometry(30, 530, 150, 40)
        self.next_img_button.setGeometry(200, 530, 150, 40)
        self.save_message_button.setGeometry(370, 530, 150, 40)
        self.show_message_button.setGeometry(540, 530, 150, 40)
        self.img_folder_text.setGeometry(30, 590, 660, 40)
        self.open_folder_button.setGeometry(710, 590, 150, 40)
        self.jump_img_text.setGeometry(30, 650, 150, 40)
        self.goto_chosen_img_button.setGeometry(200, 650, 150, 40)
        self.show_index_message.setGeometry(30, 710, 200, 40)
        self.add_border_button.setGeometry(710, 380, 150, 40)
        self.delete_border_button.setGeometry(710, 440, 150, 40)

        self.previous_img_button.clicked.connect(self.previous_img)
        self.next_img_button.clicked.connect(self.next_img)
        self.save_message_button.clicked.connect(self.save_message)
        self.show_message_button.clicked.connect(self.show_message)
        self.open_folder_button.clicked.connect(self.open_folder)
        self.add_border_button.clicked.connect(self.save_current_border)
        self.delete_border_button.clicked.connect(self.delete_border)
        self.goto_chosen_img_button.clicked.connect(self.goto_chosen_img)

        self.label_combo = QComboBox(self)
        for i in range(len(LABEL_LIST)):
            self.label_combo.addItem(LABEL_LIST[i])
        self.label_combo.move(900, 30)
        self.label_combo.activated[str].connect(self.label_on_activated)

        self.listview = QListView(self)
        self.listview.setGeometry(710, 30, 150, 320)
        self.listview.doubleClicked.connect(self.list_clicked)
        self.listview.setEditTriggers(QListView.NoEditTriggers)

    def previous_img(self):
        if self.current_img_index == 1:
            QMessageBox.information(self, 'warning', '已经是第一张啦')
            return
        self.current_img_index -= 1
        self.refresh_img()

    def next_img(self):
        if self.current_img_index == self.total_img_number:
            QMessageBox.information(self, 'warning', '已经是最后一张啦')
            return
        self.current_img_index += 1
        self.refresh_img()

    def show_message(self):
        if len(self.qlabel.rectangle_label) > 0:
            reply = QMessageBox.question(self, '确认', '当前有未保存信息,是否继续?',
                                         QMessageBox.Yes | QMessageBox.No,
                                         QMessageBox.No)
            if reply == QMessageBox.No:
                return
        self.qlabel.rectangle_label.clear()
        if os.path.isfile(self.img_name_list[self.current_img_index - 1] +
                          '.csv') == False:
            QMessageBox.information(self, 'warning', '当前图片无信息')
            return
        message = pd.read_csv(self.img_name_list[self.current_img_index - 1] +
                              '.csv',
                              sep=',',
                              header=None)
        message = np.array(message.T)
        message = message.astype(int)
        for i in range(len(message)):
            self.qlabel.rectangle_label.append(
                Rectangle(message[i][1], message[i][2], message[i][3],
                          message[i][4], True, message[i][0]))
        self.update_list()
        self.refresh_img()

        QMessageBox.information(self, 'complete', '信息加载完毕')

    def open_folder(self):
        self.folder_path = self.img_folder_text.text()
        if os.path.isdir(self.folder_path) == False:
            QMessageBox.information(self, 'warning', '文件夹路径非法')
            return
        self.img_list.clear()
        self.img_name_list.clear()
        for file_name in os.listdir(self.folder_path + '/'):
            img = cv2.imread(self.folder_path + '/' + file_name)
            if img is None:
                continue
            self.img_list.append(img)
            self.img_name_list.append(
                os.path.splitext(self.folder_path + '/' + file_name)[0])
        QMessageBox.information(self, 'complete', '图片加载完毕')
        self.total_img_number = len(self.img_list)
        self.current_img_index = 1
        self.refresh_img()

    def goto_chosen_img(self):
        if int(self.jump_img_text.text()) <= 0 or int(
                self.jump_img_text.text()) > self.total_img_number:
            QMessageBox.information(self, 'warning', '已经是最后一张啦')
            return
        self.current_img_index = int(self.jump_img_text.text())
        self.refresh_img()

    def refresh_img(self):
        img = self.img_list[self.current_img_index - 1]
        self.qlabel.img = img.copy()
        self.qlabel.update_qlabel_img()
        self.update_img()
        self.show_index_message.setText('一共' + str(self.total_img_number) +
                                        '张图片,当前第' +
                                        str(self.current_img_index) + '张图片')

    def label_on_activated(self):
        self.label = self.label_combo.currentIndex()

    def update_list(self):
        slm = QStringListModel()
        string_list = []
        for i in range(len(self.qlabel.rectangle_label)):
            string_list.append(
                LABEL_LIST[self.qlabel.rectangle_label[i].label])
        slm.setStringList(string_list)
        self.listview.setModel(slm)

    def list_clicked(self, qModelIndex):
        if self.qlabel.rectangle_label[
                qModelIndex.row()].whether_display == True:
            self.qlabel.rectangle_label[
                qModelIndex.row()].whether_display = False
        else:
            self.qlabel.rectangle_label[
                qModelIndex.row()].whether_display = True
        self.qlabel.update_qlabel_img()
        self.update_img()

    def save_current_border(self):
        self.qlabel.save_current_border(self.label)
        self.qlabel.update_qlabel_img()
        self.update_img()
        self.update_list()

    def update_img(self):
        img_resize = cv2.resize(
            self.qlabel.img_current,
            (self.qlabel.qlabel_length, self.qlabel.qlabel_width))
        height, width, bytesPerComponent = img_resize.shape
        bytesPerLine = 3 * width
        cv2.cvtColor(img_resize, cv2.COLOR_BGR2RGB, img_resize)
        QImg = QImage(img_resize.data, width, height, bytesPerLine,
                      QImage.Format_RGB888)
        pixmap = QPixmap.fromImage(QImg)
        self.qlabel.setPixmap(pixmap)
        self.qlabel.setCursor(Qt.CrossCursor)

    def label_clicked(self):
        sender = self.sender()
        if sender == self.label_button:
            self.label = self.label_button.checkedId()

    def save_message(self):
        self.save_current_angle()
        img = cv2.imread('data/test.png')  # 打开图片
        self.qlabel.rectangle_label.clear()
        self.update_img()
        self.update_list()
        self.qlabel.img = img.copy()
        self.qlabel.img_current = img.copy()
        self.update_img()

    def save_current_angle(self):
        if os.path.isfile(self.img_name_list[self.current_img_index - 1] +
                          '.csv'):
            reply = QMessageBox.question(self, '确认', '是否覆盖当前图片已保存信息?',
                                         QMessageBox.Yes | QMessageBox.No,
                                         QMessageBox.No)
            if reply == QMessageBox.No:
                return
        save_data = []
        for i in range(5):
            save_data.append([])
        if len(self.qlabel.rectangle_label) > 0:
            for i in range(len(self.qlabel.rectangle_label)):
                save_data[0].append(self.qlabel.rectangle_label[i].label)
                save_data[1].append(self.qlabel.rectangle_label[i].x0)
                save_data[2].append(self.qlabel.rectangle_label[i].x1)
                save_data[3].append(self.qlabel.rectangle_label[i].y0)
                save_data[4].append(self.qlabel.rectangle_label[i].y1)

            if np.shape(np.array(save_data)) != (5, 0):
                print(self.current_img_index)
                np.savetxt(self.img_name_list[self.current_img_index - 1] +
                           '.csv',
                           np.array(save_data),
                           delimiter=',')

    def delete_border(self):
        if self.listview.currentIndex().row() > -1:
            self.qlabel.delete_border(self.listview.currentIndex().row())
            self.qlabel.update_qlabel_img()
            self.update_img()
            self.update_list()
        else:
            QMessageBox.information(self, 'warning', '请先选中一行')
Exemple #16
0
class JsonEdit(QWidget):
    def __init__(self,
                 dataPath,
                 ico,
                 parent=None,
                 flags=Qt.WindowCloseButtonHint):
        super(JsonEdit, self).__init__(parent, flags)

        self.setStyleSheet(
            '''JsonEdit{background:#272626}QLabel{color:#ffffff;font-family:"Microsoft YaHei", SimHei, SimSun;font:11pt;}
                                QPushButton{border:0px;background:#4d4d4d;color:#ffffff;font-family: "Microsoft YaHei", SimHei, SimSun;font:11pt;}
                                QPushButton:pressed{background:#606162;font:10pt;}
                                QPushButton:checked{background:#70bbe4;}
                                QPushButton:hover{border-style:solid;border-width:1px;border-color:#ffffff;}
                                QLineEdit{background-color:#4d4d4d;color:#ffffff;font-family:"Microsoft YaHei", SimHei, SimSun;font:11pt;border:0px;padding-left:5px}
                                QLineEdit:hover{border-style:solid;border-width:1px;border-color:#ffffff;padding-left:4px;}
                                QListView{background-color:#4d4d4d;color:#ffffff;font-family:"Microsoft YaHei", SimHei, SimSun;font:12pt;}
                                QComboBox:hover{border-style:solid;border-width:1px;border-color:#ffffff;padding-left:4px;}
                                QComboBox{background-color:#4d4d4d;color:#ffffff;font-family:"Microsoft YaHei", SimHei, SimSun;font:11pt;padding-left:5px;border:0px;}
                                QComboBox:drop-down{width:0px;}
                                QComboBox:down-arrow{width:0px}
                                QComboBox:selected{background-color:#606162;}
                                QComboBox:QAbstractItemView::item{font-family:"Microsoft YaHei", SimHei, SimSun;font:11pt;}
                                QComboBox:QAbstractItemView::item:selected{background-color:#606162;}
                                QInputDialog{background-color:#272626;}
                                QScrollBar:vertical{width:8px;background:rgba(0,0,0,0%);margin:0px,0px,0px,0px;padding-top:0px;padding-bottom:0px;}
                                QScrollBar:handle:vertical{width:8px;background:rgba(0,0,0,25%);border-radius:0px;min-height:20;}
                                QScrollBar:handle:vertical:hover{width:8px;background:rgba(0,0,0,50%);border-radius:0px;min-height:20;}
                                QScrollBar:add-line:vertical{height:0px;width:0px;subcontrol-position:bottom;}
                                QScrollBar:sub-line:vertical{height:0px;width:0px;subcontrol-position:top;}
                                QScrollBar:add-page:vertical,QScrollBar:sub-page:vertical{background:rgba(0,0,0,10%);border-radius:0px;}
                                QScrollBar:horizontal{height:8px;background:rgba(0,0,0,0%);margin:0px,0px,0px,0px;padding-top:0px;padding-bottom:0px;}
                                QScrollBar:handle:horizontal{width:8px;background:rgba(0,0,0,25%);border-radius:0px;min-height:20;}
                                QScrollBar:handle:horizontal:hover{width:8px;background:rgba(0,0,0,50%);border-radius:0px;min-height:20;}
                                QScrollBar:add-line:horizontal{height:0px;width:0px;subcontrol-position:bottom;}
                                QScrollBar:sub-line:horizontal{height:0px;width:0px;subcontrol-position:top;}
                                QScrollBar:add-page:horizontal,QScrollBar:sub-page:horizontal{background:rgba(0,0,0,10%);border-radius:0px;}'''
        )

        self.setWindowIcon(QIcon(ico))
        self.isshow = False

        self.isBootyMode = False
        self.bootyName = '固源岩'

        self.selPanel = BootyChoice(self, ico)

        self.json = dataPath + '/schedule.json'
        self.scheduleAdd = {
            'part': 'MAIN',
            'chap': '',
            'objLevel': '',
            'times': ''
        }
        self.transEX = {
            'ex1': '切尔诺伯格',
            'ex2': '龙门外环',
            'ex3': '龙门市区',
            'ex4': '当期委托'
        }

        self.partList = ['主线', '物资筹备', '芯片搜索', '剿灭作战']
        self.partListJson = ['MAIN', 'RS', 'PR', 'EX']
        self.mainChapList = [
            '序章', '第一章', '第二章', '第三章', '第四章', '第五章', '第六章', '第七章', '第八章'
        ]
        self.rsChapList = ['战术演习', '粉碎防御', '空中威胁', '货物运送', '资源保障']
        self.prChapList = ['医疗重装', '术士狙击', '辅助先锋', '特种近卫']
        self.exChapList = ['切尔诺伯格', '龙门外环', '龙门市区', '当期委托']
        self.chapList = [
            self.mainChapList, self.rsChapList, self.prChapList,
            self.exChapList
        ]

        self.selIndex = None

        self.grid = QGridLayout()
        self.lsv = QListView()  #计划显示框
        self.lsv.setFixedWidth(200)
        self.lsv.clicked.connect(self.clickSchedule)
        self.lsv.setContextMenuPolicy(Qt.CustomContextMenu)
        self.lsv.customContextMenuRequested.connect(self.lsvRearrange)
        self.actMoveUp = QAction('上移')
        self.actMoveUp.triggered.connect(self.moveUpLine)
        self.actMoveDown = QAction('下移')
        self.actMoveDown.triggered.connect(self.moveDownLine)
        self.actEdit = QAction('修改次数/个数')
        self.actEdit.triggered.connect(self.editLine)
        self.actDel = QAction('删除')
        self.actDel.triggered.connect(self.delLine)

        self.slm = QStringListModel()

        self.partCb = QComboBox()
        self.partCb.addItems(self.partList)
        self.partCb.activated[int].connect(self.changeChapList)
        self.partCb.setFixedSize(80, 40)
        self.partCb.setView(QListView())

        self.chapCb = QComboBox()
        self.chapCb.addItems(self.mainChapList)
        self.chapCb.activated[int].connect(self.changeLevel1List)
        self.chapCb.setFixedSize(100, 40)
        self.chapCb.setView(QListView())

        self.level1Cb = QComboBox()
        self.level1Cb.setFixedSize(60, 40)
        self.level1Cb.setView(QListView())

        self.lineLable = QLabel()
        self.lineLable.setText('-')

        self.level2Edit = QLineEdit()
        self.level2Edit.setFixedSize(50, 40)

        self.timesLable = QLabel()
        self.timesLable.setText('次数:')

        self.timeEdit = QLineEdit()
        self.timeEdit.setFixedSize(50, 40)

        self.bootyModeBtn = QPushButton()
        self.bootyModeBtn.setCheckable(True)
        self.bootyModeBtn.setText('素材模式')
        self.bootyModeBtn.setFixedHeight(40)
        self.bootyModeBtn.clicked[bool].connect(self.setBootMode)

        self.bootySelBtn = QPushButton()
        self.bootySelBtn.setText('——')
        self.bootySelBtn.setFixedHeight(40)
        self.bootySelBtn.clicked.connect(self.selPanel.myShow)

        self.delBtn = QPushButton()
        self.delBtn.setText('删除')
        self.delBtn.clicked.connect(self.delLine)
        self.delBtn.setFixedHeight(40)
        self.clearBtn = QPushButton()
        self.clearBtn.setText('清空')
        self.clearBtn.clicked.connect(self.clearLine)
        self.clearBtn.setFixedHeight(40)

        self.addBtn = QPushButton()
        self.addBtn.setText('添加')
        self.addBtn.clicked.connect(self.addLine)
        self.addBtn.setFixedHeight(40)

        self.planCb = QComboBox()
        self.planCb.setFixedSize(200, 40)
        self.planCb.setView(QListView())

        self.loadPlanBtn = QPushButton()
        self.loadPlanBtn.setText('加载配置')
        self.loadPlanBtn.setFixedHeight(40)
        self.loadPlanBtn.clicked.connect(self.loadPlan)

        self.addPlanBtn = QPushButton()
        self.addPlanBtn.setText('以当前配置新建')
        self.addPlanBtn.setFixedHeight(40)
        self.addPlanBtn.clicked.connect(self.addPlan)

        self.delPlanBtn = QPushButton()
        self.delPlanBtn.setText('删除此配置')
        self.delPlanBtn.setFixedHeight(40)
        self.delPlanBtn.clicked.connect(self.delPlan)

        self.listScheduleBefore = []
        self.listSchedule = []
        self.initJson()
        self.slm.setStringList(self.listSchedule)
        self.lsv.setModel(self.slm)
        self.lsv.setEditTriggers(QListView.NoEditTriggers)

        self.changeLevel1List(0)

        self.grid.addWidget(self.lsv, 0, 0, 3, 1)
        self.grid.addWidget(self.partCb, 0, 1, 1, 1)
        self.grid.addWidget(self.chapCb, 0, 2, 1, 1)
        self.grid.addWidget(self.level1Cb, 0, 3, 1, 1)
        self.grid.addWidget(self.lineLable, 0, 4, 1, 1)
        self.grid.addWidget(self.level2Edit, 0, 5, 1, 1)
        self.grid.addWidget(self.timesLable, 0, 6, 1, 1)
        self.grid.addWidget(self.timeEdit, 0, 7, 1, 1)
        self.grid.addWidget(self.bootyModeBtn, 1, 1, 1, 1)
        self.grid.addWidget(self.bootySelBtn, 1, 2, 1, 1)
        self.grid.addWidget(self.addBtn, 1, 3, 1, 5)
        self.grid.addWidget(self.delBtn, 2, 1, 1, 4)
        self.grid.addWidget(self.clearBtn, 2, 5, 1, 3)
        self.grid.addWidget(self.planCb, 3, 0, 1, 1)
        self.grid.addWidget(self.loadPlanBtn, 3, 1, 1, 1)
        self.grid.addWidget(self.addPlanBtn, 3, 2, 1, 3)
        self.grid.addWidget(self.delPlanBtn, 3, 5, 1, 3)

        self.setLayout(self.grid)

        self.setWindowTitle('路线规划')
        #self.resize(600,400)

        self.myTimer()
        #self.show()

    def editerShow(self):
        if not self.isVisible():
            self.show()
            cp = QDesktopWidget().availableGeometry().center()
            self.move(int(cp.x() - self.width() / 2),
                      int(cp.y() - self.height() / 2))

    def myTimer(self):
        self.updateTimer = QTimer()
        self.updateTimer.timeout.connect(self.updateList)
        self.updateTimer.start(10)

    def lsvRearrange(self):
        self.selIndex = self.lsv.currentIndex().row()
        rightClickMeun = QMenu()
        rightClickMeun.setStyleSheet(
            '''QMenu {color:#ffffff;font-family: "Microsoft YaHei", SimHei, SimSun;font:10pt;
                                        background-color:#272626; margin:3px;}
                                        QMenu:item {padding:8px 32px;}
                                        QMenu:item:selected { background-color: #3f4140;}
                                        QMenu:icon{padding: 8px 20px;}
                                        QMenu:separator{background-color: #7C7C7C; height:1px; margin-left:2px; margin-right:2px;}'''
        )
        rightClickMeun.addAction(self.actMoveUp)
        rightClickMeun.addAction(self.actMoveDown)
        rightClickMeun.addAction(self.actEdit)
        rightClickMeun.addAction(self.actDel)
        rightClickMeun.exec_(QCursor.pos())

    def initJson(self):
        with open(self.json, 'r', encoding='UTF-8') as s:
            data = s.read()
        self.jsonAll = loads(data)["main"]
        self.selPlan = self.jsonAll[0]
        self.allPlanList = self.selPlan['allplan'].split('|')

        #配置选单显示
        self.planCb.addItems(self.allPlanList)

        self.jsonDict = self.jsonAll[0]['sel']
        self.selList = self.jsonDict.copy()
        self.refreshJsonView()

    def refreshJsonView(self):
        self.listSchedule = []
        for eachDict in self.selList:
            temp = eachDict['objLevel']
            if 'ex' in temp:
                temp = self.transEX[temp]
            if eachDict['chap'] == 'LS':
                temp = temp.replace('S', 'LS')
            if isinstance(eachDict['times'], dict):
                self.listSchedule.append('{0}({1}共{2}个)'.format(
                    temp, eachDict['times']['bootyName'],
                    eachDict['times']['bootyNum']))
            else:
                self.listSchedule.append('{0}(共{1}次)'.format(
                    temp, eachDict['times']))

    def updateJson(self):
        self.jsonAll[0]['sel'] = self.selList.copy()
        self.jsonAll[0]['allplan'] = '|'.join(self.allPlanList)
        #self.jsonAll[0]['selno'] = str(self.selNo)
        tempNewJson = {'main': self.jsonAll}
        newData = dumps(tempNewJson,
                        sort_keys=True,
                        indent=4,
                        separators=(',', ': '),
                        ensure_ascii=False)
        with open(self.json, 'w', encoding='UTF-8') as j:
            j.write(newData)

    def updateList(self):
        if self.listSchedule != self.listScheduleBefore:
            self.listScheduleBefore = self.listSchedule.copy()
            self.slm.setStringList(self.listSchedule)
            self.updateJson()

    def changeChapList(self, indexI):
        self.scheduleAdd['part'] = self.partListJson[indexI]
        self.chapCb.clear()
        self.chapCb.addItems(self.chapList[indexI])
        self.changeLevel1List(0)

    def changeLevel1List(self, indexI):
        self.level1Cb.clear()
        selChap = self.chapCb.currentText()
        self.level2Edit.setReadOnly(False)
        levelList = []
        if '章' in selChap:
            self.scheduleAdd['chap'] = str(int(indexI))
            if int(indexI) != 8:
                levelList.append(f'{int(indexI)}')
            if int(indexI) != 0 and int(indexI) != 1:
                if int(indexI) != 8:
                    levelList.append(f'S{int(indexI)}')
                elif int(indexI) == 8:
                    levelList.extend([
                        f'R{int(indexI)}', f'M{int(indexI)}',
                        f'JT{int(indexI)}'
                    ])

        elif selChap == '战术演习':
            self.scheduleAdd['chap'] = 'LS'
            levelList.append('LS')

        elif selChap == '粉碎防御':
            self.scheduleAdd['chap'] = 'AP'
            levelList.append('AP')

        elif selChap == '空中威胁':
            self.scheduleAdd['chap'] = 'CA'
            levelList.append('CA')

        elif selChap == '货物运送':
            self.scheduleAdd['chap'] = 'CE'
            levelList.append('CE')

        elif selChap == '资源保障':
            self.scheduleAdd['chap'] = 'SK'
            levelList.append('SK')

        elif selChap == '医疗重装':
            self.scheduleAdd['chap'] = 'A'
            levelList.append('PR-A')

        elif selChap == '术士狙击':
            self.scheduleAdd['chap'] = 'B'
            levelList.append('PR-B')

        elif selChap == '辅助先锋':
            self.scheduleAdd['chap'] = 'C'
            levelList.append('PR-C')

        elif selChap == '特种近卫':
            self.scheduleAdd['chap'] = 'D'
            levelList.append('PR-D')

        else:
            if selChap == '切尔诺伯格':
                self.scheduleAdd['chap'] = 'external'
                self.scheduleAdd['objLevel'] = 'ex1'
            elif selChap == '龙门外环':
                self.scheduleAdd['chap'] = 'external'
                self.scheduleAdd['objLevel'] = 'ex2'
            elif selChap == '龙门市区':
                self.scheduleAdd['chap'] = 'external'
                self.scheduleAdd['objLevel'] = 'ex3'
            elif selChap == '当期委托':
                self.scheduleAdd['chap'] = 'external'
                self.scheduleAdd['objLevel'] = 'ex4'

            self.level2Edit.clear()
            self.level2Edit.setReadOnly(True)

        self.level1Cb.addItems(levelList)

    def addLine(self):
        tempLevel = self.level2Edit.text()
        if 'EX' != self.scheduleAdd['part']:
            self.scheduleAdd['objLevel'] = ''
        tempTimes = self.timeEdit.text()
        self.scheduleAdd['times'] = ''
        if tempLevel != '':
            part1 = self.level1Cb.currentText()
            if part1 == 'LS':
                part1 = 'S'
            if tempLevel.isdecimal():
                self.scheduleAdd['objLevel'] = part1 + '-' + tempLevel
        if tempTimes.isdecimal():
            if self.isBootyMode:
                self.scheduleAdd['times'] = {
                    'bootyName': self.bootyName,
                    'bootyNum': tempTimes
                }
            else:
                self.scheduleAdd['times'] = tempTimes
        if self.scheduleAdd['objLevel'] != '' and self.scheduleAdd[
                'times'] != '':
            self.selList.append(self.scheduleAdd.copy())
            self.refreshJsonView()

    def clickSchedule(self, qModelIndex):
        self.selIndex = qModelIndex.row()

    def delLine(self):
        if self.selIndex != None:
            self.listSchedule.pop(self.selIndex)
            self.selList.pop(self.selIndex)
        self.selIndex = None

    def moveUpLine(self):
        if self.selIndex != 0 and self.selIndex != None:
            #temp = self.listSchedule[self.selIndex - 1]
            self.listSchedule[self.selIndex - 1], self.listSchedule[self.selIndex] = \
                                            self.listSchedule[self.selIndex], self.listSchedule[self.selIndex - 1]
            self.selList[self.selIndex - 1], self.selList[self.selIndex] = \
                                            self.selList[self.selIndex], self.selList[self.selIndex - 1]
        self.selIndex = None

    def moveDownLine(self):
        if self.selIndex != (len(self.listSchedule) -
                             1) and self.selIndex != None:
            #temp = self.listSchedule[self.selIndex - 1]
            self.listSchedule[self.selIndex + 1], self.listSchedule[self.selIndex] = \
                                            self.listSchedule[self.selIndex], self.listSchedule[self.selIndex + 1]
            self.selList[self.selIndex + 1], self.selList[self.selIndex] = \
                                            self.selList[self.selIndex], self.selList[self.selIndex + 1]
        self.selIndex = None

    def editLine(self):
        if self.selIndex != None:
            if isinstance(self.selList[self.selIndex]['times'], dict):
                newNum, isOk = QInputDialog.getText(self, '修改', '请输入新的掉落物个数')
                if isOk:
                    self.selList[self.selIndex]['times']['bootyNum'] = newNum
            else:
                newNum, isOk = QInputDialog.getText(self, '修改', '请输入新的次数')
                self.selList[self.selIndex]['times'] = newNum
            self.refreshJsonView()
        self.selIndex = None

    def clearLine(self):
        self.listSchedule.clear()
        self.selList.clear()

    def loadPlan(self):
        if self.planCb.currentIndex() != 0:
            self.jsonDict = self.jsonAll[self.planCb.currentIndex() + 1][
                self.allPlanList[self.planCb.currentIndex()]]
            self.selList = self.jsonDict.copy()
            self.refreshJsonView()

    def addPlan(self):
        planName, ok = QInputDialog.getText(self, '配置名称', '请输入配置名称:')
        if ok:
            if '|' in planName:
                planName.replace('|', '·')
            self.allPlanList.append(planName)
            tempDict = dict()
            tempDict[planName] = self.selList.copy()
            self.jsonAll.append(tempDict)
            self.updateJson()
            self.planCb.clear()
            self.planCb.addItems(self.allPlanList)

    def delPlan(self):
        if self.planCb.currentIndex() != 0:
            self.allPlanList.pop(self.planCb.currentIndex())
            self.jsonAll.pop(self.planCb.currentIndex() + 1)
            self.updateJson()
            self.planCb.clear()
            self.planCb.addItems(self.allPlanList)

    def setBootMode(self, isChecked):
        self.isBootyMode = isChecked
        if self.isBootyMode:
            self.timesLable.setText('个数:')
            self.bootySelBtn.setText('选择掉落物')
        else:
            self.timesLable.setText('次数:')
            self.bootySelBtn.setText('———')

    def test(self):
        self.listSchedule.append('add')
        print(self.listSchedule)
Exemple #17
0
class DesktopIconWidget(QFrame):
    def __init__(self, parent):
        QFrame.__init__(self, parent)
        self.setFrameStyle(QFrame.Box | QFrame.Sunken)
        self.setStyleSheet("QListView{background:transparent;}")

        self.listView = QListView(self)
        self.setLayout(QHBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().addWidget(self.listView)

        self.listView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.listView.setMovement(QListView.Snap)
        self.listView.setFlow(QListView.LeftToRight)
        self.listView.setResizeMode(QListView.Adjust)
        self.listView.setGridSize(
            QSize(self.logicalDpiX() / 96 * 70,
                  self.logicalDpiY() / 96 * 70))
        self.listView.setViewMode(QListView.IconMode)

        self.quickDesktopModel = QuickDesktopModel(
            self.window().platform.databaseFile)
        self.listView.setModel(self.quickDesktopModel)
        self.createActions()
        self.makeConnections()

    def createActions(self):
        self.actionCreateComputer = QAction(self.tr("我的电脑(&C)"), self)
        self.actionCreateDocuments = QAction(self.tr("我的文档(&D)"), self)
        self.actionCreateMusic = QAction(self.tr("我的音乐(&M)"), self)
        self.actionCreatePictures = QAction(self.tr("我的图片(&P)"), self)
        self.actionCreateShortcut = QAction(self.tr("创建快捷方式(&C)"), self)
        self.actionCreateShortcut.setIcon(QIcon(":/images/new.png"))
        self.actionCreateBookmark = QAction(self.tr("创建网络链接(&B)"), self)
        self.actionCreateBookmark.setIcon(QIcon(":/images/insert-link.png"))
        self.actionRemoveShortcut = QAction(self.tr("删除快捷方式(&R)"), self)
        self.actionRemoveShortcut.setIcon(QIcon(":/images/delete.png"))
        self.actionRenameShortcut = QAction(self.tr("重命名(&N)"), self)
        self.actionRenameShortcut.setIcon(QIcon(":/images/edit-rename.png"))
        self.actionEditShortcut = QAction(self.tr("编辑快捷方式(&E)"), self)
        self.actionEditShortcut.setIcon(QIcon(":/images/edit.png"))

    def makeConnections(self):
        self.listView.customContextMenuRequested.connect(
            self.onQuickDesktopContextMenuRequest)
        self.listView.activated.connect(self.runQuickDesktopShortcut)

        self.actionCreateComputer.triggered.connect(
            self.createComputerShortcut)
        self.actionCreateDocuments.triggered.connect(
            self.createDocumentsShortcut)
        self.actionCreateMusic.triggered.connect(self.createMusicShortcut)
        self.actionCreatePictures.triggered.connect(
            self.createPicturesShortcut)
        self.actionCreateShortcut.triggered.connect(self.createShortcut)
        self.actionCreateBookmark.triggered.connect(self.createBookmark)
        self.actionEditShortcut.triggered.connect(self.editShortcut)
        self.actionRemoveShortcut.triggered.connect(self.removeShortcut)
        self.actionRenameShortcut.triggered.connect(self.renameShortcut)

    def onQuickDesktopContextMenuRequest(self, pos):
        index = self.listView.indexAt(pos)
        self.listView.setCurrentIndex(index)
        menu = QMenu()
        menu.addAction(self.actionCreateShortcut)
        menu.addAction(self.actionCreateBookmark)
        menu2 = menu.addMenu(self.tr("创建特殊快捷方式(&S)"))
        if os.name == "nt":
            menu2.addAction(self.actionCreateComputer)
        menu2.addAction(self.actionCreateDocuments)
        menu2.addAction(self.actionCreatePictures)
        menu2.addAction(self.actionCreateMusic)
        if index.isValid():
            menu.addAction(self.actionRemoveShortcut)
            if not self.quickDesktopModel.isSpecialShortcut(index):
                menu.addAction(self.actionEditShortcut)
            menu.addAction(self.actionRenameShortcut)
        try:
            getattr(menu, "exec")(QCursor.pos())
        except AttributeError:
            getattr(menu, "exec_")(QCursor.pos())

    def createShortcut(self):
        d = ShortcutDialog(self)
        if self.window().runDialog(d.create) == QDialog.Accepted:
            shortcut = d.getResult()
            shortcut["id"] = str(uuid.uuid4())
            self.quickDesktopModel.addShortcut(shortcut)
        d.deleteLater()

    def createBookmark(self):
        d = BookmarkDialog(self)
        if self.window().runDialog(d.create) == QDialog.Accepted:
            shortcut = {
                "id": str(uuid.uuid4()),
                "icon": "",
                "openwith": "",
                "dir": "",
            }
            shortcut.update(d.getResult())
            self.quickDesktopModel.addShortcut(shortcut)
        d.deleteLater()

    def createComputerShortcut(self):
        shortcut = {
            "id": str(uuid.uuid4()),
            "name": self.tr("我的电脑"),
            "path": COMPUTER_PATH,
            "icon": "",
            "dir": "",
            "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def createDocumentsShortcut(self):
        shortcut = {
            "id": str(uuid.uuid4()),
            "name": self.tr("我的文档"),
            "path": DOCUMENTS_PATH,
            "icon": "",
            "dir": "",
            "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def createPicturesShortcut(self):
        shortcut = {
            "id": str(uuid.uuid4()),
            "name": self.tr("图片收藏"),
            "path": PICTURES_PATH,
            "icon": "",
            "dir": "",
            "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def createMusicShortcut(self):
        shortcut = {
            "id": str(uuid.uuid4()),
            "name": self.tr("我的音乐"),
            "path": MUSIC_PATH,
            "icon": "",
            "dir": "",
            "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def renameShortcut(self):
        self.listView.edit(self.listView.currentIndex())

    def removeShortcut(self):
        self.quickDesktopModel.removeShortcut(self.listView.currentIndex())

    def editShortcut(self):
        index = self.listView.currentIndex()
        if not index.isValid():
            return
        shortcut = self.quickDesktopModel.shortcutAt(index)
        url = QUrl.fromUserInput(shortcut["path"])
        if not url.isValid():
            return
        if url.scheme() == "special":
            QMessageBox.information(self, self.tr("编辑快捷方式"),
                                    self.tr("不能编辑特殊图标。"))
            return
        elif url.scheme() == "file":
            d = ShortcutDialog(self)
        else:
            d = BookmarkDialog(self)
        if self.window().runDialog(d.edit, shortcut) == QDialog.Accepted:
            shortcut.update(d.getResult())
            self.quickDesktopModel.updateShortcut(shortcut, index)
        d.deleteLater()

    def runQuickDesktopShortcut(self):
        index = self.listView.currentIndex()
        if not index.isValid():
            return
        if not self.quickDesktopModel.runShortcut(index):
            QMessageBox.information(self, self.tr("快捷面板"), \
                    self.tr("不能运行快捷方式。请检查文件是否存在或者程序是否正确。"))
        else:
            self.window().close()
Exemple #18
0
class MyApp(QWidget):

    is_resize = False
    is_rotate = False
    is_hfilp = False
    is_vfilp = False

    img_fomat = '(*.jpg , *.png , *.jpeg)'
    img_fomat_extension = ('.jpg', '.png', '.jpeg')
    file_paths = ()
    rotate_data = 90

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Resize
        cb = QCheckBox('Resize', self)
        cb.stateChanged.connect(self.ischeckResize)

        self.le_width = QLineEdit(self)  # resize img width
        self.le_width.setValidator(QIntValidator(0, 9999))

        self.le_height = QLineEdit(self)  # resize img height
        self.le_height.setValidator(QIntValidator(0, 9999))

        #Rotate
        cb1 = QCheckBox('Rotate', self)
        cb1.stateChanged.connect(self.ischeckRotate)

        self.le_degree = QLineEdit(self)
        self.le_degree.setValidator(QIntValidator(1, 359))
        self.le_degree.setText('90')

        #hflip
        cb2 = QCheckBox('hflip', self)
        cb2.stateChanged.connect(self.ischeckHfilp)

        #vflip
        cb3 = QCheckBox('vflip', self)
        cb3.stateChanged.connect(self.ischeckVfilp)

        #set path
        btn_path = QPushButton(self)
        btn_path.setText('set file path')
        btn_path.clicked.connect(self.setFilePath)

        btn_path_delete = QPushButton(self)
        btn_path_delete.setText('Delete file path')
        btn_path_delete.clicked.connect(self.deleteFilePath)

        self.listview = QListView(self)
        self.model = QStandardItemModel()

        #run
        btn_run = QPushButton(self)
        btn_run.setText('Run')
        btn_run.clicked.connect(self.file_change)
        btn_run.resize(100, 100)

        mainLayout = QGridLayout()
        mainLayout.setSizeConstraint(QLayout.SetFixedSize)

        #line 1
        mainLayout.addWidget(cb, 0, 0, 1, 1)
        mainLayout.addWidget(self.le_width, 0, 1, 1, 1)
        mainLayout.addWidget(self.le_height, 0, 2, 1, 1)
        mainLayout.addWidget(btn_run, 0, 3, 1, 1)

        #line 2
        mainLayout.addWidget(cb1, 1, 0, 1, 1)
        mainLayout.addWidget(self.le_degree, 1, 1, 1, 1)

        #line 3, 4
        mainLayout.addWidget(cb2, 2, 0, 1, 1)
        mainLayout.addWidget(cb3, 3, 0, 1, 1)

        #line 5
        mainLayout.addWidget(btn_path, 4, 1, 1, 1)
        mainLayout.addWidget(btn_path_delete, 4, 2, 1, 1)

        mainLayout.addWidget(self.listview, 5, 0, 4, 4)

        self.setLayout(mainLayout)
        self.setWindowTitle('ImageAug')

        self.show()

    def ischeckResize(self, state):
        if state == Qt.Checked:
            self.is_resize = True
        else:
            self.is_resize = False

    def ischeckRotate(self, state):
        if state == Qt.Checked:
            self.is_rotate = True
        else:
            self.is_rotate = False

    def ischeckHfilp(self, state):
        if state == Qt.Checked:
            self.is_hfilp = True
        else:
            self.is_hfilp = False

    def ischeckVfilp(self, state):
        if state == Qt.Checked:
            self.is_vfilp = True
        else:
            self.is_vfilp = False

    def setFilePath(self):
        #self.textEdit.setText('')
        fname = QFileDialog.getOpenFileNames(self, 'Open file', './',
                                             self.img_fomat)
        for a in fname[0]:
            #self.textEdit.setText(self.textEdit.toPlainText()+'\n'+a)
            self.model.appendRow(QStandardItem(a))
        self.listview.setModel(self.model)

    def deleteFilePath(self):
        delete_item = self.listview.currentIndex().row()
        self.model.removeRow(delete_item)

    def file_change(self):
        if self.is_rotate:
            for i in range(self.model.rowCount()):
                path = self.model.index(i, 0,
                                        QModelIndex()).data(Qt.DisplayRole)
                self.setImgRotate(path)

        if self.is_resize:
            for i in range(self.model.rowCount()):
                path = self.model.index(i, 0,
                                        QModelIndex()).data(Qt.DisplayRole)
                self.setImgResize(path)

        if self.is_vfilp:
            for i in range(self.model.rowCount()):
                path = self.model.index(i, 0,
                                        QModelIndex()).data(Qt.DisplayRole)
                self.setImgFlip(path, 'v')

        if self.is_hfilp:
            for i in range(self.model.rowCount()):
                path = self.model.index(i, 0,
                                        QModelIndex()).data(Qt.DisplayRole)
                self.setImgFlip(path, 'h')

    def setImgResize(self, path):
        ## file name
        #print(path)
        name_idx = self.seach_filename(path)
        #print(path[name_idx : len(path)])
        file_name = path[name_idx:len(path)]
        extension_idx = self.seach_extension(file_name)

        resize_file_name = file_name[0:extension_idx] \
                           + '_resize_' \
                           +file_name[extension_idx : len(file_name)]

        ## file resize
        img = Image.open(path)
        w = img.width
        h = img.height

        resize_width = int(self.le_width.text())
        resize_height = int(self.le_height.text())

        cvImage = np.ones((w, h, 3), np.uint8) * 255
        cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB, cvImage)
        img_cv = cv2.imread(path)  ## open cv read img file
        resizeImage = cv2.resize(img_cv, dsize=(resize_width, resize_height))
        cv2.imwrite(path[0:name_idx] + resize_file_name, resizeImage)

    def setImgRotate(self, path):
        ## file name
        #print(path)
        degree = int(self.le_degree.text())

        name_idx = self.seach_filename(path)
        #print(path[name_idx : len(path)])
        file_name = path[name_idx:len(path)]
        extension_idx = self.seach_extension(file_name)

        rotate_file_name = file_name[0:extension_idx] \
                           + '_rotate_{}'.format(degree) \
                           +file_name[extension_idx : len(file_name)]
        ## file rotate
        img = Image.open(path)
        w = img.width
        h = img.height

        cvImage = np.ones((2 * w, 2 * h, 3), np.uint8) * 255
        cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB, cvImage)
        img_cv = cv2.imread(path)  ## open cv read img file
        # 2배의 이미지에 1/2이미지를 회전한다.
        resizeImage = cv2.resize(img_cv, dsize=(2 * w, 2 * h))  # img size X 2
        M = cv2.getRotationMatrix2D((w, h), degree, 0.5)  # 0.5 scale rotate
        rotated = cv2.warpAffine(resizeImage, M, (2 * w, 2 * h))
        # 배경 이미지를 줄이기 위해 좌표 계산후 이미지를 자른다.
        x_min, x_max, y_min, y_max = self.rotate_xy_min_max(w, h, degree)
        rotated2 = rotated[y_min:y_max, x_min:x_max]  # img cut
        cv2.imwrite(path[0:name_idx] + rotate_file_name, rotated2)

    def setImgFlip(self, path, mode):
        ## file name
        #print(path)
        name_idx = self.seach_filename(path)
        #print(path[name_idx : len(path)])
        file_name = path[name_idx:len(path)]
        extension_idx = self.seach_extension(file_name)

        resize_file_name = file_name[0:extension_idx] \
                           + '_{}flip_'.format(mode) \
                           +file_name[extension_idx : len(file_name)]

        ## file flip
        img = Image.open(path)
        w = img.width
        h = img.height

        cvImage = np.ones((w, h, 3), np.uint8) * 255
        cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB, cvImage)
        img_cv = cv2.imread(path)  ## open cv read img file
        if 'v' in mode:
            flipImage = cv2.flip(img_cv, 1)
        elif 'h' in mode:
            flipImage = cv2.flip(img_cv, 0)

        cv2.imwrite(path[0:name_idx] + resize_file_name, flipImage)

    def seach_filename(self, path):
        str = path
        result = 0
        while True:
            idx = str.find('/')
            if idx > -1:
                #print(idx)
                str = str[idx + 1:len(str)]
                result += idx + 1
            else:
                break
        return result

    def seach_extension(self, name):
        for extension in self.img_fomat_extension:
            extension_idx = name.find(extension)
            if extension_idx > -1:
                return extension_idx

    def rotate_xy_min_max(self, w, h, degrees):
        th = math.radians(degrees)
        sin = math.sin(th)
        cos = math.cos(th)

        x1 = (w / 2 * 3 - w) * cos - (h / 2 - h) * sin + w
        x2 = (w / 2 - w) * cos - (h / 2 - h) * sin + w
        x3 = (w / 2 - w) * cos - (h / 2 * 3 - h) * sin + w
        x4 = (w / 2 * 3 - w) * cos - (h / 2 * 3 - h) * sin + w

        y1 = (w / 2 * 3 - w) * sin + (h / 2 - h) * cos + h
        y2 = (w / 2 - w) * sin + (h / 2 - h) * cos + h
        y3 = (w / 2 - w) * sin + (h / 2 * 3 - h) * cos + h
        y4 = (w / 2 * 3 - w) * sin + (h / 2 * 3 - h) * cos + h

        x_min = 99999
        x_max = 0
        y_min = 99999
        y_max = 0
        x_range = (x1, x2, x3, x4)
        y_range = (y1, y2, y3, y4)

        for i in range(4):
            if x_max < x_range[i]:
                x_max = x_range[i]
            if x_range[i] < x_min:
                x_min = x_range[i]

            if y_max < y_range[i]:
                y_max = y_range[i]
            if y_range[i] < y_min:
                y_min = y_range[i]
        '''
        print('{} , {} '.format(w,h))
        print(' {} , {} , {} , {} '.format(x_range[0] , x_range[1], x_range[2],  x_range[3]))
        print(' {} , {} , {} , {} '.format(y_range[0] , y_range[1], y_range[2], y_range[3]))
        print(' {} , {} , {} , {} '.format(int(x_min) , int(x_max) , int(y_min) , int(y_max)))
        print(' {} , {} , {} , {} '.format(x1,x2,x3,x4))
        print(' {} , {} , {} , {} '.format(y1, y2, y3, y4))
        '''

        return int(x_min), int(x_max), int(y_min), int(y_max)
class MyApp(Data):
    def __init__(self):
        super().__init__()
        # setting tabs
        self.tab1 = QGroupBox()
        self.tab2 = QGroupBox()
        self.tab3 = QGroupBox()
        self.tabs = QTabWidget()

        self.stack = QStackedWidget(self)

        # tab3 setting
        self.btn_show = QPushButton("show")
        self.tab3_group_11 = QVBoxLayout()
        self.tab3_group_22 = QVBoxLayout()
        self.stack2 = QStackedWidget(self)

        self.week = ("mon", "tue", "wed", "thu", "fri")

        self.classes_input = [
        ]  # input text from first tab 'lineEdit' to next tab 'btns_name'
        self.btns_name = [
        ]  # QRadioButton, set by the classes_input with next push button
        self.btns_week = []  # QRadioButton for week on second window
        self.btn_set = QPushButton("SET")  # SET 버튼 누를 때마다 데이터 저장
        self.initUI()  #

    def initUI(self):
        #
        # tab1 레이아웃 설정
        self.Tab1()
        # tab1 레이아웃 설정 반영
        #

        #
        # stack 에 요일들 추가
        self.set_stack()
        #
        # tab2 레이아웃 설정
        self.Tab2()
        # tab2 레이아웃 설정 반영
        #

        #
        # tab3 레이아웃 설정
        self.Tab3()
        # tab3 레이아웃 설정 반영
        #

        self.tabs.addTab(self.tab1, "수업 이름 설정")
        self.tabs.addTab(self.tab2, "수업 시간들 추가")
        self.tabs.addTab(self.tab3, "시간표")  # tab3 추가

        vbox = QVBoxLayout()
        vbox.addWidget(self.tabs)

        self.setLayout(vbox)

        self.setWindowTitle('Timetable Maker')
        lotus = QIcon(self.resource_path('./assets/lotus.ico'))
        self.setWindowIcon(lotus)
        self.setGeometry(1200, 500, 500, 500)
        self.show()

    def next1_clicked(self):
        for i in range(10):
            self.btns_name[i].setText(self.classes_input[i].text())
        self.tabs.setCurrentIndex(1)

    def Tab1(self):
        # setting for tab1
        layout_1 = QGridLayout()
        for i in range(10):
            layout_1.addWidget(QLabel("Class %d." % (i + 1)), i, 0)
        for i in range(10):
            self.classes_input.append(QLineEdit())

        for i in range(10):
            layout_1.addWidget(self.classes_input[i], i, 1)
        btn_next = QPushButton("&next")
        layout_1.addWidget(btn_next, 11, 2)
        btn_next.clicked.connect(self.next1_clicked)
        self.tabs.tabBarClicked.connect(self.next1_clicked)
        self.tab1.setLayout(layout_1)

    def Tab2(self):
        # setting for tab2
        layout_2 = QGridLayout()
        # 1. class 이름 목록
        group_1 = QGroupBox("class")
        group_11 = QVBoxLayout()
        for i in range(10):
            self.btns_name.append(QRadioButton())
            group_11.addWidget(self.btns_name[i])  # lineEdit 과 connect 하기
            self.btns_name[i].clicked.connect(self.class_name_clicked)
        group_1.setLayout(group_11)
        # class 이름 목록 설정 완료

        # 2. week 목록
        week = ("mon", "tue", "wed", "thu", "fri")
        group_2 = QGroupBox("week")
        group_22 = QVBoxLayout()
        for i in range(5):
            self.btns_week.append(QRadioButton(week[i]))
            group_22.addWidget(self.btns_week[i])
            self.btns_week[i].clicked.connect(self.week_changed)
        group_2.setLayout(group_22)

        layout_2.addWidget(group_1, 0, 0)
        layout_2.addWidget(group_2, 0, 1)
        layout_2.addWidget(self.stack, 0, 2)

        btn_set = QPushButton("SET")
        btn_set.setStyleSheet(
            "color: red; selection-color: yellow; background-color: yellow; font: bold 14px"
        )
        layout_2.addWidget(btn_set, 1, 2)
        btn_set.clicked.connect(self.set_clicked)

        self.tab2.setLayout(layout_2)

    def class_name_clicked(self):
        for t in range(50):
            self.unify_time[t].setChecked(False)
        self.set_color_blue()

    def Tab3(self):
        # tab3 outfit
        layout_3 = QGridLayout()

        group_1 = QGroupBox("Options")
        group_1.setLayout(self.tab3_group_11)
        layout_3.addWidget(group_1, 0, 0, 1, 1)
        group_1.setMaximumSize(400, 2000)

        group_2 = QGroupBox("Table")
        group_2.setLayout(self.tab3_group_22)
        layout_3.addWidget(self.stack2, 0, 1, 1, 3)

        save = QPushButton("SAVE")
        info = QPushButton("info")

        self.btn_show.clicked.connect(self.btn_show_clicked)
        save.clicked.connect(self.save_clicked)
        info.clicked.connect(self.info_clicked)

        layout_3.addWidget(self.btn_show, 1, 0)
        layout_3.addWidget(save, 1, 3)
        layout_3.addWidget(info, 1, 2)
        self.tab3.setLayout(layout_3)

    def save_clicked(self):
        view_index = self.view.currentIndex()
        index = view_index.row()
        text_write = []
        class_info = ""
        for i, j in enumerate(self.table_making.class_seq[index]):
            temp_dialog_message = ""
            for k in self.sets_list[i][j]:
                temp_num_week = int(k) // 10
                temp_num_time = int(k) % 10
                temp_dialog_message += f"{self.week[temp_num_week]}_{temp_num_time + 1}, "
            class_info += "{0} ---> {1} \n".format(
                str(self.classes_input[i].text()), temp_dialog_message)
        indexed_table_list = self.table_making.lines[index * 11:index * 11 +
                                                     11]
        for line in indexed_table_list:
            text_write.append(str(line) + '\n')
        with open(f"..\\option{index + 1}.txt", 'w') as f:
            for one_line in text_write:
                f.write(one_line)
            f.write('\n')
            f.write(class_info)
            f.write('\n')
            f.write("(set font to 'D2CODING' or any monospaced font)")

    def tab3_show(self):
        self.view = QListView(self)
        self.model = QStandardItemModel()
        option_length = len(self.table_making.class_set)
        for option in range(option_length):
            self.model.appendRow(QStandardItem("option%d" % (option + 1)))
            table = QGroupBox("table%d" % (option + 1))
            table_box = QVBoxLayout()
            for i in self.table_making.lines[option * 11:(option * 11 + 11)]:
                label = QLabel(i, self)
                label.setFont(QFont('D2Coding Bold'))
                table_box.addWidget(label)
            table.setLayout(table_box)
            self.stack2.addWidget(table)
        self.view.setModel(self.model)
        self.tab3_group_11.addWidget(self.view)
        self.view.clicked.connect(self.slot_clicked_item)

    def slot_clicked_item(self, index):
        self.stack2.setCurrentIndex(index.row())

    def info_clicked(self):
        view_index = self.view.currentIndex()
        index = view_index.row()
        title = "option%d" % (index + 1)
        message = ""
        for i, j in enumerate(self.table_making.class_seq[index]):
            temp_dialog_message = ""
            for k in self.sets_list[i][j]:
                temp_num_week = int(k) // 10
                temp_num_time = int(k) % 10
                temp_dialog_message += f"{self.week[temp_num_week]}_{temp_num_time + 1}, "
            message += "{0} ---> {1} \n".format(
                str(self.classes_input[i].text()), temp_dialog_message)
        QMessageBox.information(self, title, message)

    def resource_path(self, relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative_path)
        return os.path.join(os.path.abspath('.'), relative_path)
class comics_project_manager_docker(DockWidget):
    setupDictionary = {}
    stringName = i18n("Comics Manager")
    projecturl = None

    def __init__(self):
        super().__init__()
        self.setWindowTitle(self.stringName)

        # Setup layout:
        base = QHBoxLayout()
        widget = QWidget()
        widget.setLayout(base)
        baseLayout = QSplitter()
        base.addWidget(baseLayout)
        self.setWidget(widget)
        buttonLayout = QVBoxLayout()
        buttonBox = QWidget()
        buttonBox.setLayout(buttonLayout)
        baseLayout.addWidget(buttonBox)

        # Comic page list and pages model
        self.comicPageList = QListView()
        self.comicPageList.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.comicPageList.setDragEnabled(True)
        self.comicPageList.setDragDropMode(QAbstractItemView.InternalMove)
        self.comicPageList.setDefaultDropAction(Qt.MoveAction)
        self.comicPageList.setAcceptDrops(True)
        self.comicPageList.setItemDelegate(comic_page_delegate())
        self.pagesModel = QStandardItemModel()
        self.comicPageList.doubleClicked.connect(self.slot_open_page)
        self.comicPageList.setIconSize(QSize(128, 128))
        # self.comicPageList.itemDelegate().closeEditor.connect(self.slot_write_description)
        self.pagesModel.layoutChanged.connect(self.slot_write_config)
        self.pagesModel.rowsInserted.connect(self.slot_write_config)
        self.pagesModel.rowsRemoved.connect(self.slot_write_config)
        self.pagesModel.rowsMoved.connect(self.slot_write_config)
        self.comicPageList.setModel(self.pagesModel)
        pageBox = QWidget()
        pageBox.setLayout(QVBoxLayout())
        zoomSlider = QSlider(Qt.Horizontal, None)
        zoomSlider.setRange(1, 8)
        zoomSlider.setValue(4)
        zoomSlider.setTickInterval(1)
        zoomSlider.setMinimumWidth(10)
        zoomSlider.valueChanged.connect(self.slot_scale_thumbnails)
        self.projectName = Elided_Text_Label()
        pageBox.layout().addWidget(self.projectName)
        pageBox.layout().addWidget(zoomSlider)
        pageBox.layout().addWidget(self.comicPageList)
        baseLayout.addWidget(pageBox)

        self.btn_project = QToolButton()
        self.btn_project.setPopupMode(QToolButton.MenuButtonPopup)
        self.btn_project.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)
        menu_project = QMenu()
        self.action_new_project = QAction(i18n("New Project"), self)
        self.action_new_project.triggered.connect(self.slot_new_project)
        self.action_load_project = QAction(i18n("Open Project"), self)
        self.action_load_project.triggered.connect(self.slot_open_config)
        menu_project.addAction(self.action_new_project)
        menu_project.addAction(self.action_load_project)
        self.btn_project.setMenu(menu_project)
        self.btn_project.setDefaultAction(self.action_load_project)
        buttonLayout.addWidget(self.btn_project)

        # Settings dropdown with actions for the different settings menus.
        self.btn_settings = QToolButton()
        self.btn_settings.setPopupMode(QToolButton.MenuButtonPopup)
        self.btn_settings.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
        self.action_edit_project_settings = QAction(i18n("Project Settings"),
                                                    self)
        self.action_edit_project_settings.triggered.connect(
            self.slot_edit_project_settings)
        self.action_edit_meta_data = QAction(i18n("Meta Data"), self)
        self.action_edit_meta_data.triggered.connect(self.slot_edit_meta_data)
        self.action_edit_export_settings = QAction(i18n("Export Settings"),
                                                   self)
        self.action_edit_export_settings.triggered.connect(
            self.slot_edit_export_settings)
        menu_settings = QMenu()
        menu_settings.addAction(self.action_edit_project_settings)
        menu_settings.addAction(self.action_edit_meta_data)
        menu_settings.addAction(self.action_edit_export_settings)
        self.btn_settings.setDefaultAction(self.action_edit_project_settings)
        self.btn_settings.setMenu(menu_settings)
        buttonLayout.addWidget(self.btn_settings)
        self.btn_settings.setDisabled(True)

        # Add page drop down with different page actions.
        self.btn_add_page = QToolButton()
        self.btn_add_page.setPopupMode(QToolButton.MenuButtonPopup)
        self.btn_add_page.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)

        self.action_add_page = QAction(i18n("Add Page"), self)
        self.action_add_page.triggered.connect(self.slot_add_new_page_single)
        self.action_add_template = QAction(i18n("Add Page from Template"),
                                           self)
        self.action_add_template.triggered.connect(
            self.slot_add_new_page_from_template)
        self.action_add_existing = QAction(i18n("Add Existing Pages"), self)
        self.action_add_existing.triggered.connect(self.slot_add_page_from_url)
        self.action_remove_selected_page = QAction(i18n("Remove Page"), self)
        self.action_remove_selected_page.triggered.connect(
            self.slot_remove_selected_page)
        self.action_resize_all_pages = QAction(i18n("Batch Resize"), self)
        self.action_resize_all_pages.triggered.connect(self.slot_batch_resize)
        self.btn_add_page.setDefaultAction(self.action_add_page)
        self.action_show_page_viewer = QAction(i18n("View Page In Window"),
                                               self)
        self.action_show_page_viewer.triggered.connect(
            self.slot_show_page_viewer)
        self.action_scrape_authors = QAction(i18n("Scrape Author Info"), self)
        self.action_scrape_authors.setToolTip(
            i18n(
                "Search for author information in documents and add it to the author list. This does not check for duplicates."
            ))
        self.action_scrape_authors.triggered.connect(
            self.slot_scrape_author_list)
        self.action_scrape_translations = QAction(
            i18n("Scrape Text for Translation"), self)
        self.action_scrape_translations.triggered.connect(
            self.slot_scrape_translations)
        actionList = []
        menu_page = QMenu()
        actionList.append(self.action_add_page)
        actionList.append(self.action_add_template)
        actionList.append(self.action_add_existing)
        actionList.append(self.action_remove_selected_page)
        actionList.append(self.action_resize_all_pages)
        actionList.append(self.action_show_page_viewer)
        actionList.append(self.action_scrape_authors)
        actionList.append(self.action_scrape_translations)
        menu_page.addActions(actionList)
        self.btn_add_page.setMenu(menu_page)
        buttonLayout.addWidget(self.btn_add_page)
        self.btn_add_page.setDisabled(True)

        self.comicPageList.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.comicPageList.addActions(actionList)

        # Export button that... exports.
        self.btn_export = QPushButton(i18n("Export Comic"))
        self.btn_export.clicked.connect(self.slot_export)
        buttonLayout.addWidget(self.btn_export)
        self.btn_export.setDisabled(True)

        self.btn_project_url = QPushButton(i18n("Copy Location"))
        self.btn_project_url.setToolTip(
            i18n(
                "Copies the path of the project to the clipboard. Useful for quickly copying to a file manager or the like."
            ))
        self.btn_project_url.clicked.connect(self.slot_copy_project_url)
        self.btn_project_url.setDisabled(True)
        buttonLayout.addWidget(self.btn_project_url)

        self.page_viewer_dialog = comics_project_page_viewer.comics_project_page_viewer(
        )

        Application.notifier().imageSaved.connect(
            self.slot_check_for_page_update)

        buttonLayout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum,
                        QSizePolicy.MinimumExpanding))

    """
    Open the config file and load the json file into a dictionary.
    """

    def slot_open_config(self):
        self.path_to_config = QFileDialog.getOpenFileName(
            caption=i18n("Please select the JSON comic config file."),
            filter=str(i18n("JSON files") + "(*.json)"))[0]
        if os.path.exists(self.path_to_config) is True:
            configFile = open(self.path_to_config,
                              "r",
                              newline="",
                              encoding="utf-16")
            self.setupDictionary = json.load(configFile)
            self.projecturl = os.path.dirname(str(self.path_to_config))
            configFile.close()
            self.load_config()

    """
    Further config loading.
    """

    def load_config(self):
        self.projectName.setMainText(
            text=str(self.setupDictionary["projectName"]))
        self.fill_pages()
        self.btn_settings.setEnabled(True)
        self.btn_add_page.setEnabled(True)
        self.btn_export.setEnabled(True)
        self.btn_project_url.setEnabled(True)

    """
    Fill the pages model with the pages from the pages list.
    """

    def fill_pages(self):
        self.loadingPages = True
        self.pagesModel.clear()
        pagesList = []
        if "pages" in self.setupDictionary.keys():
            pagesList = self.setupDictionary["pages"]
        progress = QProgressDialog()
        progress.setMinimum(0)
        progress.setMaximum(len(pagesList))
        progress.setWindowTitle(i18n("Loading Pages..."))
        for url in pagesList:
            absurl = os.path.join(self.projecturl, url)
            if (os.path.exists(absurl)):
                #page = Application.openDocument(absurl)
                page = zipfile.ZipFile(absurl, "r")
                thumbnail = QImage.fromData(page.read("preview.png"))
                pageItem = QStandardItem()
                dataList = self.get_description_and_title(
                    page.read("documentinfo.xml"))
                if (dataList[0].isspace() or len(dataList[0]) < 1):
                    dataList[0] = os.path.basename(url)
                pageItem.setText(dataList[0].replace("_", " "))
                pageItem.setDragEnabled(True)
                pageItem.setDropEnabled(False)
                pageItem.setEditable(False)
                pageItem.setIcon(QIcon(QPixmap.fromImage(thumbnail)))
                pageItem.setData(dataList[1], role=CPE.DESCRIPTION)
                pageItem.setData(url, role=CPE.URL)
                pageItem.setData(dataList[2], role=CPE.KEYWORDS)
                pageItem.setData(dataList[3], role=CPE.LASTEDIT)
                pageItem.setData(dataList[4], role=CPE.EDITOR)
                pageItem.setToolTip(url)
                page.close()
                self.pagesModel.appendRow(pageItem)
                progress.setValue(progress.value() + 1)
        progress.setValue(len(pagesList))
        self.loadingPages = False

    """
    Function that is triggered by the zoomSlider
    Resizes the thumbnails.
    """

    def slot_scale_thumbnails(self, multiplier=4):
        self.comicPageList.setIconSize(QSize(multiplier * 32, multiplier * 32))

    """
    Function that takes the documentinfo.xml and parses it for the title, subject and abstract tags,
    to get the title and description.
    
    @returns a stringlist with the name on 0 and the description on 1.
    """

    def get_description_and_title(self, string):
        xmlDoc = ET.fromstring(string)
        calligra = str("{http://www.calligra.org/DTD/document-info}")
        name = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'title')):
            name = xmlDoc[0].find(calligra + 'title').text
            if name is None:
                name = " "
        desc = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'subject')):
            desc = xmlDoc[0].find(calligra + 'subject').text
        if desc is None or desc.isspace() or len(desc) < 1:
            if ET.iselement(xmlDoc[0].find(calligra + 'abstract')):
                desc = xmlDoc[0].find(calligra + 'abstract').text
                if desc is not None:
                    if desc.startswith("<![CDATA["):
                        desc = desc[len("<![CDATA["):]
                    if desc.startswith("]]>"):
                        desc = desc[:-len("]]>")]
        keywords = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'keyword')):
            keywords = xmlDoc[0].find(calligra + 'keyword').text
        date = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'date')):
            date = xmlDoc[0].find(calligra + 'date').text
        author = []
        if ET.iselement(xmlDoc[1].find(calligra + 'creator-first-name')):
            string = xmlDoc[1].find(calligra + 'creator-first-name').text
            if string is not None:
                author.append(string)
        if ET.iselement(xmlDoc[1].find(calligra + 'creator-last-name')):
            string = xmlDoc[1].find(calligra + 'creator-last-name').text
            if string is not None:
                author.append(string)
        if ET.iselement(xmlDoc[1].find(calligra + 'full-name')):
            string = xmlDoc[1].find(calligra + 'full-name').text
            if string is not None:
                author.append(string)

        return [name, desc, keywords, date, " ".join(author)]

    """
    Scrapes authors from the author data in the document info and puts them into the author list.
    Doesn't check for duplicates.
    """

    def slot_scrape_author_list(self):
        listOfAuthors = []
        if "authorList" in self.setupDictionary.keys():
            listOfAuthors = self.setupDictionary["authorList"]
        if "pages" in self.setupDictionary.keys():
            for relurl in self.setupDictionary["pages"]:
                absurl = os.path.join(self.projecturl, relurl)
                page = zipfile.ZipFile(absurl, "r")
                xmlDoc = ET.fromstring(page.read("documentinfo.xml"))
                calligra = str("{http://www.calligra.org/DTD/document-info}")
                authorelem = xmlDoc.find(calligra + 'author')
                author = {}
                if ET.iselement(authorelem.find(calligra + 'full-name')):
                    author["nickname"] = str(
                        authorelem.find(calligra + 'full-name').text)

                if ET.iselement(
                        authorelem.find(calligra + 'creator-first-name')):
                    author["first-name"] = str(
                        authorelem.find(calligra + 'creator-first-name').text)

                if ET.iselement(authorelem.find(calligra + 'initial')):
                    author["initials"] = str(
                        authorelem.find(calligra + 'initial').text)

                if ET.iselement(authorelem.find(calligra +
                                                'creator-last-name')):
                    author["last-name"] = str(
                        authorelem.find(calligra + 'creator-last-name').text)

                if ET.iselement(authorelem.find(calligra + 'email')):
                    author["email"] = str(
                        authorelem.find(calligra + 'email').text)

                if ET.iselement(authorelem.find(calligra + 'contact')):
                    contact = authorelem.find(calligra + 'contact')
                    contactMode = contact.get("type")
                    if contactMode == "email":
                        author["email"] = str(contact.text)
                    if contactMode == "homepage":
                        author["homepage"] = str(contact.text)

                if ET.iselement(authorelem.find(calligra + 'position')):
                    author["role"] = str(
                        authorelem.find(calligra + 'position').text)
                listOfAuthors.append(author)
                page.close()
        self.setupDictionary["authorList"] = listOfAuthors

    """
    Edit the general project settings like the project name, concept, pages location, export location, template location, metadata
    """

    def slot_edit_project_settings(self):
        dialog = comics_project_settings_dialog.comics_project_details_editor(
            self.projecturl)
        dialog.setConfig(self.setupDictionary, self.projecturl)

        if dialog.exec_() == QDialog.Accepted:
            self.setupDictionary = dialog.getConfig(self.setupDictionary)
            self.slot_write_config()
            self.projectName.setMainText(
                str(self.setupDictionary["projectName"]))

    """
    This allows users to select existing pages and add them to the pages list. The pages are currently not copied to the pages folder. Useful for existing projects.
    """

    def slot_add_page_from_url(self):
        # get the pages.
        urlList = QFileDialog.getOpenFileNames(
            caption=i18n("Which existing pages to add?"),
            directory=self.projecturl,
            filter=str(i18n("Krita files") + "(*.kra)"))[0]

        # get the existing pages list.
        pagesList = []
        if "pages" in self.setupDictionary.keys():
            pagesList = self.setupDictionary["pages"]

        # And add each url in the url list to the pages list and the model.
        for url in urlList:
            if self.projecturl not in urlList:
                newUrl = os.path.join(self.projecturl,
                                      self.setupDictionary["pagesLocation"],
                                      os.path.basename(url))
                shutil.move(url, newUrl)
                url = newUrl
            relative = os.path.relpath(url, self.projecturl)
            if url not in pagesList:
                page = zipfile.ZipFile(url, "r")
                thumbnail = QImage.fromData(page.read("preview.png"))
                dataList = self.get_description_and_title(
                    page.read("documentinfo.xml"))
                if (dataList[0].isspace() or len(dataList[0]) < 1):
                    dataList[0] = os.path.basename(url)
                newPageItem = QStandardItem()
                newPageItem.setIcon(QIcon(QPixmap.fromImage(thumbnail)))
                newPageItem.setDragEnabled(True)
                newPageItem.setDropEnabled(False)
                newPageItem.setEditable(False)
                newPageItem.setText(dataList[0].replace("_", " "))
                newPageItem.setData(dataList[1], role=CPE.DESCRIPTION)
                newPageItem.setData(relative, role=CPE.URL)
                newPageItem.setData(dataList[2], role=CPE.KEYWORDS)
                newPageItem.setData(dataList[3], role=CPE.LASTEDIT)
                newPageItem.setData(dataList[4], role=CPE.EDITOR)
                newPageItem.setToolTip(relative)
                page.close()
                self.pagesModel.appendRow(newPageItem)

    """
    Remove the selected page from the list of pages. This does not remove it from disk(far too dangerous).
    """

    def slot_remove_selected_page(self):
        index = self.comicPageList.currentIndex()
        self.pagesModel.removeRow(index.row())

    """
    This function adds a new page from the default template. If there's no default template, or the file does not exist, it will 
    show the create/import template dialog. It will remember the selected item as the default template.
    """

    def slot_add_new_page_single(self):
        templateUrl = "templatepage"
        templateExists = False

        if "singlePageTemplate" in self.setupDictionary.keys():
            templateUrl = self.setupDictionary["singlePageTemplate"]
        if os.path.exists(os.path.join(self.projecturl, templateUrl)):
            templateExists = True

        if templateExists is False:
            if "templateLocation" not in self.setupDictionary.keys():
                self.setupDictionary["templateLocation"] = os.path.relpath(
                    QFileDialog.getExistingDirectory(
                        caption=i18n("Where are the templates located?"),
                        options=QFileDialog.ShowDirsOnly), self.projecturl)

            templateDir = os.path.join(
                self.projecturl, self.setupDictionary["templateLocation"])
            template = comics_template_dialog.comics_template_dialog(
                templateDir)

            if template.exec_() == QDialog.Accepted:
                templateUrl = os.path.relpath(template.url(), self.projecturl)
                self.setupDictionary["singlePageTemplate"] = templateUrl
        if os.path.exists(os.path.join(self.projecturl, templateUrl)):
            self.add_new_page(templateUrl)

    """
    This function always asks for a template showing the new template window. This allows users to have multiple different
    templates created for back covers, spreads, other and have them accessible, while still having the convenience of a singular
    "add page" that adds a default.
    """

    def slot_add_new_page_from_template(self):
        if "templateLocation" not in self.setupDictionary.keys():
            self.setupDictionary["templateLocation"] = os.path.relpath(
                QFileDialog.getExistingDirectory(
                    caption=i18n("Where are the templates located?"),
                    options=QFileDialog.ShowDirsOnly), self.projecturl)

        templateDir = os.path.join(self.projecturl,
                                   self.setupDictionary["templateLocation"])
        template = comics_template_dialog.comics_template_dialog(templateDir)

        if template.exec_() == QDialog.Accepted:
            templateUrl = os.path.relpath(template.url(), self.projecturl)
            self.add_new_page(templateUrl)

    """
    This is the actual function that adds the template using the template url.
    It will attempt to name the new page projectName+number.
    """

    def add_new_page(self, templateUrl):

        # check for page list and or location.
        pagesList = []
        if "pages" in self.setupDictionary.keys():
            pagesList = self.setupDictionary["pages"]
        if not "pageNumber" in self.setupDictionary.keys():
            self.setupDictionary['pageNumber'] = 0

        if (str(self.setupDictionary["pagesLocation"]).isspace()):
            self.setupDictionary["pagesLocation"] = os.path.relpath(
                QFileDialog.getExistingDirectory(
                    caption=i18n("Where should the pages go?"),
                    options=QFileDialog.ShowDirsOnly), self.projecturl)

        # Search for the possible name.
        extraUnderscore = str()
        if str(self.setupDictionary["projectName"])[-1].isdigit():
            extraUnderscore = "_"
        self.setupDictionary['pageNumber'] += 1
        pageName = str(self.setupDictionary["projectName"]).replace(
            " ", "_") + extraUnderscore + str(
                format(self.setupDictionary['pageNumber'], "03d"))
        url = os.path.join(str(self.setupDictionary["pagesLocation"]),
                           pageName + ".kra")

        # open the page by opening the template and resaving it, or just opening it.
        absoluteUrl = os.path.join(self.projecturl, url)
        if (os.path.exists(absoluteUrl)):
            newPage = Application.openDocument(absoluteUrl)
        else:
            booltemplateExists = os.path.exists(
                os.path.join(self.projecturl, templateUrl))
            if booltemplateExists is False:
                templateUrl = os.path.relpath(
                    QFileDialog.getOpenFileName(
                        caption=i18n(
                            "Which image should be the basis the new page?"),
                        directory=self.projecturl,
                        filter=str(i18n("Krita files") + "(*.kra)"))[0],
                    self.projecturl)
            newPage = Application.openDocument(
                os.path.join(self.projecturl, templateUrl))
            newPage.waitForDone()
            newPage.setFileName(absoluteUrl)
            newPage.setName(pageName.replace("_", " "))
            newPage.save()
            newPage.waitForDone()

        # Get out the extra data for the standard item.
        newPageItem = QStandardItem()
        newPageItem.setIcon(
            QIcon(QPixmap.fromImage(newPage.thumbnail(256, 256))))
        newPageItem.setDragEnabled(True)
        newPageItem.setDropEnabled(False)
        newPageItem.setEditable(False)
        newPageItem.setText(pageName.replace("_", " "))
        newPageItem.setData("", role=CPE.DESCRIPTION)
        newPageItem.setData(url, role=CPE.URL)
        newPageItem.setData("", role=CPE.KEYWORDS)
        newPageItem.setData("", role=CPE.LASTEDIT)
        newPageItem.setData("", role=CPE.EDITOR)
        newPageItem.setToolTip(url)

        # close page document.
        while os.path.exists(absoluteUrl) is False:
            qApp.processEvents()

        newPage.close()

        # add item to page.
        self.pagesModel.appendRow(newPageItem)

    """
    Write to the json configuration file.
    This also checks the current state of the pages list.
    """

    def slot_write_config(self):

        # Don't load when the pages are still being loaded, otherwise we'll be overwriting our own pages list.
        if (self.loadingPages is False):
            print("CPMT: writing comic configuration...")

            # Generate a pages list from the pagesmodel.
            pagesList = []
            for i in range(self.pagesModel.rowCount()):
                index = self.pagesModel.index(i, 0)
                url = str(self.pagesModel.data(index, role=CPE.URL))
                if url not in pagesList:
                    pagesList.append(url)
            self.setupDictionary["pages"] = pagesList

            # Save to our json file.
            configFile = open(self.path_to_config,
                              "w",
                              newline="",
                              encoding="utf-16")
            json.dump(self.setupDictionary,
                      configFile,
                      indent=4,
                      sort_keys=True,
                      ensure_ascii=False)
            configFile.close()
            print("CPMT: done")

    """
    Open a page in the pagesmodel in Krita.
    """

    def slot_open_page(self, index):
        if index.column() is 0:
            # Get the absolute url from the relative one in the pages model.
            absoluteUrl = os.path.join(
                self.projecturl, str(self.pagesModel.data(index,
                                                          role=CPE.URL)))

            # Make sure the page exists.
            if os.path.exists(absoluteUrl):
                page = Application.openDocument(absoluteUrl)

                # Set the title to the filename if it was empty. It looks a bit neater.
                if page.name().isspace or len(page.name()) < 1:
                    page.setName(
                        str(self.pagesModel.data(index,
                                                 role=Qt.DisplayRole)).replace(
                                                     "_", " "))

                # Add views for the document so the user can use it.
                Application.activeWindow().addView(page)
                Application.setActiveDocument(page)
            else:
                print(
                    "CPMT: The page cannot be opened because the file doesn't exist:",
                    absoluteUrl)

    """
    Call up the metadata editor dialog. Only when the dialog is "Accepted" will the metadata be saved.
    """

    def slot_edit_meta_data(self):
        dialog = comics_metadata_dialog.comic_meta_data_editor()

        dialog.setConfig(self.setupDictionary)
        if (dialog.exec_() == QDialog.Accepted):
            self.setupDictionary = dialog.getConfig(self.setupDictionary)
            self.slot_write_config()

    """
    An attempt at making the description editable from the comic pages list.
    It is currently not working because ZipFile has no overwrite mechanism,
    and I don't have the energy to write one yet.
    """

    def slot_write_description(self, index):

        for row in range(self.pagesModel.rowCount()):
            index = self.pagesModel.index(row, 1)
            indexUrl = self.pagesModel.index(row, 0)
            absoluteUrl = os.path.join(
                self.projecturl,
                str(self.pagesModel.data(indexUrl, role=CPE.URL)))
            page = zipfile.ZipFile(absoluteUrl, "a")
            xmlDoc = ET.ElementTree()
            ET.register_namespace("",
                                  "http://www.calligra.org/DTD/document-info")
            location = os.path.join(self.projecturl, "documentinfo.xml")
            xmlDoc.parse(location)
            xmlroot = ET.fromstring(page.read("documentinfo.xml"))
            calligra = "{http://www.calligra.org/DTD/document-info}"
            aboutelem = xmlroot.find(calligra + 'about')
            if ET.iselement(aboutelem.find(calligra + 'subject')):
                desc = aboutelem.find(calligra + 'subject')
                desc.text = self.pagesModel.data(index, role=Qt.EditRole)
                xmlstring = ET.tostring(xmlroot,
                                        encoding='unicode',
                                        method='xml',
                                        short_empty_elements=False)
                page.writestr(zinfo_or_arcname="documentinfo.xml",
                              data=xmlstring)
                for document in Application.documents():
                    if str(document.fileName()) == str(absoluteUrl):
                        document.setDocumentInfo(xmlstring)
            page.close()

    """
    Calls up the export settings dialog. Only when accepted will the configuration be written.
    """

    def slot_edit_export_settings(self):
        dialog = comics_export_dialog.comic_export_setting_dialog()
        dialog.setConfig(self.setupDictionary)

        if (dialog.exec_() == QDialog.Accepted):
            self.setupDictionary = dialog.getConfig(self.setupDictionary)
            self.slot_write_config()

    """
    Export the comic. Won't work without export settings set.
    """

    def slot_export(self):

        #ensure there is a unique identifier
        if "uuid" not in self.setupDictionary.keys():
            uuid = str()
            if "acbfID" in self.setupDictionary.keys():
                uuid = str(self.setupDictionary["acbfID"])
            else:
                uuid = QUuid.createUuid().toString()
            self.setupDictionary["uuid"] = uuid

        exporter = comics_exporter.comicsExporter()
        exporter.set_config(self.setupDictionary, self.projecturl)
        exportSuccess = exporter.export()
        if exportSuccess:
            print(
                "CPMT: Export success! The files have been written to the export folder!"
            )
            QMessageBox.information(
                self, i18n("Export success"),
                i18n("The files have been written to the export folder."),
                QMessageBox.Ok)

    """
    Calls up the comics project setup wizard so users can create a new json file with the basic information.
    """

    def slot_new_project(self):
        setup = comics_project_setup_wizard.ComicsProjectSetupWizard()
        setup.showDialog()

    """
    This is triggered by any document save.
    It checks if the given url in in the pages list, and if so,
    updates the appropriate page thumbnail.
    This helps with the management of the pages, because the user
    will be able to see the thumbnails as a todo for the whole comic,
    giving a good overview over whether they still need to ink, color or
    the like for a given page, and it thus also rewards the user whenever
    they save.
    """

    def slot_check_for_page_update(self, url):
        if "pages" in self.setupDictionary.keys():
            relUrl = os.path.relpath(url, self.projecturl)
            if relUrl in self.setupDictionary["pages"]:
                index = self.pagesModel.index(
                    self.setupDictionary["pages"].index(relUrl), 0)
                if index.isValid():
                    pageItem = self.pagesModel.itemFromIndex(index)
                    page = zipfile.ZipFile(url, "r")
                    dataList = self.get_description_and_title(
                        page.read("documentinfo.xml"))
                    if (dataList[0].isspace() or len(dataList[0]) < 1):
                        dataList[0] = os.path.basename(url)
                    thumbnail = QImage.fromData(page.read("preview.png"))
                    pageItem.setIcon(QIcon(QPixmap.fromImage(thumbnail)))
                    pageItem.setText(dataList[0])
                    pageItem.setData(dataList[1], role=CPE.DESCRIPTION)
                    pageItem.setData(url, role=CPE.URL)
                    pageItem.setData(dataList[2], role=CPE.KEYWORDS)
                    pageItem.setData(dataList[3], role=CPE.LASTEDIT)
                    pageItem.setData(dataList[4], role=CPE.EDITOR)
                    self.pagesModel.setItem(index.row(), index.column(),
                                            pageItem)

    """
    Resize all the pages in the pages list.
    It will show a dialog with the options for resizing.
    Then, it will try to pop up a progress dialog while resizing.
    The progress dialog shows the remaining time and pages.
    """

    def slot_batch_resize(self):
        dialog = QDialog()
        dialog.setWindowTitle(i18n("Resize all Pages"))
        buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        buttons.accepted.connect(dialog.accept)
        buttons.rejected.connect(dialog.reject)
        sizesBox = comics_export_dialog.comic_export_resize_widget(
            "Scale", batch=True, fileType=False)
        exporterSizes = comics_exporter.sizesCalculator()
        dialog.setLayout(QVBoxLayout())
        dialog.layout().addWidget(sizesBox)
        dialog.layout().addWidget(buttons)

        if dialog.exec_() == QDialog.Accepted:
            progress = QProgressDialog(i18n("Resizing pages..."), str(), 0,
                                       len(self.setupDictionary["pages"]))
            progress.setWindowTitle(i18n("Resizing Pages"))
            progress.setCancelButton(None)
            timer = QElapsedTimer()
            timer.start()
            config = {}
            config = sizesBox.get_config(config)
            for p in range(len(self.setupDictionary["pages"])):
                absoluteUrl = os.path.join(self.projecturl,
                                           self.setupDictionary["pages"][p])
                progress.setValue(p)
                timePassed = timer.elapsed()
                if (p > 0):
                    timeEstimated = (len(self.setupDictionary["pages"]) -
                                     p) * (timePassed / p)
                    passedString = str(int(timePassed / 60000)) + ":" + format(
                        int(timePassed / 1000), "02d") + ":" + format(
                            timePassed % 1000, "03d")
                    estimatedString = str(int(
                        timeEstimated / 60000)) + ":" + format(
                            int(timeEstimated / 1000), "02d") + ":" + format(
                                int(timeEstimated % 1000), "03d")
                    progress.setLabelText(
                        str(
                            i18n(
                                "{pages} of {pagesTotal} done. \nTime passed: {passedString}:\n Estimated:{estimated}"
                            )).format(pages=p,
                                      pagesTotal=len(
                                          self.setupDictionary["pages"]),
                                      passedString=passedString,
                                      estimated=estimatedString))
                    qApp.processEvents()
                if os.path.exists(absoluteUrl):
                    doc = Application.openDocument(absoluteUrl)
                    listScales = exporterSizes.get_scale_from_resize_config(
                        config["Scale"], [
                            doc.width(),
                            doc.height(),
                            doc.resolution(),
                            doc.resolution()
                        ])
                    doc.scaleImage(listScales[0], listScales[1], listScales[2],
                                   listScales[3], "bicubic")
                    doc.waitForDone()
                    doc.save()
                    doc.waitForDone()
                    doc.close()

    def slot_show_page_viewer(self):
        index = int(self.comicPageList.currentIndex().row())
        self.page_viewer_dialog.load_comic(self.path_to_config)
        self.page_viewer_dialog.go_to_page_index(index)
        self.page_viewer_dialog.show()

    """
    Function to copy the current project location into the clipboard.
    This is useful for users because they'll be able to use that url to quickly
    move to the project location in outside applications.
    """

    def slot_copy_project_url(self):
        if self.projecturl is not None:
            clipboard = qApp.clipboard()
            clipboard.setText(str(self.projecturl))

    """
    Scrape text files with the textlayer keys for text, and put those in a POT
    file. This makes it possible to handle translations.
    """

    def slot_scrape_translations(self):
        translationFolder = self.setupDictionary.get("translationLocation",
                                                     "translations")
        fullTranslationPath = os.path.join(self.projecturl, translationFolder)
        os.makedirs(fullTranslationPath, exist_ok=True)
        textLayersToSearch = self.setupDictionary.get("textLayerNames",
                                                      ["text"])

        scraper = comics_project_translation_scraper.translation_scraper(
            self.projecturl, translationFolder, textLayersToSearch,
            self.setupDictionary["projectName"])
        # Run text scraper.
        language = self.setupDictionary.get("language", "en")
        metadata = {}
        metadata["title"] = self.setupDictionary.get("title", "")
        metadata["summary"] = self.setupDictionary.get("summary", "")
        metadata["keywords"] = ", ".join(
            self.setupDictionary.get("otherKeywords", [""]))
        metadata["transnotes"] = self.setupDictionary.get(
            "translatorHeader", "Translator's Notes")
        scraper.start(self.setupDictionary["pages"], language, metadata)
        QMessageBox.information(
            self, i18n("Scraping success"),
            str(i18n("POT file has been written to: {file}")).format(
                file=fullTranslationPath), QMessageBox.Ok)

    """
    This is required by the dockwidget class, otherwise unused.
    """

    def canvasChanged(self, canvas):
        pass
Exemple #21
0
class LocationCompleterView(QWidget):
    def __init__(self):
        super().__init__(None)
        self._view = None  # QListView
        self._delegate = None  # LocationCompleterDelegate
        self._searchEnginesLayout = None  # QHBoxLayout
        self._resizeHeight = -1
        self._resizeTimer = None  # QTimer
        self._forceResize = True

        self.setAttribute(Qt.WA_ShowWithoutActivating)
        self.setAttribute(Qt.WA_X11NetWmWindowTypeCombo)

        if gVar.app.platformName() == 'xcb':
            self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint
                                | Qt.BypassWindowManagerHint)
        else:
            self.setWindowFlags(Qt.Popup)

        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self._view = QListView(self)
        layout.addWidget(self._view)

        self._view.setUniformItemSizes(True)
        self._view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self._view.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self._view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self._view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self._view.setSelectionMode(QAbstractItemView.SingleSelection)

        self._view.setMouseTracking(True)
        gVar.app.installEventFilter(self)

        self._delegate = LocationCompleterDelegate(self)
        self._view.setItemDelegate(self._delegate)

        searchFrame = QFrame(self)
        searchFrame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        searchLayout = QHBoxLayout(searchFrame)
        searchLayout.setContentsMargins(10, 4, 4, 4)

        searchSettingsButton = ToolButton(self)
        searchSettingsButton.setIcon(IconProvider.settingsIcon())
        searchSettingsButton.setToolTip(_('Manage Search Engines'))
        searchSettingsButton.setAutoRaise(True)
        searchSettingsButton.setIconSize(QSize(16, 16))
        searchSettingsButton.clicked.connect(self.searchEnginesDialogRequested)

        searchLabel = QLabel(_('Search with:'))
        self._searchEnginesLayout = QHBoxLayout()

        self._setupSearchEngines()
        gVar.app.searchEnginesManager().enginesChanged.connect(
            self._setupSearchEngines)

        searchLayout.addWidget(searchLabel)
        searchLayout.addLayout(self._searchEnginesLayout)
        searchLayout.addStretch()
        searchLayout.addWidget(searchSettingsButton)

        layout.addWidget(searchFrame)

    def model(self):
        '''
        @return: QAbstractItemModel
        '''
        return self._view.model()

    def setModel(self, model):
        '''
        @param model QAbstractItemModel
        '''
        self._view.setModel(model)

    def selectionModel(self):
        '''
        @return: QItemSelectionModel
        '''
        return self._view.selectionModel()

    def currentIndex(self):
        '''
        @return: QModelIndex
        '''
        return self._view.currentIndex()

    def setCurrentIndex(self, index):
        '''
        @param index QModelIndex
        '''
        self._view.setCurrentIndex(index)

    def adjustSize(self):
        maxItemsCount = 12
        newHeight = self._view.sizeHintForRow(0) * min(maxItemsCount,
                                                       self.model().rowCount())

        if not self._resizeTimer:
            self._resizeTimer = QTimer(self)
            self._resizeTimer.setInterval(200)

            def func():
                if self._resizeHeight > 0:
                    self._view.setFixedHeight(self._resizeHeight)
                    self.setFixedHeight(self.sizeHint().height())
                self._resizeHeight = -1

            self._resizeTimer.timeout.connect(func)

        if not self._forceResize:
            if newHeight == self._resizeHeight:
                return
            elif newHeight == self._view.height():
                self._resizeHeight = -1
                return
            elif newHeight < self._view.height():
                self._resizeHeight = newHeight
                self._resizeTimer.start()
                return

        self._resizeHeight = -1
        self._forceResize = False
        self._view.setFixedHeight(newHeight)
        self.setFixedHeight(self.sizeHint().height())

    # override
    def eventFilter(self, obj, event):  # noqa C901
        '''
        @param obj QObject
        @param event QEvent
        @return: bool
        '''
        # Event filter based on QCompleter::eventFilter from qcompleter.cpp
        if obj == self or obj == self._view or not self.isVisible():
            return False

        evtType = event.type()
        if obj == self._view.viewport():
            if evtType == QEvent.MouseButtonRelease:
                # QMouseEvent
                e = event
                index = self._view.indexAt(e.pos())
                if not index.isValid():
                    return False

                # Qt::MouseButton
                button = e.button()
                # Qt::KeyboardModifiers
                modifiers = e.modifiers()

                if button == Qt.LeftButton and modifiers == Qt.NoModifier:
                    self.indexActivated.emit(index)
                    return True

                if button == Qt.MiddleButton or (button == Qt.LeftButton
                                                 and modifiers
                                                 == Qt.ControlModifier):
                    self.indexCtrlActivated.emit(index)
                    return True

                if button == Qt.LeftButton and modifiers == Qt.ShiftModifier:
                    self.indexShiftActivated.emit(index)
                    return True

            return False

        if evtType == QEvent.KeyPress:
            # QKeyEvent
            keyEvent = event
            evtKey = keyEvent.key()
            modifiers = keyEvent.modifiers()
            index = self._view.currentIndex()
            item = self.model().index(0, 0)
            if item.data(LocationCompleterModel.VisitSearchItemRole):
                visitSearchIndex = item
            else:
                visitSearchIndex = QModelIndex()

            if (evtKey == Qt.Key_Up or evtKey == Qt.Key_Down) and \
                    self._view.currentIndex() != index:
                self._view.setCurrentIndex(index)  # TODO: ?

            if evtKey in (Qt.Key_Return, Qt.Key_Enter):
                if index.isValid():
                    if modifiers == Qt.NoModifier or modifiers == Qt.KeypadModifier:
                        self.indexActivated.emit(index)
                        return True

                    if modifiers == Qt.ControlModifier:
                        self.indexCtrlActivated.emit(index)
                        return True

                    if modifiers == Qt.ShiftModifier:
                        self.indexShiftActivated.emit(index)
                        return True

            elif evtKey == Qt.Key_End:
                if modifiers & Qt.ControlModifier:
                    self._view.setCurrentIndex(self.model().index(
                        self.model().rowCount() - 1, 0))
                    return True
                else:
                    self.close()

            elif evtKey == Qt.Key_Home:
                if modifiers & Qt.ControlModifier:
                    self._view.setCurrentIndex(self.model().index(0, 0))
                    self._view.scrollToTop()
                    return True
                else:
                    self.close()

            elif evtKey == Qt.Key_Escape:
                self.close()
                return True

            elif evtKey == Qt.Key_F4:
                if modifiers == Qt.AltModifier:
                    self.close()
                    return False

            elif evtKey in (Qt.Key_Tab, Qt.Key_Backtab):
                if modifiers != Qt.NoModifier and modifiers != Qt.ShiftModifier:
                    return False
                isBack = evtKey == Qt.Key_Backtab
                if evtKey == Qt.Key_Tab and modifiers == Qt.ShiftModifier:
                    isBack = True
                ev = QKeyEvent(QKeyEvent.KeyPress, isBack and Qt.Key_Up
                               or Qt.Key_Down, Qt.NoModifier)
                QApplication.sendEvent(self.focusProxy(), ev)
                return True

            elif evtKey in (Qt.Key_Up, Qt.Key_PageUp):
                if modifiers != Qt.NoModifier:
                    return False
                step = evtKey == Qt.Key_PageUp and 5 or 1
                if not index.isValid() or index == visitSearchIndex:
                    rowCount = self.model().rowCount()
                    lastIndex = self.model().index(rowCount - 1, 0)
                    self._view.setCurrentIndex(lastIndex)
                elif index.row() == 0:
                    self._view.setCurrentIndex(QModelIndex())
                else:
                    row = max(0, index.row() - step)
                    self._view.setCurrentIndex(self.model().index(row, 0))
                return True

            elif evtKey in (Qt.Key_Down, Qt.Key_PageDown):
                if modifiers != Qt.NoModifier:
                    return False
                step = evtKey == Qt.Key_PageDown and 5 or 1
                if not index.isValid():
                    firstIndex = self.model().index(0, 0)
                    self._view.setCurrentIndex(firstIndex)
                elif index != visitSearchIndex and index.row(
                ) == self.model().rowCount() - 1:
                    self._view.setCurrentIndex(visitSearchIndex)
                    self._view.scrollToTop()
                else:
                    row = min(self.model().rowCount() - 1, index.row() + step)
                    self._view.setCurrentIndex(self.model().index(row, 0))
                return True

            elif evtKey == Qt.Key_Delete:
                if index != visitSearchIndex and self._view.viewport().rect(
                ).contains(self._view.visualRect(index)):
                    self.indexDeleteRequested.emit(index)
                    return True

            elif evtKey == Qt.Key_Shift:
                self._delegate.setForceVisitItem(True)
                self._view.viewport().update()

            # end of switch evtKey

            if self.focusProxy():
                self.focusProxy().event(keyEvent)

            return True

        elif evtType == QEvent.KeyRelease:
            if event.key() == Qt.Key_Shift:
                self._delegate.setForceVisitItem(False)
                self._view.viewport().update()
                return True

        elif evtType in (QEvent.Wheel, QEvent.MouseButtonPress):
            if not self.underMouse():
                self.close()
                return False

        elif evtType == QEvent.FocusOut:
            # QFocusEvent
            focusEvent = event
            reason = focusEvent.reason()
            if reason != Qt.PopupFocusReason and reason != Qt.MouseFocusReason:
                self.close()

        elif evtType in (QEvent.Move, QEvent.Resize):
            w = obj
            if isinstance(w, QWidget) and w.isWindow() and self.focusProxy(
            ) and w == self.focusProxy().window():
                self.close()

        # end of switch evtType
        return False

    # Q_SIGNALS
    closed = pyqtSignal()
    searchEnginesDialogRequested = pyqtSignal()
    loadRequested = pyqtSignal(LoadRequest)

    indexActivated = pyqtSignal(QModelIndex)
    indexCtrlActivated = pyqtSignal(QModelIndex)
    indexShiftActivated = pyqtSignal(QModelIndex)
    indexDeleteRequested = pyqtSignal(QModelIndex)

    # public Q_SLOTS:
    def close(self):
        self.hide()
        self._view.verticalScrollBar().setValue(0)
        self._delegate.setForceVisitItem(False)
        self._forceResize = True

        self.closed.emit()

    # private:
    def _setupSearchEngines(self):
        for idx in (range(self._searchEnginesLayout.count())):
            item = self._searchEnginesLayout.takeAt(0)
            item.deleteLater()

        engines = gVar.app.searchEnginesManager().allEngines()
        for engine in engines:
            button = ToolButton(self)
            button.setIcon(engine.icon)
            button.setToolTip(engine.name)
            button.setAutoRaise(True)
            button.setIconSize(QSize(16, 16))

            def func():
                text = self.model().index(0, 0).data(
                    LocationCompleterModel.SearchStringRole)
                self.loadRequested.emit(
                    gVar.app.searchEngineManager().searchResult(engine, text))

            button.clicked.connect(func)
            self._searchEnginesLayout.addWidget(button)
class comic_export_setting_dialog(QDialog):
    acbfStylesList = [
        "speech", "commentary", "formal", "letter", "code", "heading", "audio",
        "thought", "sign", "sound", "emphasis", "strong"
    ]

    def __init__(self):
        super().__init__()
        self.setLayout(QVBoxLayout())
        self.setWindowTitle(i18n("Export Settings"))
        buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)

        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        mainWidget = QTabWidget()
        self.layout().addWidget(mainWidget)
        self.layout().addWidget(buttons)

        # Set basic crop settings
        # Set which layers to remove before export.
        mainExportSettings = QWidget()
        mainExportSettings.setLayout(QVBoxLayout())
        groupExportCrop = QGroupBox(i18n("Crop Settings"))
        formCrop = QFormLayout()
        groupExportCrop.setLayout(formCrop)
        self.chk_toOutmostGuides = QCheckBox(i18n("Crop to outmost guides"))
        self.chk_toOutmostGuides.setChecked(True)
        self.chk_toOutmostGuides.setToolTip(
            i18n(
                "This will crop to the outmost guides if possible and otherwise use the underlying crop settings."
            ))
        formCrop.addRow("", self.chk_toOutmostGuides)
        btn_fromSelection = QPushButton(
            i18n("Set Margins from Active Selection"))
        btn_fromSelection.clicked.connect(self.slot_set_margin_from_selection)
        # This doesn't work.
        formCrop.addRow("", btn_fromSelection)
        self.spn_marginLeft = QSpinBox()
        self.spn_marginLeft.setMaximum(99999)
        self.spn_marginLeft.setSuffix(" px")
        formCrop.addRow(i18n("Left:"), self.spn_marginLeft)
        self.spn_marginTop = QSpinBox()
        self.spn_marginTop.setMaximum(99999)
        self.spn_marginTop.setSuffix(" px")
        formCrop.addRow(i18n("Top:"), self.spn_marginTop)
        self.spn_marginRight = QSpinBox()
        self.spn_marginRight.setMaximum(99999)
        self.spn_marginRight.setSuffix(" px")
        formCrop.addRow(i18n("Right:"), self.spn_marginRight)
        self.spn_marginBottom = QSpinBox()
        self.spn_marginBottom.setMaximum(99999)
        self.spn_marginBottom.setSuffix(" px")
        formCrop.addRow(i18n("Bottom:"), self.spn_marginBottom)
        groupExportLayers = QGroupBox(i18n("Layers"))
        formLayers = QFormLayout()
        groupExportLayers.setLayout(formLayers)
        self.cmbLabelsRemove = labelSelector()
        formLayers.addRow(i18n("Label for removal:"), self.cmbLabelsRemove)
        self.ln_text_layer_name = QLineEdit()
        self.ln_text_layer_name.setToolTip(
            i18n(
                "These are keywords that can be used to identify text layers. A layer only needs to contain the keyword to be recognized. Keywords should be comma separated."
            ))
        self.ln_panel_layer_name = QLineEdit()
        self.ln_panel_layer_name.setToolTip(
            i18n(
                "These are keywords that can be used to identify panel layers. A layer only needs to contain the keyword to be recognized. Keywords should be comma separated."
            ))
        formLayers.addRow(i18n("Text Layer Key:"), self.ln_text_layer_name)
        formLayers.addRow(i18n("Panel Layer Key:"), self.ln_panel_layer_name)

        mainExportSettings.layout().addWidget(groupExportCrop)
        mainExportSettings.layout().addWidget(groupExportLayers)
        mainWidget.addTab(mainExportSettings, i18n("General"))

        # CBZ, crop, resize, which metadata to add.
        CBZexportSettings = QWidget()
        CBZexportSettings.setLayout(QVBoxLayout())
        self.CBZactive = QCheckBox(i18n("Export to CBZ"))
        CBZexportSettings.layout().addWidget(self.CBZactive)
        self.CBZgroupResize = comic_export_resize_widget("CBZ")
        CBZexportSettings.layout().addWidget(self.CBZgroupResize)
        self.CBZactive.clicked.connect(self.CBZgroupResize.setEnabled)
        CBZgroupMeta = QGroupBox(i18n("Metadata to Add"))
        # CBZexportSettings.layout().addWidget(CBZgroupMeta)
        CBZgroupMeta.setLayout(QFormLayout())

        mainWidget.addTab(CBZexportSettings, i18n("CBZ"))

        # ACBF, crop, resize, creator name, version history, panel layer, text layers.
        ACBFExportSettings = QWidget()
        ACBFform = QFormLayout()
        ACBFExportSettings.setLayout(QVBoxLayout())
        ACBFdocInfo = QGroupBox()
        ACBFdocInfo.setTitle(i18n("ACBF Document Info"))
        ACBFdocInfo.setLayout(ACBFform)
        self.lnACBFID = QLabel()
        self.lnACBFID.setToolTip(
            i18n(
                "By default this will be filled with a generated universal unique identifier. The ID by itself is merely so that comic book library management programs can figure out if this particular comic is already in their database and whether it has been rated. Of course, the UUID can be changed into something else by manually changing the JSON, but this is advanced usage."
            ))
        self.spnACBFVersion = QSpinBox()
        self.ACBFhistoryModel = QStandardItemModel()
        acbfHistoryList = QListView()
        acbfHistoryList.setModel(self.ACBFhistoryModel)
        btn_add_history = QPushButton(i18n("Add History Entry"))
        btn_add_history.clicked.connect(self.slot_add_history_item)
        self.chkIncludeTranslatorComments = QCheckBox()
        self.chkIncludeTranslatorComments.setText(
            i18n("Include translator's comments"))
        self.chkIncludeTranslatorComments.setToolTip(
            i18n(
                "A PO file can contain translator's comments. If this is checked, the translations comments will be added as references into the ACBF file."
            ))
        self.lnTranslatorHeader = QLineEdit()

        ACBFform.addRow(i18n("ACBF UID:"), self.lnACBFID)
        ACBFform.addRow(i18n("Version:"), self.spnACBFVersion)
        ACBFform.addRow(i18n("Version history:"), acbfHistoryList)
        ACBFform.addRow("", btn_add_history)
        ACBFform.addRow("", self.chkIncludeTranslatorComments)
        ACBFform.addRow(i18n("Translator header:"), self.lnTranslatorHeader)

        ACBFAuthorInfo = QWidget()
        acbfAVbox = QVBoxLayout(ACBFAuthorInfo)
        infoLabel = QLabel(
            i18n(
                "The people responsible for the generation of the CBZ/ACBF files."
            ))
        infoLabel.setWordWrap(True)
        ACBFAuthorInfo.layout().addWidget(infoLabel)
        self.ACBFauthorModel = QStandardItemModel(0, 6)
        labels = [
            i18n("Nick Name"),
            i18n("Given Name"),
            i18n("Middle Name"),
            i18n("Family Name"),
            i18n("Email"),
            i18n("Homepage")
        ]
        self.ACBFauthorModel.setHorizontalHeaderLabels(labels)
        self.ACBFauthorTable = QTableView()
        acbfAVbox.addWidget(self.ACBFauthorTable)
        self.ACBFauthorTable.setModel(self.ACBFauthorModel)
        self.ACBFauthorTable.verticalHeader().setDragEnabled(True)
        self.ACBFauthorTable.verticalHeader().setDropIndicatorShown(True)
        self.ACBFauthorTable.verticalHeader().setSectionsMovable(True)
        self.ACBFauthorTable.verticalHeader().sectionMoved.connect(
            self.slot_reset_author_row_visual)
        AuthorButtons = QHBoxLayout()
        btn_add_author = QPushButton(i18n("Add Author"))
        btn_add_author.clicked.connect(self.slot_add_author)
        AuthorButtons.addWidget(btn_add_author)
        btn_remove_author = QPushButton(i18n("Remove Author"))
        btn_remove_author.clicked.connect(self.slot_remove_author)
        AuthorButtons.addWidget(btn_remove_author)
        acbfAVbox.addLayout(AuthorButtons)

        ACBFStyle = QWidget()
        ACBFStyle.setLayout(QHBoxLayout())
        self.ACBFStylesModel = QStandardItemModel()
        self.ACBFStyleClass = QListView()
        self.ACBFStyleClass.setModel(self.ACBFStylesModel)
        ACBFStyle.layout().addWidget(self.ACBFStyleClass)
        ACBFStyleEdit = QWidget()
        ACBFStyleEditVB = QVBoxLayout(ACBFStyleEdit)
        self.ACBFuseFont = QCheckBox(i18n("Use font"))
        self.ACBFFontList = QListView()
        self.ACBFFontList.setItemDelegate(font_list_delegate())
        self.ACBFuseFont.toggled.connect(self.font_slot_enable_font_view)
        self.ACBFFontListModel = QStandardItemModel()
        self.ACBFFontListModel.rowsRemoved.connect(
            self.slot_font_current_style)
        self.ACBFFontListModel.itemChanged.connect(
            self.slot_font_current_style)
        self.btnAcbfAddFont = QPushButton()
        self.btnAcbfAddFont.setIcon(Application.icon("list-add"))
        self.btnAcbfAddFont.clicked.connect(self.font_slot_add_font)
        self.btn_acbf_remove_font = QPushButton()
        self.btn_acbf_remove_font.setIcon(Application.icon("edit-delete"))
        self.btn_acbf_remove_font.clicked.connect(self.font_slot_remove_font)
        self.ACBFFontList.setModel(self.ACBFFontListModel)
        self.ACBFdefaultFont = QComboBox()
        self.ACBFdefaultFont.addItems(
            ["sans-serif", "serif", "monospace", "cursive", "fantasy"])
        acbfFontButtons = QHBoxLayout()
        acbfFontButtons.addWidget(self.btnAcbfAddFont)
        acbfFontButtons.addWidget(self.btn_acbf_remove_font)
        self.ACBFBold = QCheckBox(i18n("Bold"))
        self.ACBFItal = QCheckBox(i18n("Italic"))
        self.ACBFStyleClass.clicked.connect(self.slot_set_style)
        self.ACBFStyleClass.selectionModel().selectionChanged.connect(
            self.slot_set_style)
        self.ACBFStylesModel.itemChanged.connect(self.slot_set_style)
        self.ACBFBold.toggled.connect(self.slot_font_current_style)
        self.ACBFItal.toggled.connect(self.slot_font_current_style)
        colorWidget = QGroupBox(self)
        colorWidget.setTitle(i18n("Text Colors"))
        colorWidget.setLayout(QVBoxLayout())
        self.regularColor = QColorDialog()
        self.invertedColor = QColorDialog()
        self.btn_acbfRegColor = QPushButton(i18n("Regular Text"), self)
        self.btn_acbfRegColor.clicked.connect(self.slot_change_regular_color)
        self.btn_acbfInvColor = QPushButton(i18n("Inverted Text"), self)
        self.btn_acbfInvColor.clicked.connect(self.slot_change_inverted_color)
        colorWidget.layout().addWidget(self.btn_acbfRegColor)
        colorWidget.layout().addWidget(self.btn_acbfInvColor)
        ACBFStyleEditVB.addWidget(colorWidget)
        ACBFStyleEditVB.addWidget(self.ACBFuseFont)
        ACBFStyleEditVB.addWidget(self.ACBFFontList)
        ACBFStyleEditVB.addLayout(acbfFontButtons)
        ACBFStyleEditVB.addWidget(self.ACBFdefaultFont)
        ACBFStyleEditVB.addWidget(self.ACBFBold)
        ACBFStyleEditVB.addWidget(self.ACBFItal)
        ACBFStyleEditVB.addStretch()
        ACBFStyle.layout().addWidget(ACBFStyleEdit)

        ACBFTabwidget = QTabWidget()
        ACBFTabwidget.addTab(ACBFdocInfo, i18n("Document Info"))
        ACBFTabwidget.addTab(ACBFAuthorInfo, i18n("Author Info"))
        ACBFTabwidget.addTab(ACBFStyle, i18n("Style Sheet"))
        ACBFExportSettings.layout().addWidget(ACBFTabwidget)
        mainWidget.addTab(ACBFExportSettings, i18n("ACBF"))

        # Epub export, crop, resize, other questions.
        EPUBexportSettings = QWidget()
        EPUBexportSettings.setLayout(QVBoxLayout())
        self.EPUBactive = QCheckBox(i18n("Export to EPUB"))
        EPUBexportSettings.layout().addWidget(self.EPUBactive)
        self.EPUBgroupResize = comic_export_resize_widget("EPUB")
        EPUBexportSettings.layout().addWidget(self.EPUBgroupResize)
        self.EPUBactive.clicked.connect(self.EPUBgroupResize.setEnabled)
        mainWidget.addTab(EPUBexportSettings, i18n("EPUB"))

        # For Print. Crop, no resize.
        TIFFExportSettings = QWidget()
        TIFFExportSettings.setLayout(QVBoxLayout())
        self.TIFFactive = QCheckBox(i18n("Export to TIFF"))
        TIFFExportSettings.layout().addWidget(self.TIFFactive)
        self.TIFFgroupResize = comic_export_resize_widget("TIFF")
        TIFFExportSettings.layout().addWidget(self.TIFFgroupResize)
        self.TIFFactive.clicked.connect(self.TIFFgroupResize.setEnabled)
        mainWidget.addTab(TIFFExportSettings, i18n("TIFF"))

        # SVG, crop, resize, embed vs link.
        #SVGExportSettings = QWidget()

        #mainWidget.addTab(SVGExportSettings, i18n("SVG"))

    """
    Add a history item to the acbf version history list.
    """

    def slot_add_history_item(self):
        newItem = QStandardItem()
        newItem.setText(
            str(i18n("v{version}-in this version...")).format(
                version=str(self.spnACBFVersion.value())))
        self.ACBFhistoryModel.appendRow(newItem)

    """
    Get the margins by treating the active selection in a document as the trim area.
    This allows people to snap selections to a vector or something, and then get the margins.
    """

    def slot_set_margin_from_selection(self):
        doc = Application.activeDocument()
        if doc is not None:
            if doc.selection() is not None:
                self.spn_marginLeft.setValue(doc.selection().x())
                self.spn_marginTop.setValue(doc.selection().y())
                self.spn_marginRight.setValue(doc.width() -
                                              (doc.selection().x() +
                                               doc.selection().width()))
                self.spn_marginBottom.setValue(doc.height() -
                                               (doc.selection().y() +
                                                doc.selection().height()))

    """
    Add an author with default values initialised.
    """

    def slot_add_author(self):
        listItems = []
        listItems.append(QStandardItem(i18n("Anon")))  # Nick name
        listItems.append(QStandardItem(i18n("John")))  # First name
        listItems.append(QStandardItem())  # Middle name
        listItems.append(QStandardItem(i18n("Doe")))  # Last name
        listItems.append(QStandardItem())  # email
        listItems.append(QStandardItem())  # homepage
        self.ACBFauthorModel.appendRow(listItems)

    """
    Remove the selected author from the author list.
    """

    def slot_remove_author(self):
        self.ACBFauthorModel.removeRow(
            self.ACBFauthorTable.currentIndex().row())

    """
    Ensure that the drag and drop of authors doesn't mess up the labels.
    """

    def slot_reset_author_row_visual(self):
        headerLabelList = []
        for i in range(self.ACBFauthorTable.verticalHeader().count()):
            headerLabelList.append(str(i))
        for i in range(self.ACBFauthorTable.verticalHeader().count()):
            logicalI = self.ACBFauthorTable.verticalHeader().logicalIndex(i)
            headerLabelList[logicalI] = str(i + 1)
        self.ACBFauthorModel.setVerticalHeaderLabels(headerLabelList)

    """
    Set the style item to the gui item's style.
    """

    def slot_set_style(self):
        index = self.ACBFStyleClass.currentIndex()
        if index.isValid():
            item = self.ACBFStylesModel.item(index.row())
            fontUsed = item.data(role=styleEnum.FONT)
            if fontUsed is not None:
                self.ACBFuseFont.setChecked(fontUsed)
            else:
                self.ACBFuseFont.setChecked(False)
            self.font_slot_enable_font_view()
            fontList = item.data(role=styleEnum.FONTLIST)
            self.ACBFFontListModel.clear()
            for font in fontList:
                NewItem = QStandardItem(font)
                NewItem.setEditable(True)
                self.ACBFFontListModel.appendRow(NewItem)
            self.ACBFdefaultFont.setCurrentText(
                str(item.data(role=styleEnum.FONTGENERIC)))
            bold = item.data(role=styleEnum.BOLD)
            if bold is not None:
                self.ACBFBold.setChecked(bold)
            else:
                self.ACBFBold.setChecked(False)
            italic = item.data(role=styleEnum.ITALIC)
            if italic is not None:
                self.ACBFItal.setChecked(italic)
            else:
                self.ACBFItal.setChecked(False)

    """
    Set the gui items to the currently selected style.
    """

    def slot_font_current_style(self):
        index = self.ACBFStyleClass.currentIndex()
        if index.isValid():
            item = self.ACBFStylesModel.item(index.row())
            fontList = []
            for row in range(self.ACBFFontListModel.rowCount()):
                font = self.ACBFFontListModel.item(row)
                fontList.append(font.text())
            item.setData(self.ACBFuseFont.isChecked(), role=styleEnum.FONT)
            item.setData(fontList, role=styleEnum.FONTLIST)
            item.setData(self.ACBFdefaultFont.currentText(),
                         role=styleEnum.FONTGENERIC)
            item.setData(self.ACBFBold.isChecked(), role=styleEnum.BOLD)
            item.setData(self.ACBFItal.isChecked(), role=styleEnum.ITALIC)
            self.ACBFStylesModel.setItem(index.row(), item)

    """
    Change the regular color
    """

    def slot_change_regular_color(self):
        if (self.regularColor.exec_() == QDialog.Accepted):
            square = QPixmap(32, 32)
            square.fill(self.regularColor.currentColor())
            self.btn_acbfRegColor.setIcon(QIcon(square))

    """
    change the inverted color
    """

    def slot_change_inverted_color(self):
        if (self.invertedColor.exec_() == QDialog.Accepted):
            square = QPixmap(32, 32)
            square.fill(self.invertedColor.currentColor())
            self.btn_acbfInvColor.setIcon(QIcon(square))

    def font_slot_enable_font_view(self):
        self.ACBFFontList.setEnabled(self.ACBFuseFont.isChecked())
        self.btn_acbf_remove_font.setEnabled(self.ACBFuseFont.isChecked())
        self.btnAcbfAddFont.setEnabled(self.ACBFuseFont.isChecked())
        self.ACBFdefaultFont.setEnabled(self.ACBFuseFont.isChecked())
        if self.ACBFFontListModel.rowCount() < 2:
            self.btn_acbf_remove_font.setEnabled(False)

    def font_slot_add_font(self):
        NewItem = QStandardItem(QFont().family())
        NewItem.setEditable(True)
        self.ACBFFontListModel.appendRow(NewItem)

    def font_slot_remove_font(self):
        index = self.ACBFFontList.currentIndex()
        if index.isValid():
            self.ACBFFontListModel.removeRow(index.row())
            if self.ACBFFontListModel.rowCount() < 2:
                self.btn_acbf_remove_font.setEnabled(False)

    """
    Load the UI values from the config dictionary given.
    """

    def setConfig(self, config):
        if "cropToGuides" in config.keys():
            self.chk_toOutmostGuides.setChecked(config["cropToGuides"])
        if "cropLeft" in config.keys():
            self.spn_marginLeft.setValue(config["cropLeft"])
        if "cropTop" in config.keys():
            self.spn_marginTop.setValue(config["cropTop"])
        if "cropRight" in config.keys():
            self.spn_marginRight.setValue(config["cropRight"])
        if "cropBottom" in config.keys():
            self.spn_marginBottom.setValue(config["cropBottom"])
        if "labelsToRemove" in config.keys():
            self.cmbLabelsRemove.setLabels(config["labelsToRemove"])
        if "textLayerNames" in config.keys():
            self.ln_text_layer_name.setText(", ".join(
                config["textLayerNames"]))
        else:
            self.ln_text_layer_name.setText("text")
        if "panelLayerNames" in config.keys():
            self.ln_panel_layer_name.setText(", ".join(
                config["panelLayerNames"]))
        else:
            self.ln_panel_layer_name.setText("panels")
        self.CBZgroupResize.set_config(config)
        if "CBZactive" in config.keys():
            self.CBZactive.setChecked(config["CBZactive"])
        self.EPUBgroupResize.set_config(config)
        if "EPUBactive" in config.keys():
            self.EPUBactive.setChecked(config["EPUBactive"])
        self.TIFFgroupResize.set_config(config)
        if "TIFFactive" in config.keys():
            self.TIFFactive.setChecked(config["TIFFactive"])

        if "acbfAuthor" in config.keys():
            if isinstance(config["acbfAuthor"], list):
                for author in config["acbfAuthor"]:
                    listItems = []
                    listItems.append(QStandardItem(author.get("nickname", "")))
                    listItems.append(
                        QStandardItem(author.get("first-name", "")))
                    listItems.append(QStandardItem(author.get("initials", "")))
                    listItems.append(QStandardItem(author.get("last-name",
                                                              "")))
                    listItems.append(QStandardItem(author.get("email", "")))
                    listItems.append(QStandardItem(author.get("homepage", "")))
                    self.ACBFauthorModel.appendRow(listItems)
                pass
            else:
                listItems = []
                listItems.append(QStandardItem(
                    config["acbfAuthor"]))  # Nick name
                for i in range(0, 5):
                    listItems.append(QStandardItem())  # First name
                self.ACBFauthorModel.appendRow(listItems)

        if "uuid" in config.keys():
            self.lnACBFID.setText(config["uuid"])
        elif "acbfID" in config.keys():
            self.lnACBFID.setText(config["acbfID"])
        else:
            config["uuid"] = QUuid.createUuid().toString()
            self.lnACBFID.setText(config["uuid"])
        if "acbfVersion" in config.keys():
            self.spnACBFVersion.setValue(config["acbfVersion"])
        if "acbfHistory" in config.keys():
            for h in config["acbfHistory"]:
                item = QStandardItem()
                item.setText(h)
                self.ACBFhistoryModel.appendRow(item)
        if "acbfStyles" in config.keys():
            styleDict = config.get("acbfStyles", {})
            for key in self.acbfStylesList:
                keyDict = styleDict.get(key, {})
                style = QStandardItem(key.title())
                style.setCheckable(True)
                if key in styleDict.keys():
                    style.setCheckState(Qt.Checked)
                else:
                    style.setCheckState(Qt.Unchecked)
                fontOn = False
                if "font" in keyDict.keys() or "genericfont" in keyDict.keys():
                    fontOn = True
                style.setData(fontOn, role=styleEnum.FONT)
                if "font" in keyDict:
                    fontlist = keyDict["font"]
                    if isinstance(fontlist, list):
                        font = keyDict.get("font", QFont().family())
                        style.setData(font, role=styleEnum.FONTLIST)
                    else:
                        style.setData([fontlist], role=styleEnum.FONTLIST)
                else:
                    style.setData([QFont().family()], role=styleEnum.FONTLIST)
                style.setData(keyDict.get("genericfont", "sans-serif"),
                              role=styleEnum.FONTGENERIC)
                style.setData(keyDict.get("bold", False), role=styleEnum.BOLD)
                style.setData(keyDict.get("ital", False),
                              role=styleEnum.ITALIC)
                self.ACBFStylesModel.appendRow(style)
            keyDict = styleDict.get("general", {})
            self.regularColor.setCurrentColor(
                QColor(keyDict.get("color", "#000000")))
            square = QPixmap(32, 32)
            square.fill(self.regularColor.currentColor())
            self.btn_acbfRegColor.setIcon(QIcon(square))
            keyDict = styleDict.get("inverted", {})
            self.invertedColor.setCurrentColor(
                QColor(keyDict.get("color", "#FFFFFF")))
            square.fill(self.invertedColor.currentColor())
            self.btn_acbfInvColor.setIcon(QIcon(square))
        else:
            for key in self.acbfStylesList:
                style = QStandardItem(key.title())
                style.setCheckable(True)
                style.setCheckState(Qt.Unchecked)
                style.setData(False, role=styleEnum.FONT)
                style.setData(QFont().family(), role=styleEnum.FONTLIST)
                style.setData("sans-serif", role=styleEnum.FONTGENERIC)
                style.setData(False, role=styleEnum.BOLD)  #Bold
                style.setData(False, role=styleEnum.ITALIC)  #Italic
                self.ACBFStylesModel.appendRow(style)
        self.CBZgroupResize.setEnabled(self.CBZactive.isChecked())
        self.lnTranslatorHeader.setText(
            config.get("translatorHeader", "Translator's Notes"))
        self.chkIncludeTranslatorComments.setChecked(
            config.get("includeTranslComment", False))

    """
    Store the GUI values into the config dictionary given.
    
    @return the config diactionary filled with new values.
    """

    def getConfig(self, config):

        config["cropToGuides"] = self.chk_toOutmostGuides.isChecked()
        config["cropLeft"] = self.spn_marginLeft.value()
        config["cropTop"] = self.spn_marginTop.value()
        config["cropBottom"] = self.spn_marginRight.value()
        config["cropRight"] = self.spn_marginBottom.value()
        config["labelsToRemove"] = self.cmbLabelsRemove.getLabels()
        config["CBZactive"] = self.CBZactive.isChecked()
        config = self.CBZgroupResize.get_config(config)
        config["EPUBactive"] = self.EPUBactive.isChecked()
        config = self.EPUBgroupResize.get_config(config)
        config["TIFFactive"] = self.TIFFactive.isChecked()
        config = self.TIFFgroupResize.get_config(config)
        authorList = []
        for row in range(self.ACBFauthorTable.verticalHeader().count()):
            logicalIndex = self.ACBFauthorTable.verticalHeader().logicalIndex(
                row)
            listEntries = [
                "nickname", "first-name", "initials", "last-name", "email",
                "homepage"
            ]
            author = {}
            for i in range(len(listEntries)):
                entry = self.ACBFauthorModel.data(
                    self.ACBFauthorModel.index(logicalIndex, i))
                if entry is None:
                    entry = " "
                if entry.isspace() is False and len(entry) > 0:
                    author[listEntries[i]] = entry
                elif listEntries[i] in author.keys():
                    author.pop(listEntries[i])
            authorList.append(author)
        config["acbfAuthor"] = authorList
        config["acbfVersion"] = self.spnACBFVersion.value()
        versionList = []
        for r in range(self.ACBFhistoryModel.rowCount()):
            index = self.ACBFhistoryModel.index(r, 0)
            versionList.append(
                self.ACBFhistoryModel.data(index, Qt.DisplayRole))
        config["acbfHistory"] = versionList

        acbfStylesDict = {}
        for row in range(0, self.ACBFStylesModel.rowCount()):
            entry = self.ACBFStylesModel.item(row)
            if entry.checkState() == Qt.Checked:
                key = entry.text().lower()
                style = {}
                if entry.data(role=styleEnum.FONT):
                    font = entry.data(role=styleEnum.FONTLIST)
                    if font is not None:
                        style["font"] = font
                    genericfont = entry.data(role=styleEnum.FONTGENERIC)
                    if font is not None:
                        style["genericfont"] = genericfont
                bold = entry.data(role=styleEnum.BOLD)
                if bold is not None:
                    style["bold"] = bold
                italic = entry.data(role=styleEnum.ITALIC)
                if italic is not None:
                    style["ital"] = italic
                acbfStylesDict[key] = style
        acbfStylesDict["general"] = {
            "color": self.regularColor.currentColor().name()
        }
        acbfStylesDict["inverted"] = {
            "color": self.invertedColor.currentColor().name()
        }
        config["acbfStyles"] = acbfStylesDict
        config["translatorHeader"] = self.lnTranslatorHeader.text()
        config[
            "includeTranslComment"] = self.chkIncludeTranslatorComments.isChecked(
            )

        # Turn this into something that retrieves from a line-edit when string freeze is over.
        config["textLayerNames"] = self.ln_text_layer_name.text().split(",")
        config["panelLayerNames"] = self.ln_panel_layer_name.text().split(",")
        return config
class MainWindow(QMainWindow):
    graph_legend = []

    def __init__(self):
        super().__init__()

        self.setWindowTitle('GraphMaster')
        self.setWindowIcon(QIcon('../Icons/formula.png'))
        self.setGeometry(400, 400, 900, 600)
        self.MyUI()

    def MyUI(self):
        self.fig, self.axes = self.plot_sigle_empty_graph()
        self.canvas = Canvas(self.fig)
        self.toolbar = NavigationToolbar(self.canvas, self)

        self.v_layout = QVBoxLayout()
        self.h_layout = QHBoxLayout()

        self.list_view = QListView()
        self.plot_dots_model = DsaGraphicalObjectsModel()
        self.list_view.setModel(self.plot_dots_model)
        self.btn_clear = QPushButton('Delete')
        self.btn_clear.clicked.connect(self.remove_plot)

        self.v_layout.addWidget(self.canvas)
        self.v_layout.addWidget(self.toolbar)

        self.lbl_func = QLabel()
        self.lbl_func.setPixmap(
            QPixmap('../Icons/function-mathematical-symbol.png'))
        self.f_field = QLineEdit()

        self.h_layout.addWidget(self.lbl_func)
        self.h_layout.addWidget(self.f_field)

        self.layout = QGridLayout()

        self.btn = QPushButton('Plot')
        self.btn.clicked.connect(self.on_clicked_plot)

        self.layout.addLayout(self.h_layout, 0, 0, 1, 6)

        self.layout.addWidget(self.btn, 1, 4, 1, 2)
        self.layout.addWidget(self.btn_clear, 1, 0, 1, 2)
        self.layout.addLayout(self.v_layout, 0, 6, 5, 5)
        self.layout.addWidget(self.list_view, 2, 0, 5, 6)

        self.central_widget = QWidget()
        self.central_widget.setLayout(self.layout)

        self.setCentralWidget(self.central_widget)

    def get_f_str(self):
        return self.f_field.text()

    def on_clicked_plot(self):
        self.plot()

    def plot_sigle_empty_graph(self):
        fig, axes = plt.subplots(nrows=1,
                                 ncols=1,
                                 figsize=(10, 7),
                                 dpi=100,
                                 facecolor='grey',
                                 frameon=True,
                                 edgecolor='black',
                                 linewidth=1)
        fig.subplots_adjust(wspace=0.4,
                            hspace=0.6,
                            left=0.15,
                            right=0.85,
                            top=0.9,
                            bottom=0.1)
        axes.grid(True, c='lightgrey', alpha=0.7)
        axes.set_title('Diagram Header', fontsize=10)
        axes.set_xlabel('X', fontsize=8)
        axes.set_ylabel('Y', fontsize=8)
        return fig, axes

    def plot_custom_function(self,
                             axes=None,
                             function=None,
                             legend=None,
                             name=None,
                             limits=None,
                             type='y=f(x)'):
        left_limit = limits[0]
        right_limit = limits[1]
        step = (max(limits) - min(limits)) / 100000
        if type == 'y=f(x)':
            legend.append('y=' + str(function))
            x_vals = np.arange(left_limit, right_limit, step)
            f = StringFunction(function)
            y_vals = [f.calculate_f(x) for x in x_vals]
            plot_instance = axes.plot(x_vals, y_vals, '-', lw=1)
            axes.set_xlim(left_limit, right_limit)
            axes.set_ylim(left_limit, right_limit)
            axes.legend(legend, loc='best', fontsize=8)
        return plot_instance

    def plot(self):
        function = self.f_field.text()
        instance = self.plot_custom_function(axes=self.axes,
                                             function=function,
                                             legend=self.graph_legend,
                                             limits=[0.01, 40])
        self.fig.canvas.draw()
        self.plot_dots_model.insertRows(0, 1, data=['y=' + function, instance])

    def remove_plot(self):
        index = self.list_view.currentIndex()
        position = index.row()
        model = index.model()
        model.removeRows(position=position, rows=1)
        self.fig.canvas.draw()
Exemple #24
0
class CollectData(QWidget):
    def __init__(self):
        super().__init__()
        self.init_variable()
        self.init_img()

        self.init_ui()
        self.show()

    '''
    def paintEvent(self, QPaintEvent):
        painter = QPainter(self)
        painter.setPen(QColor(166,66,250))          
        painter.begin(self)
        painter.draw()
        painter.end()
    '''

    def init_img(self):
        self.qlabel = myLabel(self)
        img = cv2.imread('data/test.png')  # 打开图片
        self.qlabel.img = img.copy()
        self.qlabel.img_current = img.copy()
        self.qlabel.update_img()

    def init_variable(self):
        self.label = 0
        self.transformation_type = 0
        self.total_img_number = 0
        self.current_img_index = 0
        self.folder_path = r"data"
        self.jump_img_index = -1
        self.img_list = []
        self.img_name_list = []
        self.whether_to_crop = 0

    def init_ui(self):
        self.setGeometry(200, 200, 1000, 800)
        self.setWindowTitle('数据标注')
        self.qlabel.setGeometry(QRect(30, 30, 640, 480))
        self.init_buttons()

        for file_name in os.listdir(self.folder_path + '/'):
            img = cv2.imread(self.folder_path + '/' + file_name)
            if img is None:
                continue
            self.img_list.append(img)
            self.img_name_list.append(os.path.splitext(file_name)[0])
        #QMessageBox.information(self, 'complete', '图片加载完毕')
        self.total_img_number = len(self.img_list)
        self.current_img_index = 1
        self.refresh_img()

        self.update_list()

    def init_buttons(self):
        self.previous_img_button = QPushButton("上一张图片", self)
        self.next_img_button = QPushButton("下一张图片", self)
        self.save_message_button = QPushButton("保存当前图片信息", self)
        self.show_message_button = QPushButton("显示当前图片信息", self)
        self.open_folder_button = QPushButton("打开文件夹", self)
        self.add_border_button = QPushButton("保存当前框", self)
        self.delete_border_button = QPushButton("删除选中框", self)
        self.img_folder_text = QLineEdit('data', self)
        self.goto_chosen_img_button = QPushButton("跳转图片", self)
        self.jump_img_text = QLineEdit('', self)
        self.show_index_message = QLabel(self)
        self.crop_message_box = QCheckBox('裁剪所选图片', self)

        self.img_folder_text.selectAll()
        self.img_folder_text.setFocus()

        self.previous_img_button.setGeometry(30, 530, 150, 40)
        self.next_img_button.setGeometry(200, 530, 150, 40)
        self.save_message_button.setGeometry(370, 530, 150, 40)
        self.show_message_button.setGeometry(540, 530, 150, 40)
        self.img_folder_text.setGeometry(30, 590, 660, 40)
        self.open_folder_button.setGeometry(710, 590, 150, 40)
        self.jump_img_text.setGeometry(30, 650, 150, 40)
        self.goto_chosen_img_button.setGeometry(200, 650, 150, 40)
        self.show_index_message.setGeometry(30, 710, 300, 40)
        self.crop_message_box.setGeometry(30, 750, 150, 40)
        self.add_border_button.setGeometry(710, 380, 150, 40)
        self.delete_border_button.setGeometry(710, 440, 150, 40)

        self.previous_img_button.clicked.connect(self.previous_img)
        self.next_img_button.clicked.connect(self.next_img)
        self.save_message_button.clicked.connect(self.save_message)
        self.show_message_button.clicked.connect(self.show_message)
        self.open_folder_button.clicked.connect(self.open_folder)
        self.add_border_button.clicked.connect(self.save_current_border)
        self.delete_border_button.clicked.connect(self.delete_border)
        self.goto_chosen_img_button.clicked.connect(self.goto_chosen_img)
        self.crop_message_box.stateChanged.connect(self.crop_message)

        self.label_combo = QComboBox(self)
        for i in range(len(LABEL_LIST)):
            self.label_combo.addItem(LABEL_LIST[i])
        self.label_combo.move(900, 30)
        self.label_combo.activated[str].connect(self.label_on_activated)

        self.listview = QListView(self)
        self.listview.setGeometry(710, 30, 150, 320)
        self.listview.doubleClicked.connect(self.list_clicked)
        self.listview.setEditTriggers(QListView.NoEditTriggers)

    def crop_message(self):
        self.whether_to_crop = self.crop_message_box.checkState()

    def previous_img(self):
        if self.current_img_index == 1:
            QMessageBox.information(self, 'warning', '已经是第一张啦')
            return
        self.current_img_index -= 1
        self.refresh_img()

    def next_img(self):
        if self.current_img_index == self.total_img_number:
            QMessageBox.information(self, 'warning', '已经是最后一张啦')
            return
        self.current_img_index += 1
        self.refresh_img()

    def show_message(self):
        if len(self.qlabel.rectangle_label) > 0:
            reply = QMessageBox.question(self, '确认', '当前有未保存信息,是否继续?',
                                         QMessageBox.Yes | QMessageBox.No,
                                         QMessageBox.No)
            if reply == QMessageBox.No:
                return
        self.qlabel.rectangle_label.clear()
        if os.path.isfile(self.folder_path + '/' +
                          self.img_name_list[self.current_img_index - 1] +
                          '.csv') == False:
            QMessageBox.information(self, 'warning', '当前图片无信息')
            return
        message = pd.read_csv(self.folder_path + '/' +
                              self.img_name_list[self.current_img_index - 1] +
                              '.csv',
                              sep=',',
                              header=None)
        message = np.array(message.T)
        message = message.astype(int)
        for i in range(len(message)):
            self.qlabel.rectangle_label.append(
                Rectangle(message[i][1], message[i][2], message[i][3],
                          message[i][4], True, message[i][0]))
        self.update_list()
        self.refresh_img()

        QMessageBox.information(self, 'complete', '信息加载完毕')

    def open_folder(self):
        self.folder_path = self.img_folder_text.text()
        if os.path.isdir(self.folder_path) == False:
            QMessageBox.information(self, 'warning', '文件夹路径非法')
            return
        self.img_list.clear()
        self.img_name_list.clear()
        for file_name in os.listdir(self.folder_path + '/'):
            img = cv2.imread(self.folder_path + '/' + file_name)
            if img is None:
                continue
            self.img_list.append(img)
            self.img_name_list.append(os.path.splitext(file_name)[0])
        QMessageBox.information(self, 'complete', '图片加载完毕')
        self.total_img_number = len(self.img_list)
        self.current_img_index = 1
        self.refresh_img()

    def goto_chosen_img(self):
        if self.jump_img_text.text().isdigit() == False:
            QMessageBox.information(self, 'warning', '请输入合法的数字')
            return
        if int(self.jump_img_text.text()) <= 0 or int(
                self.jump_img_text.text()) > self.total_img_number:
            QMessageBox.information(self, 'warning', '请输入合法的数字')
            return
        self.current_img_index = int(self.jump_img_text.text())
        self.refresh_img()

    def refresh_img(self):
        img = self.img_list[self.current_img_index - 1]
        self.qlabel.img = img.copy()
        self.qlabel.update_qlabel_img()
        self.qlabel.update_img()
        self.show_index_message.setText('一共' + str(self.total_img_number) +
                                        '张图片,当前第' +
                                        str(self.current_img_index) + '张图片')

    def label_on_activated(self):
        self.label = self.label_combo.currentIndex()

    def update_list(self):
        slm = QStringListModel()
        string_list = []
        for i in range(len(self.qlabel.rectangle_label)):
            string_list.append(
                LABEL_LIST[self.qlabel.rectangle_label[i].label])
        slm.setStringList(string_list)
        self.listview.setModel(slm)

    def list_clicked(self, qModelIndex):
        if self.qlabel.rectangle_label[
                qModelIndex.row()].whether_display == True:
            self.qlabel.rectangle_label[
                qModelIndex.row()].whether_display = False
        else:
            self.qlabel.rectangle_label[
                qModelIndex.row()].whether_display = True
        self.qlabel.update_qlabel_img()
        self.qlabel.update_img()

    def save_current_border(self):
        self.qlabel.save_current_border(self.label)
        self.qlabel.update_qlabel_img()
        self.qlabel.update_img()
        self.update_list()

    def label_clicked(self):
        sender = self.sender()
        if sender == self.label_button:
            self.label = self.label_button.checkedId()

    def save_message(self):
        if self.save_current_angle() == False:
            return
        self.qlabel.rectangle_label.clear()
        self.update_list()
        self.refresh_img()

    def save_current_angle(self):
        save_data = []
        for i in range(5):
            save_data.append([])
        if len(self.qlabel.rectangle_label) > 0:
            if os.path.isfile(self.folder_path + '/' +
                              self.img_name_list[self.current_img_index - 1] +
                              '.csv'):
                reply = QMessageBox.question(self, '确认', '是否覆盖当前图片已保存信息?',
                                             QMessageBox.Yes | QMessageBox.No,
                                             QMessageBox.No)
                if reply == QMessageBox.No:
                    return False
            for i in range(len(self.qlabel.rectangle_label)):
                save_data[0].append(self.qlabel.rectangle_label[i].label)
                save_data[1].append(self.qlabel.rectangle_label[i].x0)
                save_data[2].append(self.qlabel.rectangle_label[i].x1)
                save_data[3].append(self.qlabel.rectangle_label[i].y0)
                save_data[4].append(self.qlabel.rectangle_label[i].y1)

                if os.path.exists('crop_img/') == False:
                    os.makedirs('crop_img/')
                h, w, channel = self.qlabel.img.shape
                img_after_crop = self.qlabel.img[
                    self.qlabel.rectangle_label[i].y0 * h // self.qlabel.
                    qlabel_width:self.qlabel.rectangle_label[i].y1 * h //
                    self.qlabel.qlabel_width,
                    self.qlabel.rectangle_label[i].x0 * w // self.qlabel.
                    qlabel_length:self.qlabel.rectangle_label[i].x1 * w //
                    self.qlabel.qlabel_length]
                if self.whether_to_crop == 1:
                    cv2.imwrite(
                        'crop_img/' +
                        self.img_name_list[self.current_img_index - 1] + '_' +
                        str(i) + '.jpg', img_after_crop)

            if np.shape(np.array(save_data)) != (5, 0):
                np.savetxt(self.folder_path + '/' +
                           self.img_name_list[self.current_img_index - 1] +
                           '.csv',
                           np.array(save_data),
                           delimiter=',')

    def delete_border(self):
        if self.listview.currentIndex().row() > -1:
            self.qlabel.delete_border(self.listview.currentIndex().row())
            self.qlabel.update_qlabel_img()
            self.qlabel.update_img()
            self.update_list()
        else:
            QMessageBox.information(self, 'warning', '请先选中一行')
Exemple #25
0
class DesktopIconWidget(QFrame):
    def __init__(self, parent):
        QFrame.__init__(self, parent)
        self.setFrameStyle(QFrame.Box | QFrame.Sunken)
        self.setStyleSheet("QListView{background:transparent;}")

        self.listView = QListView(self)
        self.setLayout(QHBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().addWidget(self.listView)

        self.listView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.listView.setMovement(QListView.Snap)
        self.listView.setFlow(QListView.LeftToRight)
        self.listView.setResizeMode(QListView.Adjust)
        self.listView.setGridSize(QSize(self.logicalDpiX() / 96 * 70,
                                        self.logicalDpiY() / 96 * 70))
        self.listView.setViewMode(QListView.IconMode)

        self.quickDesktopModel = QuickDesktopModel(self.window().platform.databaseFile)
        self.listView.setModel(self.quickDesktopModel)
        self.createActions()
        self.makeConnections()

    def createActions(self):
        self.actionCreateComputer = QAction(self.tr("我的电脑(&C)"), self)
        self.actionCreateDocuments = QAction(self.tr("我的文档(&D)"), self)
        self.actionCreateMusic = QAction(self.tr("我的音乐(&M)"), self)
        self.actionCreatePictures = QAction(self.tr("我的图片(&P)"), self)
        self.actionCreateShortcut = QAction(self.tr("创建快捷方式(&C)"), self)
        self.actionCreateShortcut.setIcon(QIcon(":/images/new.png"))
        self.actionCreateBookmark = QAction(self.tr("创建网络链接(&B)"), self)
        self.actionCreateBookmark.setIcon(QIcon(":/images/insert-link.png"))
        self.actionRemoveShortcut = QAction(self.tr("删除快捷方式(&R)"), self)
        self.actionRemoveShortcut.setIcon(QIcon(":/images/delete.png"))
        self.actionRenameShortcut = QAction(self.tr("重命名(&N)"), self)
        self.actionRenameShortcut.setIcon(QIcon(":/images/edit-rename.png"))
        self.actionEditShortcut = QAction(self.tr("编辑快捷方式(&E)"), self)
        self.actionEditShortcut.setIcon(QIcon(":/images/edit.png"))

    def makeConnections(self):
        self.listView.customContextMenuRequested.connect(self.onQuickDesktopContextMenuRequest)
        self.listView.activated.connect(self.runQuickDesktopShortcut)

        self.actionCreateComputer.triggered.connect(self.createComputerShortcut)
        self.actionCreateDocuments.triggered.connect(self.createDocumentsShortcut)
        self.actionCreateMusic.triggered.connect(self.createMusicShortcut)
        self.actionCreatePictures.triggered.connect(self.createPicturesShortcut)
        self.actionCreateShortcut.triggered.connect(self.createShortcut)
        self.actionCreateBookmark.triggered.connect(self.createBookmark)
        self.actionEditShortcut.triggered.connect(self.editShortcut)
        self.actionRemoveShortcut.triggered.connect(self.removeShortcut)
        self.actionRenameShortcut.triggered.connect(self.renameShortcut)

    def onQuickDesktopContextMenuRequest(self, pos):
        index = self.listView.indexAt(pos)
        self.listView.setCurrentIndex(index)
        menu = QMenu()
        menu.addAction(self.actionCreateShortcut)
        menu.addAction(self.actionCreateBookmark)
        menu2 = menu.addMenu(self.tr("创建特殊快捷方式(&S)"))
        if os.name == "nt":
            menu2.addAction(self.actionCreateComputer)
        menu2.addAction(self.actionCreateDocuments)
        menu2.addAction(self.actionCreatePictures)
        menu2.addAction(self.actionCreateMusic)
        if index.isValid():
            menu.addAction(self.actionRemoveShortcut)
            if not self.quickDesktopModel.isSpecialShortcut(index):
                menu.addAction(self.actionEditShortcut)
            menu.addAction(self.actionRenameShortcut)
        try:
            getattr(menu, "exec")(QCursor.pos())
        except AttributeError:
            getattr(menu, "exec_")(QCursor.pos())

    def createShortcut(self):
        d = ShortcutDialog(self)
        if self.window().runDialog(d.create) == QDialog.Accepted:
            shortcut = d.getResult()
            shortcut["id"] = str(uuid.uuid4())
            self.quickDesktopModel.addShortcut(shortcut)
        d.deleteLater()

    def createBookmark(self):
        d = BookmarkDialog(self)
        if self.window().runDialog(d.create) == QDialog.Accepted:
            shortcut = {
                    "id": str(uuid.uuid4()),
                    "icon": "",
                    "openwith": "",
                    "dir": "",
            }
            shortcut.update(d.getResult())
            self.quickDesktopModel.addShortcut(shortcut)
        d.deleteLater()

    def createComputerShortcut(self):
        shortcut = {
                "id": str(uuid.uuid4()),
                "name": self.tr("我的电脑"),
                "path": COMPUTER_PATH,
                "icon": "",
                "dir": "",
                "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def createDocumentsShortcut(self):
        shortcut = {
                "id": str(uuid.uuid4()),
                "name": self.tr("我的文档"),
                "path": DOCUMENTS_PATH,
                "icon": "",
                "dir": "",
                "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def createPicturesShortcut(self):
        shortcut = {
                "id": str(uuid.uuid4()),
                "name": self.tr("图片收藏"),
                "path": PICTURES_PATH,
                "icon": "",
                "dir": "",
                "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def createMusicShortcut(self):
        shortcut = {
                "id": str(uuid.uuid4()),
                "name": self.tr("我的音乐"),
                "path": MUSIC_PATH,
                "icon": "",
                "dir": "",
                "openwith": "",
        }
        self.quickDesktopModel.addShortcut(shortcut)

    def renameShortcut(self):
        self.listView.edit(self.listView.currentIndex())

    def removeShortcut(self):
        self.quickDesktopModel.removeShortcut(self.listView.currentIndex())

    def editShortcut(self):
        index = self.listView.currentIndex()
        if not index.isValid():
            return
        shortcut = self.quickDesktopModel.shortcutAt(index)
        url = QUrl.fromUserInput(shortcut["path"])
        if not url.isValid():
            return
        if url.scheme() == "special":
            QMessageBox.information(self, self.tr("编辑快捷方式"), self.tr("不能编辑特殊图标。"))
            return
        elif url.scheme() == "file":
            d = ShortcutDialog(self)
        else:
            d = BookmarkDialog(self)
        if self.window().runDialog(d.edit, shortcut) == QDialog.Accepted:
            shortcut.update(d.getResult())
            self.quickDesktopModel.updateShortcut(shortcut, index)
        d.deleteLater()

    def runQuickDesktopShortcut(self):
        index = self.listView.currentIndex()
        if not index.isValid():
            return
        if not self.quickDesktopModel.runShortcut(index):
            QMessageBox.information(self, self.tr("快捷面板"), \
                    self.tr("不能运行快捷方式。请检查文件是否存在或者程序是否正确。"))
        else:
            self.window().close()