Добавлен: 30.10.2023
Просмотров: 27
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
self.channels_telegram = QtWidgets.QListWidget(self)
self.channels_telegram.setObjectName("channels_telegram")
self.channels_telegram.setIconSize(QSize(32,32))
self.channels_telegram.setFixedSize(200,340)
self.channels_telegram.itemClicked.connect(self.item_changed_telegram_channels)
self.wgt_us_chan = QtWidgets.QWidget()
self.users_channels = QtWidgets.QVBoxLayout(self)
self.users_channels.addWidget(self.users_telegram)
self.users_channels.addWidget(self.channels_telegram)
self.wgt_us_chan.setLayout(self.users_channels)
self.item_users_channels = QListWidgetItem(self.telegram_list)
self.item_users_channels.setSizeHint(self.wgt_us_chan.sizeHint())
self.telegram_list.setItemWidget(self.item_users_channels, self.wgt_us_chan)
self.telegram_connect = QtWidgets.QPushButton("Войти в Telegram!", self)
self.telegram_connect.setFixedSize(180, 30)
self.telegram_connect.clicked.connect(self.clicked_chats_telegram)
self.wgt_telegram = QtWidgets.QWidget()
self.layout_users_telegram = QtWidgets.QVBoxLayout(self)
self.layout_users_telegram.addWidget(self.telegram_connect)
self.wgt_telegram.setLayout(self.layout_users_telegram)
self.item_telegram = QListWidgetItem(self.users_telegram)
self.item_telegram.setSizeHint(self.wgt_telegram.sizeHint())
self.users_telegram.setItemWidget(self.item_telegram, self.wgt_telegram)
self.tab_chats.addTab(self.telegram_list, "Telegram")
Листинг 2 – Динамическое создание объектов
Как видно из листинга 2 сначала создается виджет QGridLayout, который позволяет нам удобно расположить объекты в приложении. Далее создается виджет QListWidget, в котором будут располагаться списки контактов и каналов, у виджета задается фиксированный размер, чтобы он не растягивался по всему окну. Следующим шагом создается два отдельных QListWidget, в которых по отдельности расположатся спикски контактов и каналов, эти списки помещаются в виджет QVBoxLayout, чтобы расположить их в QListWidget, который создавался до этого. Потом соответственно QListWidget с готовыми списками, добавляется в QGridLayout, для отображения на форме приложения.
На рисунке 1 можно увидеть как расположились объекты. Но в данный момент используется стандартный интерфейс, что не выглядит визуально привлекательно и пользователь может не заинтересоваться нашим приложением. Эту проблему можно решить с помощью инструмента QSS[2].
Рисунок 1 – Вид приложения со стандартным интерфейсом
2.2 Графическая составляющая приложения
Ниже приведен листинг 3, который задает характеристики заднего фона, вкладок, кнопок, текстовых редакторов, списков виджетов, а также различные события при наведение курсора на компонет и нажатия на него.
QWidget
{
color: #b1b1b1;
background-color: #323232;
}
QWidget:item:hover
{
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #ca0619);
color: #000000;
}
QWidget:item:selected
{
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
}
QPushButton
{
color: #b1b1b1;
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
border-width: 1px;
border-color: #1e1e1e;
border-style: solid;
border-radius: 6;
padding: 3px;
font-size: 12px;
padding-left: 5px;
padding-right: 5px;
}
QPushButton:pressed
{
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0
#2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
}
QPushButton:hover
{
border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
}
QTextEdit:focus
{
border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
}
QTextEdit
{
background-color: #242424;
}
Листинг 3 – задание стилей для виджетов
В листинге 3 задаются стили для объектов, а также псевдоклассы, когда происходят различные события с этими объектами. В данном листинге можно видеть что, для компонента item задается псевдокласс hover, который обрабатывает события наведения курсора на объект, а также задаются стили на событие, когда нажата кнопка.
Как видим на рисунке 2, используя для виджетов инструмент QSS, приложение стало выглядеть визуально привлекательно, у такого приложения уже будет больше спрос у пользователей[4].
Рисунок 2 – Вид приложения с использованием инструмента QSS
-
Логическая составляющая приложения
Когда пользователь пытается зайти в официальный клиент «Telegram» или «ВКонтакте» перед ним появляется поля, куда он может ввести свои данные для авторизации. Для того чтобы в приложение была возможность для авторизации, был использован принцип объектно-ориентированного программирования. Созданы два класса, которые передавали данные для авторизации пользователя в определенные функции главного класса. На листинге 4 продемонстрирована функция, которая позволяет авторизоваться пользователю в «Telegram»:
def connect_telegram(self):
if self.flag_telegram == False:
if len(self.login_telegram) and len(self.phone_telegram):
self.client=TelegramClient(str(self.login_telegram), api_id,api_hash)
self.client.connect()
if not self.client.is_user_authorized():
self.client.send_code_request(self.phone_telegram)
self.client.sign_in(self.phone_telegram,input('Enter the code:)
self.result1=self.client(GetDialogsRequest(offset_date=None,offset_id=0, offset_peer = InputPeerEmpty(),limit = 200))
self.flag_telegram = True
self.user.extend(self.result1.users)
self.channel.extend(self.result1.chats)
if self.flag_photo_telegram == False:
try:
for user_value in range(0, len(self.user), 1):
users = self.user[user_value]
self.client.download_profile_photo(users)
for channels_value in range(0,len(self.channel), 1):
channels = self.channel[channels_value]
self.client.download_profile_photo(channels)
except ValueError:
pass
except TimeoutError:
pass
else:
self.timer_autoriziting_telegram.stop()
self.telegram_contact()
self.channels_connect()
Листинг 4 – Авторизация в «Telegram»
В описанном листинге выше, сначала принимаются данные с класса авторизации, которые передают телефон и логин пользователя. Если пользователь авторизуются в данном приложении, в канале «Telegram» впервые, то на телефон придет сообщение с кодом для авторизации. Когда авторизации прошла успешно, происходит загрузка сообщений и фотографий контактов и каналов[8].
После авторизации надо отобразить контакты пользователя и каналы. На листинге 5 продемонстрированы эти функции.
def telegram_contact(self):
self.users_telegram.clear()
for user_value in range(0, len(self.user), 1):
users = self.user[user_value]
if users.last_name!=None:
user_n = str(users.first_name) + " " + str(users.last_name)
self.listItem = QListWidgetItem(user_n)
else:
user_n = str(users.first_name)
self.listItem = QListWidgetItem(user_n)
if users.username!=None:
self.listItem.setIcon(QIcon(str(users.username) + ".jpg"))
else:
self.listItem.setIcon(QIcon(str(users.first_name) + ".jpg"))
self.users_telegram.addItem(self.listItem)
self.users_telegram.sortItems()
self.users_telegram.show()
def channels_connect(self):
self.channels_telegram.clear()
for channels_value in range(0,len(self.channel), 1):
channels = self.channel[channels_value]
self.listItem = QListWidgetItem(channels.title)
self.listItem.setIcon(QIcon(str(channels.username)+".jpg)
self.channels_telegram.addItem(self.listItem)
self.channels_telegram.sortItems()
self.channels_telegram.show()
Листинг 5 – Отображение контактов и каналов «Telegram»
В данных функциях загружаются контакты, беседы и каналы в компонент QListWidget, для отображения фотографий используется компонент QIcon, также с помощью метода sortItems все данные в QListWidget сортируется по алфавиту, что позволяет пользователю быстро найти нужным ему контакт, канал или беседу[9].
При выборе нужного пункта в списках, происходит загрузка сообщений, для того что обновлять сообщения используется таймер. В приложения используется всего один таймер для обновления сообщений в контактах, каналах и беседах, потому что при использовании нескольких таймеров приложения начинает тормозить и им становится невозможно пользоваться. Для того чтобы сообщения обновляясь в определенном месте, используются логические переменные, так называемые флаги, которые могут принимать всего два значения – True и False. Например, если пользователь выбирает контакт из «Telegram», то ответственный за контакты флаг принимает значение True, а все остальные False. Функция, реализующая обновления сообщений в «Telegram» представленная на листинге 6.
def message_telgram(self):
login_telegram = ""
users_telegram = ""
if self.flag_telegram_message == True:
self.message_telegram.clear()
self.message_telegram.setVisible(True)
self.message_telegram.setReadOnly(True)
for user_val in range(0,self.users_telegram.count(),1):
users = self.user[user_val]
log_tl = str(users.first_name) + " " + str(users.last_name)
if(self.tabBar.tabText(self.tab_message.currentIndex())==str(users.firs t_name)) or (self.tabBar.tabText(self.tab_message.currentIndex())==log_tl) or (self.tabBar.tabText(self.tab_message.currentIndex())==str(users.username)):
result=self.client(GetHistoryRequest(users,limit=20000000,
offset_date=None,offset_id=0,max_id=0,min_id=0,add_offset=0))
try:
message = result.messages
for message_value in range(0, len(message), 1):
messages = message[message_value]
if (self.my_self.id == messages.from_id):
if self.my_self.last_name == None:
login_telegram = str(self.my_self.first_name)
else:
login_telegram=str(self.my_self.first_name)
" "+str(self.my_self.last_name)
cursor=QTextCursor(self.message_telegram.document())
cursor.insertHtml(""+""+login_telegram+""+"
"+str(messages.date) +"
"+str(messages.message) +"
"+"")
self.message_telegram.moveCursor(QtGui.QTextCursor.End)
else:
if users.last_name == None:
users_telegram=str(users.first_name)
else:
users_telegram=str(users.first_name)+
" "+str(users.last_name)
cursor=QTextCursor(self.message_telegram.document())
cursor.insertHtml(""+""+users_telegram+""+"
"+str(messages.date) + "
" + str(messages.message) + "
"+"")
self.message_telegram.moveCursor(QtGui.QTextCursor.End)
except ValueError:
pass
except TimeoutError:
pass
except MemoryError:
pass
except OverflowError:
pass
Листинг 6 – Обновление сообщений «Telegram»
В данной функции сначала определяется, какой выбран контакт или канал, потом этот контакт сравнивается с теми контактами, которые загрузились при авторизации, если контакты совпали, то вызывается метод, который загружает сообщения с выбранным контактом. Далее происходит разделение сообщений на те, которые относятся к пользователю и которые относятся к выбранному контакту и происходит форматирование вывода сообщения c помощью языка разметки html. Процесс обновления сообщений в функции происходит следующим образом: сначала очищается все сообщения, которые вывелись, а потом снова вызывается метод для получения сообщений, так как в таймере задается маленький промежуток обновления, то пользователь не замечает очищения сообщений.
Для обновления сообщений в «ВКонтакте» используется метод LongPoll – это метод получает мгновенный ответ с сервера, то есть не надо будет каждый раз очищать старые сообщения и снова вызывать метод для их получения, сообщения будут отображаться по мере их поступления. Данный метод использовался в функции представленной на листинге 7.
def update_message(self):
for event in self.longpoll.listen():
if event.type == VkEventType.MESSAGE_NEW:
user = self.vk.users.get(user_ids = event.user_id)
user_vk = user[0].get('first_name') + " " + user[0].get('last_name')
if event.from_chat:
chats_vk = self.vk.messages.getChat(chat_id = event.chat_id)
chats_vk_title = chats_vk.get('title')
if self.tabBar.tabText(self.tab_message.currentIndex())==chats_vk_title:
time = event.timestamp
mes = str(event.text)
data=datetime.datetime.fromtimestamp(int(time)).strftime(
'%Y-%m-%d %H:%M:%S')
user_chat=self.vk.users.get(user_ids=event.user_id)
user_vk_chat=user[0].get('first_name')+" "+ user[0].get('last_name')
self.chats_vk_message.append(""+""+user_vk_chat+"" + " " +str(data) + "
" + mes + "
"+"")
self.chats_vk_message.moveCursor(QtGui.QTextCursor.End)
if self.tabBar.tabText(self.tab_message.currentIndex())==user_vk:
if event.from_me:
time = event.timestamp
mes = str(event.text)
data=datetime.datetime.fromtimestamp(int(time)).strftime
('%Y-%m-%d %H:%M:%S')
self.vk_message.append(""+ ""+self.my_self_vk+
"" + " "+str(data) + "
" + mes + "
"+"")
self.vk_message.moveCursor(QtGui.QTextCursor.End)
elif event.to_me:
time = event.timestamp
mes = str(event.text)
data=datetime.datetime.fromtimestamp(int(time)).strftime
('%Y-%m-%d %H:%M:%S')
self.vk_message.append(""+""+user_vk+""+" "+str(data)+"
"+mes+"
"+"")
self.vk_message.moveCursor(QtGui.QTextCursor.End)
Листинг 7 – Обновление сообщений в «ВКонтакте»
В приложение также есть возможность обмениваться сообщениями, но не с одним контактом из одного клиента, а сразу с несколькими и из разных клиентов, эта функция приложения реализована с помощью компонента QTabWidget. Функции для отправки сообщений в «Telegram», представлена на листинге 8:
def telegram_send(self):
if (self.flag_telegram_message == True):
if (len(self.message_text.toPlainText())):
for user_val1 in range(0,self.users_telegram.count(),1):
users = self.user[user_val1]
log_tl = str(users.first_name) + " " + str(users.last_name)
if(self.tabBar.tabText(self.tab_message.currentIndex())==str(users.first_name))or(self.tabBar.tabText(self.tab_message.currentIndex())==log_tl)or(self.tabBar.tabText(self.tab_message.currentIndex())==str(users.username)):
self.client.send_message(users, self.message_text.toPlainText())
self.message_text.clear()
self.timer_message_telegram.start(5000)
Листинг 8 – Отправка сообщений в «Telegram»
В данной функции тоже используют флаги для определения, какому контакту, каналу или в какую беседу хочет пользователь отправить сообщения, чтобы не произошло ошибки, и сообщение не отправилось в другой место, имя контакта, или название беседы берется с названия вкладки, если контакт с «Telegram», то полученного имя хватает. В случае с «ВКонтакте» нужно определить еще id выбранного контакта, если сообщение отправляется в беседу в «ВКонтакте», то к полученному id беседы прибавляется еще два миллиарда.
ЗАКЛЮЧЕНИЕ
В данном курсовом проекте мной были решены следующие задачи:
-
Анализ социальных сетей и выбор самых популярных для использования в приложении. -
Анализ различных библиотек с исходным открытым кодом для дальнейшего использования. -
Изучение высокоуровневого языка программирования Python. -
Изучение среды разработки PyQt. -
Ознакомление с механизм QSS, позволяющий настраивать внешний вид виджетов библиотеки Qt.