You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-console-gui/pym/consolegui/application/ConnectionTabs.py

590 lines
20 KiB

#-*- coding: utf-8 -*-
# Copyright 2010-2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import dbus
import dbus.service
import dbus.mainloop.glib
from .. import qt
import time, sys
import calculate.contrib
from suds import MethodNotFound
import os, pwd, shutil
# import ConfigParser
import calculate.lib.configparser as ConfigParser
from .TrayIcon import TrayIcon
from .more import get_sid, get_view_params, _print, get_icon, get_system_rgb, \
dpivalue
from .MainClass import ApiClient
from ..datavars import DataVarsGui
from .pid_information import client_pid_info
#from calculate.lib.cl_lang import setLocalTranslate
#setLocalTranslate('console_gui',sys.modules[__name__])
import gettext
_ = gettext.gettext
class SelectedMethodWgt(qt.QWidget):
def __init__(self, app, args):
super().__init__()
self.args = args
self.user_changed_flag = False
self.lang = args.lang
self.method = args.method
self.skip_options = args.skip_options
# Initialization GUI variables
self.VarsGui = DataVarsGui()
self.VarsGui.importGui()
self.VarsGui.flIniFile()
self.ClientObj = ApiClient(app, self)
self.port = args.port or self.VarsGui.GetInteger('core.cl_core_port')
self.MethodWidget = self.ClientObj.MainWidget
self.MethodWidget.topmenu.hide()
layout = qt.QHBoxLayout(self)
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
layout.addWidget(self.MethodWidget)
icon = get_icon('console-gui-%s'%self.method.replace("_","-"),
'calculate-%s'%self.method.replace("_","-"))
self.setWindowIcon(icon)
qt.QApplication.setWindowIcon(icon)
conf_path = self.VarsGui.Get('cl_gui_config_path')
homePath = self.VarsGui.Get('ur_home_path')
self.user_config = conf_path.replace("~",homePath)
if self.connect():
sys.exit(1)
if not self.get_size():
# definition of screen resolution
prim_screen = app.desktop().primaryScreen()
d_size = app.desktop().screenGeometry(prim_screen).size()
# resize main widget
if d_size.height() < 768:
self.resize(900,560)
else:
self.resize(900, 726)
self.setMinimumHeight(100)
self.setMinimumWidth(500)
self.show()
def connect(self):
self.MethodWidget.connect_to_localhost(self.args.host, self.port)
if not self.ClientObj.client:
return 1
self.ClientObj.sid = get_sid(self.ClientObj.client)
try:
view_params = get_view_params(self.ClientObj.client, \
self.args.method + '_view', step = 0)
view = self.ClientObj.client.service[0][self.args.method + \
'_view'](int(self.ClientObj.sid), view_params)
except MethodNotFound:
_print('Method not found: ', self.args.method + '_view')
self.close()
sys.exit(1)
if self.args.method in self.ClientObj.method_names:
view_method = self.ClientObj.method_names[self.args.method]
else:
view_method = self.args.method
self.setWindowTitle(view_method + ' - ' + \
self.ClientObj._parent.windowTitle())
#self.MethodWidget.MainFrameWgt.call_server_method(False)
#self.MethodWidget.main_frame_view(view, self.args.method,
# skip_options=not self.args.skip_options)
self.MethodWidget.main_frame_view(view, self.args.method,
skip_options=self.args.skip_options)
return 0
def translate(self, lang = None):
return 0
def connect_count_changed(self, host, port, count):
pass
def has_update(self, update):
print("Update", update)
def get_size(self):
self.config = ConfigParser.ConfigParser()
self.config.read(self.user_config)
try:
size = self.config.get('gui', 'size')
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
return False
tup_size = [int(x) for x in size.split(',')]
self.resize(tup_size[0], tup_size[1])
return True
def set_size(self):
self.config = ConfigParser.ConfigParser()
self.config.read(self.user_config)
try:
selfsize = self.size()
self.config.set('gui', 'size',
"{},{}".format(selfsize.width(), selfsize.height()))
with open(self.user_config, 'w') as f:
self.config.write(f)
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
return False
def closeEvent(self, event):
close_event = self._closeEvent()
# event.ignore()
if close_event:
self.set_size()
save_path = os.path.join('/tmp', 'calculate-' + \
pwd.getpwuid(os.getuid()).pw_name)
if os.path.isdir(save_path):
shutil.rmtree(save_path)
event.accept()
else:
event.ignore()
def _closeEvent(self):
if not self.isVisible():
if self.ClientObj.signaling.isRunning():
self.ClientObj.signaling.close()
self.ClientObj.signaling.wait()
return 1
if not self.user_changed_flag:
reply = qt.QMessageBox.Yes
else:
reply = self.show_close_messagebox()
from .mainframe import MainFrame
if reply == qt.QMessageBox.Yes:
if hasattr (self, 'con_lost_lbl'):
self.con_lost_lbl.hide()
self.con_lost_lbl.close()
# Exit with closing session
if self.ClientObj.signaling.isRunning():
self.ClientObj.signaling.close()
self.ClientObj.signaling.wait()
if type (self.MethodWidget.MainFrameWgt) == MainFrame:
return 1
else:
pid = int(self.MethodWidget.MainFrameWgt.cur_pid)
self.MethodWidget.MainFrameWgt.close()
self.ClientObj.client.service.pid_kill(pid, self.ClientObj.sid)
while True:
client_pid_info(self.ClientObj, self.ClientObj.client, 0)
if 'status' not in self.ClientObj.process_dict[str(pid)]:
return 1
if self.ClientObj.process_dict[str(pid)]['status'] != '1':
return 1
time.sleep(1)
elif reply == qt.QMessageBox.No:
return 0
def user_changed(self):
self.user_changed_flag = True
def show_close_messagebox(self):
msgBox = qt.QMessageBox(self)
if self.method in self.ClientObj.method_names:
method_name = self.ClientObj.method_names[self.method]
else:
method_name = self.method
msgBox.setText(_("Close") +' "%s"?' %method_name)
msgBox.setStandardButtons(qt.QMessageBox.Yes | qt.QMessageBox.No)
# translate
msgBox.button(msgBox.Yes).setText(_('Yes'))
msgBox.button(msgBox.No).setText(_('No'))
icon = get_icon('dialog-close')
if not icon.isNull():
msgBox.button(msgBox.No).setIcon(icon)
msgBox.setDefaultButton(qt.QMessageBox.No)
msgBox.setWindowIcon(get_icon("application-exit"))
reply = msgBox.exec_()
return reply
def parse():
import gettext
import locale
try:
# set_lang = gettext.locale.getdefaultlocale()[0][:2]
set_lang = locale.getdefaultlocale()[0][:2]
lang = gettext.translation('cl_consolegui3', languages=[set_lang],fallback=True)
try:
lang.install()
# lang.install(unicode=True)
except UnboundLocalError:
pass
except (IOError, TypeError):
pass
_ = gettext.gettext
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
'-h', '--help', action='store_true', default=False,
dest='help', help=_("show this help message and exit"))
parser.add_argument(
'-l', '--lang', type=str, dest='lang',
help=_("translation language"))
parser.add_argument(
'--method', type=str, dest='method',
help=_('call method'))
parser.add_argument(
'--skip-options', action='store_true',
dest='skip_options', default=False,
help=_('run the method without options'))
parser.add_argument(
'-p', '--port', type=int, dest='port',
help=_('port number'))
parser.add_argument(
'--host', type=str, default = 'localhost', dest='host',
help=_('destination host'))
return parser
class MyTabBar(qt.QTabBar):
def __init__(self, _parent):
super().__init__()
self._parent = _parent
def wheelEvent(self, event):
event.ignore()
def mousePressEvent(self, event):
if event.button() == qt.Qt.LeftButton:
self.setCurrentIndex(self.tabAt(event.pos()))
event.accept()
if event.button() == qt.Qt.MiddleButton:
self._parent.close_tab(self.tabAt(event.pos()))
class ToolTabWidget(qt.QTabWidget):
def __init__(self, app, args = None, host = None, port = None):
super().__init__()
self.app = app
if args:
if args.lang:
self.lang = args.lang
self.current_icon = None
self.setContentsMargins(0,0,0,0)
self.init_variables()
# Initialization GUI variables
self.VarsGui = DataVarsGui()
self.VarsGui.importGui()
self.VarsGui.flIniFile()
ClientObj = ApiClient(app, self)
self.FirstWidget = ClientObj.MainWidget
self.PlusWidget = qt.QWidget(self)
self.tabbar = MyTabBar(self)
self.setTabBar(self.tabbar)
self.gui_icon = get_icon("video-display")
self.other_icon = get_icon("list-add", "preferences-desktop")
self.addTab(self.FirstWidget, self.gui_icon , self.new_con_txt)
self.addTab(self.PlusWidget, self.other_icon, '')
self.last_close_index = -1
self.tabCloseRequested.connect(self.close_tab)
self.currentChanged.connect(self.add_tab)
self.currentChanged.connect(self.changeWindowTitle)
self.setTabsClosable(True)
self.tabbar.tabButton(1, qt.QTabBar.RightSide).hide()
if not self.get_size():
# definition of screen resolution
prim_screen = self.app.desktop().primaryScreen()
d_size = self.app.desktop().screenGeometry(prim_screen).size()
# resize main widget
if d_size.height() < 768:
self.resize(900,560)
else:
self.resize(dpivalue(900), dpivalue(700))
self.setMinimumHeight(100)
self.setMinimumWidth(500)
self.setWindowTitle(self.Name)
hbg = get_system_rgb(self, qt.QPalette.Base)
bg = "transparent"
leftpadding = 8
width = 24
#self.setStyleSheet('''
#QTabBar::tab:last {
#background: %s;
#margin: 2px 2px 3px 0px;
#width: %s;
#padding: 0px 0px 0px %spx;}
#QTabBar::tab:last::hover {
# background: %s;}''' % (bg, width, leftpadding, hbg))
self.set_offline_icon()
self.show()
self.app.processEvents()
self.connect_dict = {}
self.connect_count = 0
if not host or host == 'localhost':
self.host = '127.0.0.1'
else:
self.host = host
if not port:
self.port = self.VarsGui.GetInteger('core.cl_core_port')
else:
self.port = port
self.setEnabled(False)
qt.QTimer.singleShot(200, self.connect_after_init)
self.create_tray()
if self.FirstWidget.ClientObj.client:
self.tray.set_icon(True)
def connect_after_init(self):
self.FirstWidget.connect_to_localhost(self.host, self.port)
self.setEnabled(True)
if self.FirstWidget.ClientObj.client:
self.FirstWidget.updateColors()
if self.host in ['127.0.0.1', 'localhost']:
self.localhost_ClientObj = self.FirstWidget.ClientObj
if not self.host in self.connect_dict:
self.connect_dict[self.host] = [self.port]
else:
if self.port:
if not self.port in self.connect_dict[self.host]:
self.connect_dict[self.host].append(self.port)
def set_offline_icon(self):
if self.current_icon != "offline":
self.current_icon = "offline"
self.setWindowIcon(get_icon(
'/usr/share/pixmaps/calculate-console-offline.svg'))
def set_online_icon(self):
if self.current_icon != "online":
self.current_icon = "online"
self.setWindowIcon(get_icon(
'/usr/share/pixmaps/calculate-console-online.svg'))
def connect_count_changed(self, host, port, count):
if count:
if not host in self.connect_dict:
self.connect_dict[host] = [port]
else:
if port:
if not port in self.connect_dict[host]:
self.connect_dict[host].append(port)
else:
if host in self.connect_dict:
if port in self.connect_dict[host]:
self.connect_dict[host].remove(port)
if not self.connect_dict[host]:
self.connect_dict.pop(host)
if self.connect_dict:
self.set_online_icon()
if hasattr(self, 'tray'):
self.tray.set_icon(True)
else:
self.set_offline_icon()
if hasattr(self, 'tray'):
self.tray.set_icon(False)
def init_variables(self):
try:
self.Version = self.VarsGui.Get('cl_ver')
except:
self.Version = ''
#try:
# self.Name = self.VarsGui.Get('cl_name')
#except:
self.Name = 'Calculate Console'
self.new_con_txt = _('New connection')
self.sys_update_pid = None
def close_tab(self, cur_num = None, hard = False):
exit_flag = 0
if cur_num == None:
cur_num = self.currentIndex()
if cur_num != self.count() - 1:
# for delete widget
self.setCurrentIndex(cur_num)
wgt = self.currentWidget()
if wgt == self.FirstWidget and not hard:
return exit_flag
if wgt._closeEvent():
wgt.close()
self.last_close_index = cur_num
if cur_num:
self.setCurrentIndex(cur_num - 1)
else:
self.setCurrentIndex(0)
self.removeTab(cur_num)
exit_flag = 1
if self.count() < 2:
self.add_tab()
return exit_flag
def add_tab(self):
if self.currentIndex() == self.count() - 1:
# not add if exists clean tab
for tab_num in range(self.count() - 1):
self.setCurrentIndex(tab_num)
if not self.currentWidget().ClientObj.client:
return 0
ClientObj = ApiClient(self.app, self)
widget = ClientObj.MainWidget
widget.cur_window_title = self.Name
self.insertTab(self.count() - 1, widget, self.gui_icon , \
self.new_con_txt)
self.setCurrentIndex(self.count() - 2)
if self.currentWidget().ClientObj.client:
self.tabbar.setTabEnabled(self.count() - 1, True)
else:
self.tabbar.setTabEnabled(self.count() - 1, False)
def rename_tab(self, text = None, ind = None):
if not text:
text = self.new_con_txt
if not ind:
ind = self.currentIndex()
self.setTabText(ind, text)
def changeWindowTitle(self, tab_num):
try:
text = self.currentWidget().cur_window_title
self.setWindowTitle(text)
except AttributeError:
pass
def setWindowTitle(self, title):
self.currentWidget().cur_window_title = title
super(ToolTabWidget, self).setWindowTitle(title)
def create_tray(self):
self.tray = TrayIcon(self)
self.tray.setVisible(True)
self.app.processEvents()
def translate(self, lang = None):
self.new_con_txt = _('New connection')
# self.new_con_txt = self.new_con_txt.decode('utf-8')
current = self.currentIndex()
# not add if exists clean tab
for tab_num in range(self.count() - 1):
self.setCurrentIndex(tab_num)
if not self.currentWidget().ClientObj.client:
self.setTabText(tab_num, self.new_con_txt)
self.setCurrentIndex(current)
if hasattr(self, 'tray'):
self.tray.translate()
def set_localhost(self, ClientObj):
self.localhost_ClientObj = ClientObj
# if ClientObj:
# self.connect_dict[ClientObj.host_name] = \
# [ClientObj, self.currentIndex()]
# self.tabbar.tabButton(self.currentIndex(), \
# qt.QTabBar.RightSide).hide()
def find_host(self, host_name, port):
ind = self.currentIndex()
for i in range (self.count() - 1):
self.setCurrentIndex(i)
wgt = self.currentWidget()
if hasattr (wgt, 'ClientObj'):
ClientObj = wgt.ClientObj
if host_name == ClientObj.host_name and \
port == ClientObj.port and ClientObj.client:
self.removeTab(ind)
return 1
self.setCurrentIndex(ind)
return 0
def closeEvent(self, event):
self.cur_pos = self.pos()
self.hide()
from os import environ
if environ.get("XSESSION","").lower() == "plasma":
event.accept()
else:
event.ignore()
def _closeEvent(self):
for tab_num in range(self.count()):
if not self.close_tab(0, True):
return 1
self.set_size()
save_path = os.path.join('/tmp', 'calculate-' + \
pwd.getpwuid(os.getuid()).pw_name)
if os.path.isdir(save_path):
shutil.rmtree(save_path)
self.app.exit()
def get_size(self):
conf_path = self.VarsGui.Get('cl_gui_config_path')
homePath = self.VarsGui.Get('ur_home_path')
self.user_config = conf_path.replace("~",homePath)
self.config = ConfigParser.ConfigParser()
self.config.read(self.user_config)
try:
size = self.config.get('gui', 'size')
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
return False
tup_size = [int(x) for x in size.split(',')]
self.resize(tup_size[0], tup_size[1])
return True
def set_size(self):
self.config = ConfigParser.ConfigParser()
self.config.read(self.user_config)
try:
selfsize = self.size()
self.config.set('gui', 'size',
"{},{}".format(selfsize.width(), selfsize.height()))
with open(self.user_config, 'w') as f:
self.config.write(f)
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
return False
def keyPressEvent(self, e):
if e.key() == qt.Qt.Key_Return:
self.currentWidget().keyPressEvent(e)
else:
qt.QTabWidget.keyPressEvent(self, e)