예제 #1
0
class MenuBuilderDialog(QDialog, Ui_Dialog):
    def __init__(self, uiparent):
        super(MenuBuilderDialog, self).__init__()

        self.setupUi(self)

        # reference to caller
        self.uiparent = uiparent

        self.combo_profile.lineEdit().setPlaceholderText(
            self.tr("Profile name"))

        # add icons
        self.button_add_menu.setIcon(
            QIcon(":/plugins/MenuBuilder/resources/plus.svg"))
        self.button_delete_profile.setIcon(
            QIcon(":/plugins/MenuBuilder/resources/delete.svg"))

        # custom qtreeview
        self.target = CustomQtTreeView(self)
        self.target.setGeometry(QRect(440, 150, 371, 451))
        self.target.setAcceptDrops(True)
        self.target.setDragEnabled(True)
        self.target.setDragDropMode(QAbstractItemView.DragDrop)
        self.target.setObjectName("target")
        self.target.setDropIndicatorShown(True)
        self.target.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.target.setHeaderHidden(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.target.sizePolicy().hasHeightForWidth())
        self.target.setSizePolicy(sizePolicy)
        self.target.setAutoFillBackground(True)
        self.verticalLayout_2.addWidget(self.target)

        self.browser = QgsBrowserModel()
        self.source.setModel(self.browser)
        self.source.setHeaderHidden(True)
        self.source.setDragEnabled(True)
        self.source.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.menumodel = MenuTreeModel(self)
        self.target.setModel(self.menumodel)
        self.target.setAnimated(True)

        # add a dock widget
        self.dock_widget = QDockWidget("Menus")
        self.dock_widget.resize(400, 300)
        self.dock_widget.setFloating(True)
        self.dock_widget.setObjectName(self.tr("Menu Tree"))
        self.dock_widget_content = QWidget()
        self.dock_widget.setWidget(self.dock_widget_content)
        dock_layout = QVBoxLayout()
        self.dock_widget_content.setLayout(dock_layout)
        self.dock_view = DockQtTreeView(self.dock_widget_content)
        self.dock_view.setDragDropMode(QAbstractItemView.DragOnly)
        self.dock_menu_filter = QLineEdit()
        self.dock_menu_filter.setPlaceholderText(
            self.tr("Filter by table description (postgis only)"))
        dock_layout.addWidget(self.dock_menu_filter)
        dock_layout.addWidget(self.dock_view)
        self.dock_view.setHeaderHidden(True)
        self.dock_view.setDragEnabled(True)
        self.dock_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.dock_view.setAnimated(True)
        self.dock_view.setObjectName("treeView")
        self.proxy_model = LeafFilterProxyModel(self)
        self.proxy_model.setFilterRole(Qt.ToolTipRole)
        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.profile_list = []
        self.table = 'qgis_menubuilder_metadata'

        self.layer_handler = {
            'vector': self.load_vector,
            'raster': self.load_raster
        }

        # connect signals and handlers
        self.combo_database.activated.connect(
            partial(self.set_connection, dbname=None))
        self.combo_schema.activated.connect(self.update_profile_list)
        self.combo_profile.activated.connect(
            partial(self.update_model_idx, self.menumodel))
        self.button_add_menu.released.connect(self.add_menu)
        self.button_delete_profile.released.connect(self.delete_profile)
        self.dock_menu_filter.textEdited.connect(self.filter_update)
        self.dock_view.doubleClicked.connect(self.load_from_index)

        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
            self.apply)

    def filter_update(self):
        text = self.dock_menu_filter.displayText()
        self.proxy_model.setFilterRegExp(text)

    def show_dock(self, state, profile=None, schema=None):
        if not state:
            # just hide widget
            self.dock_widget.setVisible(state)
            return
        # dock must be read only and deepcopy of model is not supported (c++ inside!)
        self.dock_model = MenuTreeModel(self)
        if profile:
            # bypass combobox
            self.update_model(self.dock_model, schema, profile)
        else:
            self.update_model_idx(self.dock_model,
                                  self.combo_profile.currentIndex())
        self.dock_model.setHorizontalHeaderLabels(["Menus"])
        self.dock_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.proxy_model.setSourceModel(self.dock_model)
        self.dock_view.setModel(self.proxy_model)
        self.dock_widget.setVisible(state)

    def show_menus(self, state, profile=None, schema=None):
        if state:
            self.load_menus(profile=profile, schema=schema)
            return
        # remove menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(
                menu.menuAction())

    def add_menu(self):
        """
        Add a menu inside qtreeview
        """
        item = QStandardItem('NewMenu')
        item.setIcon(QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
        # select current index selected and insert as a sibling
        brother = self.target.selectedIndexes()

        if not brother or not brother[0].parent():
            # no selection, add menu at the top level
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return

        parent = self.menumodel.itemFromIndex(brother[0].parent())
        if not parent:
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return
        parent.appendRow(item)

    def update_database_list(self):
        """update list of defined postgres connections"""
        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections")
        keys = settings.childGroups()
        self.combo_database.clear()
        self.combo_schema.clear()
        self.menumodel.clear()
        self.combo_database.addItems(keys)
        self.combo_database.setCurrentIndex(-1)
        settings.endGroup()
        # clear profile list
        self.combo_profile.clear()
        self.combo_profile.setCurrentIndex(-1)

    def set_connection(self, databaseidx, dbname=None):
        """
        Connect to selected postgresql database
        """
        selected = self.combo_database.itemText(databaseidx) or dbname
        if not selected:
            return

        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections/{}".format(selected))

        if not settings.contains("database"):
            # no entry?
            QMessageBox.critical(self, "Error",
                                 "There is no defined database connection")
            return

        uri = QgsDataSourceURI()

        settingsList = [
            "service", "host", "port", "database", "username", "password"
        ]
        service, host, port, database, username, password = map(
            lambda x: settings.value(x, "", type=str), settingsList)

        useEstimatedMetadata = settings.value("estimatedMetadata",
                                              False,
                                              type=bool)
        sslmode = settings.value("sslmode",
                                 QgsDataSourceURI.SSLprefer,
                                 type=int)

        settings.endGroup()

        if service:
            uri.setConnection(service, database, username, password, sslmode)
        else:
            uri.setConnection(host, port, database, username, password,
                              sslmode)

        uri.setUseEstimatedMetadata(useEstimatedMetadata)

        # connect to db
        self.connect_to_uri(uri)
        # update schema list
        self.update_schema_list()

    @contextmanager
    def transaction(self):
        try:
            yield
            self.connection.commit()
        except self.pg_error_types() as e:
            self.connection.rollback()
            raise e

    def check_connected(func):
        """
        Decorator that checks if a database connection is active before executing function
        """
        @wraps(func)
        def wrapped(inst, *args, **kwargs):
            if not getattr(inst, 'connection', False):
                QMessageBox(
                    QMessageBox.Warning, "Menu Builder",
                    inst.tr(
                        "Not connected to any database, please select one"),
                    QMessageBox.Ok, inst).exec_()
                return
            if inst.connection.closed:
                QMessageBox(
                    QMessageBox.Warning, "Menu Builder",
                    inst.tr(
                        "Not connected to any database, please select one"),
                    QMessageBox.Ok, inst).exec_()
                return
            return func(inst, *args, **kwargs)

        return wrapped

    def connect_to_uri(self, uri):
        self.close_connection()
        self.host = uri.host() or os.environ.get('PGHOST')
        self.port = uri.port() or os.environ.get('PGPORT')

        username = uri.username() or os.environ.get(
            'PGUSER') or os.environ.get('USER')
        password = uri.password() or os.environ.get('PGPASSWORD')

        try:
            self.connection = psycopg2.connect(uri.connectionInfo())
        except self.pg_error_types() as e:
            err = str(e)
            conninfo = uri.connectionInfo()

            ok, username, password = QgsCredentials.instance().get(
                conninfo, username, password, err)
            if not ok:
                raise Exception(e)

            if username:
                uri.setUsername(username)

            if password:
                uri.setPassword(password)

            self.connection = psycopg2.connect(uri.connectionInfo())

        self.pgencoding = self.connection.encoding

        return True

    def pg_error_types(self):
        return (psycopg2.InterfaceError, psycopg2.OperationalError,
                psycopg2.ProgrammingError)

    @check_connected
    def update_schema_list(self):
        self.combo_schema.clear()
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select nspname
                from pg_namespace
                where nspname not ilike 'pg_%'
                and nspname not in ('pg_catalog', 'information_schema')
                """)
            schemas = [row[0] for row in cur.fetchall()]
            self.combo_schema.addItems(schemas)

    @check_connected
    def update_profile_list(self, schemaidx):
        """
        update profile list from database
        """
        schema = self.combo_schema.itemText(schemaidx)
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select 1
                from pg_tables
                    where schemaname = '{0}'
                    and tablename = '{1}'
                union
                select 1
                from pg_matviews
                    where schemaname = '{0}'
                    and matviewname = '{1}'
                """.format(schema, self.table))
            tables = cur.fetchone()
            if not tables:
                box = QMessageBox(
                    QMessageBox.Warning, "Menu Builder",
                    self.tr("Table '{}.{}' not found in this database, "
                            "would you like to create it now ?").format(
                                schema, self.table),
                    QMessageBox.Cancel | QMessageBox.Yes, self)
                ret = box.exec_()
                if ret == QMessageBox.Cancel:
                    return False
                elif ret == QMessageBox.Yes:
                    cur.execute("""
                        create table {}.{} (
                            id serial,
                            name varchar,
                            profile varchar,
                            model_index varchar,
                            datasource_uri text
                        )
                        """.format(schema, self.table))
                    self.connection.commit()
                    return False

            cur.execute("""
                select distinct(profile) from {}.{}
                """.format(schema, self.table))
            profiles = [row[0] for row in cur.fetchall()]
            saved_profile = self.combo_profile.currentText()
            self.combo_profile.clear()
            self.combo_profile.addItems(profiles)
            self.combo_profile.setCurrentIndex(
                self.combo_profile.findText(saved_profile))

    @check_connected
    def delete_profile(self):
        """
        Delete profile currently selected
        """
        idx = self.combo_profile.currentIndex()
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.itemText(idx)
        box = QMessageBox(QMessageBox.Warning, "Menu Builder",
                          self.tr("Delete '{}' profile ?").format(profile),
                          QMessageBox.Cancel | QMessageBox.Yes, self)
        ret = box.exec_()
        if ret == QMessageBox.Cancel:
            return False
        elif ret == QMessageBox.Yes:
            self.combo_profile.removeItem(idx)
            with self.transaction():
                cur = self.connection.cursor()
                cur.execute("""
                    delete from {}.{}
                    where profile = '{}'
                    """.format(schema, self.table, profile))
        self.menumodel.clear()
        self.combo_profile.setCurrentIndex(-1)

    def update_model_idx(self, model, profile_index):
        """
        wrapper that checks combobox
        """
        profile = self.combo_profile.itemText(profile_index)
        schema = self.combo_schema.currentText()
        self.update_model(model, schema, profile)

    def sortby_modelindex(self, rows):
        return sorted(
            rows,
            key=lambda line: '/'.join(
                ['{:04}'.format(elem[0]) for elem in json.loads(line[2])]))

    @check_connected
    def update_model(self, model, schema, profile):
        """
        Update the model by retrieving the profile given in database
        """
        menudict = {}

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
            model.clear()
            for name, profile, model_index, datasource_uri in self.sortby_modelindex(
                    rows):
                menu = model.invisibleRootItem()
                indexes = json.loads(model_index)
                parent = ''
                for idx, subname in indexes[:-1]:
                    parent += '{}-{}/'.format(idx, subname)
                    if parent in menudict:
                        # already created entry
                        menu = menudict[parent]
                        continue
                    # create menu
                    item = QStandardItem(subname)
                    uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                    item.setData(uri_struct)
                    item.setIcon(
                        QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
                    item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                                  | Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
                                  | Qt.ItemIsEditable)
                    item.setWhatsThis("menu")
                    menu.appendRow(item)
                    menudict[parent] = item
                    # set current menu to the new created item
                    menu = item

                # add leaf (layer item)
                item = QStandardItem(name)
                uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                # fix layer name instead of table name
                # usefull when the layer has been renamed in menu
                uri_struct.name = name
                if uri_struct.providerKey in ICON_MAPPER:
                    item.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))
                item.setData(uri_struct)
                # avoid placing dragged layers on it
                item.setDropEnabled(False)
                if uri_struct.providerKey == 'postgres':
                    # set tooltip to postgres comment
                    comment = self.get_table_comment(uri_struct.uri)
                    item.setToolTip(comment)
                menudict[parent].appendRow(item)

    @check_connected
    def save_changes(self, save_to_db=True):
        """
        Save changes in the postgres table
        """
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.currentText()
        if not profile:
            QMessageBox(QMessageBox.Warning, "Menu Builder",
                        self.tr("Profile cannot be empty"), QMessageBox.Ok,
                        self).exec_()
            return False

        if save_to_db:
            try:
                with self.transaction():
                    cur = self.connection.cursor()
                    cur.execute(
                        "delete from {}.{} where profile = '{}'".format(
                            schema, self.table, profile))
                    for item, data in self.target.iteritems():
                        if not data:
                            continue
                        cur.execute(
                            """
                        insert into {}.{} (name,profile,model_index,datasource_uri)
                        values (%s, %s, %s, %s)
                        """.format(schema, self.table),
                            (item[-1][1], profile, json.dumps(item),
                             data.data()))
            except Exception as exc:
                QMessageBox(QMessageBox.Warning, "Menu Builder",
                            exc.message.decode(self.pgencoding),
                            QMessageBox.Ok, self).exec_()
                return False

        self.save_session(self.combo_database.currentText(), schema, profile,
                          self.activate_dock.isChecked(),
                          self.activate_menubar.isChecked())
        self.update_profile_list(self.combo_schema.currentIndex())
        self.show_dock(self.activate_dock.isChecked())
        self.show_menus(self.activate_menubar.isChecked())
        return True

    @check_connected
    def load_menus(self, profile=None, schema=None):
        """
        Load menus in the main windows qgis bar
        """
        if not schema:
            schema = self.combo_schema.currentText()
        if not profile:
            profile = self.combo_profile.currentText()
        # remove previous menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(
                menu.menuAction())

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
        # item accessor ex: '0-menu/0-submenu/1-item/'
        menudict = {}
        # reference to parent item
        parent = ''
        # reference to qgis main menu bar
        menubar = self.uiparent.iface.mainWindow().menuBar()

        for name, profile, model_index, datasource_uri in self.sortby_modelindex(
                rows):
            uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
            indexes = json.loads(model_index)
            # root menu
            parent = '{}-{}/'.format(indexes[0][0], indexes[0][1])
            if parent not in menudict:
                menu = QMenu(self.uiparent.iface.mainWindow())
                self.uiparent.menus.append(menu)
                menu.setObjectName(indexes[0][1])
                menu.setTitle(indexes[0][1])
                menubar.insertMenu(
                    self.uiparent.iface.firstRightStandardMenu().menuAction(),
                    menu)
                menudict[parent] = menu
            else:
                # menu already there
                menu = menudict[parent]

            for idx, subname in indexes[1:-1]:
                # intermediate submenus
                parent += '{}-{}/'.format(idx, subname)
                if parent not in menudict:
                    submenu = menu.addMenu(subname)
                    submenu.setObjectName(subname)
                    submenu.setTitle(subname)
                    menu = submenu
                    # store it for later use
                    menudict[parent] = menu
                    continue
                # already treated
                menu = menudict[parent]

            # last item = layer
            layer = QAction(name, self.uiparent.iface.mainWindow())

            if uri_struct.providerKey in ICON_MAPPER:
                layer.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))

            if uri_struct.providerKey == 'postgres':
                # set tooltip to postgres comment
                comment = self.get_table_comment(uri_struct.uri)
                layer.setStatusTip(comment)
                layer.setToolTip(comment)

            layer.setData(uri_struct.uri)
            layer.setWhatsThis(uri_struct.providerKey)
            layer.triggered.connect(self.layer_handler[uri_struct.layerType])
            menu.addAction(layer)

    def get_table_comment(self, uri):
        schema, table = re.match('.*table=(.*)\(.*',
                                 uri).group(1).strip().replace('"',
                                                               '').split('.')
        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select description from pg_description
                join pg_class on pg_description.objoid = pg_class.oid
                join pg_namespace on pg_class.relnamespace = pg_namespace.oid
                where relname = '{}' and nspname='{}'
                """.format(table, schema)
            cur.execute(select)
            row = cur.fetchone()
            if row:
                return row[0]
        return ''

    def load_from_index(self, index):
        """Load layers from selected item index"""
        item = self.dock_model.itemFromIndex(
            self.proxy_model.mapToSource(index))
        if item.whatsThis() == 'menu':
            return
        if item.data().layerType == 'vector':
            layer = QgsVectorLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        elif item.data().layerType == 'raster':
            layer = QgsRasterLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        if not layer:
            return
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_vector(self):
        action = self.sender()
        layer = QgsVectorLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_raster(self):
        action = self.sender()
        layer = QgsRasterLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def accept(self):
        if self.save_changes():
            QDialog.reject(self)
            self.close_connection()

    def apply(self):
        if self.save_changes(save_to_db=False):
            QDialog.reject(self)

    def reject(self):
        self.close_connection()
        QDialog.reject(self)

    def close_connection(self):
        """close current pg connection if exists"""
        if getattr(self, 'connection', False):
            if self.connection.closed:
                return
            self.connection.close()

    def save_session(self, database, schema, profile, dock, menubar):
        """save current profile for next session"""
        settings = QSettings()
        settings.setValue("MenuBuilder/database", database)
        settings.setValue("MenuBuilder/schema", schema)
        settings.setValue("MenuBuilder/profile", profile)
        settings.setValue("MenuBuilder/dock", dock)
        settings.setValue("MenuBuilder/menubar", menubar)

    def restore_session(self):
        settings = QSettings()
        database = settings.value("MenuBuilder/database", False)
        schema = settings.value("MenuBuilder/schema", 'public')
        profile = settings.value("MenuBuilder/profile", False)
        dock = settings.value("MenuBuilder/dock", False)
        menubar = settings.value("MenuBuilder/menubar", False)
        if not any([database, profile]):
            return

        self.set_connection(0, dbname=database)
        self.show_dock(bool(dock), profile=profile, schema=schema)
        if bool(dock):
            self.uiparent.iface.addDockWidget(Qt.LeftDockWidgetArea,
                                              self.dock_widget)
        self.show_menus(bool(menubar), profile=profile, schema=schema)
예제 #2
0
class ComboBoxBasic(QtGui.QWidget):
    """
    An basic example combo box application
    """
    def __init__(self):
        super(ComboBoxBasic, self).__init__()
        self.obj = Statistic()
        self.text = ''
        # create GUI
        #QtGui.QMainWindow.__init__(self)
        #self.setWindowTitle('VIEW STATISTIC')
        # Set the window dimensions
        #self.resize(250,290)]
        self.setFixedSize(250, 290)

        # vertical layout for widgets
        self.vbox = QtGui.QGridLayout()
        self.setLayout(self.vbox)

        # Create a combo box and add it to our layout
        self.label = QtGui.QLabel("service", self)
        self.vbox.addWidget(self.label, 1, 1)
        self.combo = QtGui.QComboBox()
        self.vbox.addWidget(self.combo, 1, 0)
        self.combo2 = QtGui.QComboBox()
        self.vbox.addWidget(self.combo2, 2, 0)
        self.label2 = QtGui.QLabel("metric", self)
        self.vbox.addWidget(self.label2, 2, 1)

        self.combo3 = QtGui.QComboBox()
        self.vbox.addWidget(self.combo3, 3, 0)
        self.label3 = QtGui.QLabel("time", self)
        self.vbox.addWidget(self.label3, 3, 1)

        self.combo4 = QtGui.QComboBox(self)
        self.vbox.addWidget(self.combo4, 4, 1)

        # Or add a sequence in one call
        distrolist = ['BROADBAND', 'IPTV', 'VOIP']
        self.combo.addItems(distrolist)
        #self.t = self.combo.currentText()
        self.connect(self.combo, QtCore.SIGNAL('activated(QString)'),
                     self.hello)

        con = cx_Oracle.connect('orcdb/[email protected]/orcl')
        self.cur = con.cursor()
        self.cur.execute(
            "select METRIC_TYPE from METRICS WHERE IDSERVICE='BROADBAND'")
        data = self.cur.fetchall()
        for el in data:
            self.combo2.addItems(el)

        self.connect(self.combo, QtCore.SIGNAL('activated(QString)'),
                     self.hello)

        distrolist3 = ['15 min', '30 min', '60 min', '1 day']
        self.combo3.addItems(distrolist3)

        distrolist4 = ['MAX', 'AVG', 'MIN']
        self.combo4.addItems(distrolist4)

        self.combo4.move(130, 49)

        quit = QtGui.QPushButton('VIEW STATISTIC', self)
        quit.setGeometry(90, 250, 140, 35)
        self.vbox.addWidget(quit, 5, 0)

        self.le = QLineEdit(self)
        #self.le.setGeometry(1,200,75,35)
        self.vbox.addWidget(self.le, 4, 0)

        i = str(self.combo4.currentText()) + "(" + str(
            self.combo2.currentText()) + ")"
        self.le.setText(str(i))

        self.connect(self.combo2, QtCore.SIGNAL('activated(QString)'),
                     self.edit)

        self.connect(self.combo4, QtCore.SIGNAL('activated(QString)'),
                     self.edit)

        self.connect(quit, QtCore.SIGNAL('clicked()'), self.combo_chosen)

    def combo_chosen(self):
        self.obj.select_dev(str(self.combo.currentText()),
                            str(self.combo2.currentText()),
                            str(self.combo3.currentText()),
                            str(self.combo4.currentText()),
                            str(self.le.displayText()))

    def edit(self):
        i = str(self.combo4.currentText()) + "(" + str(
            self.combo2.currentText()) + ")"

        self.le.setText(str(i))

    def hello(self):
        self.t = self.combo.currentText()
        self.combo2.clear()
        if self.t == "IPTV":
            self.cur.execute(
                "select METRIC_TYPE from METRICS WHERE IDSERVICE='IPTV'")
            data = self.cur.fetchall()
            for el in data:
                self.combo2.addItems(el)
        elif self.t == "VOIP":
            self.cur.execute(
                "select METRIC_TYPE from METRICS WHERE IDSERVICE='VOIP'")
            data = self.cur.fetchall()
            for el in data:
                self.combo2.addItems(el)
        elif self.t == "BROADBAND":
            self.cur.execute(
                "select METRIC_TYPE from METRICS WHERE IDSERVICE='BROADBAND'")
            data = self.cur.fetchall()
            for el in data:
                self.combo2.addItems(el)
class MenuBuilderDialog(QDialog, FORM_CLASS):
    def __init__(self, uiparent):
        super(MenuBuilderDialog, self).__init__()

        self.setupUi(self)

        # reference to caller
        self.uiparent = uiparent

        self.combo_profile.lineEdit().setPlaceholderText(self.tr("Profile name"))

        # add icons
        self.button_add_menu.setIcon(QIcon(":/plugins/MenuBuilder/resources/plus.svg"))
        self.button_delete_profile.setIcon(QIcon(":/plugins/MenuBuilder/resources/delete.svg"))

        # custom qtreeview
        self.target = CustomQtTreeView(self)
        self.target.setGeometry(QRect(440, 150, 371, 451))
        self.target.setAcceptDrops(True)
        self.target.setDragEnabled(True)
        self.target.setDragDropMode(QAbstractItemView.DragDrop)
        self.target.setObjectName("target")
        self.target.setDropIndicatorShown(True)
        self.target.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.target.setHeaderHidden(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.target.sizePolicy().hasHeightForWidth())
        self.target.setSizePolicy(sizePolicy)
        self.target.setAutoFillBackground(True)
        self.verticalLayout_2.addWidget(self.target)

        self.browser = QgsBrowserModel()
        self.source.setModel(self.browser)
        self.source.setHeaderHidden(True)
        self.source.setDragEnabled(True)
        self.source.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.menumodel = MenuTreeModel(self)
        self.target.setModel(self.menumodel)
        self.target.setAnimated(True)

        # add a dock widget
        self.dock_widget = QDockWidget("Menus", self.uiparent.iface.mainWindow())
        self.dock_widget.resize(400, 300)
        self.dock_widget.setFloating(True)
        self.dock_widget.setObjectName(self.tr("Menu Tree"))
        self.dock_widget_content = QWidget()
        self.dock_widget.setWidget(self.dock_widget_content)
        dock_layout = QVBoxLayout()
        self.dock_widget_content.setLayout(dock_layout)
        self.dock_view = DockQtTreeView(self.dock_widget_content)
        self.dock_view.setDragDropMode(QAbstractItemView.DragOnly)
        self.dock_menu_filter = QLineEdit()
        self.dock_menu_filter.setPlaceholderText(self.tr("Filter by table description (postgis only)"))
        dock_layout.addWidget(self.dock_menu_filter)
        dock_layout.addWidget(self.dock_view)
        self.dock_view.setHeaderHidden(True)
        self.dock_view.setDragEnabled(True)
        self.dock_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.dock_view.setAnimated(True)
        self.dock_view.setObjectName("treeView")
        self.proxy_model = LeafFilterProxyModel(self)
        self.proxy_model.setFilterRole(Qt.ToolTipRole)
        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.profile_list = []
        self.table = 'qgis_menubuilder_metadata'

        self.layer_handler = {
            'vector': self.load_vector,
            'raster': self.load_raster
        }

        # connect signals and handlers
        self.combo_database.activated.connect(partial(self.set_connection, dbname=None))
        self.combo_schema.activated.connect(self.update_profile_list)
        self.combo_profile.activated.connect(partial(self.update_model_idx, self.menumodel))
        self.button_add_menu.released.connect(self.add_menu)
        self.button_delete_profile.released.connect(self.delete_profile)
        self.dock_menu_filter.textEdited.connect(self.filter_update)
        self.dock_view.doubleClicked.connect(self.load_from_index)

    def filter_update(self):
        text = self.dock_menu_filter.displayText()
        self.proxy_model.setFilterRegExp(text)

    def show_dock(self, state, profile=None, schema=None):
        if not state:
            # just hide widget
            self.dock_widget.setVisible(state)
            return
        # dock must be read only and deepcopy of model is not supported (c++ inside!)
        self.dock_model = MenuTreeModel(self)
        if profile:
            # bypass combobox
            self.update_model(self.dock_model, schema, profile)
        else:
            self.update_model_idx(self.dock_model, self.combo_profile.currentIndex())
        self.dock_model.setHorizontalHeaderLabels(["Menus"])
        self.dock_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.proxy_model.setSourceModel(self.dock_model)
        self.dock_view.setModel(self.proxy_model)
        self.dock_widget.setVisible(state)

    def show_menus(self, state, profile=None, schema=None):
        if state:
            self.load_menus(profile=profile, schema=schema)
            return
        # remove menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(menu.menuAction())

    def add_menu(self):
        """
        Add a menu inside qtreeview
        """
        item = QStandardItem('NewMenu')
        item.setIcon(QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
        # select current index selected and insert as a sibling
        brother = self.target.selectedIndexes()

        if not brother or not brother[0].parent():
            # no selection, add menu at the top level
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return

        parent = self.menumodel.itemFromIndex(brother[0].parent())
        if not parent:
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return
        parent.appendRow(item)

    def update_database_list(self):
        """update list of defined postgres connections"""
        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections")
        keys = settings.childGroups()
        self.combo_database.clear()
        self.combo_schema.clear()
        self.menumodel.clear()
        self.combo_database.addItems(keys)
        self.combo_database.setCurrentIndex(-1)
        settings.endGroup()
        # clear profile list
        self.combo_profile.clear()
        self.combo_profile.setCurrentIndex(-1)

    def set_connection(self, databaseidx, dbname=None):
        """
        Connect to selected postgresql database
        """
        selected = self.combo_database.itemText(databaseidx) or dbname
        if not selected:
            return

        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections/{}".format(selected))

        if not settings.contains("database"):
            # no entry?
            QMessageBox.critical(self, "Error", "There is no defined database connection")
            return

        uri = QgsDataSourceURI()

        settingsList = ["service", "host", "port", "database", "username", "password"]
        service, host, port, database, username, password = map(
            lambda x: settings.value(x, "", type=str), settingsList)

        useEstimatedMetadata = settings.value("estimatedMetadata", False, type=bool)
        sslmode = settings.value("sslmode", QgsDataSourceURI.SSLprefer, type=int)

        settings.endGroup()

        if service:
            uri.setConnection(service, database, username, password, sslmode)
        else:
            uri.setConnection(host, port, database, username, password, sslmode)

        uri.setUseEstimatedMetadata(useEstimatedMetadata)

        # connect to db
        self.connect_to_uri(uri)
        # update schema list
        self.update_schema_list()

    @contextmanager
    def transaction(self):
        try:
            yield
            self.connection.commit()
        except self.pg_error_types() as e:
            self.connection.rollback()
            raise e

    def check_connected(func):
        """
        Decorator that checks if a database connection is active before executing function
        """
        @wraps(func)
        def wrapped(inst, *args, **kwargs):
            if not getattr(inst, 'connection', False):
                QMessageBox(
                    QMessageBox.Warning,
                    "Menu Builder",
                    inst.tr("Not connected to any database, please select one"),
                    QMessageBox.Ok,
                    inst
                ).exec_()
                return
            if inst.connection.closed:
                QMessageBox(
                    QMessageBox.Warning,
                    "Menu Builder",
                    inst.tr("Not connected to any database, please select one"),
                    QMessageBox.Ok,
                    inst
                ).exec_()
                return
            return func(inst, *args, **kwargs)
        return wrapped

    def connect_to_uri(self, uri):
        self.close_connection()
        self.host = uri.host() or os.environ.get('PGHOST')
        self.port = uri.port() or os.environ.get('PGPORT')

        username = uri.username() or os.environ.get('PGUSER') or os.environ.get('USER')
        password = uri.password() or os.environ.get('PGPASSWORD')

        try:
            self.connection = psycopg2.connect(uri.connectionInfo())
        except self.pg_error_types() as e:
            err = str(e)
            conninfo = uri.connectionInfo()

            ok, username, password = QgsCredentials.instance().get(
                conninfo, username, password, err)
            if not ok:
                raise Exception(e)

            if username:
                uri.setUsername(username)

            if password:
                uri.setPassword(password)

            self.connection = psycopg2.connect(uri.connectionInfo())

        self.pgencoding = self.connection.encoding

        return True

    def pg_error_types(self):
        return psycopg2.InterfaceError,\
               psycopg2.OperationalError,\
               psycopg2.ProgrammingError

    @check_connected
    def update_schema_list(self):
        self.combo_schema.clear()
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select nspname
                from pg_namespace
                where nspname not ilike 'pg_%'
                and nspname not in ('pg_catalog', 'information_schema')
                """)
            schemas = [row[0] for row in cur.fetchall()]
            self.combo_schema.addItems(schemas)

    @check_connected
    def update_profile_list(self, schemaidx):
        """
        update profile list from database
        """
        schema = self.combo_schema.itemText(schemaidx)
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select 1
                from pg_tables
                    where schemaname = '{0}'
                    and tablename = '{1}'
                union
                select 1
                from pg_matviews
                    where schemaname = '{0}'
                    and matviewname = '{1}'
                """.format(schema, self.table))
            tables = cur.fetchone()
            if not tables:
                box = QMessageBox(
                    QMessageBox.Warning,
                    "Menu Builder",
                    self.tr("Table '{}.{}' not found in this database, "
                            "would you like to create it now ?")
                    .format(schema, self.table),
                    QMessageBox.Cancel | QMessageBox.Yes,
                    self
                )
                ret = box.exec_()
                if ret == QMessageBox.Cancel:
                    return False
                elif ret == QMessageBox.Yes:
                    cur.execute("""
                        create table {}.{} (
                            id serial,
                            name varchar,
                            profile varchar,
                            model_index varchar,
                            datasource_uri text
                        )
                        """.format(schema, self.table))
                    self.connection.commit()
                    return False

            cur.execute("""
                select distinct(profile) from {}.{}
                """.format(schema, self.table))
            profiles = [row[0] for row in cur.fetchall()]
            saved_profile = self.combo_profile.currentText()
            self.combo_profile.clear()
            self.combo_profile.addItems(profiles)
            self.combo_profile.setCurrentIndex(self.combo_profile.findText(saved_profile))

    @check_connected
    def delete_profile(self):
        """
        Delete profile currently selected
        """
        idx = self.combo_profile.currentIndex()
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.itemText(idx)
        box = QMessageBox(
            QMessageBox.Warning,
            "Menu Builder",
            self.tr("Delete '{}' profile ?").format(profile),
            QMessageBox.Cancel | QMessageBox.Yes,
            self
        )
        ret = box.exec_()
        if ret == QMessageBox.Cancel:
            return False
        elif ret == QMessageBox.Yes:
            self.combo_profile.removeItem(idx)
            with self.transaction():
                cur = self.connection.cursor()
                cur.execute("""
                    delete from {}.{}
                    where profile = '{}'
                    """.format(schema, self.table, profile))
        self.menumodel.clear()
        self.combo_profile.setCurrentIndex(-1)

    def update_model_idx(self, model, profile_index):
        """
        wrapper that checks combobox
        """
        profile = self.combo_profile.itemText(profile_index)
        schema = self.combo_schema.currentText()
        self.update_model(model, schema, profile)

    def sortby_modelindex(self, rows):
        return sorted(
            rows,
            key=lambda line: '/'.join(
                ['{:04}'.format(elem[0]) for elem in json.loads(line[2])]
            ))

    @check_connected
    def update_model(self, model, schema, profile):
        """
        Update the model by retrieving the profile given in database
        """
        menudict = {}

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
            model.clear()
            for name, profile, model_index, datasource_uri in self.sortby_modelindex(rows):
                menu = model.invisibleRootItem()
                indexes = json.loads(model_index)
                parent = ''
                for idx, subname in indexes[:-1]:
                    parent += '{}-{}/'.format(idx, subname)
                    if parent in menudict:
                        # already created entry
                        menu = menudict[parent]
                        continue
                    # create menu
                    item = QStandardItem(subname)
                    uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                    item.setData(uri_struct)
                    item.setIcon(QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
                    item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable |
                                  Qt.ItemIsEnabled | Qt.ItemIsDropEnabled |
                                  Qt.ItemIsEditable)
                    item.setWhatsThis("menu")
                    menu.appendRow(item)
                    menudict[parent] = item
                    # set current menu to the new created item
                    menu = item

                # add leaf (layer item)
                item = QStandardItem(name)
                uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                # fix layer name instead of table name
                # usefull when the layer has been renamed in menu
                uri_struct.name = name
                if uri_struct.providerKey in ICON_MAPPER:
                    item.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))
                item.setData(uri_struct)
                # avoid placing dragged layers on it
                item.setDropEnabled(False)
                if uri_struct.providerKey == 'postgres':
                    # set tooltip to postgres comment
                    comment = self.get_table_comment(uri_struct.uri)
                    item.setToolTip(comment)
                menudict[parent].appendRow(item)

    @check_connected
    def save_changes(self):
        """
        Save changes in the postgres table
        """
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.currentText()
        if not profile:
            QMessageBox(
                QMessageBox.Warning,
                "Menu Builder",
                self.tr("Profile cannot be empty"),
                QMessageBox.Ok,
                self
            ).exec_()
            return False

        try:
            with self.transaction():
                cur = self.connection.cursor()
                cur.execute("delete from {}.{} where profile = '{}'".format(
                    schema, self.table, profile))
                for item, data in self.target.iteritems():
                    if not data:
                        continue
                    cur.execute("""
                    insert into {}.{} (name,profile,model_index,datasource_uri)
                    values (%s, %s, %s, %s)
                    """.format(schema, self.table), (
                        item[-1][1],
                        profile,
                        json.dumps(item),
                        data.data())
                    )
        except psycopg2.ProgrammingError as exc:
            QMessageBox(
                QMessageBox.Warning,
                "Menu Builder",
                exc.message.decode(self.pgencoding),
                QMessageBox.Ok,
                self
            ).exec_()

        self.save_session(
            self.combo_database.currentText(),
            schema,
            profile,
            self.activate_dock.isChecked(),
            self.activate_menubar.isChecked()
        )
        self.update_profile_list(self.combo_schema.currentIndex())
        self.show_dock(self.activate_dock.isChecked())
        self.show_menus(self.activate_menubar.isChecked())
        return True

    @check_connected
    def load_menus(self, profile=None, schema=None):
        """
        Load menus in the main windows qgis bar
        """
        if not schema:
            schema = self.combo_schema.currentText()
        if not profile:
            profile = self.combo_profile.currentText()
        # remove previous menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(menu.menuAction())

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
        # item accessor ex: '0-menu/0-submenu/1-item/'
        menudict = {}
        # reference to parent item
        parent = ''
        # reference to qgis main menu bar
        menubar = self.uiparent.iface.mainWindow().menuBar()

        for name, profile, model_index, datasource_uri in self.sortby_modelindex(rows):
            uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
            indexes = json.loads(model_index)
            # root menu
            parent = '{}-{}/'.format(indexes[0][0], indexes[0][1])
            if parent not in menudict:
                menu = QMenu(self.uiparent.iface.mainWindow())
                self.uiparent.menus.append(menu)
                menu.setObjectName(indexes[0][1])
                menu.setTitle(indexes[0][1])
                menubar.insertMenu(
                    self.uiparent.iface.firstRightStandardMenu().menuAction(),
                    menu)
                menudict[parent] = menu
            else:
                # menu already there
                menu = menudict[parent]

            for idx, subname in indexes[1:-1]:
                # intermediate submenus
                parent += '{}-{}/'.format(idx, subname)
                if parent not in menudict:
                    submenu = menu.addMenu(subname)
                    submenu.setObjectName(subname)
                    submenu.setTitle(subname)
                    menu = submenu
                    # store it for later use
                    menudict[parent] = menu
                    continue
                # already treated
                menu = menudict[parent]

            # last item = layer
            layer = QAction(name, self.uiparent.iface.mainWindow())

            if uri_struct.providerKey in ICON_MAPPER:
                layer.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))

            if uri_struct.providerKey == 'postgres':
                # set tooltip to postgres comment
                comment = self.get_table_comment(uri_struct.uri)
                layer.setStatusTip(comment)
                layer.setToolTip(comment)

            layer.setData(uri_struct.uri)
            layer.setWhatsThis(uri_struct.providerKey)
            layer.triggered.connect(self.layer_handler[uri_struct.layerType])
            menu.addAction(layer)

    def get_table_comment(self, uri):
        schema, table = re.match(
            '.*table=(.*)\(.*',
            uri
        ).group(1).strip().replace('"', '').split('.')
        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select description from pg_description
                join pg_class on pg_description.objoid = pg_class.oid
                join pg_namespace on pg_class.relnamespace = pg_namespace.oid
                where relname = '{}' and nspname='{}'
                """.format(table, schema)
            cur.execute(select)
            row = cur.fetchone()
            if row:
                return row[0]
        return ''

    def load_from_index(self, index):
        """Load layers from selected item index"""
        item = self.dock_model.itemFromIndex(self.proxy_model.mapToSource(index))
        if item.whatsThis() == 'menu':
            return
        if item.data().layerType == 'vector':
            layer = QgsVectorLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        elif item.data().layerType == 'raster':
            layer = QgsRasterLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        if not layer:
            return
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_vector(self):
        action = self.sender()
        layer = QgsVectorLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_raster(self):
        action = self.sender()
        layer = QgsRasterLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def accept(self):
        if self.save_changes():
            QDialog.reject(self)
            self.close_connection()

    def reject(self):
        self.close_connection()
        QDialog.reject(self)

    def close_connection(self):
        """close current pg connection if exists"""
        if getattr(self, 'connection', False):
            if self.connection.closed:
                return
            self.connection.close()

    def save_session(self, database, schema, profile, dock, menubar):
        """save current profile for next session"""
        settings = QSettings()
        settings.setValue("MenuBuilder/database", database)
        settings.setValue("MenuBuilder/schema", schema)
        settings.setValue("MenuBuilder/profile", profile)
        settings.setValue("MenuBuilder/dock", dock)
        settings.setValue("MenuBuilder/menubar", menubar)

    def restore_session(self):
        settings = QSettings()
        database = settings.value("MenuBuilder/database", False)
        schema = settings.value("MenuBuilder/schema", 'public')
        profile = settings.value("MenuBuilder/profile", False)
        dock = settings.value("MenuBuilder/dock", False)
        menubar = settings.value("MenuBuilder/menubar", False)
        if not any([database, profile]):
            return

        self.set_connection(0, dbname=database)
        self.show_dock(bool(dock), profile=profile, schema=schema)
        self.show_menus(bool(menubar), profile=profile, schema=schema)
예제 #4
0
class PyranhaBrowser(QMainWindow):

    COMMAND = ['inicio','pesta','detener','recarga','video','musica','deporte']
    QUICK = {}
    width = 0
    height = 0
  
    def __init__(self):
        QMainWindow.__init__(self)
        
        #----------------- Configurando desde el archivo ---------------#
        config = etree.parse('config.xml')
        #-- configurando Browser
        browser_cfg = config.find('browser')
        self.width = int(browser_cfg.findtext('width'))
        self.height = int(browser_cfg.findtext('height'))
        self.resize(self.width, self.height)
        self.setWindowIcon(QIcon(browser_cfg.findtext('windows_icon')))
        self.setWindowTitle(browser_cfg.findtext('windows_tittle'))
        self.default_url=browser_cfg.findtext('home')
        #-- configurando Teclado
        self.keyboard_cfg = config.find('keyboard')
        #----------------------------------------------------------------#

        self.initGui()
        self.voice = Vox()
        self.handDetector = Hand()
        self.loadHome()
        self.jquery = getJquery()
        self.funcionesJs=getFuncionesJs()
        self.resizeEvent = self.onResize
        self.activeKey = False;
        self.sql = PyranhaSqliteHandler()
        self.initQuick()
        
    
    def initQuick(self):

        """ Metodo que toma de la base de datos SQLITE los sitios favoritos. Estos estan clasificados por categorias
        es entonces que cargandose en QUICK el usuario podra utilizar los comandos por VOZ llamando a las categorias
        (deporte, musica, video, noticias, etc)
        """
        self.sql.start()
        listQuick = self.sql.get_quick()
        print(listQuick)
        for l in listQuick:
           self.QUICK.update({str(l[0]):str(l[1])})
        print(self.QUICK)
        self.sql.close_connection()

    def initGui(self):
        print("Pyranha Browser - initGui: Iniciando interfaz")
        self.centralwidget = QWidget(self)
        self.mainLayout = QVBoxLayout(self.centralwidget)
        self.mainLayout.setMargin(0)
        self.mainLayout.setSpacing(0)
        self.createTabBar()
        print("Pyranha Browser - initGui: creando teclado")
        self.keyboard = QKeyboardPyranha(self)
        self.mainLayout.addWidget(self.keyboard)
        self.centerWidget(self.mainLayout, self.keyboard)
        self.setCss()
        self.setCentralWidget(self.centralwidget)

      
    def keyPressEvent(self, event):
        if(event.isAutoRepeat()):
            None
        else:
            if type(event) == QKeyEvent and event.key() == Qt.Key_AltGr: 
                self.keyboard.click()
            else:
                try:
                    QLineEdit.keyPressEvent(self.focusWidget(), event)
                except TypeError:
                    print("Ingresando caracter en widget no compatible")
  
    def hideKeyboard(self):
        self.keyboard.hide()

    def showKeyboard(self):
        self.keyboard.show()

    def onResize(self, event):
        self.centerWidget(self.tabLayout, self.keyboard)

    def loadHome(self):
        self.createTab(self.default_url)
        #self.createTab("https://www.google.com")
        #self.createTab("https://www.facebook.com")
        #self.createTab("http://www.ole.com.ar")
        #self.createTab("http://www.tekoavirtual.chubut.edu.ar")
        #self.createTab("http://www.chubut.edu.ar")

    def createTabBar(self):
        print("Pyranha Browser - createTabBar: Creando barra de pestanias")
        self.tabBarWidget = QTabWidget(self)
        self.tabBarWidget.setMovable(True)
        self.tabBarWidget.setTabsClosable(True)
        self.tabBarWidget.currentChanged.connect(self.tabChanged)
        self.tabBarWidget.tabCloseRequested.connect(self.closeTab)
        self.addtabButton = QToolButton()
        self.addtabButton.setIcon(QIcon('img/addTab.png'))
        self.addtabButton.clicked.connect(lambda: self.createTab(self.default_url))
        self.tabBarWidget.setCornerWidget(self.addtabButton,Qt.TopRightCorner)
        self.mainLayout.addWidget(self.tabBarWidget)

    def createTab(self, url):
        self.tabLayout = QVBoxLayout()
        self.tabLayout.setMargin(0)
        self.tabLayout.setSpacing(0)
        tab = QWidget()
        tab.setLayout(self.tabLayout)

        #-- Creando NavBar
        navBar = QWidget()
        navBar.setMaximumHeight(27)
        backButton = QToolButton()
        backButton.setIcon(QIcon('img/goBack5.png'))
        nextButton = QToolButton()
        nextButton.setIcon(QIcon('img/goNext5.png'))
        stopButton = QToolButton()
        stopButton.setIcon(QIcon('img/stopLoad5.png'))
        buttonGO = QToolButton()
        buttonGO.setIcon(QIcon('img/goGo5.png'))
        self.urlBox = QLineEdit()

        navBarLayout = QHBoxLayout()
        navBarLayout.setMargin(0)
        navBarLayout.setSpacing(0)
        navBarLayout.addWidget(backButton)
        navBarLayout.addWidget(nextButton)
        navBarLayout.addWidget(stopButton)
        navBarLayout.addWidget(self.urlBox)
        navBarLayout.addWidget(buttonGO)
        navBar.setLayout(navBarLayout)


        self.tabLayout.addWidget(navBar)

        #-- Creando la vista Web
        self.web = QWebView()
        self.tabLayout.addWidget(self.web)

        #-- Signals
        self.urlBox.returnPressed.connect(lambda: self.loadURL(self.web, self.urlBox.displayText()))
        buttonGO.clicked.connect(lambda: self.loadURL(self.web, self.urlBox.displayText()))
        backButton.clicked.connect(lambda: self.goBack(self.web, self.urlBox))
        nextButton.clicked.connect(lambda: self.goBack(self.web, self.urlBox))
        #stopButton.clicked.connect(self.stopLoad)
        self.web.loadFinished.connect(lambda:self.loadFinished(self.web,self.urlBox))
        self.web.linkClicked.connect(self.handleLinkClicked)

        #web.urlChanged.connect(self.updateUrlBox)
        #web.connect(web, QtCore.SIGNAL('loadFinished(bool)'), self.loadFinished)
        self.tabBarWidget.setCurrentIndex(self.tabBarWidget.addTab(tab, 'Cargando...'))
        self.web.load(QUrl(str(url)))

        #Set Focus URL Box
        self.urlBox.setFocus()
        self.urlBox.selectAll()

    def centerWidget(self, layout, widget):
        layout.setAlignment(widget, Qt.AlignCenter)

    def closeTab(self, num):
        self.tabBarWidget.removeTab(num)

    def tabChanged(self, num):
        for child in self.tabBarWidget.widget(num).findChildren(QWebView):
            self.setWindowTitle("Pyranha  " + child.title())
        #for child in self.tabBarWidget.widget(num).findChildren(QLineEdit):
            #self.focusURLBox(child)

    def loadFinished(self, web, urlBox):
        print("Load Finished")
        print(web.url().host())
        if web.url().host() != "":
            urlBox.setText(web.url().scheme()+"://" + web.url().host())
        else:
            urlBox.setText("Inicio")
        espacios = ""

        for child in self.tabBarWidget.currentWidget().findChildren(QWebView):
            if len(child.title()) > 20:
                str = child.title()[0:17] + "..."
            elif len(child.title()) <= 20:
                for x in range(1, 21 - len(child.title())):
                    espacios = espacios +" "
                str = child.title()+espacios
            self.setWindowTitle("Pyranha  " + child.title())
            self.tabBarWidget.setTabText(self.tabBarWidget.currentIndex(),str)
        
        #web.page().mainFrame().evaluateJavaScript(self.jquery)
        #web.page().mainFrame().evaluateJavaScript(self.funcionesJs)

        """inputCollection = doc.findAll("input")

        #inputList = inputCollection.toList()
        t = []
        for we in inputList:
            print("---> "+we.toOuterXml())
            #print("ACA: ---> "+t.toOuterXml())
        for we in inputList:
            if we.toOuterXml().contains("submit", 1):
                print("Sacando Boton")
            if we.toOuterXml().contains("hidden", 1):
                print("Sacando Input Oculto")
            if we.toOuterXml().contains("radio", 1):
                print("Sacando Radio")
            if we.toOuterXml().contains("checkbox", 1):
                print("Sacando Checkbox")
            else:
                t.append(we)
        for h in t:
            print("Ejecutando JS A: "+h.toOuterXml())

            if h.hasFocus():
                print("FOCO---> "+h.toOuterXml())"""


    def commandHandler(self,opc,extra):
        

        if opc == 1:
            if extra == '':
                self.createTab(self.default_url)
            else:
                self.createTab(extra)
        elif opc == 2:
            self.loadHome()
        elif opc == 3:
            self.web.stop()
        elif opc == 4:
            self.web.reload()
        elif opc == 5:
            print(self.QUICK.get('Video'))
            self.createTab(self.QUICK.get('Video'))
        elif opc == 6:
            self.createTab(self.QUICK.get('Music'))
        elif opc == 7:
            self.createTab(self.QUICK.get('Sport'))
        elif opc == 8:
            self.createTab(self.QUICK.get('News'))
        else:
            print "No hay comando reconocido"

    #----- NavBar Function -----#
    def handleLinkClicked(self, url):
        print(url.toString())


    def loadURL(self, web, text):
        print("loadURL")
        
        text = str(text)

        print("Cargando: " + text)
        if not text.startswith("http://") and not text.startswith("https://") and not text.startswith("~") and not os.path.isdir(text) and not text.startswith("file://") and not text.startswith("javascript:") and not text.startswith("about:"):
            text = "http://" + text
            web.load(QUrl(str(text)))
        else:
            web.load(QUrl(str(text)))
        
        self.updateUrlBox();


    def goBack(self, web, urlBox):
        web.back()
        #focusURLBox(urlbox)

    def goNext(self, web, urlBox):
        web.forward()
        url = self.web.url()
        url = url.toString()
        url = str(url)
        urlBox.setText(url)
        self.focusURLBox(urlBox)

    def zoomOut(self):
        self.web.setZoomFactor(self.web.zoomFactor()+.2)
    
    def zoomIn(self):
        self.web.setZoomFactor(self.web.zoomFactor()-.2)

    def stopLoad(self):
        self.web.stop()

    def updateUrlBox(self):
        url = self.web.url()
        url = url.toString()
        url = str(url)
        self.urlBox.setText(url)


    #---- set Style Css ----- #
    def setCss(self):
        #-- Fondo:             #46483E
        #-- Fondo Oscuro:      #33342D
        #-- Objetos Verdes:    #8CC84B
        #-- Objetos Naranjas:  #ed6400
        #-- Gradient Effect:   background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0 #646464, stop: 1 #5d5d5d);

        css = """

        QToolTip
        {
             border: 1px solid black;
             /*background-color: #ffa02f;*/
             padding: 1px;
             border-radius: 3px;
             opacity: 100;
        }

        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);*/
        }

        QWidget:disabled
        {
            color: #404040;
            background-color: #323232;
        }

        QAbstractItemView
        {
            background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0.1 #646464, stop: 1 #5d5d5d);
        }

        QWidget:focus
        {
            /*border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);*/
        }

        QLineEdit
        {
            background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0 #646464, stop: 1 #5d5d5d);
            padding: 1px;
            border-style: solid;
            border: 1px solid #1e1e1e;
            color: #8CC84B;
            selection-background-color: #8CC84B;
            border-radius: 5;
        }

        QToolButton
        {
            background: transparent;
        }


        QTextEdit:focus
        {
            border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
        }


        QTextEdit
        {
            background-color: #242424;
        }

        QPlainTextEdit
        {
            background-color: #242424;
        }

        QMainWindow {
            background-color: #323232;

        }
        QMainWindow::separator
        {
            /*background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);*/

            color: white;
            padding-left: 4px;
            border: 1px solid #4c4c4c;
            spacing: 3px; /* spacing between items in the tool bar */
        }

        QMainWindow::separator:hover
        {

            /*background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #d7801a, stop:0.5 #b56c17 stop:1 #ffa02f);*/
            
            color: white;
            padding-left: 4px;
            border: 1px solid #6c6c6c;
            spacing: 3px; /* spacing between items in the tool bar */
        }

        QTabBar::tab {
            background: transparent;
            color: #b1b1b1;
            border: 1px solid #444;
            border-bottom-style: none;
            background-color: #323232;
            padding-left: 10px;
            padding-right: 10px;
            padding-top: 3px;
            padding-bottom: 2px;
            margin-right: -1px;
        }

        QTabWidget::pane {
            border: 1px solid #444;
            top: 1px;
        }

        QTabBar::tab:last
        {
            margin-right: 0; /* the last selected tab has nothing to overlap with on the right */
            border-top-right-radius: 3px;
        }

        QTabBar::tab:first:!selected
        {
            margin-left: 0px; /* the last selected tab has nothing to overlap with on the right */
            border-top-left-radius: 3px;
        }

        QTabBar::tab:!selected
        {
            color: #b1b1b1;
            border-bottom-style: solid;
            margin-top: 3px;
            background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
        }

        QTabBar::tab:selected
        {
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
            margin-bottom: 0px;
        }

        QTabBar::tab:!selected:hover
        {
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
            background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #424242, stop:0.2 #636363, stop:0.1 #848484);
        }


        """

        self.setAutoFillBackground(True)
        self.setStyleSheet(css)
예제 #5
0
class ComboBoxBasic(QtGui.QWidget):
    """
    An basic example combo box application
    """

    def __init__(self):
        super(ComboBoxBasic,self).__init__()
        self.obj = Statistic()
        self.text = ''
        # create GUI
        #QtGui.QMainWindow.__init__(self)
        #self.setWindowTitle('VIEW STATISTIC')
        # Set the window dimensions
        #self.resize(250,290)]
        self.setFixedSize(250,290)

        
        # vertical layout for widgets
        self.vbox = QtGui.QGridLayout()
        self.setLayout(self.vbox)

        # Create a combo box and add it to our layout
        self.label = QtGui.QLabel("service",self)
        self.vbox.addWidget(self.label,1,1)
        self.combo = QtGui.QComboBox()
        self.vbox.addWidget(self.combo,1,0)
        self.combo2 = QtGui.QComboBox()
        self.vbox.addWidget(self.combo2,2,0)
        self.label2 = QtGui.QLabel("metric",self)
        self.vbox.addWidget(self.label2,2,1)


        self.combo3 = QtGui.QComboBox()
        self.vbox.addWidget(self.combo3,3,0)
        self.label3 = QtGui.QLabel("time",self)
        self.vbox.addWidget(self.label3,3,1)


        self.combo4 = QtGui.QComboBox(self)
        self.vbox.addWidget(self.combo4,4,1)

       

     

        # Or add a sequence in one call
        distrolist = ['BROADBAND','IPTV', 'VOIP']
        self.combo.addItems(distrolist)
        #self.t = self.combo.currentText()
        self.connect(self.combo, QtCore.SIGNAL('activated(QString)'), self.hello)
  
        con = cx_Oracle.connect('orcdb/[email protected]/orcl')
        self.cur = con.cursor()
        self.cur.execute("select METRIC_TYPE from METRICS WHERE IDSERVICE='BROADBAND'")
        data = self.cur.fetchall()
        for el in data:
            self.combo2.addItems(el)

        self.connect(self.combo, QtCore.SIGNAL('activated(QString)'), self.hello)
        
        distrolist3 = ['15 min','30 min', '60 min','1 day']
        self.combo3.addItems(distrolist3)

        distrolist4 = ['MAX','AVG', 'MIN']
        self.combo4.addItems(distrolist4)
        
        self.combo4.move(130,49)

        quit = QtGui.QPushButton('VIEW STATISTIC', self)
        quit.setGeometry(90, 250, 140, 35)
        self.vbox.addWidget(quit,5,0)
        
        self.le = QLineEdit(self)
        #self.le.setGeometry(1,200,75,35)
        self.vbox.addWidget(self.le,4,0)
        
        i=str(self.combo4.currentText())+"("+str(self.combo2.currentText())+")"
        self.le.setText(str(i))
      
        self.connect(self.combo2, QtCore.SIGNAL('activated(QString)'),self.edit)

        self.connect(self.combo4, QtCore.SIGNAL('activated(QString)'),self.edit)
        
        self.connect(quit, QtCore.SIGNAL('clicked()'),self.combo_chosen)

    def combo_chosen(self):
        self.obj.select_dev(str(self.combo.currentText()),str(self.combo2.currentText()),str(self.combo3.currentText()),str(self.combo4.currentText()),str(self.le.displayText()))

    def edit(self):
        i=str(self.combo4.currentText())+"("+str(self.combo2.currentText())+")"

        self.le.setText(str(i))
            
    def hello(self):
        self.t = self.combo.currentText()
        self.combo2.clear()
        if self.t == "IPTV":
            self.cur.execute("select METRIC_TYPE from METRICS WHERE IDSERVICE='IPTV'")
            data = self.cur.fetchall()
            for el in data:
                self.combo2.addItems(el)
        elif self.t == "VOIP":
            self.cur.execute("select METRIC_TYPE from METRICS WHERE IDSERVICE='VOIP'")
            data = self.cur.fetchall()
            for el in data:
               self.combo2.addItems(el)
        elif self.t == "BROADBAND":
            self.cur.execute("select METRIC_TYPE from METRICS WHERE IDSERVICE='BROADBAND'")
            data = self.cur.fetchall()
            for el in data:
               self.combo2.addItems(el)