void MangaListWidget::goToRead(QModelIndex modelIndex) {
  QStandardItem* currentItem = _model->itemFromIndex(modelIndex);
  QStandardItem* currentItemParent = currentItem->parent();

  if (currentItemParent == nullptr)
    return;

  markRead();

  emit chapterSelected(currentItemParent->text(), currentItem->text());
}
NewsItem::NewsItem(int idFeed, int idNews, int width, QWidget * parent)
  : QWidget(parent)
  , feedId_(idFeed)
  , newsId_(idNews)
  , read_(false)
{
  setCursor(Qt::PointingHandCursor);
  setMinimumHeight(17);

  iconLabel_ = new QLabel(this);
  iconLabel_->setFixedWidth(19);

  textLabel_ = new QLabel(this);
  textLabel_->setFixedWidth(width);
  textLabel_->setStyleSheet("QLabel:hover {color: #1155CC;}");

  readButton_ = new ToolButton(this);
  readButton_->setIcon(QIcon(":/images/bulletUnread"));
  readButton_->setToolTip(tr("Mark Read/Unread"));
  readButton_->setAutoRaise(true);

  openExternalBrowserButton_ = new ToolButton(this);
  openExternalBrowserButton_->setIcon(QIcon(":/images/openBrowser"));
  openExternalBrowserButton_->setAutoRaise(true);

  deleteButton_ = new ToolButton(this);
  deleteButton_->setIcon(QIcon(":/images/editClear"));
  deleteButton_->setToolTip(tr("Delete News"));
  deleteButton_->setAutoRaise(true);

  QHBoxLayout *mainLayout = new QHBoxLayout();
  mainLayout->setMargin(0);
  mainLayout->setSpacing(1);
  mainLayout->addWidget(readButton_);
  mainLayout->addWidget(iconLabel_);
  mainLayout->addWidget(textLabel_, 1);
  mainLayout->addStretch(0);
  mainLayout->addWidget(openExternalBrowserButton_);
  mainLayout->addWidget(deleteButton_);
  setLayout(mainLayout);

  connect(readButton_, SIGNAL(clicked()), this, SLOT(markRead()));
  connect(openExternalBrowserButton_, SIGNAL(clicked()), this, SLOT(openExternalBrowser()));
  connect(deleteButton_, SIGNAL(clicked()), this, SLOT(deleteNews()));

  installEventFilter(this);
}
Example #3
0
void ChatChannel::doSetActive(bool active)
{
	if (active)
		markRead(Q_UINT64_C(0xffffffffffffffff));
}
Example #4
0
void
LocalConnection_as::update()
{
    // Check whether local connection is disabled(!): brilliant choice of
    // function name.
    if (rcfile.getLocalConnection()) {
        log_security("Attempting to write to disabled LocalConnection!");
        movie_root& mr = getRoot(owner());
        mr.removeAdvanceCallback(this);
        return;
    }

    // No-op if already attached. Nothing to do if it fails, but we
    // should probably stop trying.
    if (!_shm.attach()) {
        log_error("Failed to attach shared memory segment");
        return;
    }

    // We need the lock to prevent simultaneous reads/writes from other
    // processes.
    SharedMem::Lock lock(_shm);
    if (!lock.locked()) {
        log_debug("Failed to get shm lock");
        return;
    }

    SharedMem::iterator ptr = _shm.begin();
    
    // First check timestamp data.

    // These are not network byte order by default, but not sure about 
    // host byte order.
    const boost::uint32_t timestamp = readLong(ptr + 8);
    const boost::uint32_t size = readLong(ptr + 12);

    // As long as there is a timestamp in the shared memory, we mustn't
    // write anything.
    //
    // We check if this is data we are listening for. If it is, read it and
    // mark for overwriting.
    //
    // If not, we keep checking until the data has been overwritten by
    // another listener or until it's expired. If it's expired, we
    // mark for overwriting.
    if (timestamp) {

        // Start after 16-byte header.
        const boost::uint8_t* b = ptr + 16;

        // End at reported size of AMF sequence.
        const boost::uint8_t* end = b + size;

        amf::Reader rd(b, end, getGlobal(owner()));
        as_value a;

        // Get the connection name. That's all we need to remove expired
        // data.
        if (!rd(a)) {
            log_error("Invalid connection name data");
            return;
        }
        const std::string& connection = a.to_string();

        // Now check if data we wrote has expired. There's no really
        // reliable way of checking that we genuinely wrote it.
        if (_lastTime == timestamp) {
            
            const size_t timeout = 4 * 1000;

            VM& vm = getVM(owner());
            const boost::uint32_t timeNow = getTimestamp(vm);

            if (timeNow - timestamp > timeout) {
                log_debug("Data %s expired at %s. Removing its target "
                        "as a listener", timestamp, timeNow);
                removeListener(connection, _shm);
                markRead(_shm);
                _lastTime = 0;
            }
        }

        // If we are listening and the data is for us, get the rest of it
        // and call the method.
        if (_connected && connection == _domain + ":" + _name) {
            executeAMFFunction(owner(), rd);
            // Zero the timestamp bytes to signal that the shared memory
            // can be written again.
            markRead(_shm);
        }
        else {
            // The data has not expired and we didn't read it. Leave it
            // alone until it's expired or someone else has read it.
            return;
        }
    }

    // If we have no data to send, there's nothing more to do.
    if (_queue.empty()) {
        // ...except remove the callback if we aren't listening for anything.
        if (!_connected) {
            movie_root& mr = getRoot(owner());
            mr.removeAdvanceCallback(this);
        }
        return;
    }

    // Get the first buffer.
    boost::shared_ptr<ConnectionData> cd = _queue.front();
    _queue.pop_front();

    // If the correct listener isn't there, iterate until we find one or
    // there aren't any left.
    while (!findListener(_domain + ":" + cd->name, _shm)) {
        if (_queue.empty()) {
            // Make sure we send the empty header later.
            cd->ts = 0;
            break;
        }
        cd = _queue.front();
        _queue.pop_front();
    }

    // Yes, there is data to send.
    const char i[] = { 1, 0, 0, 0, 1, 0, 0, 0 };
    std::copy(i, i + arraySize(i), ptr);

    SimpleBuffer& buf = cd->data;

    SharedMem::iterator tmp = ptr + 8;
    writeLong(tmp, cd->ts);
    writeLong(tmp, cd->ts ? buf.size() : 0);
    std::copy(buf.data(), buf.data() + buf.size(), tmp);

    // Note the timestamp of our last send. We will keep calling update()
    // until the data has expired or been read.
    _lastTime = cd->ts;

}
MangaListWidget::MangaListWidget(QWidget* parent):
  QWidget(parent),
  _scansDirectory(Utils::getScansDirectory()),
  _currentChaptersListOnWeb(),
  _chaptersToCheck(),
  _currentIndex(),
  _editOn(false),
  _coverHasToBeSet(false) {


  /// Available chapters process

  _checkAvailableChaptersProcess = new QProcess(this);
  connect(_checkAvailableChaptersProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(checkAvailableChapterIsDone(int,QProcess::ExitStatus)));
  connect(_checkAvailableChaptersProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));


  /// Top buttons

  _markReadButton = new QPushButton;
  _markReadButton->setIcon(QIcon(Utils::getIconsPath()+"/check.gif"));
  _markReadButton->setFixedWidth(37);
  connect(_markReadButton, SIGNAL(clicked()), this, SLOT(markRead()));

  _markUnreadButton = new QPushButton;
  _markUnreadButton->setIcon(QIcon(Utils::getIconsPath()+"/uncheck.gif"));
  _markUnreadButton->setFixedWidth(37);
  connect(_markUnreadButton, SIGNAL(clicked()), this, SLOT(markUnread()));

  _downloadButton = new QPushButton;
  _downloadButton->setIcon(QIcon(Utils::getIconsPath()+"/download.gif"));
  _downloadButton->setFixedWidth(37);
  connect(_downloadButton, SIGNAL(clicked()), this, SLOT(goToDownload()));

  _addMangaButton = new QPushButton;
  _addMangaButton->setIcon(QIcon(Utils::getIconsPath()+"/plus.png"));
  _addMangaButton->setFixedWidth(37);
  connect(_addMangaButton, SIGNAL(clicked()), this, SLOT(addManga()));

  _checkNewChaptersButton = new QPushButton;
  _checkNewChaptersButton->setIcon(QIcon(Utils::getIconsPath()+"/checkChapters.png"));
  _checkNewChaptersButton->setFixedWidth(37);
  connect(_checkNewChaptersButton, SIGNAL(clicked()), this, SLOT(decorateMangaNames()));

  QHBoxLayout* buttonsLayout = new QHBoxLayout;
  buttonsLayout->addWidget(_markReadButton);
  buttonsLayout->addWidget(_markUnreadButton);
  buttonsLayout->addWidget(_downloadButton);
  buttonsLayout->addWidget(_addMangaButton);
  buttonsLayout->addWidget(_checkNewChaptersButton);
  buttonsLayout->setAlignment(Qt::AlignHCenter);


  /// Manga information

  QPixmap pixmap(Utils::getIconsPath()+"/setCover.png");

  _mangaPreviewLabel = new QLabel;
  _mangaPreviewLabel->setFixedHeight(400);
  _mangaPreviewLabel->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
  _mangaPreviewLabel->setStyleSheet("margin: 20px;");
  _mangaPreviewLabel->setAttribute(Qt::WA_Hover);
  _mangaPreviewLabel->installEventFilter(this);
  _mangaPreviewLabel->setPixmap(pixmap);

  _genreLabel = new QLabel;
  _genreLabel->setFont(QFont("Monospace", 8));
  _authorLabel = new QLabel;
  _authorLabel->setFont(QFont("Monospace", 8));
  _artistLabel = new QLabel;
  _artistLabel->setFont(QFont("Monospace", 8));
  _publisherLabel = new QLabel;
  _publisherLabel->setFont(QFont("Monospace", 8));
  _magazineLabel = new QLabel;
  _magazineLabel->setFont(QFont("Monospace", 8));
  _startDateLabel = new QLabel;
  _startDateLabel->setFont(QFont("Monospace", 8));

  _editMangaInfoButton = new QPushButton("Edit");
  _editMangaInfoButton->setCheckable(true);
  _editMangaInfoButton->setFixedWidth(100);
  connect(_editMangaInfoButton, SIGNAL(toggled(bool)), this, SLOT(toggleEditMangaInfo(bool)));

  QFormLayout* genreLayout = new QFormLayout;
  genreLayout->addRow("Genre:", _genreLabel);
  QFormLayout* authorLayout = new QFormLayout;
  authorLayout->addRow("Author:", _authorLabel);
  QFormLayout* artistLayout = new QFormLayout;
  artistLayout->addRow("Artist:", _artistLabel);
  QFormLayout* publisherLayout = new QFormLayout;
  publisherLayout->addRow("Publisher:", _publisherLabel);
  QFormLayout* magazineLayout = new QFormLayout;
  magazineLayout->addRow("Magazine:", _magazineLabel);
  QFormLayout* startDateLayout = new QFormLayout;
  startDateLayout->addRow("Start date:", _startDateLabel);

  QVBoxLayout* mangaInfoLayout = new QVBoxLayout;
  mangaInfoLayout->addWidget(_mangaPreviewLabel);
  mangaInfoLayout->addLayout(genreLayout);
  mangaInfoLayout->addLayout(authorLayout);
  mangaInfoLayout->addLayout(artistLayout);
  mangaInfoLayout->addLayout(publisherLayout);
  mangaInfoLayout->addLayout(magazineLayout);
  mangaInfoLayout->addLayout(startDateLayout);
  mangaInfoLayout->addWidget(_editMangaInfoButton);
  mangaInfoLayout->setAlignment(Qt::AlignTop);

  QGroupBox* mangaInfoGroupBox = new QGroupBox("Information");
  mangaInfoGroupBox->setLayout(mangaInfoLayout);
  mangaInfoGroupBox->setFixedWidth(350);
  mangaInfoGroupBox->setAlignment(Qt::AlignLeft);


  /// Chapters model

  _model = new QStandardItemModel;
  initModel();


  /// Chapters view

  _chapterInfoWidget = new ChapterInfoWidget;

  _view = new QColumnView;
  QList<int> widths;
  widths << 300 << 400 << 400;
  _view->setColumnWidths(widths);
  _view->setResizeGripsVisible(false);
  _view->setFixedWidth(1102);
  _view->setSelectionMode(QAbstractItemView::ExtendedSelection);
  _view->setModel(_model);
  _view->setPreviewWidget(_chapterInfoWidget);
  connect(_view, SIGNAL(updatePreviewWidget(QModelIndex)), this, SLOT(updateChaptersInfo(QModelIndex)));
  connect(_view, SIGNAL(clicked(QModelIndex)), this, SLOT(updateMangaInfo(QModelIndex)));
  connect(_view, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(goToRead(QModelIndex)));

  QHBoxLayout* listLayout = new QHBoxLayout;
  listLayout->addWidget(mangaInfoGroupBox);
  listLayout->addWidget(_view);

  QStringList headerLabels;
  headerLabels << "Manga";
  _model->setHorizontalHeaderLabels(headerLabels);


  /// Set current index to first manga if any

  _view->setCurrentIndex(_model->index(0, 0));
  updateMangaInfo(_model->index(0, 0));


  /// Main layout

  QLabel* titleLabel = new QLabel("Manga List");
  titleLabel->setFont(QFont("", 18, 99));

  QVBoxLayout* mainLayout = new QVBoxLayout;
  mainLayout->addWidget(titleLabel);
  mainLayout->addLayout(buttonsLayout);
  mainLayout->addLayout(listLayout);

  setLayout(mainLayout);


  /// Schedule a new available manga check every thirty minutes

  QTimer* timer = new QTimer(this);
  connect(timer, SIGNAL(timeout()), this, SLOT(decorateMangaNames()));
  timer->start(1000*60*30);
}