Hi, review time again.
Three comments in general:
1) Some of the commits look a bit too fine grained to me. I don't see any
benefits in e.g. adding the plugin interface .h declaration in once commit,
settings keys in a second one, a plugin loader in the third one and only
enabling them in cmake in the next commit. To me, that doesn't help with
bisecting and makes it harder to follow the directions in which the patch
series is going, so I'd prefer to have these squashed into a single commit.
2) The second thing, what I found a bit unintuitive was the naming of
various classes. In my opinion, "PasswordInterface" shall be named
"PasswordPlugin" because it's, well, a plugin that one can ask to execute
certain actions. The current naming has its own consistency, it's just that
I find it a bit unintuitive.
The same applies for "TrojitaPluginInterface" -- I would call it an
"AbstractPlugin".
3) Some of the commits are breaking the build. That's unacceptable; if a
commit breaks the build, it will immediately break the `git bisect`
workflow for finding regressions. As a rule of thumb, if you change API of
any class, you are supposed to fix all of its users in the same commit. If
you break any tests, you have to fix them within the same commit.
I'd prefer to have the same rules for changes which introduce breakage to
the user-facing functionality (like being able to login to an IMAP server)
-- hence my requests for backporting some of your changes to master and
rebasing your branch on top of that.
More specific issues follow; some of them are simply a repeat from the next
time. Please be sure that comments are addressed; an "I don't agree with
this, for me, the way of XYZ is better because of ABCD" is better than not
reacting to the review comment at all.
- Commit df40ea7f83ec08350c1736f9a1d20e81c8b81203 -- why do you need to
track the plugin directory in application settings? Again, why it isn't
enough to copy the same logic as for loading the .ts files for l10n?
- Why do you store the plugin's *description* in settings? I understand the
plugin ID, but not the human readable description. Perhaps it's needed --
but if so, a comment saying that *must* be in the source.
- The fact that qobject_cast doesn't work across shared library boundaries
is suspicious. Wasn't supporting *that* use case one of the reasons
(besides not requiring RTTI) for introducing qobject_cast over
dynamic_cast?
- Why is function "loadPlugin" trying to unload plugins?
- Coding style: look out for e.g. extra whitespace when changing the
includes and make sure that they are sorted (order: the cpp's matching .h,
all system headers, all Qt headers, all Trojita headers. Sort order is
alphabetical, including the path. Use with the directory path (not
including "src/") when including stuff different than .cpp's own .h.)
- The plugins, interfaces, jobs etc. shall probably be namespaced.
"namespace Plugins"?
- Why are TrojitaPluginJob::start/stop postponing the actual
operation via the event loop? I'm not saying it's bad, but I'm
wondering why. A comment explaining this would be great.
I haven't got any response about this (commit
2a70055482dd90a8834fc643e41c102aef720836).
- Please prefer member initialization within the constructor,
not its body, like this:
Foo::Foo(): member(0), something("else")
{
// more stuff
}
This one still applies as well. Commit
2a70055482dd90a8834fc643e41c102aef720836, maybe others, too.
- Why are you employing the singletton (anti)pattern within the
PluginLoader? What are the advantages of using it (i.e. a global
variable in disguise) over an ordinary member of the MainWindow?
Not answered.
- Adding "/usr/lib" into the plugin path is just broken, IMHO.
Sure, plugins "can" be installed into /usr/lib, but why exactly?
The .ts files are not looked up from random places, either.
The comments about Debian's multilib do not answer this to me. Please
explain why you need /usr/lib in there.
Also keep in mind the use case of a developer who has both a systemwide
Trojita installation from packages and a git checkout (without having
called `make install`). Trojita from git shall definitely load *local*
plugins, not the systemwide ones, IMHO.
- The plugin loader contains extra qDebug; these shall be
removed or #ifdefed.
Not addressed.
- I'd rewrite the PluginLoader::loadPlugin plugin type
detection like this, but it's just me:
if (FooPlugin *plug = qobject_cast<...>(...)) {
// got Foo
} else if (BarPlugin *plug = qobject_cast...) {
// got plugin Bar
} else {
// WTF is this
}
Have you considered this comment? A good reason for that is that the
related code (variable being defined & set and the place it's actually
used) are together.
- Why is there that feature for "reloading plugins"?
Still not clear to me.
- The plugin headers were added into libCommon. Perhaps a separate static
lib would be better.
+ // Load plugins (needs correct application data)
+ Common::PluginLoader::instance();
If a class is named "plugin loader", my understanding is that it is *used*
for loading plugins when the programmer calls some method on that class.
The fact that it happens as a side effect of the instantiation is very
surprising to me.
If you'd like to have an RAII-ish approach to plugin lifecycle management,
perhaps it should be called "AutoLoadPlugins" or something like that. If
you go that route, I would prefer to have an actual "loader" separated into
another class, though.
- commit 546581201b79d721f6bcb22bc930eb4aaca2536f:
+ if (job) {
+ disconnect(job, 0, 0, 0);
+ job->stop();
+ job->deleteLater();
+ }
This is disconnecting everything connected to any signal of that job. Did
you mean to disconnect(job, 0, this, 0)?
+ AddressbookJob *job = static_cast<AddressbookJob *>(sender());
Kevin suggested to pass Job* as an argument; that would save you a call to
sender() here.
- Commit ec7e8ca0b61b5649644ec9073bf7b1278336abfb contains a regression, it
removes the feature for showing the proper icon in the envelope view.
- Commit f13ff62ae8ea8264073a1cf3e8a048eabdadee8c should be probably
cherry-picked to master and removed from your branch because it has nothing
to do with the platform integration plugins.
- The same for 9e77b0a12f9176fc4d113f12e2048a3cae1b1a22 and
6df3e61005bed504ed4f05fe00794375d6cf09f3.
Commit 6df3e61005bed504ed4f05fe00794375d6cf09f3:
+void SMTP::sendMailContinue()
That name doesn't explain what is it for. "sendMailGotPassword"?
- qwwSmtp->sendMailBurl(from, to, imapUrl);
+ qwwSmtp->sendMailBurl(from, to, data);
That looks like a copy-paste error, isn't it?
- Are you sure that this passes the unit tests? Is the new way of setting
passwords covered by a unit test?
- Commit e2dc2346967d46815b75ecd6b35e6dee753f166a (and the next one) should
be squashed into the previous ones; otherwise you're introducing
regressions to the tree. In general, I'd prefer to have this "prompt for
SMTP password" in master before the plugins are there; it's a very useful
feature (and an already requested one). Does it work for you?
- Commit 8938f94457ca4c15bbb766dcc2b84ebd409812ae is an absolute no-go --
each and every comit *MUST* compile.
- Commit 0be7a151cbe7c2eadf122705e149d523d3ca3ac9 for XtConnect is broken;
it's a non-interactive application and therefore it will break when
passwords are requested interactively. It shall *not* request the password
from KWallet etc, it shall read it from the QSettings to prevent breakage
for the existing users.
- Commit e3923adc697e3e6ae0dbcf4e22832304d43e686e:
-void EnvelopeView::setMessage(const QModelIndex &index)
+void EnvelopeView::setMessage(const QModelIndex &modelIndex)
{
// ... some real diff here
+
+ index = modelIndex;
Looks like excess diff noise.
- That commit also queues all addresses to be looked up sequentially. Why
not sending them away all at once and watching for all requests to
complete?
- The disconnect(job, 0, 0, 0) as above.
+ setToolTip(m_link + tr("<hr/><b>Address Book:</b><br/>") +
identities);
Perhaps include the name/description of the plugin in the tooltip?
+ QPointer <AddressbookJob> addressJob;
Extra space before the first <.
- Commit 38da896ce740be286366ff09562967af1b132061 -- if it's a bugfix for
the existing master, please submit it separately. If it's fixing something
in previous commits in the gsoc branch, please squash it to the offending
commit instead.
- Commit 96dca654d3dc2db3a4dfd32f355bddbe781aa39e:
+ const QList<QPair<QString, QString> > &addressbookPlugins =
pluginLoader->availableAddressbookPlugins();
+ const QList<QPair<QString, QString> > &passwordPlugins =
pluginLoader->availablePasswordPlugins();
+ const QPair <QString, QString> &addressbookPlugin =
pluginLoader->preferredAddressbookPlugin();
+ const QPair <QString, QString> &passwordPlugin =
pluginLoader->preferredPasswordPlugin();
+ int addressbookIndex = -1;
+ int passwordIndex = -1;
Please put related code together -- e.g. passwords first, then abook.
- Why are you passing both the plugin ID and the description to the
userData of the QComboBox?
- Why using QL1S("none") instead of, say, null QVariant() to indicate a
null plugin? "none" is a magic word.
+ addressbookBox->addItem(addressbookPlugin.second + QLatin1Char(' ') +
tr("(not found)")
addressbookBox->addItem(tr("%1 (not found)").arg(addressbookPlugin.second)
preferrably with some explaining comment (check QObject::tr's docs on how
to pass it, it's a magic comment iirc) telling the translators what is it
for.
In general, one shall not make assumptions on how is some thing done in a
foreign language.
- You can use QComboBox::findData to find the correct index.
commit 978ad3b4d6242c072eeacdbb6976d8e04f7f0b9e
+QMessageBox::critical(this, tr("IMAP password"), tr("Storing IMAP
password failed"));
Please tell the user:
- that the error comes from some plugin,
- which plugin it is,
- anything that the plugin might have to add ("cannot connect to your fancy
proprietary PW storage because you need to pay $100 for your license
extension", "cannot contact UberSafe PW daemon: not enough entropy, please
move your mouse" etc)
The same applies to other places which are saving passwords as well.
+PasswordJob *job = password->requestPassword(imapUser->text(),
QLatin1String("imap"));
How is this going to change when Trojita supports multiple passwords? It
shall probably include the hostname at least.
- Commit 983414e26f38a0780431471dadb933b94ac03afb:
Would be cool to not show the fancy border of the warning label when saving
in encrypted storage. Also perhaps include the plugin name?
- Commits c162f6e22db41156231c5ede4e4be8eb5478cc1b and
7ee728efb0ca0ee1741a5112b47f5a0099ad92bf break the build as you're moving
files around without modifying CMakeLists.txt. This *must* be fixed and
makes me unhappy.
- Commit 35628964681e7d662d6a301ebf5290781c4a05aa -- what's the point of
said API changes? I understand the namespace move, but not the rest. Also,
it's apprently breaking the build -> a no go.
- Commit 6e9c3dbf79dd86a2bcf8d40004e229be5eb8c903:
+ if (m_accountType == QLatin1String("imap"))
+ password =
QSettings().value(Common::SettingsNames::imapPassKey);
+ else if (m_accountType == QLatin1String("smtp"))
+ password =
QSettings().value(Common::SettingsNames::smtpPassKey);
+ if (password.type() != QVariant::String)
+ emit error(PasswordJob::NoSuchPassword);
+ else
+ emit passwordAvailable(password.toString());
- In this case, please use {} braces even for one liners; it will
dramatically improve readability. I had to look twice to notice that it's
not one big blcok of if/else-if/else-if/else, but in fact two separate
ones.
- It shall include an else (for unrecognized PW type) complainig that it
got called with wrong account info (not "imap" or "smtp"). Yes, it's
covered by the first condition of the second if switch, but that's more of
a side effect than a robust code, IMHO.
- This class apparently requires the delayed call to doStart so that the
connections are already set up. I'm still not sold on that it's a good idea
to enforce this for all TrojitaPluginJobs, but perhaps you're right. This
shall be documented in that generic class.
- Whenever any branch of the if/else contains {} braces, *all* branches
must have them.
- Again, separate commits for adding .cpp/.h and another for cmake
modifications are wrong.
- What are NullAddressbook and NullPasswordPlugin and why are they needed?
- Commit 70ce7d1b20d2419f4f56d629479891b5356fabd8 -- is there some error
handling for `kaddressbook` not being available, crashing etc?
- Commit 8d2c9128ebb94dbd4fdd950cf20d172febb673c2 shall be squashed into
the previous two.
- WITH_KDE cannot supported with Qt5.
- include(KDE4Defaults) and messing around with
add_definitions(${KDE4_ENABLE_EXCEPTIONS}), etc -- what about simply
applying the KDE-specific stuff to only the KDE-specific plugins?
- What about making a standalone CMAkeLists.txt for the KDE-specific
plugins? That should make it very easy for packages, won't it?
Cheers,
Jan
--
Trojitá, a fast Qt IMAP e-mail client -- http://trojita.flaska.net/