问:
@font-face not working locally but works when linked externally
So, I have a .ttf font (plus others) that I'm using for a website, with the code formatted as follows:

@font-face {
    font-family: DEP;
    src: local("fonts/DEP/DEP.ttf") format("truetype");
    src: local("fonts/DEP/DEP.woff") format("woff");
    src: local("fonts/DEP/DEP.otf") format("opentype");
    src: url(https://codehs.com/uploads/98892640bda8f3fe5654e3c6d20d5c8c) format("truetype");
}```

I know it's good to have a fallback link in case the local files fail to load, but I noticed when I was editing the code offline that the local files weren't working. I triple-checked the folder structure, tested the code (minus the external link) on the main site to see if it was just my html previewer, etc etc. I don't understand why it won't link properly.

My code is also on github if you want to investigate this further. Thanks!

答: local() accepts locally installed fonts' system identifier, not path to file, see: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face#specifying_local_font_alternatives

Body:
So, I have a .ttf font (plus others) that I'm using for a website, with the code formatted as follows:

@font-face {
    font-family: DEP;
    src: local("fonts/DEP/DEP.ttf") format("truetype");
    src: local("fonts/DEP/DEP.woff") format("woff");
    src: local("fonts/DEP/DEP.otf") format("opentype");
    src: url(https://codehs.com/uploads/98892640bda8f3fe5654e3c6d20d5c8c) format("truetype");
}

I know it's good to have a fallback link in case the local files fail to load, but I noticed when I was editing the code offline that the local files weren't working. I triple-checked the folder structure, tested the code (minus the external link) on the main site to see if it was just my html previewer, etc etc. I don't understand why it won't link properly.

My code is also on github if you want to investigate this further. Thanks!


来源: stackexchange

问:
Create a systemd service script for multiple module app
I'm currently writing a python app forking with Pyro4 and flask.
In order to start up the app I to need :

Start pyro4 name server

Register my object in the pyro4 name server

Start a flask web app to access pyro4 objects

I would like to do this with a systemd service file.
I first though of using ExecStarPre and ExecStarPost for running pyro4 nameserver and flask web app ; but it seems that those fields are not use for long-running commands...

Do I need to make 3 systemd services which I start in a bash script that i call from a 4th systemd service ?

Thx for helping me

I'm trying to write a systemd service file

答:
You don't need four systemd services; three should do.

pyro-nameserver.service: The Pyro nameserver

mysvc-objects.service: The server for your custom Pyro objects. Use Requires=pyro-nameserver.service and After=pyro-nameserver.service

mysvc.service: The actual Flask webapp. Uses Requires=mysvc-objects.service and After=mysvc-objects.service to ensure that it only tries to start when the nameserver is already up and your objects are registered.

You should never, under any circumstances enable or disable a systemd service from an ExecStartPre or an ExecStartPost.

BTW, one thing that's a little tricky is controlling when systemd considers something to be "up" for purposes of starting the next service in the chain only after that service is done with initialization and ready to use. In a perfect would you build services with Type=notify that use sd_notify("READY=1") to tell systemd when they finished initialization; but if you haven't built that, it's an option to build an ExecStartPost script that waits until the service it's associated with is actually running before it exits.

ContentLicense: CC BY-SA 4.0


问:
MongoDB aggregation multiple partial matches
I am in the process of moving pagination / filtering away from the client and onto the server.

Data is presented in a table, each column header has a text input where you can type and filter the dataset by what is typed in. This uses a simple indexOf check on the inputted text and the dataset to allow partial matches.

Example table column

```<code>{ name: "test 1" }, { name: "test 2" }
</code>```

The image / data above shows a column in the table. If I were to type in "tes" both results would appear.

```<code>let filteredResults = data.filter(row => row.name.toLowerCase().indexOf(filterValue) > -1)
</code>```

I have now moved this filtering onto the server but I am struggling to work out how to do a similar partial match when querying my data.

This is my query:

```<code>aggregate([
            {
                $facet: {
                    results: [
                        {
                            $match: {
                                "name": req.body.name
                            }
                        },
                        {
                            $skip: pageOptions?.pageNo ? (pageOptions.pageNo - 1) * 10 : 0
                        },
                        {
                            $limit: 10
                        }
                    ],
                    totalCount: [
                        {
                            $match: {
                                "name": req.body.name
                            }
                        },
                        { $count: 'totalCount' }
                    ]
                }
            },
            {
                $addFields:
                {
                    "total": { $arrayElemAt: ["$totalCount.totalCount", 0] }
                }
            },
            {
                $project: {
                    "totalCount": 0
                }
            }
        ]
</code>```

Each of the fields in the $match stage are possible columns from the table, in this example just the name field. You could filter by more then 1. The above works with exact matches so if we were to search the name column with "test 1" then that record would be returned but if we search for "tes" nothing would be returned.

Any help with this would be great!

答:
You can use a $regex match to perform your case-insensitive, partial string match.

db.collection.aggregate([
  {
    $match: {
      "name": {
        // put your query in $regex option
        $regex: "tes",
        $options: "i"
      }
    }
  },
  {
    $facet: {
      results: [
        {
          $skip: 0
        },
        {
          $limit: 10
        }
      ],
      totalCount: [
        {
          $count: "totalCount"
        }
      ]
    }
  },
  {
    $addFields: {
      "total": {
        $arrayElemAt: [
          "$totalCount.totalCount",
          0
        ]
      }
    }
  },
  {
    $project: {
      "totalCount": 0
    }
  }
])
```

Here is the Mongo playground for your reference.

Body:
I am in the process of moving pagination / filtering away from the client and onto the server.

Data is presented in a table, each column header has a text input where you can type and filter the dataset by what is typed in. This uses a simple indexOf check on the inputted text and the dataset to allow partial matches.

Example table column

{ name: "test 1" }, { name: "test 2" }

The image / data above shows a column in the table. If I were to type in "tes" both results would appear.

let filteredResults = data.filter(row => row.name.toLowerCase().indexOf(filterValue) > -1)

I have now moved this filtering onto the server but I am struggling to work out how to do a similar partial match when querying my data.

This is my query:

aggregate([
            {
                $facet: {
                    results: [
                        {
                            $match: {
                                "name": req.body.name
                            }
                        },
                        {
                            $skip: pageOptions?.pageNo ? (pageOptions.pageNo - 1) * 10 : 0
                        },
                        {
                            $limit: 10
                        }
                    ],
                    totalCount: [
                        {
                            $match: {
                                "name": req.body.name
                            }
                        },
                        { $count: 'totalCount' }
                    ]
                }
            },
            {
                $addFields:
                {
                    "total": { $arrayElemAt: ["$totalCount.totalCount", 0] }
                }
            },
            {
                $project: {
                    "totalCount": 0
                }
            }
        ]

Each of the fields in the $match stage are possible columns from the table, in this example just the name field. You could filter by more then 1. The above works with exact matches so if we were to search the name column with "test 1" then that record would be returned but if we search for "tes" nothing would be returned.

Any help with this would be great!

Body:
You can use a $regex match to perform your case-insensitive, partial string match.

db.collection.aggregate([
  {
    $match: {
      "name": {
        // put your query in $regex option
        $regex: "tes",
        $options: "i"
      }
    }
  },
  {
    $facet: {
      results: [
        {
          $skip: 0
        },
        {
          $limit: 10
        }
      ],
      totalCount: [
        {
          $count: "totalCount"
        }
      ]
    }
  },
  {
    $addFields: {
      "total": {
        $arrayElemAt: [
          "$totalCount.totalCount",
          0
        ]
      }
    }
  },
  {
    $project: {
      "totalCount": 0
    }
  }
])

Here is the Mongo playground for your reference.


问:
How do you draw lines between columns (or rows) with PyQt5?
I've been trying to learn PyQt5 to reimplement an application I did with Tkinter, but with some design differences. Since it's not a complex application, I'd like to make it have a style similar to this small window from GitHub desktop (options on the left side of the window, and the rest in the remaining space):

I know my colors don't look great now, but I can take care of that later. However, I haven't found out how to draw lines/boxes similar to those, or at lesat in the divisions between my columns/rows.

Here's what I have so far:

import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QWidget, QFileDialog, QGridLayout, QFrame
from PyQt5 import QtGui, QtCore

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Some Window Title')
        self.app = QApplication(sys.argv)
        self.screen = self.app.primaryScreen()
        self.screen_size = self.screen.size()
        self.screen_width = self.screen_size.width()
        self.screen_height = self.screen_size.height()

        self.setGeometry(
            self.screen_width * 0.1,
            self.screen_height * 0.1,
            self.screen_width * 0.8,
            self.screen_height * 0.8
        )
        self.setStyleSheet('background: #020a19;')

        self.grid = QGridLayout()
        self.grid.setVerticalSpacing(0)
        self.grid.setContentsMargins(0, 0, 0, 0)

        self.option_button_stylesheet =  '''
            QPushButton {
                background: #020a19;
                color: #c5cad4;
                border-color: #c5cad4;
                border: 0px 0px 0px 0px;
                border-style: outset;
                border-radius: 5px;
                font-size: 15px;
                font-weight: bold;
                padding: 10px;
                margin: 15px;
                width: 2px;

            }

            QPushButton:hover {
                background-color: #00384d;
            }
            '''

        self.placeholder_button_stylesheet = '''
            QPushButton {
                background: #020a19;
                color: #c5cad4;
                border-top: none;
                border-right: 1px;
                border-left:none;
                border-bottom: none;
                border-color: #c5cad4;
                border-style: outset;
                padding: 10px;
                margin: 0px;
                width: 2px;
                height: 100%;

            }

            QPushButton:hover {
                background-color: #020a19;
            }
            '''

        self.header_label = QLabel('Some Application')
        self.option_1_button = QPushButton('Option 1')
        self.option_2_button = QPushButton('Option 2')
        self.option_3_button = QPushButton('Option 3')

        self.header_label.setStyleSheet(
            '''
            font-size: 25px;
            color: #c5cad4;
            padding-left: 10px;
            padding-top: 16px;
            padding-bottom: 20px;
            height: 10%;
            border-bottom: 1px solid #c5cad4;
            '''
        )
        self.header_label.setFixedHeight(120)
        self.grid.addWidget(self.header_label, 0, 0, 1, 2)

        self.option_1_button.setStyleSheet(self.option_button_stylesheet)
        self.option_1_button.setFixedWidth(200)
        self.option_1_button.setFixedHeight(100)
        self.grid.addWidget(self.option_1_button, 1, 0)

        self.option_2_button.setStyleSheet(self.option_button_stylesheet)
        self.option_2_button.setFixedWidth(200)
        self.option_2_button.setFixedHeight(100)
        self.grid.addWidget(self.option_2_button, 2, 0)

        self.option_3_button.setStyleSheet(self.option_button_stylesheet)
        self.option_3_button.setFixedWidth(200)
        self.option_3_button.setFixedHeight(100)
        self.grid.addWidget(self.option_3_button, 3, 0)

        self.grid.setRowStretch(4, 1)

        self.initUI()

        self.setLayout(self.grid)
        self.show()

    def initUI(self):

        self.greet_text = QLabel('Welcome')
        self.greet_text.setAlignment(QtCore.Qt.AlignCenter)
        self.greet_text.setStyleSheet(
            """
            font-size: 35px;
            color: #c5cad4;
            """
        )
        self.grid.addWidget(self.greet_text, 1, 1, 5, 1)

def run():
    window = Window()
    sys.exit(window.app.exec())

run()
```

As you can see, I'm using QWidget as my window element. I know I could use QMainWindow, but that changes the way widgets are placed and I'm finding it easier to use QWidget. I also don't need a toolbar or anything like that for this app.

How can I draw those lines?

答:
Qt style sheets (QSS) don't provide such a feature, as it's only possible to style specific widgets without being able to consider their position within the layout. This is important in your case, as what you want to do is draw the "separation" between layout items.

It is theoretically possible to achieve this by setting a background for the container widget that will be the line color, have all its child widgets drawing their full contents with opaque colors, and ensure that the layout always has a spacing equal to the width of the line, but if the inner widgets don't respect their full size, they use an alpha channel, or some stretch or further spacing is added, the result would be ugly.

One possibility is to use a QWidget subclass, override its paintEvent() and draw those lines with QPainter.

The idea is that we cycle through all layout items, and draw lines that are placed in the middle between the "current" item and the previous.

In the following example I've created a basic QWidget subclass that implements the above concept, depending on the layout used.

Note that I had to make some changes and corrections to your original code:

as already noted in comments, an existing QApplication is mandatory to allow the creation of a QWidget, and while it's possible to make it an attribute of the object (before calling the super().__init__()), it is still conceptually wrong;

highly hierarchical structures in grid layouts should not use individual rows and columns for their direct child objects, but proper sub-layouts or child widgets should be added instead; in your case, the should be only two rows and columns: the header will have a 2-column-span in the first row, the menu will be on the second row (index 1) and first column, the right side in the second column, and the menu buttons will have their own layout;

setting generic style sheet properties for parent widgets is highly discouraged, as complex widgets (such as QComboBox, QScrollBar and scroll areas children) require that all properties are set to properly work; using setStyleSheet('background: ...') should always be avoided for parents or the application;

style sheets that are shared among many widgets should be set on the parent or the application, and proper selectors should always be used;

the QSS width property should be used with care, as it could make widgets partially invisible and unusable;

if you don't want any border, just use border: none;;

only absolute units are supported for style sheet sizes (see the Length property type), percent values are ignored;

setting fixed heights, paddings and margins can result in unexpected behavior; ensure that you carefully read the box model and do some testing to understand its behavior;

classes should not show themselves automatically during construction, so show() should not be called within the __init__() (this is not specifically "forbidden" or discouraged, but it's still good practice);

an if __name__ == '__main__': block should always be used, especially when dealing with programs or toolkits that rely on event loops (like all UI frameworks, as Qt is);

Here is a rewriting of your original code:

```<code>class LayoutLineWidget(QWidget):
    _borderColor = QColor('#c5cad4')

    def paintEvent(self, event):
        # QWidget subclasses *must* do this to properly use style sheets;
        # (see doc.qt.io/qt-5/stylesheet-reference.html#qwidget-widget)
        opt = QStyleOption()
        opt.initFrom(self)
        qp = QStylePainter(self)
        qp.drawPrimitive(QStyle.PE_Widget, opt)
        # end of default painting

        layout = self.layout()
        if not layout or layout.count() <= 1:
            return
        if layout.spacing() < 1:
            layout.setSpacing(1)
            return

        qp.setPen(self._borderColor)
        if isinstance(layout, QBoxLayout):
            lastGeo = layout.itemAt(0).geometry()
            if isinstance(layout, QVBoxLayout):
                for row in range(1, layout.count()):
                    newGeo = layout.itemAt(row).geometry()
                    y = (lastGeo.bottom()
                         + (newGeo.y() - lastGeo.bottom()) // 2)
                    qp.drawLine(0, y, self.width(), y)
                    lastGeo = newGeo
            else:
                for col in range(1, layout.count()):
                    newGeo = layout.itemAt(row).geometry()
                    x = (lastGeo.right()
                         + (newGeo.x() - lastGeo.right()) // 2)
                    qp.drawLine(x, 0, x, self.height())
                    lastGeo = newGeo
        elif isinstance(layout, QGridLayout):
            for i in range(layout.count()):
                row, col, rowSpan, colSpan = layout.getItemPosition(i)
                if not row and not col:
                    continue
                cellRect = layout.cellRect(row, col)
                if rowSpan:
                    cellRect |= layout.cellRect(row + rowSpan - 1, col)
                if colSpan:
                    cellRect |= layout.cellRect(row, col + colSpan - 1)
                if row:
                    aboveCell = layout.cellRect(row - 1, col)
                    y = (aboveCell.bottom()
                         + (cellRect.y() - aboveCell.bottom()) // 2)
                    qp.drawLine(cellRect.x(), y, cellRect.right() + 1, y)
                if col:
                    leftCell = layout.cellRect(row, col - 1)
                    x = (leftCell.right()
                         + (cellRect.x() - leftCell.right()) // 2)
                    qp.drawLine(x, cellRect.y(), x, cellRect.bottom() + 1)

class Window(LayoutLineWidget):
    def __init__(self):
        super().__init__()
        self.setStyleSheet('''
            Window {
                background: #020a19;
            }
            QLabel#header {
                qproperty-alignment: AlignCenter;
                font-size: 25px;
                color: #c5cad4;
                padding-left: 10px;
                padding-top: 16px;
                padding-bottom: 20px;
            }
            QWidget#content {
                border: 1px solid #c5cad4;
                border-radius: 5px;
            }
            QPushButton {
                background: #020a19;
                color: #c5cad4;
                border: none;
                border-radius: 5px;
                font-size: 15px;
                font-weight: bold;
                padding: 10px;
            }
            QPushButton:hover {
                background-color: #00384d;
            }
            QWidget#menu > QPushButton {
                width: 180px;
                height: 80px;
            }
        ''')

        mainLayout = QGridLayout(self)
        mainLayout.setContentsMargins(0, 0, 0, 0)
        mainLayout.setSpacing(0)

        self.header_label = QLabel('Some Application', objectName='header')
        self.header_label.setMinimumHeight(120)
        mainLayout.addWidget(self.header_label, 0, 0, 1, 2)

        menuContainer = QWidget(objectName='menu')
        mainLayout.addWidget(menuContainer)
        menuLayout = QVBoxLayout(menuContainer)
        menuLayout.setSpacing(15)

        self.option_1_button = QPushButton('Option 1')
        self.option_2_button = QPushButton('Option 2')
        self.option_3_button = QPushButton('Option 3')

        menuLayout.addWidget(self.option_1_button)
        menuLayout.addWidget(self.option_2_button)
        menuLayout.addWidget(self.option_3_button)
        menuLayout.addStretch()

        rightLayout = QVBoxLayout()
        mainLayout.addLayout(rightLayout, 1, 1)

        self.content = QStackedWidget()
        self.content.setContentsMargins(40, 40, 40, 40)
        rightLayout.addWidget(self.content)
        rightLayout.addStretch(1)

        self.firstPage = LayoutLineWidget(objectName='content')
        self.content.addWidget(self.firstPage)
        firstPageLayout = QVBoxLayout(self.firstPage)
        spacing = sum(firstPageLayout.getContentsMargins()) // 2
        firstPageLayout.setSpacing(spacing)

        self.other_option_1_button = QPushButton('Other 1')
        self.other_option_2_button = QPushButton('Other 2')
        self.other_option_3_button = QPushButton('Other 3')

        firstPageLayout.addWidget(self.other_option_1_button)
        firstPageLayout.addWidget(self.other_option_2_button)
        firstPageLayout.addWidget(self.other_option_3_button)

        screen = QApplication.primaryScreen()
        rect = QRect(QPoint(), screen.size() * .8)
        rect.moveCenter(screen.geometry().center())
        self.setGeometry(rect)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())
</code>```

This is the visual result:

Note that the above code will cause calling the paintEvent() and its instructions very often, so it's always a good idea to provide some caching. A possibility is to use QPicture, which is a sort of "QPainter recorder"; since it completely relies on the C++ implementation, this allows to optimize the painting by drawing the existing content until it's changed.

```<code>class LayoutLineWidget(QWidget):
    _borderColor = QColor('#c5cad4')
    _paintCache = None
    _redrawEvents = QEvent.LayoutRequest, QEvent.Resize

    def event(self, event):
        if event.type() in self._redrawEvents:
            self._paintCache = None
            self.update()
        return super().event(event)

    def paintEvent(self, event):
        # QWidget subclasses *must* do the following to properly use style sheets;
        # see https://doc.qt.io/qt-5/stylesheet-reference.html#qwidget-widget
        qp = QStylePainter(self)
        opt = QStyleOption()
        opt.initFrom(self)
        qp.drawPrimitive(QStyle.PE_Widget, opt)

        layout = self.layout()
        if not layout or layout.count() <= 1:
            return
        if layout.spacing() < 1:
            layout.setSpacing(1)
            return

        try:
            qp.drawPicture(0, 0, self._paintCache)
        except TypeError:
            self._rebuildPaintCache()
            qp.drawPicture(0, 0, self._paintCache)

    def _rebuildPaintCache(self):
        layout = self.layout()
        self._paintCache = QPicture()
        qp = QPainter(self._paintCache)
        # from this point, it's exactly the same as above
        qp.setPen(self._borderColor)
        if isinstance(layout, QBoxLayout):
        # ...
</code>```

Further notes:

the above codes haven't been tested against widgets with different margin/padding settings and complex row/column spans for grid layouts; it might need further fixing;

one of the hidden features of QGridLayout is that it's possible to set more widgets for each grid "cell"; while this feature can be useful for complex layouts, it has an important drawback: whenever a child widget or layout uses spanning, the layout spacing is ignored, so child items might have inconsistent geometries and the above code might not work as expected;

don't underestimate the aspects related to the box model, especially when dealing with sizes;

font sizes should not be set in pixels, as screens can have different DPI settings; always prefer device based units: pt, em or ex;

Body:
I've been trying to learn PyQt5 to reimplement an application I did with Tkinter, but with some design differences. Since it's not a complex application, I'd like to make it have a style similar to this small window from GitHub desktop (options on the left side of the window, and the rest in the remaining space):

I know my colors don't look great now, but I can take care of that later. However, I haven't found out how to draw lines/boxes similar to those, or at lesat in the divisions between my columns/rows.

Here's what I have so far:

import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QWidget, QFileDialog, QGridLayout, QFrame
from PyQt5 import QtGui, QtCore

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Some Window Title')
        self.app = QApplication(sys.argv)
        self.screen = self.app.primaryScreen()
        self.screen_size = self.screen.size()
        self.screen_width = self.screen_size.width()
        self.screen_height = self.screen_size.height()

        self.setGeometry(
            self.screen_width * 0.1,
            self.screen_height * 0.1,
            self.screen_width * 0.8,
            self.screen_height * 0.8
        )
        self.setStyleSheet('background: #020a19;')

        self.grid = QGridLayout()
        self.grid.setVerticalSpacing(0)
        self.grid.setContentsMargins(0, 0, 0, 0)

        self.option_button_stylesheet =  '''
            QPushButton {
                background: #020a19;
                color: #c5cad4;
                border-color: #c5cad4;
                border: 0px 0px 0px 0px;
                border-style: outset;
                border-radius: 5px;
                font-size: 15px;
                font-weight: bold;
                padding: 10px;
                margin: 15px;
                width: 2px;

            }

            QPushButton:hover {
                background-color: #00384d;
            }
            '''

        self.placeholder_button_stylesheet = '''
            QPushButton {
                background: #020a19;
                color: #c5cad4;
                border-top: none;
                border-right: 1px;
                border-left:none;
                border-bottom: none;
                border-color: #c5cad4;
                border-style: outset;
                padding: 10px;
                margin: 0px;
                width: 2px;
                height: 100%;

            }

            QPushButton:hover {
                background-color: #020a19;
            }
            '''

        self.header_label = QLabel('Some Application')
        self.option_1_button = QPushButton('Option 1')
        self.option_2_button = QPushButton('Option 2')
        self.option_3_button = QPushButton('Option 3')

        self.header_label.setStyleSheet(
            '''
            font-size: 25px;
            color: #c5cad4;
            padding-left: 10px;
            padding-top: 16px;
            padding-bottom: 20px;
            height: 10%;
            border-bottom: 1px solid #c5cad4;
            '''
        )
        self.header_label.setFixedHeight(120)
        self.grid.addWidget(self.header_label, 0, 0, 1, 2)

        self.option_1_button.setStyleSheet(self.option_button_stylesheet)
        self.option_1_button.setFixedWidth(200)
        self.option_1_button.setFixedHeight(100)
        self.grid.addWidget(self.option_1_button, 1, 0)

        self.option_2_button.setStyleSheet(self.option_button_stylesheet)
        self.option_2_button.setFixedWidth(200)
        self.option_2_button.setFixedHeight(100)
        self.grid.addWidget(self.option_2_button, 2, 0)

        self.option_3_button.setStyleSheet(self.option_button_stylesheet)
        self.option_3_button.setFixedWidth(200)
        self.option_3_button.setFixedHeight(100)
        self.grid.addWidget(self.option_3_button, 3, 0)

        self.grid.setRowStretch(4, 1)

        self.initUI()

        self.setLayout(self.grid)
        self.show()

    def initUI(self):

        self.greet_text = QLabel('Welcome')
        self.greet_text.setAlignment(QtCore.Qt.AlignCenter)
        self.greet_text.setStyleSheet(
            """
            font-size: 35px;
            color: #c5cad4;
            """
        )
        self.grid.addWidget(self.greet_text, 1, 1, 5, 1)

def run():
    window = Window()
    sys.exit(window.app.exec())

run()

As you can see, I'm using QWidget as my window element. I know I could use QMainWindow, but that changes the way widgets are placed and I'm finding it easier to use QWidget. I also don't need a toolbar or anything like that for this app.

How can I draw those lines?

Body:
Qt style sheets (QSS) don't provide such a feature, as it's only possible to style specific widgets without being able to consider their position within the layout. This is important in your case, as what you want to do is draw the "separation" between layout items.

It is theoretically possible to achieve this by setting a background for the container widget that will be the line color, have all its child widgets drawing their full contents with opaque colors, and ensure that the layout always has a spacing equal to the width of the line, but if the inner widgets don't respect their full size, they use an alpha channel, or some stretch or further spacing is added, the result would be ugly.

One possibility is to use a QWidget subclass, override its paintEvent() and draw those lines with QPainter.

The idea is that we cycle through all layout items, and draw lines that are placed in the middle between the "current" item and the previous.

In the following example I've created a basic QWidget subclass that implements the above concept, depending on the layout used.

Note that I had to make some changes and corrections to your original code:

as already noted in comments, an existing QApplication is mandatory to allow the creation of a QWidget, and while it's possible to make it an attribute of the object (before calling the super().__init__()), it is still conceptually wrong;

highly hierarchical structures in grid layouts should not use individual rows and columns for their direct child objects, but proper sub-layouts or child widgets should be added instead; in your case, the should be only two rows and columns: the header will have a 2-column-span in the first row, the menu will be on the second row (index 1) and first column, the right side in the second column, and the menu buttons will have their own layout;

setting generic style sheet properties for parent widgets is highly discouraged, as complex widgets (such as QComboBox, QScrollBar and scroll areas children) require that all properties are set to properly work; using setStyleSheet('background: ...') should always be avoided for parents or the application;

style sheets that are shared among many widgets should be set on the parent or the application, and proper selectors should always be used;

the QSS width property should be used with care, as it could make widgets partially invisible and unusable;

if you don't want any border, just use border: none;;

only absolute units are supported for style sheet sizes (see the Length property type), percent values are ignored;

setting fixed heights, paddings and margins can result in unexpected behavior; ensure that you carefully read the box model and do some testing to understand its behavior;

classes should not show themselves automatically during construction, so show() should not be called within the __init__() (this is not specifically "forbidden" or discouraged, but it's still good practice);

an if __name__ == '__main__': block should always be used, especially when dealing with programs or toolkits that rely on event loops (like all UI frameworks, as Qt is);

Here is a rewriting of your original code:

class LayoutLineWidget(QWidget):
    _borderColor = QColor('#c5cad4')

    def paintEvent(self, event):
        # QWidget subclasses *must* do this to properly use style sheets;
        # (see doc.qt.io/qt-5/stylesheet-reference.html#qwidget-widget)
        opt = QStyleOption()
        opt.initFrom(self)
        qp = QStylePainter(self)
        qp.drawPrimitive(QStyle.PE_Widget, opt)
        # end of default painting

        layout = self.layout()
        if not layout or layout.count() <= 1:
            return
        if layout.spacing() < 1:
            layout.setSpacing(1)
            return

        qp.setPen(self._borderColor)
        if isinstance(layout, QBoxLayout):
            lastGeo = layout.itemAt(0).geometry()
            if isinstance(layout, QVBoxLayout):
                for row in range(1, layout.count()):
                    newGeo = layout.itemAt(row).geometry()
                    y = (lastGeo.bottom()
                         + (newGeo.y() - lastGeo.bottom()) // 2)
                    qp.drawLine(0, y, self.width(), y)
                    lastGeo = newGeo
            else:
                for col in range(1, layout.count()):
                    newGeo = layout.itemAt(row).geometry()
                    x = (lastGeo.right()
                         + (newGeo.x() - lastGeo.right()) // 2)
                    qp.drawLine(x, 0, x, self.height())
                    lastGeo = newGeo
        elif isinstance(layout, QGridLayout):
            for i in range(layout.count()):
                row, col, rowSpan, colSpan = layout.getItemPosition(i)
                if not row and not col:
                    continue
                cellRect = layout.cellRect(row, col)
                if rowSpan:
                    cellRect |= layout.cellRect(row + rowSpan - 1, col)
                if colSpan:
                    cellRect |= layout.cellRect(row, col + colSpan - 1)
                if row:
                    aboveCell = layout.cellRect(row - 1, col)
                    y = (aboveCell.bottom()
                         + (cellRect.y() - aboveCell.bottom()) // 2)
                    qp.drawLine(cellRect.x(), y, cellRect.right() + 1, y)
                if col:
                    leftCell = layout.cellRect(row, col - 1)
                    x = (leftCell.right()
                         + (cellRect.x() - leftCell.right()) // 2)
                    qp.drawLine(x, cellRect.y(), x, cellRect.bottom() + 1)

class Window(LayoutLineWidget):
    def __init__(self):
        super().__init__()
        self.setStyleSheet('''
            Window {
                background: #020a19;
            }
            QLabel#header {
                qproperty-alignment: AlignCenter;
                font-size: 25px;
                color: #c5cad4;
                padding-left: 10px;
                padding-top: 16px;
                padding-bottom: 20px;
            }
            QWidget#content {
                border: 1px solid #c5cad4;
                border-radius: 5px;
            }
            QPushButton {
                background: #020a19;
                color: #c5cad4;
                border: none;
                border-radius: 5px;
                font-size: 15px;
                font-weight: bold;
                padding: 10px;
            }
            QPushButton:hover {
                background-color: #00384d;
            }
            QWidget#menu > QPushButton {
                width: 180px;
                height: 80px;
            }
        ''')

        mainLayout = QGridLayout(self)
        mainLayout.setContentsMargins(0, 0, 0, 0)
        mainLayout.setSpacing(0)

        self.header_label = QLabel('Some Application', objectName='header')
        self.header_label.setMinimumHeight(120)
        mainLayout.addWidget(self.header_label, 0, 0, 1, 2)

        menuContainer = QWidget(objectName='menu')
        mainLayout.addWidget(menuContainer)
        menuLayout = QVBoxLayout(menuContainer)
        menuLayout.setSpacing(15)

        self.option_1_button = QPushButton('Option 1')
        self.option_2_button = QPushButton('Option 2')
        self.option_3_button = QPushButton('Option 3')

        menuLayout.addWidget(self.option_1_button)
        menuLayout.addWidget(self.option_2_button)
        menuLayout.addWidget(self.option_3_button)
        menuLayout.addStretch()

        rightLayout = QVBoxLayout()
        mainLayout.addLayout(rightLayout, 1, 1)

        self.content = QStackedWidget()
        self.content.setContentsMargins(40, 40, 40, 40)
        rightLayout.addWidget(self.content)
        rightLayout.addStretch(1)

        self.firstPage = LayoutLineWidget(objectName='content')
        self.content.addWidget(self.firstPage)
        firstPageLayout = QVBoxLayout(self.firstPage)
        spacing = sum(firstPageLayout.getContentsMargins()) // 2
        firstPageLayout.setSpacing(spacing)

        self.other_option_1_button = QPushButton('Other 1')
        self.other_option_2_button = QPushButton('Other 2')
        self.other_option_3_button = QPushButton('Other 3')

        firstPageLayout.addWidget(self.other_option_1_button)
        firstPageLayout.addWidget(self.other_option_2_button)
        firstPageLayout.addWidget(self.other_option_3_button)

        screen = QApplication.primaryScreen()
        rect = QRect(QPoint(), screen.size() * .8)
        rect.moveCenter(screen.geometry().center())
        self.setGeometry(rect)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

This is the visual result:

Note that the above code will cause calling the paintEvent() and its instructions very often, so it's always a good idea to provide some caching. A possibility is to use QPicture, which is a sort of "QPainter recorder"; since it completely relies on the C++ implementation, this allows to optimize the painting by drawing the existing content until it's changed.

class LayoutLineWidget(QWidget):
    _borderColor = QColor('#c5cad4')
    _paintCache = None
    _redrawEvents = QEvent.LayoutRequest, QEvent.Resize

    def event(self, event):
        if event.type() in self._redrawEvents:
            self._paintCache = None
            self.update()
        return super().event(event)

    def paintEvent(self, event):
        # QWidget subclasses *must* do the following to properly use style sheets;
        # see https://doc.qt.io/qt-5/stylesheet-reference.html#qwidget-widget
        qp = QStylePainter(self)
        opt = QStyleOption()
        opt.initFrom(self)
        qp.drawPrimitive(QStyle.PE_Widget, opt)

        layout = self.layout()
        if not layout or layout.count() <= 1:
            return
        if layout.spacing() < 1:
            layout.setSpacing(1)
            return

        try:
            qp.drawPicture(0, 0, self._paintCache)
        except TypeError:
            self._rebuildPaintCache()
            qp.drawPicture(0, 0, self._paintCache)

    def _rebuildPaintCache(self):
        layout = self.layout()
        self._paintCache = QPicture()
        qp = QPainter(self._paintCache)
        # from this point, it's exactly the same as above
        qp.setPen(self._borderColor)
        if isinstance(layout, QBoxLayout):
        # ...

Further notes:

the above codes haven't been tested against widgets with different margin/padding settings and complex row/column spans for grid layouts; it might need further fixing;

one of the hidden features of QGridLayout is that it's possible to set more widgets for each grid "cell"; while this feature can be useful for complex layouts, it has an important drawback: whenever a child widget or layout uses spanning, the layout spacing is ignored, so child items might have inconsistent geometries and the above code might not work as expected;

don't underestimate the aspects related to the box model, especially when dealing with sizes;

font sizes should not be set in pixels, as screens can have different DPI settings; always prefer device based units: pt, em or ex;


问:
Angular parent and children communication using a service?
I've started learning Angular, and I run into this example from official docs regarding parent-service communication using a service:

```<code>import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MissionService {

  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}
</code>```

I'm a bit confused by this part:

```<code>  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();
</code>```

I understand that .asObservable() creates a new Observable with this Subject as the source. However, why do we need it ?  missionAnnouncedSource is already an observable.
Why don't we just simply have a service like this:

```<code>import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MissionService {

  // Observable string sources
   missionAnnouncedSource = new Subject<string>();
   missionConfirmedSource = new Subject<string>();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}
</code>```

Of course,  I would need to adjust code in components to make it work, but I do not see any issues with that:

```<code>  //astronaut.component.ts

  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnouncedSource.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    });
  }
</code>```

Is this some sort of convention or I am missing something?

答: You don’t need it, but the idea is that if you only expose an observable, it is not possible to next the public variable - it should only be done from within the service.

Body:
I've started learning Angular, and I run into this example from official docs regarding parent-service communication using a service:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MissionService {

  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}

I'm a bit confused by this part:

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

I understand that .asObservable() creates a new Observable with this Subject as the source. However, why do we need it ?  missionAnnouncedSource is already an observable.
Why don't we just simply have a service like this:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MissionService {

  // Observable string sources
   missionAnnouncedSource = new Subject<string>();
   missionConfirmedSource = new Subject<string>();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}

Of course,  I would need to adjust code in components to make it work, but I do not see any issues with that:

  //astronaut.component.ts

  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnouncedSource.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    });
  }

Is this some sort of convention or I am missing something?


问:
Link to Name in Slide Show
It's me again - The code is working now, but I can't seem to be able to add a link to the '$info['name']' in the alt.
 I want to be able to add links to the picture and the name. The picture link works, but the link does not appear in the name.

I may have some mistakes in the code below.
The link works on the picture but now in the alt.

Here's the code:

```<code><!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>JQuery Cycle Plugin - Pager Demo with Prev/Next Controls</title>
<link rel="stylesheet" type="text/css" media="screen" href="../jq.css" />
<link rel="stylesheet" type="text/css" media="screen" href="cycle.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script type="text/javascript" src="http://malsup.github.com/chili-1.7.pack.js"></script>
<script type="text/javascript" src="http://malsup.github.com/jquery.cycle.all.js"></script>

<style type="text/css">
#main { margin: 20px }
#nav { margin: 10px; position: relative }
#nav li { float: left; list-style: none}
#nav a { margin: 5px; padding: 3px 5px; border: 1px solid #ccc; background: #fc0; text-decoration: none }
#nav li.activeSlide a { background: #faa; color: black }
#nav a:focus { outline: none; }

</style>

<script type="text/javascript">
$(document).ready(function() {
     $('#slideshow').cycle({
          prev:    '.prev', // Setup prev links
          next:    '.next', // Setup next links
          pager:   '.nav',       // Setup pager navs
          before: function () {
          $("#name").html($(this).children("img").attr("alt"));
      }
     });
});
</script>

<style type="text/css">
#left, #slideshow, #right { float: left; width: 200px; }
</style>
</head>
<body>

<!-- left nav bar -->
<div id="left">
    <a href="#"><span class="prev">Prev</span></a>
    <a href="#"><span class="next">Next</span></a>

    <ul class="nav"></ul>
</div>

<!-- slideshow -->
<div id="slideshow">

 <?php
                 mysql_connect("localhost", "root", "")or die("cannot connect");
                 mysql_select_db($db_name)or die("cannot select DB");

                 $data = mysql_query("SELECT * FROM people") or die(mysql_error());
                 while($info = mysql_fetch_array( $data )){

   <!--THIS CODE BELOW -->
     echo "<a href=\"display.php?id=".$info['id']."\"><img src=\"uploads/".$info['pic'] . "\" alt=\"<b><a href=\"display.php?id=".$info['id']."\">".$info['name']."</a></b><br />".$info['sex']. "<br />".$info['location'].
       "<br />".$info['age']."</a>";
  }
?>

</div>

 <div id="name">

 </div>
 <!-- right nav bar -->
 <div id="right">
     <a href="#"><span class="prev">Prev</span></a>
     <a href="#"><span class="next">Next</span></a>
     <ul class="nav"></ul>
 </div>

 </div>

</body>
</html>
</code>```

I would appreciate your help folks to be able to add link to the name dynamically.

答:
instead of echo-ing the string, why not read it into a variable and echo the variable inside you html at the appropriate location <?php echo $myString; ?> also looks like you are using HTML inside the alt attribute. You can't do that. Even if you can do that, you are using double quotes inside double quotes, which will end the double quote and break the string.

Try changing your echo command to:

```<code>echo "<a href=\"display.php?id=".$info['id']."\"><img src=\"uploads/".$info['pic'] . "\" alt=\"<b><a href='display.php?id=".$info['id']."'>".$info['name']."</a></b><br />".$info['sex']. "<br />".$info['location'].
       "<br />".$info['age']."</a>";
</code>```

The only thing Ive changed is the anchor link (i.e. the part below I replace " with '

```<code><a href='display.php?id=".$info['id']."'>
</code>```

ContentLicense: CC BY-SA 3.0

Title: Link to Name in Slide Show

Body:
It's me again - The code is working now, but I can't seem to be able to add a link to the '$info['name']' in the alt.
 I want to be able to add links to the picture and the name. The picture link works, but the link does not appear in the name.

I may have some mistakes in the code below.
The link works on the picture but now in the alt.

Here's the code:

<!DOCTYPE html>

<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>JQuery Cycle Plugin - Pager Demo with Prev/Next Controls</title>
<link rel="stylesheet" type="text/css" media="screen" href="../jq.css" />
<link rel="stylesheet" type="text/css" media="screen" href="cycle.css" />

    Prev
    Next

 <?php
                 mysql_connect("localhost", "root", "")or die("cannot connect");
                 mysql_select_db($db_name)or die("cannot select DB");

                 $data = mysql_query("SELECT * FROM people") or die(mysql_error());
                 while($info = mysql_fetch_array( $data )){

     echo "<img src=\"uploads/".$info['pic'] . "\" alt=\"".$info['name']."
".$info['sex']. "
".$info['location'].
       "
".$info['age']."";
  }
?>

     Prev
     Next

I would appreciate your help folks to be able to add link to the name dynamically.

Body:
instead of echo-ing the string, why not read it into a variable and echo the variable inside you html at the appropriate location <?php echo $myString; ?> also looks like you are using HTML inside the alt attribute. You can't do that. Even if you can do that, you are using double quotes inside double quotes, which will end the double quote and break the string.

Try changing your echo command to:

echo "<a href=\"display.php?id=".$info['id']."\"><img src=\"uploads/".$info['pic'] . "\" alt=\"<b><a href='display.php?id=".$info['id']."'>".$info['name']."</a></b><br />".$info['sex']. "<br />".$info['location'].
       "<br />".$info['age']."</a>";

The only thing Ive changed is the anchor link (i.e. the part below I replace " with '

<a href='display.php?id=".$info['id']."'>


问:
Heroku FFMPEG Postprocessing error with yt-dlp DownloadError
I am building a discord music bot that uses FFMPEG to download and play the music. yt-dlp seems to not be able to find the ffmpeg file for some reason although I give it the direct path. It works perfectly fine whe I run it on my cpu, but it doesn't work in heroku.

Here's the error in heroku:

2022-02-14T00:34:29.047823+00:00 app[worker.1]: During handling of the above exception, another exception occurred:
2022-02-14T00:34:29.047823+00:00 app[worker.1]:
2022-02-14T00:34:29.047825+00:00 app[worker.1]: Traceback (most recent call last):
2022-02-14T00:34:29.047854+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
2022-02-14T00:34:29.047855+00:00 app[worker.1]:     await coro(*args, **kwargs)
2022-02-14T00:34:29.047856+00:00 app[worker.1]:   File "/app/engine.py", line 97, in on_reaction_add
2022-02-14T00:34:29.047856+00:00 app[worker.1]:     ydl.download([f'{result["link"]}'])
2022-02-14T00:34:29.047863+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3212, in download
2022-02-14T00:34:29.047863+00:00 app[worker.1]:     self.__download_wrapper(self.extract_info)(
2022-02-14T00:34:29.047865+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3185, in wrapper
2022-02-14T00:34:29.047865+00:00 app[worker.1]:     res = func(*args, **kwargs)
2022-02-14T00:34:29.047875+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1372, in extract_info
2022-02-14T00:34:29.047876+00:00 app[worker.1]:     return self.__extract_info(url, self.get_info_extractor(ie_key), download, extra_info, process)
2022-02-14T00:34:29.047877+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1381, in wrapper
2022-02-14T00:34:29.047877+00:00 app[worker.1]:     return func(self, *args, **kwargs)
2022-02-14T00:34:29.047891+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1465, in __extract_info
2022-02-14T00:34:29.047891+00:00 app[worker.1]:     return self.process_ie_result(ie_result, download, extra_info)
2022-02-14T00:34:29.047893+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1517, in process_ie_result
2022-02-14T00:34:29.047894+00:00 app[worker.1]:     ie_result = self.process_video_result(ie_result, download=download)
2022-02-14T00:34:29.047894+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 2607, in process_video_result
2022-02-14T00:34:29.047894+00:00 app[worker.1]:     self.process_info(new_info)
2022-02-14T00:34:29.047896+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3161, in process_info
2022-02-14T00:34:29.047896+00:00 app[worker.1]:     self.report_error('Postprocessing: %s' % str(err))
2022-02-14T00:34:29.047904+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 930, in report_error
2022-02-14T00:34:29.047904+00:00 app[worker.1]:     self.trouble(f'{self._format_err("ERROR:", self.Styles.ERROR)} {message}', *args, **kwargs)
2022-02-14T00:34:29.047905+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 871, in trouble
2022-02-14T00:34:29.047905+00:00 app[worker.1]:     raise DownloadError(message, exc_info)
2022-02-14T00:34:29.047921+00:00 app[worker.1]: yt_dlp.utils.DownloadError: ERROR: Postprocessing: ffprobe and ffmpeg not found. Please install or provide the path using --ffmpeg-location
```
<p>Here's my setup:
![root level directory]: https://i.stack.imgur.com/HKo8L.png</p>
<p>Here's the code:</p>
<pre class="lang-py prettyprint-override"><code>yt_opts = {
        'format': 'bestaudio/best',
        'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }]
    }
# Getting Song From Thy YOUTUBE
     await channel.send("> Getting Song From Youtube")
     with yt_dlp.YoutubeDL(yt_opts) as ydl:
          ydl.download([f'{result["link"]}'])
</code>```

答:
You can't do this:

'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',
```
<p><code>ffmpeg.exe</code> is a <em>Windows</em> binary. It cannot be used on Heroku (and should not be part of your repository to begin with).</p>
<p>Most users who want to use <code>ffmpeg</code> on Heroku use the buildpack (see also multiple buildpacks), e.g.:</p>
<pre class="lang-none prettyprint-override"><code>heroku buildpacks:set heroku/python
heroku buildpacks:add --index 1 https://github.com/FFmpeg/FFmpeg.git
</code>```

Then remove that hard-coded ffmpeg_location, commit, and redeploy. Your app should find ffmpeg.

For local development you have a couple of of options:

Update your PATH to make sure ffmpeg.exe can be found

Update your code to set an ffmpeg_location, ideally from an environment variable

Body:
I am building a discord music bot that uses FFMPEG to download and play the music. yt-dlp seems to not be able to find the ffmpeg file for some reason although I give it the direct path. It works perfectly fine whe I run it on my cpu, but it doesn't work in heroku.

Here's the error in heroku:

2022-02-14T00:34:29.047823+00:00 app[worker.1]: During handling of the above exception, another exception occurred:
2022-02-14T00:34:29.047823+00:00 app[worker.1]:
2022-02-14T00:34:29.047825+00:00 app[worker.1]: Traceback (most recent call last):
2022-02-14T00:34:29.047854+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
2022-02-14T00:34:29.047855+00:00 app[worker.1]:     await coro(*args, **kwargs)
2022-02-14T00:34:29.047856+00:00 app[worker.1]:   File "/app/engine.py", line 97, in on_reaction_add
2022-02-14T00:34:29.047856+00:00 app[worker.1]:     ydl.download([f'{result["link"]}'])
2022-02-14T00:34:29.047863+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3212, in download
2022-02-14T00:34:29.047863+00:00 app[worker.1]:     self.__download_wrapper(self.extract_info)(
2022-02-14T00:34:29.047865+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3185, in wrapper
2022-02-14T00:34:29.047865+00:00 app[worker.1]:     res = func(*args, **kwargs)
2022-02-14T00:34:29.047875+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1372, in extract_info
2022-02-14T00:34:29.047876+00:00 app[worker.1]:     return self.__extract_info(url, self.get_info_extractor(ie_key), download, extra_info, process)
2022-02-14T00:34:29.047877+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1381, in wrapper
2022-02-14T00:34:29.047877+00:00 app[worker.1]:     return func(self, *args, **kwargs)
2022-02-14T00:34:29.047891+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1465, in __extract_info
2022-02-14T00:34:29.047891+00:00 app[worker.1]:     return self.process_ie_result(ie_result, download, extra_info)
2022-02-14T00:34:29.047893+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1517, in process_ie_result
2022-02-14T00:34:29.047894+00:00 app[worker.1]:     ie_result = self.process_video_result(ie_result, download=download)
2022-02-14T00:34:29.047894+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 2607, in process_video_result
2022-02-14T00:34:29.047894+00:00 app[worker.1]:     self.process_info(new_info)
2022-02-14T00:34:29.047896+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3161, in process_info
2022-02-14T00:34:29.047896+00:00 app[worker.1]:     self.report_error('Postprocessing: %s' % str(err))
2022-02-14T00:34:29.047904+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 930, in report_error
2022-02-14T00:34:29.047904+00:00 app[worker.1]:     self.trouble(f'{self._format_err("ERROR:", self.Styles.ERROR)} {message}', *args, **kwargs)
2022-02-14T00:34:29.047905+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 871, in trouble
2022-02-14T00:34:29.047905+00:00 app[worker.1]:     raise DownloadError(message, exc_info)
2022-02-14T00:34:29.047921+00:00 app[worker.1]: yt_dlp.utils.DownloadError: ERROR: Postprocessing: ffprobe and ffmpeg not found. Please install or provide the path using --ffmpeg-location

Here's my setup:
![root level directory]: https://i.stack.imgur.com/HKo8L.png

Here's the code:

yt_opts = {
        'format': 'bestaudio/best',
        'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }]
    }
# Getting Song From Thy YOUTUBE
     await channel.send("> Getting Song From Youtube")
     with yt_dlp.YoutubeDL(yt_opts) as ydl:
          ydl.download([f'{result["link"]}'])

Body:
You can't do this:

'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',

ffmpeg.exe is a Windows binary. It cannot be used on Heroku (and should not be part of your repository to begin with).

Most users who want to use ffmpeg on Heroku use the buildpack (see also multiple buildpacks), e.g.:

heroku buildpacks:set heroku/python
heroku buildpacks:add --index 1 https://github.com/FFmpeg/FFmpeg.git

Then remove that hard-coded ffmpeg_location, commit, and redeploy. Your app should find ffmpeg.

For local development you have a couple of of options:

Update your PATH to make sure ffmpeg.exe can be found

Update your code to set an ffmpeg_location, ideally from an environment variable


问:
I'am trying to add new field of the product price attribute value (msrp, map ) on storefront
Here is the code i am trying to use

```<code>    -  '@add':
            id: price_attribute_product_price
            parentId: product_view_specification
            blockType: product_prices
            options:
                label: visible
</code>```

but it doesn't do anything!
Am i missing something?

答:
That's how we did it too, although ours is hard-coded to the RRP attribute but it's pretty easy to customize this.

Sharing our code as I think it's been asked quite a few times in the community before.

We created our own custom Price Provider:

namespace Aligent\BaseBundle\Provider;

use Oro\Bundle\CurrencyBundle\Entity\Price;
use Oro\Bundle\EntityBundle\ORM\DoctrineHelper;
use Oro\Bundle\PricingBundle\Entity\PriceAttributePriceList;
use Oro\Bundle\PricingBundle\Entity\PriceAttributeProductPrice;
use Oro\Bundle\PricingBundle\Provider\PriceAttributePricesProvider;
use Oro\Bundle\ProductBundle\Entity\Product;

/**
 * Makes the rrp price attribute available.
 * The rrp price attribute can be found in db table: oro_price_attribute_pl
 */
class RRPPriceProvider
{
    const PRICE_ATTRIBUTE = 'RRP';

    protected DoctrineHelper $doctrineHelper;
    protected PriceAttributePricesProvider $priceAttributePricesProvider;

    /**
     * @param DoctrineHelper $doctrineHelper
     * @param PriceAttributePricesProvider $priceAttributePricesProvider
     */
    public function __construct(
        DoctrineHelper $doctrineHelper,
        PriceAttributePricesProvider $priceAttributePricesProvider
    ) {
        $this->doctrineHelper = $doctrineHelper;
        $this->priceAttributePricesProvider = $priceAttributePricesProvider;
    }

    /**
     * Get RRP price with unit and currencies from custom Product Price Attribute Price List
     * @param Product $product
     * @return array
     */
    public function getRRPPriceWithUnitAndCurrencies(Product $product) : array
    {
        /** @var PriceAttributePriceList $rrpPriceList */
        $rrpPriceList = $this->getRRPAttributePriceList();

        return $this->priceAttributePricesProvider->getPricesWithUnitAndCurrencies($rrpPriceList, $product);
    }

    /**
     * Get RRP price from custom Product Price Attribute Price List
     * @param Product $product
     * @return Price|null
     */
    public function getRRPPrice(Product $product) : ?Price
    {
        /** @var PriceAttributePriceList $rrpPriceList */
        $rrpPriceList = $this->getRRPAttributePriceList();

        /** @var PriceAttributeProductPrice $priceAttributePrice */
        $priceAttributePrice = $this->doctrineHelper
            ->getEntityRepository(PriceAttributeProductPrice::class)
            ->findOneBy(['product' => $product, 'priceList' => $rrpPriceList]);

        return $priceAttributePrice?->getPrice();
    }

    /**
     * Gets just the RRP Price Attribute Price List
     * @return PriceAttributePriceList|null
     */
    protected function getRRPAttributePriceList() : PriceAttributePriceList
    {
        return $this->doctrineHelper->getEntityRepository(PriceAttributePriceList::class)->findOneBy([
            'name' => self::PRICE_ATTRIBUTE,
        ]);
    }
}
```
<p>And then we have a Layout DataProvider to make this available in the layouts:</p>
<pre class="lang-php prettyprint-override"><code>
namespace Aligent\BaseBundle\Layout\DataProvider;

use Aligent\BaseBundle\Provider\RRPPriceProvider;
use Oro\Bundle\ProductBundle\Entity\Product;

class RRPPriceLayoutProvider
{
    protected RRPPriceProvider $rrpPriceProvider;

    public function __construct(RRPPriceProvider $RRPPriceProvider)
    {
        $this->rrpPriceProvider = $RRPPriceProvider;
    }

    /**
     * Get RRP price with unit and currencies from custom Product Price Attribute Price List
     * Called from layout.yml via: =data["product_rrp_price"].getRRPPriceWithUnitAndCurrencies(data["entity"])'
     */
    public function getRRPPriceWithUnitAndCurrencies(Product $product) : array
    {
        return $this->rrpPriceProvider->getRRPPriceWithUnitAndCurrencies($product);
    }

    /**
     * Get RRP price from custom Product Price Attribute Price List
     * Called from layout.yml via: =data["product_rrp_price"].getRRPPrice(data["entity"])'
     */
    public function getRRPPrice(Product $product) : ?string
    {
        return $this->rrpPriceProvider->getRRPPrice($product)?->getValue();
    }
}
</code>```

services.yml:

services:
    # Providers
    Aligent\BaseBundle\Provider\RRPPriceProvider:
        arguments:
            - '@oro_api.doctrine_helper'
            - '@oro_pricing.providers.price_attribute_prices'

    # Layout Providers
    Aligent\BaseBundle\Layout\DataProvider\RRPPriceLayoutProvider:
        arguments:
            - '@Aligent\BaseBundle\Provider\RRPPriceProvider'
        tags:
            - { name: layout.data_provider, alias: product_rrp_price }
```
<p>And then actually call it from your <code>layout.yml</code>:</p>
<pre class="lang-yaml prettyprint-override"><code>layout:
  actions:
    - '@add':
        id: product_rrp_price
        parentId: product_price_container
        blockType: container
        options:
            vars:
                rrp_price_data: '=data["product_rrp_price"].getRRPPrice(data["product"])'
</code>```

Additional Considerations

Your own use case may require customization (such as multiple attributes), and potentially a caching layer for performance reasons (such as storing the list of Price Attribute Price Lists in Redis etc instead of fetching them each time). If you plan on displaying this information on the PLP/Search pages I'd strongly recommend also including the price attributes in your search index rather than querying them for each of the 25 products per page.

Body:
Here is the code i am trying to use

    -  '@add':
            id: price_attribute_product_price
            parentId: product_view_specification
            blockType: product_prices
            options:
                label: visible

but it doesn't do anything!
Am i missing something?

Body:
That's how we did it too, although ours is hard-coded to the RRP attribute but it's pretty easy to customize this.

Sharing our code as I think it's been asked quite a few times in the community before.

We created our own custom Price Provider:

namespace Aligent\BaseBundle\Provider;

use Oro\Bundle\CurrencyBundle\Entity\Price;
use Oro\Bundle\EntityBundle\ORM\DoctrineHelper;
use Oro\Bundle\PricingBundle\Entity\PriceAttributePriceList;
use Oro\Bundle\PricingBundle\Entity\PriceAttributeProductPrice;
use Oro\Bundle\PricingBundle\Provider\PriceAttributePricesProvider;
use Oro\Bundle\ProductBundle\Entity\Product;

/**
 * Makes the rrp price attribute available.
 * The rrp price attribute can be found in db table: oro_price_attribute_pl
 */
class RRPPriceProvider
{
    const PRICE_ATTRIBUTE = 'RRP';

    protected DoctrineHelper $doctrineHelper;
    protected PriceAttributePricesProvider $priceAttributePricesProvider;

    /**
     * @param DoctrineHelper $doctrineHelper
     * @param PriceAttributePricesProvider $priceAttributePricesProvider
     */
    public function __construct(
        DoctrineHelper $doctrineHelper,
        PriceAttributePricesProvider $priceAttributePricesProvider
    ) {
        $this->doctrineHelper = $doctrineHelper;
        $this->priceAttributePricesProvider = $priceAttributePricesProvider;
    }

    /**
     * Get RRP price with unit and currencies from custom Product Price Attribute Price List
     * @param Product $product
     * @return array
     */
    public function getRRPPriceWithUnitAndCurrencies(Product $product) : array
    {
        /** @var PriceAttributePriceList $rrpPriceList */
        $rrpPriceList = $this->getRRPAttributePriceList();

        return $this->priceAttributePricesProvider->getPricesWithUnitAndCurrencies($rrpPriceList, $product);
    }

    /**
     * Get RRP price from custom Product Price Attribute Price List
     * @param Product $product
     * @return Price|null
     */
    public function getRRPPrice(Product $product) : ?Price
    {
        /** @var PriceAttributePriceList $rrpPriceList */
        $rrpPriceList = $this->getRRPAttributePriceList();

        /** @var PriceAttributeProductPrice $priceAttributePrice */
        $priceAttributePrice = $this->doctrineHelper
            ->getEntityRepository(PriceAttributeProductPrice::class)
            ->findOneBy(['product' => $product, 'priceList' => $rrpPriceList]);

        return $priceAttributePrice?->getPrice();
    }

    /**
     * Gets just the RRP Price Attribute Price List
     * @return PriceAttributePriceList|null
     */
    protected function getRRPAttributePriceList() : PriceAttributePriceList
    {
        return $this->doctrineHelper->getEntityRepository(PriceAttributePriceList::class)->findOneBy([
            'name' => self::PRICE_ATTRIBUTE,
        ]);
    }
}

And then we have a Layout DataProvider to make this available in the layouts:

namespace Aligent\BaseBundle\Layout\DataProvider;

use Aligent\BaseBundle\Provider\RRPPriceProvider;
use Oro\Bundle\ProductBundle\Entity\Product;

class RRPPriceLayoutProvider
{
    protected RRPPriceProvider $rrpPriceProvider;

    public function __construct(RRPPriceProvider $RRPPriceProvider)
    {
        $this->rrpPriceProvider = $RRPPriceProvider;
    }

    /**
     * Get RRP price with unit and currencies from custom Product Price Attribute Price List
     * Called from layout.yml via: =data["product_rrp_price"].getRRPPriceWithUnitAndCurrencies(data["entity"])'
     */
    public function getRRPPriceWithUnitAndCurrencies(Product $product) : array
    {
        return $this->rrpPriceProvider->getRRPPriceWithUnitAndCurrencies($product);
    }

    /**
     * Get RRP price from custom Product Price Attribute Price List
     * Called from layout.yml via: =data["product_rrp_price"].getRRPPrice(data["entity"])'
     */
    public function getRRPPrice(Product $product) : ?string
    {
        return $this->rrpPriceProvider->getRRPPrice($product)?->getValue();
    }
}

services.yml:

services:
    # Providers
    Aligent\BaseBundle\Provider\RRPPriceProvider:
        arguments:
            - '@oro_api.doctrine_helper'
            - '@oro_pricing.providers.price_attribute_prices'

    # Layout Providers
    Aligent\BaseBundle\Layout\DataProvider\RRPPriceLayoutProvider:
        arguments:
            - '@Aligent\BaseBundle\Provider\RRPPriceProvider'
        tags:
            - { name: layout.data_provider, alias: product_rrp_price }

And then actually call it from your layout.yml:

layout:
  actions:
    - '@add':
        id: product_rrp_price
        parentId: product_price_container
        blockType: container
        options:
            vars:
                rrp_price_data: '=data["product_rrp_price"].getRRPPrice(data["product"])'

Additional Considerations

Your own use case may require customization (such as multiple attributes), and potentially a caching layer for performance reasons (such as storing the list of Price Attribute Price Lists in Redis etc instead of fetching them each time). If you plan on displaying this information on the PLP/Search pages I'd strongly recommend also including the price attributes in your search index rather than querying them for each of the 25 products per page.


问:
How can I add a new tab to an existing sheet via the Google Sheets API?
I tried reading through the api docs but failed to find directions to perform queries regarding the existence of tabs and to create a tab if one does not exist.
Does anyone have a clue?</p>

答:
If you are looking for how to do this in java, here's a function that does it.

  /**
   * Adds a new tab to an existing GoogleSheet document.
   * @param service An authenticated GoogleSheet service
   * @param sheetName The GoogleSheet name of the document
   * @param tabName The name of the tab you wish to add to the GoogleSheet document
   * @return The response from adding the sheet.
   * @throws IOException Throws an IOException if anything goes wrong.
   */
  public static BatchUpdateSpreadsheetResponse AddTabToGoogleSheet(Sheets service, String sheetName, String tabName)
    throws IOException {
    List<Request> requests = new ArrayList<>();
    requests.add(new Request().setAddSheet(new AddSheetRequest().setProperties(new SheetProperties()
      .setTitle(tabName))));
    BatchUpdateSpreadsheetRequest body = new BatchUpdateSpreadsheetRequest().setRequests(requests);
    return service.spreadsheets().batchUpdate(sheetName, body).execute();
  }
```


问:
How do you write an IsPressed (a function that should only return true on first press)?
I need a function in a game loop that should only return true on first press.

I don't know which game I can give an example from which game is currently on the market, but I will explain this request in detail (I haven't played/can't play any of the modern games because I'm blind).

For example, there is an event you are listening to in the loop. When the user presses the S key, a text showing the last status of the character appears on the screen: Stamina, energy etc.
This loop can run thousands of times per second, as the loops depend on the speed of the hardware and the code you write.
We only need to detect the first press of the user. It should return false when the key is hold pressed. Otherwise, the last status of the user is shown thousands of times on the screen.

I am trying to provide this functionality using win32api. GetAsyncKeyState seems like the right option for this scenario but I don't understand how this can be done.

bool IsPressed(int key) {
return GetAsyncKeyState(key) & 1 != 0;
}
```

The function I wrote acts like a char event.

How can I write this?

I tried using other answers on StackOwerflow. However, I could not find an answer to the question I asked. Still, these answers helped me with some issues:
What is the fastest way to determine a key press and key holding in Win32?

答:
After working on it a more, I realized that I cannot do this with GetAsyncKeyState or a similar function. I wrote something simple using Windows' callback and event system.
I didn't care about data race and other issues. You probably need to use a mutex but that depends on your code.

The code below keeps the state of the keys in an array. Changes are sent to the array with a function by the callback.

If you compile the program in console mode, you will see that it is printed to the console only once when you press A. It was exactly what I was looking for.

To compile you can use:

g++ minimal.cpp

You can press a to test it on a standard querty keyboard.

#include <iostream>
#include <windows.h>
#include <vector>

// We define a struct that holds the key state.
// firstPress will be updated by IsPressed.
struct keyState {
    bool firstPress;
    bool down;
};

// We have an Array-based collection of keys. Changes will be made by callback.
std::vector<keyState> allKeyStates(256);

void keyProcess(unsigned short key, bool down)
{
        if(down) {
        if(!allKeyStates[key].down) {
            allKeyStates[key].down = true;
            allKeyStates[key].firstPress = true;
        }
        return;
    }
    allKeyStates[key].down = false;
    allKeyStates[key].firstPress = false;
}

bool IsPressed(unsigned short key)
{
    if(allKeyStates[key].firstPress) {
        allKeyStates[key].firstPress = false;
        return true;
    }
    return false;
}

// forward decleration
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int main()
{
MSG msg          = {0};
    HWND handle;

    WNDCLASS wc      = {0};
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = GetModuleHandle(NULL);
    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = "mini_windows_test";
    if( !RegisterClass(&wc) )
        return -1;
    handle = CreateWindow(wc.lpszClassName, "Minimal Key handling application", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0, 640, 480, 0, 0, GetModuleHandle(NULL), NULL);
    if(handle == NULL)
        return -1;

    while(GetMessage(&msg, NULL, 0, 0 ) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        if(IsPressed(0x41)) {
            std::cout << "Key A: it will only be print on the first press. Holding the key will not run repeatedly.\n";
        }
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message) {
        case WM_KEYDOWN:
            keyProcess((unsigned short)wParam, true);
            break;
        case WM_KEYUP:
            keyProcess((unsigned short)wParam, false);
            break;
    case WM_CLOSE:
        PostQuitMessage(0);
    break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
 }
return 0;
}
```

Apologize for the bady English and typos. You can edit my question and my answer if it works for you.

Body:
I need a function in a game loop that should only return true on first press.

I don't know which game I can give an example from which game is currently on the market, but I will explain this request in detail (I haven't played/can't play any of the modern games because I'm blind).

For example, there is an event you are listening to in the loop. When the user presses the S key, a text showing the last status of the character appears on the screen: Stamina, energy etc.
This loop can run thousands of times per second, as the loops depend on the speed of the hardware and the code you write.
We only need to detect the first press of the user. It should return false when the key is hold pressed. Otherwise, the last status of the user is shown thousands of times on the screen.

I am trying to provide this functionality using win32api. GetAsyncKeyState seems like the right option for this scenario but I don't understand how this can be done.

bool IsPressed(int key) {
return GetAsyncKeyState(key) & 1 != 0;
}

The function I wrote acts like a char event.

How can I write this?

I tried using other answers on StackOwerflow. However, I could not find an answer to the question I asked. Still, these answers helped me with some issues:
What is the fastest way to determine a key press and key holding in Win32?

Body:
After working on it a more, I realized that I cannot do this with GetAsyncKeyState or a similar function. I wrote something simple using Windows' callback and event system.
I didn't care about data race and other issues. You probably need to use a mutex but that depends on your code.

The code below keeps the state of the keys in an array. Changes are sent to the array with a function by the callback.

If you compile the program in console mode, you will see that it is printed to the console only once when you press A. It was exactly what I was looking for.

To compile you can use:

g++ minimal.cpp

You can press a to test it on a standard querty keyboard.

#include <iostream>
#include <windows.h>
#include <vector>

// We define a struct that holds the key state.
// firstPress will be updated by IsPressed.
struct keyState {
    bool firstPress;
    bool down;
};

// We have an Array-based collection of keys. Changes will be made by callback.
std::vector<keyState> allKeyStates(256);

void keyProcess(unsigned short key, bool down)
{
        if(down) {
        if(!allKeyStates[key].down) {
            allKeyStates[key].down = true;
            allKeyStates[key].firstPress = true;
        }
        return;
    }
    allKeyStates[key].down = false;
    allKeyStates[key].firstPress = false;
}

bool IsPressed(unsigned short key)
{
    if(allKeyStates[key].firstPress) {
        allKeyStates[key].firstPress = false;
        return true;
    }
    return false;
}

// forward decleration
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int main()
{
MSG msg          = {0};
    HWND handle;

    WNDCLASS wc      = {0};
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = GetModuleHandle(NULL);
    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = "mini_windows_test";
    if( !RegisterClass(&wc) )
        return -1;
    handle = CreateWindow(wc.lpszClassName, "Minimal Key handling application", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0, 640, 480, 0, 0, GetModuleHandle(NULL), NULL);
    if(handle == NULL)
        return -1;

    while(GetMessage(&msg, NULL, 0, 0 ) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        if(IsPressed(0x41)) {
            std::cout << "Key A: it will only be print on the first press. Holding the key will not run repeatedly.\n";
        }
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message) {
        case WM_KEYDOWN:
            keyProcess((unsigned short)wParam, true);
            break;
        case WM_KEYUP:
            keyProcess((unsigned short)wParam, false);
            break;
    case WM_CLOSE:
        PostQuitMessage(0);
    break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
 }
return 0;
}

Apologize for the bady English and typos. You can edit my question and my answer if it works for you.


答:
Your question give me the same doubt. So I look in to it. This is what I have found:

From de RxJS docs

A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.

So you can do the same just that Observable cant modify the value with a next(value) call.

This article is quite good, explains your doubt about best practice and this example is from there:

In the RxJS world it's considered best practice to only expose Subjects to the parts of your application that would add new data into the Observable sequence. This is the same idea behind only allowing write access to certain parts of your application, private and public class members, etc.

To create an Observable from a Subject, you can simply invoke asObservable on any Subject:

```<code>let currentUserSubject$ = new BehaviorSubject() < string > 'Eric';
let currentUser$ = currentUserSubject$.asObservable();
</code>```

We now have a new variable called currentUser$ that is an Observable of currentUserSubject$'s observable sequence. To see how this works, lets subscribe to the currentUser observable and then add some data to the currentUserSubject$:

```<code>let currentUserSubject$ = new BehaviorSubject() < string > 'Eric';
let currentUser$ = currentUserSubject$.asObservable();

currentUserSubject$.subscribe(val => {
  console.log(val);
});
// => 'Eric'

currentUserSubject$.next('hello');
// => 'hello'
</code>```

Note that if you try and call currentUser$.next(), it will throw an error because Observables can only observe a sequence - thus providing you with read-only access to the currentUserSubject!

Title: Angular parent and children communication using a service?

Body:
Your question give me the same doubt. So I look in to it. This is what I have found:

From de RxJS docs

A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.

So you can do the same just that Observable cant modify the value with a next(value) call.

This article is quite good, explains your doubt about best practice and this example is from there:

In the RxJS world it's considered best practice to only expose Subjects to the parts of your application that would add new data into the Observable sequence. This is the same idea behind only allowing write access to certain parts of your application, private and public class members, etc.

To create an Observable from a Subject, you can simply invoke asObservable on any Subject:

let currentUserSubject$ = new BehaviorSubject() < string > 'Eric';
let currentUser$ = currentUserSubject$.asObservable();

We now have a new variable called currentUser$ that is an Observable of currentUserSubject$'s observable sequence. To see how this works, lets subscribe to the currentUser observable and then add some data to the currentUserSubject$:

let currentUserSubject$ = new BehaviorSubject() < string > 'Eric';
let currentUser$ = currentUserSubject$.asObservable();

currentUserSubject$.subscribe(val => {
  console.log(val);
});
// => 'Eric'

currentUserSubject$.next('hello');
// => 'hello'

Note that if you try and call currentUser$.next(), it will throw an error because Observables can only observe a sequence - thus providing you with read-only access to the currentUserSubject!


问:
Run SQL Update Inside a For Loop
Mission:  Verify that "players" have placed vintage promotional jpegs on their social media site(s). Doing so earns them crypto tokens towards game play. All non-verified postings are displayed on an administrator's dashboard with a checkbox if the listing has been visually verified and "Approved." The value of each checkbox is the database ID of the listing (see screen capture). Once the listings have been verified and the check box ticked, the page is POST(ed) to a query page where the default value "confirm" is changed from 0 to 1. This then awards them the designated tokens.

enter image description here

However, I haven't found the right formula of code to get the UDPATE to work. The checkbox values will display in "echo" mode, but the SQL won't function within the FOREACH loop.

```<code>    <?php

    $checked_arr = $_POST['checkbox'];
    $count = count($checked_arr);
    echo "There are ".$count." checkboxe(s) are checked <br>";
    foreach($_POST['checkbox'] as $val)     {
          $sql = "UPDATE media SET confirm = 1 WHERE id = $val " ;
          echo "$val\n";
    ?>
</code>```

Scoured the Net for working examples, including Stack Overflow, but to no avail. Assume there's a simple answer here, but as a novice PHP programmer, it eludes me.

Thank you in advance for suggestions.

答:
you could use the IN operation in the conditional.

The only thing you would have to do is capture all the IDS and do an "implode" to give it the format that is needed for the sql.

for example:

```<code><?php
$ids = [];
foreach($_POST['checkbox'] as $val){
  $ids[] = $val;
}
$values = implode(",", $ids); // => 'id1, id2, id3, ...'
// this is a massive update based on selected items
$sql = "UPDATE media SET confirm = 1 WHERE id IN ($values)";
?>
</code>```

Title: Run SQL Update Inside a For Loop

Body:
Mission:  Verify that "players" have placed vintage promotional jpegs on their social media site(s). Doing so earns them crypto tokens towards game play. All non-verified postings are displayed on an administrator's dashboard with a checkbox if the listing has been visually verified and "Approved." The value of each checkbox is the database ID of the listing (see screen capture). Once the listings have been verified and the check box ticked, the page is POST(ed) to a query page where the default value "confirm" is changed from 0 to 1. This then awards them the designated tokens.

enter image description here

However, I haven't found the right formula of code to get the UDPATE to work. The checkbox values will display in "echo" mode, but the SQL won't function within the FOREACH loop.

    <?php

    $checked_arr = $_POST['checkbox'];
    $count = count($checked_arr);
    echo "There are ".$count." checkboxe(s) are checked
";
    foreach($_POST['checkbox'] as $val)     {
          $sql = "UPDATE media SET confirm = 1 WHERE id = $val " ;
          echo "$val\n";
    ?>

Scoured the Net for working examples, including Stack Overflow, but to no avail. Assume there's a simple answer here, but as a novice PHP programmer, it eludes me.

Thank you in advance for suggestions.

Body:
you could use the IN operation in the conditional.

The only thing you would have to do is capture all the IDS and do an "implode" to give it the format that is needed for the sql.

for example:

<?php
$ids = [];
foreach($_POST['checkbox'] as $val){
  $ids[] = $val;
}
$values = implode(",", $ids); // => 'id1, id2, id3, ...'
// this is a massive update based on selected items
$sql = "UPDATE media SET confirm = 1 WHERE id IN ($values)";
?>


问:
Node.js crypto.randomBytes() is not a function
For some reason a function I am trying to use is, apparently, not a function.

```<code>Welcome to Node.js v14.15.1.
Type ".help" for more information.
> const crypto = require("crypto");
undefined
> x = crypto.randomBytes(32).toString("hex")
Uncaught TypeError: crypto.randomBytes is not a function
</code>```

Documentation for randomBytes().

Is there something I am not understanding?

答:
Seems getRandomBytes() function got removed. I read some disclaimers that it is not very secure.

https://www.npmjs.com/package/crypto is clustured with deprecation messages so altough most upvotes here under https://stackoverflow.com/a/8856177/828184 it does no longer seem state of the art to me.

Before I could simply use (like you but no longer after package updates)

```<code>import crypto from "crypto";
const token = crypto.randomBytes(64).toString('hex');
</code>```

But crypto now only has getRandomValues() and I think it is not a replacement.

Only answer nr 3 with also a lot but not as many upvotes gave me a working version https://stackoverflow.com/a/25690754/828184. So maybe also try:

```<code>import { nanoid } from "nanoid";
const token = nanoid(64); //instead of crypto.randomBytes(64).toString('hex')
</code>```

And leave an upvote there if it works because.

Body:
For some reason a function I am trying to use is, apparently, not a function.

Welcome to Node.js v14.15.1.
Type ".help" for more information.
> const crypto = require("crypto");
undefined
> x = crypto.randomBytes(32).toString("hex")
Uncaught TypeError: crypto.randomBytes is not a function

Documentation for randomBytes().

Is there something I am not understanding?

Body:
Seems getRandomBytes() function got removed. I read some disclaimers that it is not very secure.

https://www.npmjs.com/package/crypto is clustured with deprecation messages so altough most upvotes here under https://stackoverflow.com/a/8856177/828184 it does no longer seem state of the art to me.

Before I could simply use (like you but no longer after package updates)

import crypto from "crypto";
const token = crypto.randomBytes(64).toString('hex');

But crypto now only has getRandomValues() and I think it is not a replacement.

Only answer nr 3 with also a lot but not as many upvotes gave me a working version https://stackoverflow.com/a/25690754/828184. So maybe also try:

import { nanoid } from "nanoid";
const token = nanoid(64); //instead of crypto.randomBytes(64).toString('hex')

And leave an upvote there if it works because.


问:
Regular expression to get last 3 characters of a string
I want to write a regular expression which will take only last 3 char of a string and append some constant string to it.

I am using C#. I am trying to make regular expression as database entry. Later Read this entry in application and do the transformation based on regex in C#.

Something like :

```<code>stringVal.Trim().Substring(0, stringVal.Trim().Length - 3) + ".ConstantValue"
</code>```

答:
w{3}$

w or \w (vary in different language)

Matches any alphanumeric character from the basic Latin alphabet, including the underscore. Equivalent to [A-Za-z0-9_]. For example, /\w/ matches "a" in "apple", "5" in "$5.28", "3" in "3D" and "m" in "Émanuel".

x{n}

Where "n" is a positive integer, matches exactly "n" occurrences of the preceding item "x". For example, /a{2}/ doesn't match the "a" in "candy", but it matches all of the "a"'s in "caandy", and the first two "a"'s in "caaandy".

$

Matches the end of input. If the multiline flag is set to true, also matches immediately before a line break character. For example, /t$/ does not match the "t" in "eater", but does match it in "eat".

Body:
I want to write a regular expression which will take only last 3 char of a string and append some constant string to it.

I am using C#. I am trying to make regular expression as database entry. Later Read this entry in application and do the transformation based on regex in C#.

Something like :

stringVal.Trim().Substring(0, stringVal.Trim().Length - 3) + ".ConstantValue"


问:
CKEditor 5 - insert text
Is it possible to insert text into the editor at current selection?

I have tried

```<code>import Text from '@ckeditor/ckeditor5-engine/src/model/text';

function insertText() {
  let text = new Text('test');
  ckEditor.model.insertContent(text, ckEditor.model.document.selection);
}
</code>```

where ckEditor is the editor object returned from ClassicEditor.create

code runs without error, but nothing happens

I have managed to get similar code to work from within a plugin, but here I am trying to inject the text from the host app

答:
Just to add, to enable the input focus after inserting the text, add this code.

editor.editing.view.focus()
```

Title: CKEditor 5 - insert text

Body:
Is it possible to insert text into the editor at current selection?

I have tried

import Text from '@ckeditor/ckeditor5-engine/src/model/text';

function insertText() {
  let text = new Text('test');
  ckEditor.model.insertContent(text, ckEditor.model.document.selection);
}

where ckEditor is the editor object returned from ClassicEditor.create

code runs without error, but nothing happens

I have managed to get similar code to work from within a plugin, but here I am trying to inject the text from the host app


问:
LINQ to count number of rows in link table
I have the following model

```<code>public class Account
{
    public int Id { get; set; }
    public List<Note> Notes { get; set; }
}
</code>```

I'm trying to query my nhibernate repository to count the number of notes for a specific account.

return this.Data.Where(x => x.Id == accountId).Select(x => x.Notes).Count();

However no matter how many notes there are, it always returns 1.

I am trying to do this in the most efficient way possible without having to get the account object and then count the number of notes.

Can anyone suggest the Linq equivalent of the following SQL.

SELECT Count(*) FROM NoteToAccount WHERE AccountId=?

Where NoteToAccount is a link table which sits between the Account and Note tables.

答:
You want to use</p>

```<code>.SelectMany(x => x.Notes)
</code>```

Body:
I have the following model

public class Account
{
    public int Id { get; set; }
    public List<Note> Notes { get; set; }
}

I'm trying to query my nhibernate repository to count the number of notes for a specific account.

return this.Data.Where(x => x.Id == accountId).Select(x => x.Notes).Count();

However no matter how many notes there are, it always returns 1.

I am trying to do this in the most efficient way possible without having to get the account object and then count the number of notes.

Can anyone suggest the Linq equivalent of the following SQL.

SELECT Count(*) FROM NoteToAccount WHERE AccountId=?

Where NoteToAccount is a link table which sits between the Account and Note tables.

Body:
You want to use

.SelectMany(x => x.Notes)