void DataFilterUploader::UploadToAcc (const QByteArray& accId) { const auto acc = AccMgr_->GetAccount (accId); if (!acc) { qWarning () << Q_FUNC_INFO << "no account for ID" << accId; deleteLater (); return; } const auto& image = Entity_.Entity_.value<QImage> (); const auto& localFile = Entity_.Entity_.toUrl ().toLocalFile (); if (!image.isNull ()) { auto tempFile = new QTemporaryFile { this }; Entity_.Entity_.value<QImage> ().save (tempFile, "PNG", 0); UploadFileName_ = tempFile->fileName (); } else if (QFile::exists (localFile)) UploadFileName_ = localFile; const auto dia = new UploadPhotosDialog { acc->GetQObject () }; dia->LockFiles (); dia->SetFiles ({ { UploadFileName_, {} } }); dia->open (); dia->setAttribute (Qt::WA_DeleteOnClose); new Util::SlotClosure<Util::DeleteLaterPolicy> { [this, dia, acc] { connect (acc->GetQObject (), SIGNAL (itemUploaded (UploadItem, QUrl)), this, SLOT (checkItemUploaded (UploadItem, QUrl))); const auto isu = qobject_cast<ISupportUploads*> (acc->GetQObject ()); isu->UploadImages (dia->GetSelectedCollection (), dia->GetSelectedFiles ()); }, dia, SIGNAL (accepted ()), dia }; connect (dia, SIGNAL (rejected ()), this, SLOT (deleteLater ())); }
void NotificationsManager::handleLocationChanged (const QString& variant) { const auto entry = qobject_cast<ICLEntry*> (sender ()); const auto acc = entry->GetParentAccount (); const auto isg = qobject_cast<ISupportGeolocation*> (acc->GetQObject ()); if (!isg) { qWarning () << Q_FUNC_INFO << "account" << acc->GetQObject () << "does not implement ISupportGeolocation"; return; } const auto& infoMap = isg->GetUserGeolocationInfo (sender (), variant); const auto& info = [&infoMap] { bool lonOk = false; bool latOk = false; GeolocationInfo info { true, infoMap ["lon"].toDouble (&lonOk), infoMap ["lat"].toDouble (&latOk), infoMap ["country"].toString (), infoMap ["locality"].toString () }; info.IsValid_ = lonOk && latOk; return info; } (); const auto& text = GetHRLocationText (entry, info); auto e = Util::MakeNotification ("LeechCraft", text, PInfo_); e.Mime_ += "+advanced"; BuildNotification (e, entry, "LocationChangeEvent"); e.Additional_ ["org.LC.AdvNotifications.EventType"] = AN::TypeIMEventLocationChange; e.Additional_ ["org.LC.AdvNotifications.FullText"] = text; e.Additional_ ["org.LC.AdvNotifications.ExtendedText"] = text; e.Additional_ ["org.LC.AdvNotifications.Count"] = 1; e.Additional_ [AN::Field::IMLocationLongitude] = info.Lon_; e.Additional_ [AN::Field::IMLocationLatitude] = info.Lat_; EntityMgr_->HandleEntity (e); }
void RadioManager::AddUrl (const QModelIndex& index, const QUrl& url, const QString& name) { WithSourceProv (index, [url, name] (Media::IRadioStationProvider *prov, const QModelIndex& srcIdx) { const auto radio = prov->GetRadioStation (srcIdx, {}); if (!radio) { qWarning () << Q_FUNC_INFO << "got a null radio station from provider"; return; } auto modifiable = qobject_cast<Media::IModifiableRadioStation*> (radio->GetQObject ()); if (!modifiable) { qWarning () << Q_FUNC_INFO << radio->GetRadioName () << "is not modifiable"; return; } modifiable->AddItem (url, name); }); }
void RecommendationsWidget::InitializeProviders () { const auto& provs = Core::Instance ().GetProxy ()->GetPluginsManager ()-> GetAllCastableTo<Media::IRecommendedArtists*> (); for (auto prov : provs) { const auto pending = prov->RequestRecommended (10); new Util::SlotClosure<Util::DeleteLaterPolicy> { [this, pending] { HandleInfos (pending->GetSimilar ()); }, pending->GetQObject (), SIGNAL (ready ()), pending->GetQObject () }; } }
void RadioManager::RemoveUrl (const QModelIndex& index) { WithSourceProv (index, [] (Media::IRadioStationProvider *prov, const QModelIndex& index) { const auto radio = prov->GetRadioStation (index, {}); if (!radio) { qWarning () << Q_FUNC_INFO << "got a null radio station from provider"; return; } auto modifiable = qobject_cast<Media::IModifiableRadioStation*> (radio->GetQObject ()); if (!modifiable) { qWarning () << Q_FUNC_INFO << radio->GetRadioName () << "is not modifiable"; return; } modifiable->RemoveItem (index); }); }
void RadioManager::RemoveUrl (const QModelIndex& index) { const auto item = StationsModel_->itemFromIndex (index); const auto root = GetRootItem (item); if (!Root2Prov_.contains (root)) { qWarning () << Q_FUNC_INFO << "unknown provider for index" << index; return; } const auto radio = Root2Prov_ [root]->GetRadioStation (item, {}); if (!radio) { qWarning () << Q_FUNC_INFO << "got a null radio station from provider"; return; } auto modifiable = qobject_cast<Media::IModifiableRadioStation*> (radio->GetQObject ()); if (!modifiable) { qWarning () << Q_FUNC_INFO << radio->GetRadioName () << "is not modifiable"; return; } modifiable->RemoveItem (index); }
void CheckModel::SetMissingReleases (const QList<Media::ReleaseInfo>& releases, const Collection::Artist& artist) { qDebug () << Q_FUNC_INFO << artist.Name_ << releases.size (); const auto item = Artist2Item_.value (artist.ID_); if (!item) { qWarning () << Q_FUNC_INFO << "no item for artist" << artist.Name_; return; } Artist2Missings_ [artist.ID_] = releases; const auto model = Artist2Submodel_.value (artist.ID_); for (const auto& release : releases) { auto item = new QStandardItem; item->setData (release.Name_, ReleasesSubmodel::ReleaseName); item->setData (release.Year_, ReleasesSubmodel::ReleaseYear); item->setData (DefaultAlbumIcon_, ReleasesSubmodel::ReleaseArt); model->appendRow (item); const auto proxy = AAProv_->RequestAlbumArt ({ artist.Name_, release.Name_ }); new Util::OneTimeRunner { [this, item, proxy] () -> void { proxy->GetQObject ()->deleteLater (); const auto& url = proxy->GetImageUrls ().value (0); if (url.isEmpty ()) return; item->setData (url, ReleasesSubmodel::ReleaseArt); }, proxy->GetQObject (), SIGNAL (urlsReady (Media::AlbumInfo, QList<QUrl>)), this }; } item->setData (releases.size (), Role::MissingCount); item->setData (true, Role::IsChecked); }
void DataFilterUploader::UploadToAcc (const QByteArray& accId) { bool shouldCleanup = true; auto deleteGuard = std::shared_ptr<void> (nullptr, [this, shouldCleanup] (void*) { if (shouldCleanup) deleteLater (); }); const auto acc = AccMgr_->GetAccount (accId); if (!acc) { qWarning () << Q_FUNC_INFO << "no account for ID" << accId; return; } const auto& image = Entity_.Entity_.value<QImage> (); const auto& localFile = Entity_.Entity_.toUrl ().toLocalFile (); if (!image.isNull ()) { auto tempFile = new QTemporaryFile { this }; Entity_.Entity_.value<QImage> ().save (tempFile, "PNG", 0); UploadFileName_ = tempFile->fileName (); } else if (QFile::exists (localFile)) UploadFileName_ = localFile; UploadPhotosDialog dia { acc->GetQObject() }; dia.LockFiles (); dia.SetFiles ({ { UploadFileName_, {} } }); if (dia.exec () != QDialog::Accepted) return; connect (acc->GetQObject (), SIGNAL (itemUploaded (UploadItem, QUrl)), this, SLOT (checkItemUploaded (UploadItem, QUrl))); const auto isu = qobject_cast<ISupportUploads*> (acc->GetQObject ()); isu->UploadImages (dia.GetSelectedCollection (), dia.GetSelectedFiles ()); shouldCleanup = false; }
void Checker::rotateQueue () { if (Artists_.isEmpty ()) { HandleReady (); return; } Current_ = Artists_.takeFirst (); const auto pending = Provider_->GetDiscography (Current_.Name_); connect (pending->GetQObject (), SIGNAL (ready ()), this, SLOT (handleDiscoReady ())); connect (pending->GetQObject (), SIGNAL (error (QString)), this, SLOT (handleDiscoError ())); }
QList<Media::IPendingAudioSearch*> PreviewHandler::RequestPreview (const Media::AudioSearchRequest& req) { QList<Media::IPendingAudioSearch*> pendings; for (auto prov : Providers_) { auto pending = prov->Search (req); connect (pending->GetQObject (), SIGNAL (ready ()), this, SLOT (handlePendingReady ())); pendings << pending; } return pendings; }
void RecommendationsWidget::on_RecProvider__activated (int index) { if (index < 0 || index >= Providers_.size ()) return; auto pending = Providers_.at (index)->RequestRecommended (10); connect (pending->GetQObject (), SIGNAL (ready ()), this, SLOT (handleGotRecs ())); auto scrob = qobject_cast<Media::IAudioScrobbler*> (ProvRoots_.at (index)); XmlSettingsManager::Instance () .setProperty ("LastUsedRecsProvider", scrob->GetServiceName ()); }
void NotificationsManager::handleMUCInvitation (const QVariantMap& ident, const QString& inviter, const QString& reason) { const auto acc = qobject_cast<IAccount*> (sender ()); if (!acc) { qWarning () << Q_FUNC_INFO << sender () << "doesn't implement IAccount"; return; } const auto& name = ident ["HumanReadableName"].toString (); const auto str = reason.isEmpty () ? tr ("You have been invited to %1 by %2.") .arg (name) .arg (inviter) : tr ("You have been invited to %1 by %2: %3") .arg (name) .arg (inviter) .arg (reason); auto e = Util::MakeNotification ("Azoth", str, PInfo_); e.Additional_ ["org.LC.AdvNotifications.SenderID"] = "org.LeechCraft.Azoth"; e.Additional_ ["org.LC.AdvNotifications.EventCategory"] = AN::CatIM; e.Additional_ ["org.LC.AdvNotifications.VisualPath"] = QStringList (name); e.Additional_ ["org.LC.AdvNotifications.EventID"] = "org.LC.Plugins.Azoth.Invited/" + name + '/' + inviter; e.Additional_ ["org.LC.AdvNotifications.EventType"] = AN::TypeIMMUCInvite; e.Additional_ ["org.LC.AdvNotifications.FullText"] = str; e.Additional_ ["org.LC.AdvNotifications.Count"] = 1; e.Additional_ ["org.LC.Plugins.Azoth.Msg"] = reason; const auto& cancel = Util::MakeANCancel (e); const auto nh = new Util::NotificationActionHandler { e }; nh->AddFunction (tr ("Join"), [this, acc, ident, cancel] () { SuggestJoiningMUC (acc, ident); EntityMgr_->HandleEntity (cancel); }); nh->AddDependentObject (acc->GetQObject ()); EntityMgr_->HandleEntity (e); }
void NotificationsManager::handleAttentionDrawn (const QString& text, const QString&) { if (XmlSettingsManager::Instance () .property ("IgnoreDrawAttentions").toBool ()) return; const auto entry = qobject_cast<ICLEntry*> (sender ()); if (!entry) { qWarning () << Q_FUNC_INFO << sender () << "doesn't implement ICLEntry"; return; } const auto& str = text.isEmpty () ? tr ("%1 requests your attention") .arg (entry->GetEntryName ()) : tr ("%1 requests your attention: %2") .arg (entry->GetEntryName ()) .arg (text); auto e = Util::MakeNotification ("Azoth", str, PInfo_); BuildNotification (e, entry, "AttentionDrawnBy"); e.Additional_ ["org.LC.AdvNotifications.DeltaCount"] = 1; e.Additional_ ["org.LC.AdvNotifications.EventType"] = AN::TypeIMAttention; e.Additional_ ["org.LC.AdvNotifications.ExtendedText"] = tr ("Attention requested"); e.Additional_ ["org.LC.AdvNotifications.FullText"] = tr ("Attention requested by %1") .arg (entry->GetEntryName ()); e.Additional_ ["org.LC.Plugins.Azoth.Msg"] = text; const auto nh = new Util::NotificationActionHandler { e, this }; nh->AddFunction (tr ("Open chat"), [entry, this] { Core::Instance ().GetChatTabsManager ()->OpenChat (entry, true); }); nh->AddDependentObject (entry->GetQObject ()); EntityMgr_->HandleEntity (e); }
void NotificationsManager::handleAuthorizationRequested (QObject *entryObj, const QString& msg) { const auto& proxy = std::make_shared<Util::DefaultHookProxy> (); emit hookGotAuthRequest (proxy, entryObj, msg); if (proxy->IsCancelled ()) return; const auto entry = qobject_cast<ICLEntry*> (entryObj); if (!entry) { qWarning () << Q_FUNC_INFO << entryObj << "doesn't implement ICLEntry"; return; } const auto& str = msg.isEmpty () ? tr ("Subscription requested by %1.") .arg (entry->GetEntryName ()) : tr ("Subscription requested by %1: %2.") .arg (entry->GetEntryName ()) .arg (msg); auto e = Util::MakeNotification ("Azoth", str, PInfo_); BuildNotification (e, entry, "AuthRequestFrom"); e.Additional_ ["org.LC.AdvNotifications.EventType"] = AN::TypeIMSubscrRequest; e.Additional_ ["org.LC.AdvNotifications.FullText"] = str; e.Additional_ ["org.LC.AdvNotifications.Count"] = 1; e.Additional_ ["org.LC.Plugins.Azoth.Msg"] = msg; const auto nh = new Util::NotificationActionHandler (e, this); nh->AddFunction (tr ("Authorize"), [this, entry] () { AuthorizeEntry (entry); }); nh->AddFunction (tr ("Deny"), [this, entry] () { DenyAuthForEntry (entry); }); nh->AddFunction (tr ("View info"), [entry] () { entry->ShowInfo (); }); nh->AddDependentObject (entry->GetQObject ()); EntityMgr_->HandleEntity (e); }
void TemplatesEditorWidget::loadTemplate () { const auto currentType = Ui_.Editor_->GetCurrentEditorType (); const auto msgType = static_cast<MsgType> (Ui_.MessageType_->currentIndex ()); Util::Visit (TemplatesMgr_->GetTemplate (currentType, msgType, nullptr).AsVariant (), [=] (const QString& tpl) { auto editor = Ui_.Editor_->GetCurrentEditor (); editor->SetContents (tpl, currentType); connect (editor->GetQObject (), SIGNAL (textChanged ()), this, SLOT (markAsDirty ())); }, [=] (const auto& err) { QMessageBox::critical (this, "LeechCraft", tr ("Unable to load template: %1.") .arg (err.what ())); }); }
void NotificationsManager::HandleMessage (IMessage *msg) { const bool showMsg = XmlSettingsManager::Instance () .property ("ShowMsgInNotifications").toBool (); const auto other = qobject_cast<ICLEntry*> (msg->OtherPart ()); const auto parentCL = qobject_cast<ICLEntry*> (msg->ParentCLEntry ()); QString msgString; bool isHighlightMsg = false; switch (msg->GetMessageType ()) { case IMessage::Type::ChatMessage: if (XmlSettingsManager::Instance () .property ("NotifyAboutIncomingMessages").toBool ()) { if (!showMsg) msgString = tr ("Incoming chat message from <em>%1</em>.") .arg (other->GetEntryName ()); else { const auto& body = msg->GetEscapedBody (); const auto& notifMsg = body.size () > 50 ? body.left (50) + "..." : body; msgString = tr ("Incoming chat message from <em>%1</em>: <em>%2</em>") .arg (other->GetEntryName ()) .arg (notifMsg); } } break; case IMessage::Type::MUCMessage: { isHighlightMsg = Core::Instance ().IsHighlightMessage (msg); if (isHighlightMsg && XmlSettingsManager::Instance () .property ("NotifyAboutConferenceHighlights").toBool ()) { if (!showMsg) msgString = tr ("Highlighted in conference <em>%1</em> by <em>%2</em>.") .arg (parentCL->GetEntryName ()) .arg (other->GetEntryName ()); else { const auto& body = msg->GetEscapedBody (); const auto& notifMsg = body.size () > 50 ? body.left (50) + "..." : body; msgString = tr ("Highlighted in conference <em>%1</em> by <em>%2</em>: <em>%3</em>") .arg (parentCL->GetEntryName ()) .arg (other->GetEntryName ()) .arg (notifMsg); } } break; } default: return; } auto e = Util::MakeNotification ("Azoth", msgString, PInfo_); if (msgString.isEmpty ()) e.Mime_ += "+advanced"; auto entry = msg->GetMessageType () == IMessage::Type::MUCMessage ? parentCL : other; BuildNotification (e, entry); const auto count = ++UnreadCounts_ [entry]; if (msg->GetMessageType () == IMessage::Type::MUCMessage) { e.Additional_ ["org.LC.Plugins.Azoth.SubSourceID"] = other->GetEntryID (); e.Additional_ ["org.LC.AdvNotifications.EventType"] = isHighlightMsg ? AN::TypeIMMUCHighlight : AN::TypeIMMUCMsg; e.Additional_ ["NotificationPixmap"] = QVariant::fromValue (other->GetAvatar ()); if (isHighlightMsg) e.Additional_ ["org.LC.AdvNotifications.FullText"] = tr ("%n message(s) from", 0, count) + ' ' + other->GetEntryName () + " <em>(" + parentCL->GetEntryName () + ")</em>"; else e.Additional_ ["org.LC.AdvNotifications.FullText"] = tr ("%n message(s) in", 0, count) + ' ' + parentCL->GetEntryName (); } else { e.Additional_ ["org.LC.AdvNotifications.EventType"] = AN::TypeIMIncMsg; e.Additional_ ["org.LC.AdvNotifications.FullText"] = tr ("%n message(s) from", 0, count) + ' ' + other->GetEntryName (); } e.Additional_ ["org.LC.AdvNotifications.Count"] = count; e.Additional_ ["org.LC.AdvNotifications.ExtendedText"] = tr ("%n message(s)", 0, count); e.Additional_ ["org.LC.Plugins.Azoth.Msg"] = msg->GetEscapedBody (); const auto nh = new Util::NotificationActionHandler { e, this }; nh->AddFunction (tr ("Open chat"), [parentCL] { Core::Instance ().GetChatTabsManager ()->OpenChat (parentCL, true); }); nh->AddDependentObject (parentCL->GetQObject ()); EntityMgr_->HandleEntity (e); }
void ContactDropFilter::HandleContactsDropped (const QMimeData *data) { const auto thisEntry = GetEntry<ICLEntry> (EntryId_); const bool isMuc = thisEntry->GetEntryType () == ICLEntry::EntryType::MUC; auto entries = DndUtil::DecodeEntryObjs (data); entries.erase (std::remove_if (entries.begin (), entries.end (), [thisEntry] (QObject *entryObj) { return !CanEntryBeInvited (thisEntry, qobject_cast<ICLEntry*> (entryObj)); }), entries.end ()); if (entries.isEmpty ()) return; QString text; if (entries.size () > 1) text = isMuc ? tr ("Enter reason to invite %n contact(s) to %1:", 0, entries.size ()) .arg (thisEntry->GetEntryName ()) : tr ("Enter reason to invite %1 to %n conference(s):", 0, entries.size ()) .arg (thisEntry->GetEntryName ()); else { const auto muc = isMuc ? thisEntry : qobject_cast<ICLEntry*> (entries.first ()); const auto entry = isMuc ? qobject_cast<ICLEntry*> (entries.first ()) : thisEntry; text = tr ("Enter reason to invite %1 to %2:") .arg (entry->GetEntryName ()) .arg (muc->GetEntryName ()); } bool ok = false; auto reason = QInputDialog::getText (nullptr, tr ("Invite to a MUC"), text, QLineEdit::Normal, {}, &ok); if (!ok) return; if (isMuc) { const auto muc = qobject_cast<IMUCEntry*> (thisEntry->GetQObject ()); for (const auto& entry : entries) muc->InviteToMUC (qobject_cast<ICLEntry*> (entry)->GetHumanReadableID (), reason); } else { const auto thisId = thisEntry->GetHumanReadableID (); for (const auto& mucEntryObj : entries) { const auto muc = qobject_cast<IMUCEntry*> (mucEntryObj); muc->InviteToMUC (thisId, reason); } } }
CheckModel::CheckModel (const Collection::Artists_t& artists, const ICoreProxy_ptr& proxy, const ILMPProxy_ptr& lmpProxy, QObject *parent) : RoleNamesMixin<QStandardItemModel> { parent } , AllArtists_ { artists } , Proxy_ { lmpProxy } , DefaultAlbumIcon_ { GetIcon (proxy, "media-optical", AASize * 2) } , DefaultArtistIcon_ { GetIcon (proxy, "view-media-artist", ArtistSize * 2) } , AAProv_ { proxy->GetPluginsManager ()-> GetAllCastableTo<Media::IAlbumArtProvider*> ().value (0) } , BioProv_ { proxy->GetPluginsManager ()-> GetAllCastableTo<Media::IArtistBioFetcher*> ().value (0) } { QHash<int, QByteArray> roleNames; roleNames [Role::ArtistId] = "artistId"; roleNames [Role::ArtistName] = "artistName"; roleNames [Role::ScheduledToCheck] = "scheduled"; roleNames [Role::IsChecked] = "isChecked"; roleNames [Role::ArtistImage] = "artistImageUrl"; roleNames [Role::Releases] = "releases"; roleNames [Role::MissingCount] = "missingCount"; roleNames [Role::PresentCount] = "presentCount"; setRoleNames (roleNames); for (const auto& artist : artists) { if (artist.Name_.contains (" vs. ") || artist.Name_.contains (" with ") || artist.Albums_.isEmpty ()) continue; auto item = new QStandardItem { artist.Name_ }; item->setData (artist.ID_, Role::ArtistId); item->setData (artist.Name_, Role::ArtistName); item->setData (true, Role::ScheduledToCheck); item->setData (false, Role::IsChecked); item->setData (DefaultArtistIcon_, Role::ArtistImage); item->setData (0, Role::MissingCount); item->setData (artist.Albums_.size (), Role::PresentCount); const auto submodel = new ReleasesSubmodel { this }; item->setData (QVariant::fromValue<QObject*> (submodel), Role::Releases); appendRow (item); Artist2Submodel_ [artist.ID_] = submodel; Artist2Item_ [artist.ID_] = item; Scheduled_ << artist.ID_; const auto proxy = BioProv_->RequestArtistBio (artist.Name_, false); new Util::OneTimeRunner { [this, artist, item, proxy] () -> void { if (!Artist2Item_.contains (artist.ID_)) return; const auto& url = proxy->GetArtistBio ().BasicInfo_.LargeImage_; item->setData (url, Role::ArtistImage); }, proxy->GetQObject (), { SIGNAL (ready ()), SIGNAL (error ()) }, this }; } }