LINUX.ORG.RU

Почтовый клиент на Qt для допила под свои каждодневные нужды.

 , , , ,


2

3

Сабж.

Подскажите opensource почтовый клиент на Qt4/Qt5 с возможностью IMAP-подключения и стандартной функциональностью.

Т.к. после очередного обновления интерфейса GMail (наверно переписанного на Angular 6 или еще каком-то дерьме) пользоваться им без торомозов стало практические нереально. Загрузка веб-интерфейса грузит CPU так, что врубается кулер... просто нет слов. Но то лирика, а это жизнь.

Пока юзаю Evolution, но, т.к. я люблю приложения на Qt вот настала пора и необходимость познакомиться с ним на практике.

P.S. На гитхабе находил парочку школьных проектов, но может есть что-то более серьёзное. KMail не предлагать.

★★★★★

Последнее исправление: Twissel (всего исправлений: 2)
Ответ на: комментарий от EXL

Они захардкоджены, ёпта!

var kIssuers = new Map ([
  ["accounts.google.com", [
    '406964657835-aq8lmia8j95dhl1a2bvharmfk3t1hgqj.apps.googleusercontent.com',
    'kSmqreRr0qwBWJgbf5Y-PjSU',
    'https://accounts.google.com/o/oauth2/auth',
    'https://www.googleapis.com/oauth2/v3/token'
  ]],

Ай, что это?

На практике в том же самом Thunderbird'Ё ключи OAuth2 прошиты(!)

Вот и думаю, что после этого безопаснее: логин/пароль или все это буржуинство...

Кому интересно лежат они в 60-й версии Громоптицы в дереве исходников здесь root_dir/comm/mailnews/base/util/OAuth2Providers.jsm

P.S. Конечно, учитывая эту спеку, по-другому сделать сложно, НО если уж по-хорошему и безопасно надо, чтобы каждый юзер генерил для своего экзепляра приложения свои ключи... и вносил в настройки аппликухи... делать этого, естественно, никто не будет.

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 3)
Ответ на: Они захардкоджены, ёпта! от Twissel

jollheef, что ты скажешь о безопасности такого подхода в частности и продуманности протокола OAuth2 в целом?

Twissel ★★★★★
() автор топика
Ответ на: комментарий от commagray

Trojita

То ли я чего-то не настроил, то ли сабж не умеет отображать картинки в HTML-письмах. Или все-таки он плохо дружит с разметкой гипертекста и всякими «новшествами» в этой области.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от gag

ошибка сборки

Команда сборки

tony@lmde:~/trojita$ sudo debuild -i -us -uc -b
-- Installing: /home/tony/trojita/debian/tmp/usr/share/icons/hicolor/scalable/apps/trojita.svg
make[1]: Leaving directory '/home/tony/trojita/obj-x86_64-linux-gnu'
   dh_install -O--buildsystem=cmake
dh_install: Cannot find (any matches for) "usr/lib/*/trojita" (tried in ., debian/tmp)

dh_install: trojita missing files: usr/lib/*/trojita
	install -d debian/trojita//usr
	cp --reflink=auto -a debian/tmp/usr/bin/ debian/trojita//usr/
	install -d debian/trojita//usr/share
	cp --reflink=auto -a debian/tmp/usr/share/applications/ debian/trojita//usr/share/
	install -d debian/trojita//usr/share/metainfo
	cp --reflink=auto -a debian/tmp/usr/share/metainfo/org.kde.trojita.appdata.xml debian/trojita//usr/share/metainfo/
dh_install: missing files, aborting
	install -d debian/.debhelper/generated/trojita
	install -d debian/.debhelper/generated/trojita-data
debian/rules:11: ошибка выполнения рецепта для цели «binary»
make: *** [binary] Ошибка 25
dpkg-buildpackage: ошибка: fakeroot debian/rules binary возвратил код ошибки 2
debuild: fatal error at line 1116:
dpkg-buildpackage -rfakeroot -us -uc -i -b failed

Содержимое /home/tony/trojita/debian/trojita.install

usr/bin/
usr/share/applications/
usr/share/metainfo/org.kde.trojita.appdata.xml

usr/lib/*/trojita

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от commagray

Вру все работает. Это был глюк.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от EXL

Не подскажешь, что почитать о хранении конфигурации приложения средствами Qt?

Или тут, кто как может так и делает?

Попытаюсь примитивно реализовать поддержку несколький ящиков в Trojita...

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Хранения каких именно конфигураций? Для простого подойдёт класс QSettings который по сути INI-файлы. Для сложного там уже нужно смотреть в сторону XML а то и SQLite.

Или тут, кто как может так и делает?

Наверное, тебе нужно найти как эта Троица хранит свои данные и уже плясать от этого, пытаясь расширить конфигурацию.

EXL ★★★★★
()
Ответ на: комментарий от gag

Разве что надо будет из ... выкинуть: ... И из debian/rules: -DWITH_ABOOKADDRESSBOOK_PLUGIN=ON.

Не, вот это не надо, спутал с аконади из kde.

gag ★★★★★
()
Ответ на: ошибка сборки от Twissel

Я использовал последний upstream git и каталог debian из lxqt репозитория. Подредактировал debian/control - и вперёд. Прошло чуть дальше:

   dh_install -O--buildsystem=cmake
	install -d debian/trojita//usr
	cp --reflink=auto -a debian/tmp/usr/bin/ debian/trojita//usr/
	install -d debian/trojita//usr/lib/x86_64-linux-gnu
	cp --reflink=auto -a debian/tmp/usr/lib/x86_64-linux-gnu/trojita debian/trojita//usr/lib/x86_64-linux-gnu/
	install -d debian/trojita//usr/share
	cp --reflink=auto -a debian/tmp/usr/share/applications/ debian/trojita//usr/share/
	install -d debian/trojita//usr/share/metainfo
	cp --reflink=auto -a debian/tmp/usr/share/metainfo/org.kde.trojita.appdata.xml debian/trojita//usr/share/metainfo/
dh_install: Cannot find (any matches for) "usr/share/trojita/locale/" (tried in ., debian/tmp)

dh_install: trojita-data missing files: usr/share/trojita/locale/
	install -d debian/.debhelper/generated/trojita
	install -d debian/trojita-data//usr/share
	cp --reflink=auto -a debian/tmp/usr/share/icons debian/trojita-data//usr/share/
dh_install: missing files, aborting
	install -d debian/.debhelper/generated/trojita-data
make: *** [debian/rules:11: binary] Error 25
dpkg-buildpackage: error: fakeroot debian/rules binary subprocess returned exit status 2

gag ★★★★★
()
Ответ на: комментарий от annulen

html2text не требует толстый движок ещё и с js. Да и почта с HTML у меня - это спам или реклама.

gag ★★★★★
()
Ответ на: комментарий от annulen

Но особое желание у меня появилось из-за того, что обычный текст не отображается нормально, т.к. каким-то образом тоже рендерится через этот HTML-движок, в котором был баг (а в Дебиан есть до сих пор). А пересборка этого монстра на C++ с мини-патчами длилась ночь с большими пиками в потреблении памяти.

gag ★★★★★
()
Ответ на: комментарий от gag

Не, можно собрать бинарник статически и бросить в /opt. Что я и сделал :-)

Хотелось по-научному, но тут издержки опенсурца. Хотя лучше один бинарь на Qt, пусть и немаленький, чем такая же говнина на Electron'е

Twissel ★★★★★
() автор топика
Ответ на: комментарий от EXL

исходники


SettingsNames.cpp

#include "SettingsNames.h"

namespace Common
{

const QString SettingsNames::identitiesKey = QStringLiteral("identities");
const QString SettingsNames::realNameKey = QStringLiteral("realName");
const QString SettingsNames::addressKey = QStringLiteral("address");
const QString SettingsNames::organisationKey = QStringLiteral("organisation");
const QString SettingsNames::signatureKey = QStringLiteral("signature");
const QString SettingsNames::obsRealNameKey = QStringLiteral("identity.realName");
const QString SettingsNames::obsAddressKey = QStringLiteral("identity.address");
const QString SettingsNames::favoriteTagsKey = QStringLiteral("favorite_tags");
const QString SettingsNames::tagNameKey = QStringLiteral("name");
const QString SettingsNames::tagColorKey = QStringLiteral("color");
const QString SettingsNames::msaMethodKey = QStringLiteral("msa.method");
const QString SettingsNames::methodSMTP = QStringLiteral("SMTP");
const QString SettingsNames::methodSSMTP = QStringLiteral("SSMTP");
const QString SettingsNames::methodSENDMAIL = QStringLiteral("sendmail");
const QString SettingsNames::methodImapSendmail = QStringLiteral("IMAP-SENDMAIL");
const QString SettingsNames::smtpHostKey = QStringLiteral("msa.smtp.host");
const QString SettingsNames::smtpPortKey = QStringLiteral("msa.smtp.port");
const QString SettingsNames::smtpAuthKey = QStringLiteral("msa.smtp.auth");
const QString SettingsNames::smtpStartTlsKey = QStringLiteral("msa.smtp.starttls");
const QString SettingsNames::smtpUserKey = QStringLiteral("msa.smtp.auth.user");
const QString SettingsNames::smtpAuthReuseImapCredsKey = QStringLiteral("msa.smtp.auth.reuseImapCredentials");
// in use by the cleartext password plugin: "msa.smtp.auth.pass"
const QString SettingsNames::sendmailKey = QStringLiteral("msa.sendmail");
const QString SettingsNames::sendmailDefaultCmd = QStringLiteral("sendmail -bm -oi");
const QString SettingsNames::smtpUseBurlKey = QStringLiteral("msa.smtp.burl");
const QString SettingsNames::imapMethodKey = QStringLiteral("imap.method");
const QString SettingsNames::methodTCP = QStringLiteral("TCP");
const QString SettingsNames::methodSSL = QStringLiteral("SSL");
const QString SettingsNames::methodProcess = QStringLiteral("process");
const QString SettingsNames::imapHostKey = QStringLiteral("imap.host");
const QString SettingsNames::imapPortKey = QStringLiteral("imap.port");
const QString SettingsNames::imapStartTlsKey = QStringLiteral("imap.starttls");
const QString SettingsNames::imapUserKey = QStringLiteral("imap.auth.user");
// in use by the cleartext password plugin: "imap.auth.pass"
const QString SettingsNames::imapProcessKey = QStringLiteral("imap.process");
const QString SettingsNames::imapStartMode = QStringLiteral("imap.startmode");
const QString SettingsNames::netOffline = QStringLiteral("OFFLINE");
const QString SettingsNames::netExpensive = QStringLiteral("EXPENSIVE");
const QString SettingsNames::netOnline = QStringLiteral("ONLINE");
const QString SettingsNames::obsImapStartOffline = QStringLiteral("imap.offline");
const QString SettingsNames::obsImapSslPemCertificate = QStringLiteral("imap.ssl.pemCertificate");
const QString SettingsNames::imapSslPemPubKey = QStringLiteral("imap.ssl.pemPubKey");
const QString SettingsNames::imapBlacklistedCapabilities = QStringLiteral("imap.capabilities.blacklist");
const QString SettingsNames::imapUseSystemProxy = QStringLiteral("imap.proxy.system");
const QString SettingsNames::imapNeedsNetwork = QStringLiteral("imap.needsNetwork");
const QString SettingsNames::imapNumberRefreshInterval = QStringLiteral("imap.numberRefreshInterval");
const QString SettingsNames::imapAccountIcon = QStringLiteral("imap.accountIcon");
const QString SettingsNames::imapArchiveFolderName = QStringLiteral("imap.archiveFolderName");
const QString SettingsNames::imapDefaultArchiveFolderName = QStringLiteral("Archive");
const QString SettingsNames::composerSaveToImapKey = QStringLiteral("composer/saveToImapEnabled");
const QString SettingsNames::composerImapSentKey = QStringLiteral("composer/imapSentName");
const QString SettingsNames::cacheMetadataKey = QStringLiteral("offline.metadataCache");
const QString SettingsNames::cacheMetadataMemory = QStringLiteral("memory");
const QString SettingsNames::cacheOfflineKey = QStringLiteral("offline.cache");
const QString SettingsNames::cacheOfflineNone = QStringLiteral("memory");
const QString SettingsNames::cacheOfflineXDays = QStringLiteral("days");
const QString SettingsNames::cacheOfflineAll = QStringLiteral("all");
const QString SettingsNames::cacheOfflineNumberDaysKey = QStringLiteral("offline.cache.numDays");
const QString SettingsNames::watchedFoldersKey = QStringLiteral("watchFolders");
const QString SettingsNames::watchOnlyInbox = QStringLiteral("INBOX");
const QString SettingsNames::watchSubscribed = QStringLiteral("subscribed");
const QString SettingsNames::watchAll = QStringLiteral("all");
const QString SettingsNames::xtConnectCacheDirectory = QStringLiteral("xtconnect.cachedir");
const QString SettingsNames::xtSyncMailboxList = QStringLiteral("xtconnect.listOfMailboxes");
const QString SettingsNames::xtDbHost = QStringLiteral("xtconnect.db.hostname");
const QString SettingsNames::xtDbPort = QStringLiteral("xtconnect.db.port");
const QString SettingsNames::xtDbDbName = QStringLiteral("xtconnect.db.dbname");
const QString SettingsNames::xtDbUser = QStringLiteral("xtconnect.db.username");
const QString SettingsNames::guiMsgListShowThreading = QStringLiteral("gui/msgList.showThreading");
const QString SettingsNames::guiMsgListHideRead = QStringLiteral("gui/msgList.hideRead");
const QString SettingsNames::guiMailboxListShowOnlySubscribed = QStringLiteral("gui/mailboxList.showOnlySubscribed");
const QString SettingsNames::guiMainWindowLayout = QStringLiteral("gui/mainWindow.layout");
const QString SettingsNames::guiMainWindowLayoutCompact = QStringLiteral("compact");
const QString SettingsNames::guiMainWindowLayoutWide = QStringLiteral("wide");
const QString SettingsNames::guiMainWindowLayoutOneAtTime = QStringLiteral("one-at-time");
const QString SettingsNames::guiPreferPlaintextRendering = QStringLiteral("gui/preferPlaintextRendering");
const QString SettingsNames::guiShowSystray = QStringLiteral("gui/showSystray");
const QString SettingsNames::guiOnSystrayClose = QStringLiteral("gui/onSystrayClose");
const QString SettingsNames::guiStartMinimized = QStringLiteral("gui/startMinimized");
const QString SettingsNames::guiSizesInMainWinWhenCompact = QStringLiteral("gui/sizeInMainWinWhenCompact-%1");
const QString SettingsNames::guiSizesInMainWinWhenWide = QStringLiteral("gui/sizeInMainWinWhenWide-%1");
const QString SettingsNames::guiSizesInaMainWinWhenOneAtATime = QStringLiteral("gui/sizeInMainWinWhenOneAtATime-%1");
const QString SettingsNames::guiAllowRawSearch = QStringLiteral("gui/allowRawSearch");
const QString SettingsNames::guiExpandedMailboxes = QStringLiteral("gui/expandedMailboxes");
const QString SettingsNames::appLoadHomepage = QStringLiteral("app.updates.checkEnabled");
const QString SettingsNames::knownEmailsKey = QStringLiteral("addressBook/knownEmails");
const QString SettingsNames::addressbookPlugin = QStringLiteral("plugin/addressbook");
const QString SettingsNames::passwordPlugin = QStringLiteral("plugin/password");
const QString SettingsNames::spellcheckerPlugin = QStringLiteral("plugin/spellchecker");
const QString SettingsNames::imapIdleRenewal = QStringLiteral("imapIdleRenewal");
const QString SettingsNames::autoMarkReadEnabled = QStringLiteral("autoMarkRead/enabled");
const QString SettingsNames::autoMarkReadSeconds = QStringLiteral("autoMarkRead/seconds");
const QString SettingsNames::interopRevealVersions = QStringLiteral("interoperability/revealVersions");
const QString SettingsNames::completeMessageWidgetGeometry = QStringLiteral("gui/completeMessageWidgetGeometry");
const QString SettingsNames::mboxDropAction = QStringLiteral("gui/mboxList.dropAction");

}

Не слишком гибкое решение, вроде бы (хелловорд на плюсах я последний раз написал 6 лет назад), но тут это очевидно. Как бы его грамотно переделать?

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от EXL

хидер

#ifndef SETTINGSNAMES_H
#define SETTINGSNAMES_H

#include <QString>

namespace Common
{

struct SettingsNames {
    static const QString identitiesKey, realNameKey, addressKey, organisationKey, signatureKey, obsRealNameKey, obsAddressKey;
    static const QString favoriteTagsKey, tagNameKey, tagColorKey;
    static const QString msaMethodKey, methodSMTP, methodSSMTP, methodSENDMAIL, methodImapSendmail, smtpHostKey,
           smtpPortKey, smtpAuthKey, smtpStartTlsKey, smtpUserKey, smtpAuthReuseImapCredsKey,
           sendmailKey, sendmailDefaultCmd;
    static const QString imapMethodKey, methodTCP, methodSSL, methodProcess, imapHostKey,
           imapPortKey, imapStartTlsKey, imapUserKey, imapProcessKey, imapStartMode, netOffline, netExpensive, netOnline,
           obsImapStartOffline, obsImapSslPemCertificate, imapSslPemPubKey,
           imapBlacklistedCapabilities, imapUseSystemProxy, imapNeedsNetwork, imapNumberRefreshInterval,
           imapAccountIcon, imapArchiveFolderName, imapDefaultArchiveFolderName;
    static const QString composerSaveToImapKey, composerImapSentKey, smtpUseBurlKey;
    static const QString cacheMetadataKey, cacheMetadataMemory,
           cacheOfflineKey, cacheOfflineNone, cacheOfflineXDays, cacheOfflineAll, cacheOfflineNumberDaysKey;
    static const QString watchedFoldersKey, watchOnlyInbox, watchSubscribed, watchAll;
    static const QString xtConnectCacheDirectory, xtSyncMailboxList, xtDbHost, xtDbPort,
           xtDbDbName, xtDbUser;
    static const QString guiMsgListShowThreading;
    static const QString guiMsgListHideRead;
    static const QString guiMailboxListShowOnlySubscribed;
    static const QString guiPreferPlaintextRendering;
    static const QString guiMainWindowLayout, guiMainWindowLayoutCompact, guiMainWindowLayoutWide, guiMainWindowLayoutOneAtTime;
    static const QString guiSizesInMainWinWhenCompact, guiSizesInMainWinWhenWide, guiSizesInaMainWinWhenOneAtATime;
    static const QString guiAllowRawSearch;
    static const QString guiExpandedMailboxes;
    static const QString appLoadHomepage;
    static const QString guiShowSystray, guiOnSystrayClose, guiStartMinimized;
    static const QString knownEmailsKey;
    static const QString addressbookPlugin, passwordPlugin, spellcheckerPlugin;
    static const QString imapIdleRenewal;
    static const QString autoMarkReadEnabled, autoMarkReadSeconds;
    static const QString interopRevealVersions;
    static const QString completeMessageWidgetGeometry;
    static const QString mboxDropAction;
};

}

#endif // SETTINGSNAMES_H
Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Не, можно собрать бинарник статически и бросить в /opt. Что я и сделал :-)

Можно. Можно и не статически со скриптиком с LD_LIBRARY_PATH для запуска, как у меня.

gag ★★★★★
()
Ответ на: комментарий от Twissel

Ноут Sandybridge 4GB ОЗУ. Собирал в один поток.

Для справки: GTK3 собирается за 18 минут в один поток.

gag ★★★★★
()
Ответ на: комментарий от EXL

Наверное, тебе нужно найти как эта Троица хранит свои данные и уже плясать от этого, пытаясь расширить конфигурацию.

Для каждого профиля создаются:

~/.config/flaska.net/trojita-PROFILE_NAME.conf
~/.cache/flaska.net/trojita/PROFILE_NAME/trojita-connection-log
~/.cache/flaska.net/trojita/PROFILE_NAME/PROFILE_NAME/imap.cache.sqlite

gag ★★★★★
()
Ответ на: комментарий от gag

Т.е. по идее для нескольких почтовых ящиков достаточно или несколько конфигов или (первое, что приходит в голову), сделать один xml-конфиг «to rule them all»

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Если цель внести как можно меньше изменений в trojita, то тогда просто создать файлик типа:

~/.config/flaska.net/trojita_accounts.conf

который будет наполняться как-то так:

account-name-1
account-name-2

А все данные к account-name-X будут храниться точь-в-точь как trojita уже умеет. Надо «только» в GUI организовать одновременный доступ к этим нескольким учёткам.

gag ★★★★★
()
Ответ на: комментарий от gag

Ну тут как говорится «Это вам не физика, тут думать надо!»

Просто, что проще парсить plaintext или xml. На первый взгляд, простой текст, если параметры конфига полностью независимы друг от друга

Twissel ★★★★★
() автор топика
Ответ на: комментарий от gag

Нет — это overhead

Тогда уже проще запилить в интерфейсе выбор профиля/конфига, чем пихать все конфиги в один файл, а потом парсить.

ИМХО, это более здравая идея.

Twissel ★★★★★
() автор топика
Ответ на: Нет — это overhead от Twissel

Тогда уже проще запилить в интерфейсе выбор профиля/конфига, чем пихать все конфиги в один файл, а потом парсить.

Я такое и не предлагал. Нужно чтобы в интерфейсе корнем были не INBOX, Sent, Spam, а account-name-1, account-name-2, перечисленные в trojita_accounts.conf. В каждом - свои INBOX,... А настройки учёток уже сейчас реализованы по отдельным каталогам.

gag ★★★★★
()
Ответ на: комментарий от gag

Понял. Но, все равно, мне кажется сначала сделать просто диалог выбора профиля (как это сделано в программах Mozilla), а потом уже идти дальше к твоему варианту.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от gag

Просто тут еще момент, что дерево конфига, где он корень это каталоги IMAP, а сам конфиг (по большему счёту) это параметры подключения к этому самому ящику по IMAP. Т.е. это разные сущности. Можно, конечно, конфиг (имя ящика) сделать корневым узлом, чисто графически, только вот смысла в этом немного. Разве что, чтобы напомнить юзеру какой ящик активен.

Так что, пока вариант с диалоговым окошком выбора конфигурации мне кажется самым оптимальным.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от EXL

Проверил, действительно, используется класс QSettings. Под онтопиком конфигурация хранится в файле, под Windows — в реестре.

P.S. Очевидно, по исходникам, но я полез в реестр и убедился.

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от gag

Я вообще думаю начать с того, что на первых порах сделать отдельный бинарник-конфигуратор, который бы выбирал конфигурацию и подсовывал её Trojita.

Так как только знакомлюсь с Qt5 и потихоньку вспоминаю свою матчасть по плюсам.

А потом, итеративно, уже можно будет доводить до ума.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

QSettings совсем не обязательно хранит инфу в реестре, он может просто в отдельных INI или CONFIG-файлах хранить. Но скорее всего сделано под реестр.

И там ещё есть какая-то SQLite база, судя по изложенному в теме.

EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от EXL

Я подробно не смотрел, но SQLite используется для хранения заголовков сообщений.

Почему я тебе написал, думал что реестр это «искоробочная» реализация этого класса на офтопике.

Но я так понимаю теперь, что это задаётся на этапе создания объекта, не?

Кинь ссылку на доку, пожалуйста, чтобы не писать тут простыни.

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от Twissel

Я вообще думаю начать с того, что на первых порах сделать отдельный бинарник-конфигуратор, который бы выбирал конфигурацию и подсовывал её Trojita.

Мне проще как уже работает:

$ trojita --profile me_at_yandex
$ trojita --profile me_at_rambler
Но на винде, может, удобнее сделать bat. Можно и «GUI», но оно тривиальное.

gag ★★★★★
()
Ответ на: комментарий от Twissel

Ага, откуда бы тогда взялись: Почтовый клиент на Qt для допила под свои каждодневные нужды. (комментарий)

Проблема только в том, что при запуске можно выбрать только одну учётку (если без параметров - то стандартную).

gag ★★★★★
()
Ответ на: комментарий от Twissel

Можно встроить внутрь того класса где происходит парсинг аргументов командной строки окно для выбора или создания профиля.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Но, опять таки, в силу того, что она на разных платформах конфиг хранит по-разному, не нужно выходить за рамки тех возможностей, которые даёт QSettings.

А вот как это сделать, будем подумать) Чем дальше, тем привлекательнее мне кажется идея выкинуть возможности командной строки и сделать отдельный конфигуратор на базе QSettings. Такое вот мыслеблудие.

На винде Тройная за собой конфиг из реестра не чистит и там пароль так и остаётся открытым текстом (только что проверил) :-)

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 2)

Кому интересно вот описание дипломной работы от автора программы Trojita. Это был его дипломный проект.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от EXL
main.cpp

for (int i = 1; i < arguments.size(); ++i) {
        const QString &arg = arguments.at(i);

        if (arg.startsWith(QLatin1Char('-'))) {
            if (arg == QLatin1String("-m") || arg == QLatin1String("--mainwindow")) {
                showMainWindow = true;
            } else if (arg == QLatin1String("-a") || arg == QLatin1String("--addressbook")) {
                showAddressbookWindow = true;
            } else if (arg == QLatin1String("-c") || arg == QLatin1String("--compose")) {
                showComposeWindow = true;
            } else if (arg == QLatin1String("-h") || arg == QLatin1String("--help")) {
                showHelp = true;
            } else if (arg == QLatin1String("-p") || arg == QLatin1String("--profile")) {
                if (i+1 == arguments.size() || arguments.at(i+1).startsWith(QLatin1Char('-'))) {
                    qErr << QObject::tr("Error: Profile was not specified") << endl;
                    error = true;
                    break;
                } else if (!profileName.isEmpty()) {
                    qErr << QObject::tr("Error: Duplicate profile option '%1'").arg(arg) << endl;
                    error = true;
                    break;
                } else {
                    profileName = arguments.at(i+1);
                    ++i;
                }
            } else if (arg == QLatin1String("--log-to-disk")) {
                logToDisk = true;
            } else {
                qErr << QObject::tr("Warning: Unknown option '%1'").arg(arg) << endl;
            }
        } else {
            if (!url.isEmpty() || !arg.startsWith(QLatin1String("mailto:"))) {
                qErr << QObject::tr("Warning: Unexpected argument '%1'").arg(arg) << endl;
            } else {
                url = arg;
                showComposeWindow = true;
            }
        }
    }

Имеет ли смысл этот код переписывать с использованием QCommandLineParser ?

P.S. если что, аргументы это app.arguments()

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от Twissel

Имеет ли смысл этот код переписывать с использованием QCommandLineParser ?

Ну если есть свободное время на это, то можно и переписать.

QCommandLineParser Class
Since: Qt 5.2

Однако, нужно уточнить, поддерживает ли автор Qt 4. Если поддерживает, то изменения он может и не принять в Upstream.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Насчёт апстрима, я пока хотел просто поиграться, а если осилю — форкнуть. И да, у автора минимальная версия Qt 5.2 для сборки.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от EXL

Хотя сейчас надо будет разобраться с базовыми вещами:

1) Считать настройки из QSettings;

2) Изменить настройки;

3) Через объект QSettings записать их в новый конфиг.

Ну и поскольку проект подзаброшен его и форкнуть не грех.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от gag

нет ничего более постоянного, чем временное

// Hack: support multiple "profiles"
    if (!profileName.isEmpty()) {
        // We are abusing the env vars here. Yes, it's a hidden global. Yes, it's ugly.
        // Take it or leave it, this is a time-limited hack.
        // The env var is also in UTF-8. I like UTF-8.
        qputenv("TROJITA_PROFILE", profileName.toUtf8());
    } else {
#ifndef Q_OS_WIN32
        unsetenv("TROJITA_PROFILE");
#else
        putenv("TROJITA_PROFILE=");
#endif
    }
Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Ну и поскольку проект подзаброшен его и форкнуть не грех.

Это не так. Просто коммерчески он не используется, т.к. автор отказался (собственноручно) разделить trojita на LGPL-библиотеку и GPL-GUI. Вот и видим, что Linux - это уже давно не just-for-fun. А настоящий just-for-fun может даже показаться «заброшенным».

gag ★★★★★
()
Ответ на: комментарий от gag

Просто как бы релизов уже 2 года не было. Что намекает, что это был достойный академический проект, но сейчас интерес к нему явно поубавился.

Twissel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.